Merge from head
This commit is contained in:
commit
3c3feed41a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/collation/; revision=290241
22
MAINTAINERS
22
MAINTAINERS
@ -18,6 +18,12 @@ However, this is not a 'big stick', it is an offer to help and a source
|
||||
of guidance. It does not override the communal nature of the tree.
|
||||
It is not a registry of 'turf' or private property.
|
||||
|
||||
***
|
||||
This list is prone to becoming stale quickly. The best way to find the recent
|
||||
maintainer of a sub-system is to check recent logs for that directory or
|
||||
sub-system.
|
||||
***
|
||||
|
||||
subsystem login notes
|
||||
-----------------------------
|
||||
kqueue jmg Pre-commit review requested. Documentation Required.
|
||||
@ -31,8 +37,6 @@ sys/security/audit rwatson Pre-commit review requested.
|
||||
ath(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org
|
||||
ahc(4) gibbs Pre-commit review requested.
|
||||
ahd(4) gibbs Pre-commit review requested.
|
||||
PC Card imp Pre-commit review requested.
|
||||
CardBus imp Pre-commit review requested.
|
||||
pci bus imp,jhb Pre-commit review requested.
|
||||
cdboot jhb Pre-commit review requested.
|
||||
pxeboot jhb Pre-commit review requested.
|
||||
@ -66,8 +70,7 @@ net80211 adrian Pre-commit review requested, send to freebsd-wireless@freebsd.or
|
||||
nvi peter Try not to break it.
|
||||
libz peter Try not to break it.
|
||||
groff ru Recommends pre-commit review.
|
||||
share/mk ru This is a vital component of the build system, so I
|
||||
offer a pre-commit review for anything non-trivial.
|
||||
share/mk imp, bapt, bdrewery, emaste, sjg Make is hard.
|
||||
ipfw ipfw Pre-commit review preferred. send to ipfw@freebsd.org
|
||||
drm rnoland Just keep me informed of changes, try not to break it.
|
||||
unifdef(1) fanf Pre-commit review requested.
|
||||
@ -81,6 +84,7 @@ file obrien Insists to keep file blocked from other's unapproved
|
||||
contrib/bzip2 obrien Pre-commit review required.
|
||||
contrib/netbsd-tests freebsd-testing,ngie Pre-commit review requested.
|
||||
contrib/pjdfstest freebsd-testing,ngie Pre-commit review requested.
|
||||
geom freebsd-geom@FreeBSD.org
|
||||
geom_concat pjd Pre-commit review preferred.
|
||||
geom_eli pjd Pre-commit review preferred.
|
||||
geom_gate pjd Pre-commit review preferred.
|
||||
@ -92,16 +96,16 @@ geom_shsec pjd Pre-commit review preferred.
|
||||
geom_stripe pjd Pre-commit review preferred.
|
||||
geom_zero pjd Pre-commit review preferred.
|
||||
sbin/geom pjd Pre-commit review preferred.
|
||||
zfs pjd Pre-commit review preferred.
|
||||
nfs alfred Will be happy to review code, but not mandatory.
|
||||
rpc.lockd alfred Will be happy to review code, but not mandatory.
|
||||
truss alfred Will be happy to review code, but not mandatory.
|
||||
rpc alfred Pre-commit review requested.
|
||||
zfs freebsd-fs@FreeBSD.org
|
||||
nfs freebsd-fs@FreeBSD.org, rmacklem is best for reviews.
|
||||
linux emul emulation Please discuss changes here.
|
||||
bs{diff,patch} cperciva Pre-commit review requested.
|
||||
portsnap cperciva Pre-commit review requested.
|
||||
freebsd-update cperciva Pre-commit review requested.
|
||||
openssl benl,jkim Pre-commit review requested.
|
||||
sys/dev/usb hselasky If in doubt, ask.
|
||||
sys/dev/sound/usb hselasky If in doubt, ask.
|
||||
sys/compat/linuxkpi hselasky If in doubt, ask.
|
||||
sys/netgraph/bluetooth emax Pre-commit review preferred.
|
||||
lib/libbluetooth emax Pre-commit review preferred.
|
||||
lib/libsdp emax Pre-commit review preferred.
|
||||
|
188
Makefile.inc1
188
Makefile.inc1
@ -30,6 +30,8 @@
|
||||
# BUILDENV_SHELL= shell to launch for the buildenv target (def:/bin/sh)
|
||||
# WORLD_FLAGS= additional flags to pass to make(1) during buildworld
|
||||
# KERNEL_FLAGS= additional flags to pass to make(1) during buildkernel
|
||||
# SUBDIR_OVERRIDE="list of dirs" to build rather than everything.
|
||||
# All libraries and includes, and some build tools will still build.
|
||||
|
||||
#
|
||||
# The intended user-driven targets are:
|
||||
@ -59,7 +61,7 @@
|
||||
# system here would require fine-grained ordering of all components based
|
||||
# on their dependencies.
|
||||
SRCDIR?= ${.CURDIR}
|
||||
.if defined(SUBDIR_OVERRIDE)
|
||||
.if !empty(SUBDIR_OVERRIDE)
|
||||
SUBDIR= ${SUBDIR_OVERRIDE}
|
||||
.else
|
||||
SUBDIR= lib libexec
|
||||
@ -113,7 +115,6 @@ SUBDIR+= ${_DIR}
|
||||
.warning ${_DIR} not added to SUBDIR list. See UPDATING 20141121.
|
||||
.endif
|
||||
.endfor
|
||||
.endif
|
||||
|
||||
# We must do etc/ last as it hooks into building the man whatis file
|
||||
# by calling 'makedb' in share/man. This is only relevant for
|
||||
@ -124,7 +125,10 @@ SUBDIR+=.WAIT
|
||||
.endif
|
||||
SUBDIR+=etc
|
||||
|
||||
.endif # !empty(SUBDIR_OVERRIDE)
|
||||
|
||||
.if defined(NOCLEAN)
|
||||
.warning NOCLEAN option is deprecated. Use NO_CLEAN instead.
|
||||
NO_CLEAN= ${NOCLEAN}
|
||||
.endif
|
||||
.if defined(NO_CLEANDIR)
|
||||
@ -394,6 +398,9 @@ TARGET_ABI= gnueabi
|
||||
.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc
|
||||
XCFLAGS+= -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
|
||||
XCXXFLAGS+= -I${WORLDTMP}/usr/include/c++/v1 -std=gnu++11 -L${WORLDTMP}/../lib/libc++
|
||||
# XXX: DEPFLAGS is a workaround for not properly passing CXXFLAGS to sub-makes
|
||||
# due to CXX="${XCXX} ${XCXXFLAGS}". bsd.dep.mk does use CXXFLAGS when
|
||||
# building C++ files so this can come out if passing CXXFLAGS down is fixed.
|
||||
DEPFLAGS+= -I${WORLDTMP}/usr/include/c++/v1
|
||||
.else
|
||||
TARGET_ABI?= unknown
|
||||
@ -513,7 +520,7 @@ KMAKE= ${KMAKEENV} ${MAKE} ${.MAKEFLAGS} ${KERNEL_FLAGS} KERNEL=${INSTKERNNAME}
|
||||
# Attempt to rebuild the entire system, with reasonable chance of
|
||||
# success, regardless of how old your existing system is.
|
||||
#
|
||||
_worldtmp:
|
||||
_worldtmp: .PHONY
|
||||
.if ${.CURDIR:C/[^,]//g} != ""
|
||||
# The m4 build of sendmail files doesn't like it if ',' is used
|
||||
# anywhere in the path of it's files.
|
||||
@ -560,6 +567,16 @@ _worldtmp:
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${WORLDTMP}/usr/lib >/dev/null
|
||||
.endif
|
||||
.if ${MK_LIB32} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${WORLDTMP}/usr >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${WORLDTMP}/legacy/usr/lib/debug/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${WORLDTMP}/usr/lib/debug/usr >/dev/null
|
||||
.endif
|
||||
.endif
|
||||
.if ${MK_TESTS} != "no"
|
||||
mkdir -p ${WORLDTMP}${TESTSBASE}
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
|
||||
@ -620,8 +637,16 @@ _includes:
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 4.1: building includes"
|
||||
@echo "--------------------------------------------------------------"
|
||||
# Special handling for SUBDIR_OVERRIDE in buildworld as they most likely need
|
||||
# headers from default SUBDIR. Do SUBDIR_OVERRIDE includes last.
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} SUBDIR_OVERRIDE= SHARED=symlinks \
|
||||
buildincludes
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} SUBDIR_OVERRIDE= SHARED=symlinks \
|
||||
installincludes
|
||||
.if !empty(SUBDIR_OVERRIDE) && make(buildworld)
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks buildincludes
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks installincludes
|
||||
.endif
|
||||
_libraries:
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@ -643,7 +668,7 @@ everything:
|
||||
@echo "--------------------------------------------------------------"
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} par-all
|
||||
.if defined(LIB32TMP)
|
||||
build32:
|
||||
build32: .PHONY
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 5.1: building 32 bit shim libraries"
|
||||
@ -653,73 +678,76 @@ build32:
|
||||
-p ${LIB32TMP}/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
|
||||
-p ${LIB32TMP}/usr/include >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${LIB32TMP}/usr >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${LIB32TMP}/usr/lib >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${LIB32TMP}/usr/lib/debug/usr >/dev/null
|
||||
.endif
|
||||
mkdir -p ${WORLDTMP}
|
||||
ln -sf ${.CURDIR}/sys ${WORLDTMP}
|
||||
.for _t in obj includes
|
||||
cd ${.CURDIR}/include; ${LIB32WMAKE} DIRPRFX=include/ ${_t}
|
||||
cd ${.CURDIR}/lib; ${LIB32WMAKE} DIRPRFX=lib/ ${_t}
|
||||
${_+_}cd ${.CURDIR}/include; ${LIB32WMAKE} DIRPRFX=include/ ${_t}
|
||||
${_+_}cd ${.CURDIR}/lib; ${LIB32WMAKE} DIRPRFX=lib/ ${_t}
|
||||
.if ${MK_CDDL} != "no"
|
||||
cd ${.CURDIR}/cddl/lib; ${LIB32WMAKE} DIRPRFX=cddl/lib/ ${_t}
|
||||
${_+_}cd ${.CURDIR}/cddl/lib; ${LIB32WMAKE} DIRPRFX=cddl/lib/ ${_t}
|
||||
.endif
|
||||
cd ${.CURDIR}/gnu/lib; ${LIB32WMAKE} DIRPRFX=gnu/lib/ ${_t}
|
||||
${_+_}cd ${.CURDIR}/gnu/lib; ${LIB32WMAKE} DIRPRFX=gnu/lib/ ${_t}
|
||||
.if ${MK_CRYPT} != "no"
|
||||
cd ${.CURDIR}/secure/lib; ${LIB32WMAKE} DIRPRFX=secure/lib/ ${_t}
|
||||
${_+_}cd ${.CURDIR}/secure/lib; ${LIB32WMAKE} DIRPRFX=secure/lib/ ${_t}
|
||||
.endif
|
||||
.if ${MK_KERBEROS} != "no"
|
||||
cd ${.CURDIR}/kerberos5/lib; ${LIB32WMAKE} DIRPRFX=kerberos5/lib ${_t}
|
||||
${_+_}cd ${.CURDIR}/kerberos5/lib; ${LIB32WMAKE} DIRPRFX=kerberos5/lib ${_t}
|
||||
.endif
|
||||
.endfor
|
||||
.for _dir in usr.bin/lex/lib
|
||||
cd ${.CURDIR}/${_dir}; ${LIB32WMAKE} DIRPRFX=${_dir}/ obj
|
||||
${_+_}cd ${.CURDIR}/${_dir}; ${LIB32WMAKE} DIRPRFX=${_dir}/ obj
|
||||
.endfor
|
||||
.for _dir in lib/ncurses/ncurses lib/ncurses/ncursesw lib/libmagic
|
||||
cd ${.CURDIR}/${_dir}; \
|
||||
${_+_}cd ${.CURDIR}/${_dir}; \
|
||||
WORLDTMP=${WORLDTMP} \
|
||||
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \
|
||||
MAKEOBJDIRPREFIX=${LIB32_OBJTREE} ${MAKE} SSP_CFLAGS= DESTDIR= \
|
||||
DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \
|
||||
build-tools
|
||||
.endfor
|
||||
cd ${.CURDIR}; \
|
||||
${_+_}cd ${.CURDIR}; \
|
||||
${LIB32WMAKE} -f Makefile.inc1 libraries
|
||||
.for _t in obj depend all
|
||||
cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32WMAKE} \
|
||||
${_+_}cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32WMAKE} \
|
||||
DIRPRFX=libexec/rtld-elf/ ${_t}
|
||||
cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32WMAKE} \
|
||||
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32WMAKE} \
|
||||
DIRPRFX=usr.bin/ldd ${_t}
|
||||
.endfor
|
||||
|
||||
distribute32 install32:
|
||||
cd ${.CURDIR}/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
distribute32 install32: .MAKE .PHONY
|
||||
${_+_}cd ${.CURDIR}/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.if ${MK_CDDL} != "no"
|
||||
cd ${.CURDIR}/cddl/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
${_+_}cd ${.CURDIR}/cddl/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.endif
|
||||
cd ${.CURDIR}/gnu/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
${_+_}cd ${.CURDIR}/gnu/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.if ${MK_CRYPT} != "no"
|
||||
cd ${.CURDIR}/secure/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
${_+_}cd ${.CURDIR}/secure/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.endif
|
||||
.if ${MK_KERBEROS} != "no"
|
||||
cd ${.CURDIR}/kerberos5/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
${_+_}cd ${.CURDIR}/kerberos5/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.endif
|
||||
cd ${.CURDIR}/libexec/rtld-elf; \
|
||||
${_+_}cd ${.CURDIR}/libexec/rtld-elf; \
|
||||
PROG=ld-elf32.so.1 ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32IMAKE} \
|
||||
${.TARGET:S/32$//}
|
||||
.endif
|
||||
|
||||
WMAKE_TGTS=
|
||||
.if !defined(SUBDIR_OVERRIDE)
|
||||
WMAKE_TGTS+= _worldtmp _legacy _bootstrap-tools
|
||||
.endif
|
||||
WMAKE_TGTS+= _cleanobj _obj _build-tools
|
||||
.if !defined(SUBDIR_OVERRIDE)
|
||||
WMAKE_TGTS+= _cross-tools
|
||||
WMAKE_TGTS+= _worldtmp _legacy
|
||||
.if empty(SUBDIR_OVERRIDE)
|
||||
WMAKE_TGTS+= _bootstrap-tools
|
||||
.endif
|
||||
WMAKE_TGTS+= _cleanobj _obj _build-tools _cross-tools
|
||||
WMAKE_TGTS+= _includes _libraries _depend everything
|
||||
.if defined(LIB32TMP) && ${MK_LIB32} != "no"
|
||||
.if defined(LIB32TMP) && ${MK_LIB32} != "no" && empty(SUBDIR_OVERRIDE)
|
||||
WMAKE_TGTS+= build32
|
||||
.endif
|
||||
|
||||
@ -901,6 +929,14 @@ distributeworld installworld: _installcheck_world
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib >/dev/null
|
||||
.endif
|
||||
.if ${MK_LIB32} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${DESTDIR}/${DISTDIR}/${dist}/usr >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib/debug/usr >/dev/null
|
||||
.endif
|
||||
.endif
|
||||
.if ${MK_TESTS} != "no" && ${dist} == "tests"
|
||||
-mkdir -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE}
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
|
||||
@ -917,10 +953,14 @@ distributeworld installworld: _installcheck_world
|
||||
sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG}
|
||||
${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \
|
||||
sed -e 's#^\./#./${dist}/usr/include/#' >> ${METALOG}
|
||||
.if ${MK_LIB32} != "no"
|
||||
${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.lib32.dist | \
|
||||
sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG}
|
||||
.endif
|
||||
.endif
|
||||
.endfor
|
||||
-mkdir ${DESTDIR}/${DISTDIR}/base
|
||||
cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
|
||||
${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
|
||||
METALOG=${METALOG} ${IMAKE_INSTALL} ${IMAKE_MTREE} \
|
||||
DISTBASE=/base DESTDIR=${DESTDIR}/${DISTDIR}/base \
|
||||
LOCAL_MTREE=${LOCAL_MTREE:Q} distrib-dirs
|
||||
@ -988,7 +1028,7 @@ packageworld:
|
||||
# and do a 'make reinstall' on the *client* to install new binaries from the
|
||||
# most recent server build.
|
||||
#
|
||||
reinstall: .MAKE
|
||||
reinstall: .MAKE .PHONY
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> Making hierarchy"
|
||||
@echo "--------------------------------------------------------------"
|
||||
@ -1003,7 +1043,7 @@ reinstall: .MAKE
|
||||
${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 install32
|
||||
.endif
|
||||
|
||||
redistribute: .MAKE
|
||||
redistribute: .MAKE .PHONY
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> Distributing everything"
|
||||
@echo "--------------------------------------------------------------"
|
||||
@ -1013,12 +1053,12 @@ redistribute: .MAKE
|
||||
DISTRIBUTION=lib32
|
||||
.endif
|
||||
|
||||
distrib-dirs: .MAKE
|
||||
cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
|
||||
distrib-dirs: .MAKE .PHONY
|
||||
${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
|
||||
${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET}
|
||||
|
||||
distribution: .MAKE
|
||||
cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
|
||||
distribution: .MAKE .PHONY
|
||||
${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
|
||||
${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET}
|
||||
${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \
|
||||
${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \
|
||||
@ -1071,14 +1111,14 @@ INSTALLKERNEL= ${_kernel}
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
buildkernel ${WMAKE_TGTS:N_worldtmp:Nbuild32} ${.ALLTARGETS:M_*:N_worldtmp}: .MAKE .PHONY
|
||||
${WMAKE_TGTS:N_worldtmp:Nbuild32} ${.ALLTARGETS:M_*:N_worldtmp}: .MAKE .PHONY
|
||||
|
||||
#
|
||||
# buildkernel
|
||||
#
|
||||
# Builds all kernels defined by BUILDKERNELS.
|
||||
#
|
||||
buildkernel:
|
||||
buildkernel: .MAKE .PHONY
|
||||
.if empty(BUILDKERNELS)
|
||||
@echo "ERROR: Missing kernel configuration file(s) (${KERNCONF})."; \
|
||||
false
|
||||
@ -1105,14 +1145,14 @@ buildkernel:
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 2.1: cleaning up the object tree"
|
||||
@echo "--------------------------------------------------------------"
|
||||
cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} ${CLEANDIR}
|
||||
${_+_}cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} ${CLEANDIR}
|
||||
.endif
|
||||
.if !defined(NO_KERNELOBJ)
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 2.2: rebuilding the object tree"
|
||||
@echo "--------------------------------------------------------------"
|
||||
cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} obj
|
||||
${_+_}cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} obj
|
||||
.endif
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@ -1124,13 +1164,13 @@ buildkernel:
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 3.1: making dependencies"
|
||||
@echo "--------------------------------------------------------------"
|
||||
cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} depend -DNO_MODULES_OBJ
|
||||
${_+_}cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} depend -DNO_MODULES_OBJ
|
||||
.endif
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 3.2: building everything"
|
||||
@echo "--------------------------------------------------------------"
|
||||
cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} all -DNO_MODULES_OBJ
|
||||
${_+_}cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} all -DNO_MODULES_OBJ
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> Kernel build for ${_kernel} completed on `LC_ALL=C date`"
|
||||
@echo "--------------------------------------------------------------"
|
||||
@ -1231,12 +1271,12 @@ packagekernel:
|
||||
#
|
||||
# Build the API documentation with doxygen
|
||||
#
|
||||
doxygen:
|
||||
doxygen: .PHONY
|
||||
@if [ ! -x `/usr/bin/which doxygen` ]; then \
|
||||
echo "You need doxygen (devel/doxygen) to generate the API documentation of the kernel." | /usr/bin/fmt; \
|
||||
exit 1; \
|
||||
fi
|
||||
cd ${.CURDIR}/tools/kerneldoc/subsys && ${MAKE} obj all
|
||||
${_+_}cd ${.CURDIR}/tools/kerneldoc/subsys && ${MAKE} obj all
|
||||
|
||||
#
|
||||
# update
|
||||
@ -1471,7 +1511,6 @@ _gcc_tools= gnu/usr.bin/cc/cc_tools
|
||||
_rescue=rescue/rescue
|
||||
.endif
|
||||
|
||||
build-tools: .MAKE
|
||||
.for _tool in \
|
||||
bin/csh \
|
||||
bin/sh \
|
||||
@ -1485,18 +1524,22 @@ build-tools: .MAKE
|
||||
usr.bin/mkesdb_static \
|
||||
usr.bin/mkcsmapper_static \
|
||||
usr.bin/vi/catalog
|
||||
build-tools_${_tool}: .PHONY
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \
|
||||
cd ${.CURDIR}/${_tool} && \
|
||||
${MAKE} DIRPRFX=${_tool}/ obj && \
|
||||
${MAKE} DIRPRFX=${_tool}/ build-tools
|
||||
build-tools: build-tools_${_tool}
|
||||
.endfor
|
||||
.for _tool in \
|
||||
${_gcc_tools}
|
||||
build-tools_${_tool}: .PHONY
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all)"; \
|
||||
cd ${.CURDIR}/${_tool} && \
|
||||
${MAKE} DIRPRFX=${_tool}/ obj && \
|
||||
${MAKE} DIRPRFX=${_tool}/ depend && \
|
||||
${MAKE} DIRPRFX=${_tool}/ all
|
||||
build-tools: build-tools_${_tool}
|
||||
.endfor
|
||||
|
||||
#
|
||||
@ -1562,7 +1605,7 @@ _cc= gnu/usr.bin/cc
|
||||
_usb_tools= sys/boot/usb/tools
|
||||
.endif
|
||||
|
||||
cross-tools: .MAKE
|
||||
cross-tools: .MAKE .PHONY
|
||||
.for _tool in \
|
||||
${_clang_libs} \
|
||||
${_clang} \
|
||||
@ -1581,12 +1624,13 @@ cross-tools: .MAKE
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX} install
|
||||
.endfor
|
||||
|
||||
NXBDESTDIR= ${OBJTREE}/nxb-bin
|
||||
NXBENV= MAKEOBJDIRPREFIX=${OBJTREE}/nxb \
|
||||
INSTALL="sh ${.CURDIR}/tools/install.sh" \
|
||||
PATH=${PATH}:${OBJTREE}/gperf_for_gcc/usr/bin
|
||||
NXBMAKE= ${NXBENV} ${MAKE} \
|
||||
TBLGEN=${OBJTREE}/nxb-bin/usr/bin/tblgen \
|
||||
CLANG_TBLGEN=${OBJTREE}/nxb-bin/usr/bin/clang-tblgen \
|
||||
TBLGEN=${NXBDESTDIR}/usr/bin/tblgen \
|
||||
CLANG_TBLGEN=${NXBDESTDIR}/usr/bin/clang-tblgen \
|
||||
MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} \
|
||||
MK_GDB=no MK_TESTS=no \
|
||||
SSP_CFLAGS= \
|
||||
@ -1601,7 +1645,7 @@ NXBMAKE= ${NXBENV} ${MAKE} \
|
||||
# For non-clang enabled targets that are still using the in tree gcc
|
||||
# we must build a gperf binary for one instance of its Makefiles. On
|
||||
# clang-enabled systems, the gperf binary is obsolete.
|
||||
native-xtools:
|
||||
native-xtools: .PHONY
|
||||
.if ${MK_GCC_BOOTSTRAP} != "no"
|
||||
mkdir -p ${OBJTREE}/gperf_for_gcc/usr/bin
|
||||
${_+_}@${ECHODIR} "===> ${_gperf} (obj,depend,all,install)"; \
|
||||
@ -1611,13 +1655,15 @@ native-xtools:
|
||||
${NXBMAKE} DIRPRFX=${_gperf}/ all && \
|
||||
${NXBMAKE} DIRPRFX=${_gperf}/ DESTDIR=${OBJTREE}/gperf_for_gcc install
|
||||
.endif
|
||||
mkdir -p ${OBJTREE}/nxb-bin/bin
|
||||
mkdir -p ${OBJTREE}/nxb-bin/sbin
|
||||
mkdir -p ${OBJTREE}/nxb-bin/usr
|
||||
mkdir -p ${NXBDESTDIR}/bin ${NXBDESTDIR}/sbin ${NXBDESTDIR}/usr
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
|
||||
-p ${OBJTREE}/nxb-bin/usr >/dev/null
|
||||
-p ${NXBDESTDIR}/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
|
||||
-p ${OBJTREE}/nxb-bin/usr/include >/dev/null
|
||||
-p ${NXBDESTDIR}/usr/include >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${NXBDESTDIR}/usr/lib >/dev/null
|
||||
.endif
|
||||
.for _tool in \
|
||||
bin/cat \
|
||||
bin/chmod \
|
||||
@ -1682,14 +1728,14 @@ native-xtools:
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ obj && \
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ depend && \
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ all && \
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${OBJTREE}/nxb-bin install
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${NXBDESTDIR} install
|
||||
.endfor
|
||||
|
||||
#
|
||||
# hierarchy - ensure that all the needed directories are present
|
||||
#
|
||||
hierarchy hier: .MAKE
|
||||
cd ${.CURDIR}/etc && ${HMAKE} distrib-dirs
|
||||
hierarchy hier: .MAKE .PHONY
|
||||
${_+_}cd ${.CURDIR}/etc && ${HMAKE} distrib-dirs
|
||||
|
||||
#
|
||||
# libraries - build all libraries, and install them under ${DESTDIR}.
|
||||
@ -1698,8 +1744,8 @@ hierarchy hier: .MAKE
|
||||
# interdependencies (__L) are built automatically by the
|
||||
# ${.CURDIR}/tools/make_libdeps.sh script.
|
||||
#
|
||||
libraries: .MAKE
|
||||
cd ${.CURDIR} && \
|
||||
libraries: .MAKE .PHONY
|
||||
${_+_}cd ${.CURDIR} && \
|
||||
${MAKE} -f Makefile.inc1 _prereq_libs && \
|
||||
${MAKE} -f Makefile.inc1 _startup_libs && \
|
||||
${MAKE} -f Makefile.inc1 _prebuild_libs && \
|
||||
@ -2197,12 +2243,12 @@ xdev: xdev-build xdev-install
|
||||
.ORDER: _xb-worldtmp _xb-bootstrap-tools _xb-build-tools _xb-cross-tools
|
||||
xdev-build: _xb-worldtmp _xb-bootstrap-tools _xb-build-tools _xb-cross-tools
|
||||
|
||||
_xb-worldtmp:
|
||||
_xb-worldtmp: .PHONY
|
||||
mkdir -p ${CDTMP}/usr
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
|
||||
-p ${CDTMP}/usr >/dev/null
|
||||
|
||||
_xb-bootstrap-tools:
|
||||
_xb-bootstrap-tools: .PHONY
|
||||
.for _tool in \
|
||||
${_clang_tblgen} \
|
||||
${_gperf}
|
||||
@ -2214,11 +2260,11 @@ _xb-bootstrap-tools:
|
||||
${CDMAKE} DIRPRFX=${_tool}/ DESTDIR=${CDTMP} install
|
||||
.endfor
|
||||
|
||||
_xb-build-tools:
|
||||
_xb-build-tools: .PHONY
|
||||
${_+_}@cd ${.CURDIR}; \
|
||||
${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools
|
||||
|
||||
_xb-cross-tools:
|
||||
_xb-cross-tools: .PHONY
|
||||
.for _tool in \
|
||||
${_binutils} \
|
||||
${_elftctools} \
|
||||
@ -2233,7 +2279,7 @@ _xb-cross-tools:
|
||||
${CDMAKE} DIRPRFX=${_tool}/ all
|
||||
.endfor
|
||||
|
||||
_xi-mtree:
|
||||
_xi-mtree: .PHONY
|
||||
${_+_}@${ECHODIR} "mtree populating ${XDDESTDIR}"
|
||||
mkdir -p ${XDDESTDIR}
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.root.dist \
|
||||
@ -2242,6 +2288,10 @@ _xi-mtree:
|
||||
-p ${XDDESTDIR}/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
|
||||
-p ${XDDESTDIR}/usr/include >/dev/null
|
||||
.if ${MK_LIB32} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \
|
||||
-p ${XDDESTDIR}/usr >/dev/null
|
||||
.endif
|
||||
.if ${MK_TESTS} != "no"
|
||||
mkdir -p ${XDDESTDIR}${TESTSBASE}
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
|
||||
@ -2251,7 +2301,7 @@ _xi-mtree:
|
||||
.ORDER: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries
|
||||
xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries
|
||||
|
||||
_xi-cross-tools:
|
||||
_xi-cross-tools: .PHONY
|
||||
@echo "_xi-cross-tools"
|
||||
.for _tool in \
|
||||
${_binutils} \
|
||||
@ -2265,17 +2315,17 @@ _xi-cross-tools:
|
||||
${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR}
|
||||
.endfor
|
||||
|
||||
_xi-includes:
|
||||
_xi-includes: .PHONY
|
||||
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 buildincludes \
|
||||
DESTDIR=${XDDESTDIR}
|
||||
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 installincludes \
|
||||
DESTDIR=${XDDESTDIR}
|
||||
|
||||
_xi-libraries:
|
||||
_xi-libraries: .PHONY
|
||||
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 libraries \
|
||||
DESTDIR=${XDDESTDIR}
|
||||
|
||||
xdev-links:
|
||||
xdev-links: .PHONY
|
||||
${_+_}cd ${XDDESTDIR}/usr/bin; \
|
||||
mkdir -p ../../../../usr/bin; \
|
||||
for i in *; do \
|
||||
|
@ -97,6 +97,15 @@ OLD_FILES+=usr/bin/colldef
|
||||
OLD_FILES+=usr/share/man/man1/colldef.1.gz
|
||||
OLD_FILES+=usr/bin/mklocale
|
||||
OLD_FILES+=usr/share/man/man1/mklocale.1.gz
|
||||
# 20151030: OpenSSL 1.0.2d import
|
||||
OLD_FILES+=usr/share/openssl/man/man3/CMS_set1_signer_certs.3.gz
|
||||
OLD_FILES+=usr/share/openssl/man/man3/EVP_PKEY_ctrl.3.gz
|
||||
OLD_FILES+=usr/share/openssl/man/man3/EVP_PKEY_ctrl_str.3.gz
|
||||
OLD_FILES+=usr/share/openssl/man/man3/d2i_509_CRL_fp.3.gz
|
||||
OLD_LIBS+=lib/libcrypto.so.7
|
||||
OLD_LIBS+=usr/lib/libssl.so.7
|
||||
OLD_LIBS+=usr/lib32/libcrypto.so.7
|
||||
OLD_LIBS+=usr/lib32/libssl.so.7
|
||||
# 20151015: test symbols moved to /usr/lib/debug
|
||||
OLD_DIRS+=usr/tests/lib/atf/libatf-c++/.debug
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/atf_c++_test.debug
|
||||
@ -503,6 +512,8 @@ OLD_DIRS+=usr/share/doc/legal/intel_wpi
|
||||
OLD_FILES+=usr/share/doc/legal/intel_wpi/LICENSE
|
||||
# 20151006: new libc++ import
|
||||
OLD_FILES+=usr/include/c++/__tuple_03
|
||||
OLD_FILES+=usr/include/c++/v1/__tuple_03
|
||||
OLD_FILES+=usr/include/c++/v1/tr1/__tuple_03
|
||||
# 20151006: new clang import which bumps version from 3.6.1 to 3.7.0.
|
||||
OLD_FILES+=usr/lib/clang/3.6.1/include/__stddef_max_align_t.h
|
||||
OLD_FILES+=usr/lib/clang/3.6.1/include/__wmmintrin_aes.h
|
||||
@ -589,11 +600,16 @@ OLD_FILES+=usr/share/man/man4/dtrace-proc.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/dtrace-sched.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/dtrace-tcp.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/dtrace-udp.4.gz
|
||||
# 20150704: nvlist private headers no longer installed
|
||||
OLD_FILES+=usr/include/sys/nv_impl.h
|
||||
OLD_FILES+=usr/include/sys/nvlist_impl.h
|
||||
OLD_FILES+=usr/include/sys/nvpair_impl.h
|
||||
# 20150624
|
||||
OLD_LIBS+=usr/lib/libugidfw.so.4
|
||||
OLD_LIBS+=usr/lib32/libugidfw.so.4
|
||||
# 20150604: Move nvlist man pages to section 9.
|
||||
OLD_FILES+=usr/share/man/man3/libnv.3.gz
|
||||
OLD_FILES+=usr/share/man/man3/nv.3.gz
|
||||
OLD_FILES+=usr/share/man/man3/nvlist.3.gz
|
||||
OLD_FILES+=usr/share/man/man3/nvlist_add_binary.3.gz
|
||||
OLD_FILES+=usr/share/man/man3/nvlist_add_bool.3.gz
|
||||
|
9
UPDATING
9
UPDATING
@ -31,6 +31,15 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
|
||||
disable the most expensive debugging functionality run
|
||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20151030:
|
||||
The OpenSSL has been upgraded to 1.0.2d. Any binaries requiring
|
||||
libcrypto.so.7 or libssl.so.7 must be recompiled.
|
||||
|
||||
20151020:
|
||||
Qlogic 24xx/25xx firmware images were updated from 5.5.0 to 7.3.0.
|
||||
Kernel modules isp_2400_multi and isp_2500_multi were removed and
|
||||
should be replaced with isp_2400 and isp_2500 modules respectively.
|
||||
|
||||
20151017:
|
||||
The build previously allowed using 'make -n' to not recurse into
|
||||
sub-directories while showing what commands would be executed, and
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#ifndef _h_config
|
||||
#define _h_config
|
||||
/****************** System dependant compilation flags ****************/
|
||||
/****************** System dependent compilation flags ****************/
|
||||
/*
|
||||
* POSIX This system supports IEEE Std 1003.1-1988 (POSIX).
|
||||
*/
|
||||
|
@ -418,10 +418,10 @@ T_flag_body()
|
||||
|
||||
atf_check -e empty -o empty -s exit:0 touch a.file
|
||||
|
||||
birthtime_in_secs=$(stat -f %B -t %s a.file)
|
||||
birthtime=$(date -j -f %s $birthtime_in_secs +"[[:space:]]+%b[[:space:]]+%e[[:space:]]+%H:%M:%S[[:space:]]+%Y")
|
||||
mtime_in_secs=$(stat -f %m -t %s a.file)
|
||||
mtime=$(date -j -f %s $mtime_in_secs +"[[:space:]]+%b[[:space:]]+%e[[:space:]]+%H:%M:%S[[:space:]]+%Y")
|
||||
|
||||
atf_check -e empty -o match:"$birthtime"'[[:space:]]+a\.file' \
|
||||
atf_check -e empty -o match:"$mtime"'[[:space:]]+a\.file' \
|
||||
-s exit:0 ls -lT a.file
|
||||
}
|
||||
|
||||
@ -626,10 +626,10 @@ l_flag_body()
|
||||
|
||||
atf_check -e empty -o empty -s exit:0 touch a.file
|
||||
|
||||
birthtime_in_secs=$(stat -f "%B" -t "%s" a.file)
|
||||
birthtime=$(date -j -f "%s" $birthtime_in_secs +"%b[[:space:]]+%e[[:space:]]+%H:%M")
|
||||
mtime_in_secs=$(stat -f "%m" -t "%s" a.file)
|
||||
mtime=$(date -j -f "%s" $mtime_in_secs +"%b[[:space:]]+%e[[:space:]]+%H:%M")
|
||||
|
||||
expected_output=$(stat -f "%Sp[[:space:]]+%l[[:space:]]+%Su[[:space:]]+%Sg[[:space:]]+%z[[:space:]]+$birthtime[[:space:]]+a\\.file" a.file)
|
||||
expected_output=$(stat -f "%Sp[[:space:]]+%l[[:space:]]+%Su[[:space:]]+%Sg[[:space:]]+%z[[:space:]]+$mtime[[:space:]]+a\\.file" a.file)
|
||||
|
||||
atf_check -e empty -o match:"$expected_output" -s exit:0 ls -l a.file
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 14, 2015
|
||||
.Dd October 24, 2015
|
||||
.Dt ZFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -272,8 +272,10 @@
|
||||
.Ar tag snapshot Ns ...
|
||||
.Nm
|
||||
.Cm holds
|
||||
.Op Fl r
|
||||
.Ar snapshot Ns ...
|
||||
.Op Fl Hp
|
||||
.Op Fl r Ns | Ns Fl d Ar depth
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns
|
||||
.Ns ...
|
||||
.Nm
|
||||
.Cm release
|
||||
.Op Fl r
|
||||
@ -3159,15 +3161,26 @@ snapshots of all descendent file systems.
|
||||
.It Xo
|
||||
.Nm
|
||||
.Cm holds
|
||||
.Op Fl r
|
||||
.Ar snapshot Ns ...
|
||||
.Op Fl Hp
|
||||
.Op Fl r Ns | Ns Fl d Ar depth
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns
|
||||
.Ns ...
|
||||
.Xc
|
||||
.Pp
|
||||
Lists all existing user references for the given snapshot or snapshots.
|
||||
Lists all existing user references for the given dataset or datasets.
|
||||
.Bl -tag -width indent
|
||||
.It Fl H
|
||||
Used for scripting mode. Do not print headers and separate fields by a single
|
||||
tab instead of arbitrary white space.
|
||||
.It Fl p
|
||||
Display numbers in parsable (exact) values.
|
||||
.It Fl r
|
||||
Lists the holds that are set on the named descendent snapshots, in addition to
|
||||
listing the holds on the named snapshot.
|
||||
Lists the holds that are set on the descendent snapshots of the named datasets
|
||||
or snapshots, in addition to listing the holds on the named snapshots, if any.
|
||||
.It Fl d Ar depth
|
||||
Recursively display any holds on the named snapshots, or descendent snapshots of
|
||||
the named datasets or snapshots, limiting the recursion to
|
||||
.Ar depth .
|
||||
.El
|
||||
.It Xo
|
||||
.Nm
|
||||
|
@ -329,7 +329,8 @@ get_usage(zfs_help_t idx)
|
||||
case HELP_HOLD:
|
||||
return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
|
||||
case HELP_HOLDS:
|
||||
return (gettext("\tholds [-r] <snapshot> ...\n"));
|
||||
return (gettext("\tholds [-Hp] [-r|-d depth] "
|
||||
"<filesystem|volume|snapshot> ...\n"));
|
||||
case HELP_RELEASE:
|
||||
return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
|
||||
case HELP_DIFF:
|
||||
@ -5543,7 +5544,8 @@ typedef struct holds_cbdata {
|
||||
*
|
||||
*/
|
||||
static void
|
||||
print_holds(boolean_t scripted, size_t nwidth, size_t tagwidth, nvlist_t *nvl)
|
||||
print_holds(boolean_t scripted, boolean_t literal, size_t nwidth,
|
||||
size_t tagwidth, nvlist_t *nvl)
|
||||
{
|
||||
int i;
|
||||
nvpair_t *nvp = NULL;
|
||||
@ -5576,10 +5578,14 @@ print_holds(boolean_t scripted, size_t nwidth, size_t tagwidth, nvlist_t *nvl)
|
||||
size_t sepnum = scripted ? 1 : 2;
|
||||
|
||||
(void) nvpair_value_uint64(nvp2, &val);
|
||||
if (literal)
|
||||
snprintf(tsbuf, DATETIME_BUF_LEN, "%llu", val);
|
||||
else {
|
||||
time = (time_t)val;
|
||||
(void) localtime_r(&time, &t);
|
||||
(void) strftime(tsbuf, DATETIME_BUF_LEN,
|
||||
gettext(STRFTIME_FMT_STR), &t);
|
||||
}
|
||||
|
||||
(void) printf("%-*s%*c%-*s%*c%s\n", nwidth, zname,
|
||||
sepnum, sep, tagwidth, tagname, sepnum, sep, tsbuf);
|
||||
@ -5600,7 +5606,7 @@ holds_callback(zfs_handle_t *zhp, void *data)
|
||||
const char *zname = zfs_get_name(zhp);
|
||||
size_t znamelen = strnlen(zname, ZFS_MAXNAMELEN);
|
||||
|
||||
if (cbp->cb_recursive) {
|
||||
if (cbp->cb_recursive && cbp->cb_snapname != NULL) {
|
||||
const char *snapname;
|
||||
char *delim = strchr(zname, '@');
|
||||
if (delim == NULL)
|
||||
@ -5628,9 +5634,12 @@ holds_callback(zfs_handle_t *zhp, void *data)
|
||||
}
|
||||
|
||||
/*
|
||||
* zfs holds [-r] <snap> ...
|
||||
* zfs holds [-Hp] [-r | -d max] <dataset|snap> ...
|
||||
*
|
||||
* -r Recursively hold
|
||||
* -H Suppress header output
|
||||
* -p Output literal values
|
||||
* -r Recursively search for holds
|
||||
* -d max Limit depth of recursive search
|
||||
*/
|
||||
static int
|
||||
zfs_do_holds(int argc, char **argv)
|
||||
@ -5639,8 +5648,9 @@ zfs_do_holds(int argc, char **argv)
|
||||
int c;
|
||||
int i;
|
||||
boolean_t scripted = B_FALSE;
|
||||
boolean_t literal = B_FALSE;
|
||||
boolean_t recursive = B_FALSE;
|
||||
const char *opts = "rH";
|
||||
const char *opts = "d:rHp";
|
||||
nvlist_t *nvl;
|
||||
|
||||
int types = ZFS_TYPE_SNAPSHOT;
|
||||
@ -5653,12 +5663,19 @@ zfs_do_holds(int argc, char **argv)
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, opts)) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
limit = parse_depth(optarg, &flags);
|
||||
recursive = B_TRUE;
|
||||
break;
|
||||
case 'r':
|
||||
recursive = B_TRUE;
|
||||
break;
|
||||
case 'H':
|
||||
scripted = B_TRUE;
|
||||
break;
|
||||
case 'p':
|
||||
literal = B_TRUE;
|
||||
break;
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
@ -5684,18 +5701,14 @@ zfs_do_holds(int argc, char **argv)
|
||||
for (i = 0; i < argc; ++i) {
|
||||
char *snapshot = argv[i];
|
||||
const char *delim;
|
||||
const char *snapname;
|
||||
const char *snapname = NULL;
|
||||
|
||||
delim = strchr(snapshot, '@');
|
||||
if (delim == NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("'%s' is not a snapshot\n"), snapshot);
|
||||
++errors;
|
||||
continue;
|
||||
}
|
||||
if (delim != NULL) {
|
||||
snapname = delim + 1;
|
||||
if (recursive)
|
||||
snapshot[delim - snapshot] = '\0';
|
||||
}
|
||||
|
||||
cb.cb_recursive = recursive;
|
||||
cb.cb_snapname = snapname;
|
||||
@ -5713,7 +5726,8 @@ zfs_do_holds(int argc, char **argv)
|
||||
/*
|
||||
* 2. print holds data
|
||||
*/
|
||||
print_holds(scripted, cb.cb_max_namelen, cb.cb_max_taglen, nvl);
|
||||
print_holds(scripted, literal, cb.cb_max_namelen, cb.cb_max_taglen,
|
||||
nvl);
|
||||
|
||||
if (nvlist_empty(nvl))
|
||||
(void) printf(gettext("no datasets available\n"));
|
||||
|
@ -683,6 +683,10 @@ tdesc_array_create(dwarf_t *dw, Dwarf_Die dim, tdesc_t *arrtdp,
|
||||
ar->ad_nelems = uval + 1;
|
||||
else if (die_signed(dw, dim, DW_AT_upper_bound, &sval, 0))
|
||||
ar->ad_nelems = sval + 1;
|
||||
else if (die_unsigned(dw, dim, DW_AT_count, &uval, 0))
|
||||
ar->ad_nelems = uval;
|
||||
else if (die_signed(dw, dim, DW_AT_count, &sval, 0))
|
||||
ar->ad_nelems = sval;
|
||||
else
|
||||
ar->ad_nelems = 0;
|
||||
|
||||
|
@ -4,7 +4,6 @@ TESTGROUP= ${.CURDIR:H:T}/${.CURDIR:T}
|
||||
TESTSRC= ${.CURDIR:H:H:H:H:H}/contrib/opensolaris/cmd/dtrace/test/tst/${TESTGROUP}
|
||||
TESTSDIR= ${TESTSBASE}/cddl/usr.sbin/dtrace/${TESTGROUP}
|
||||
|
||||
.if !defined(_RECURSING_PROGS)
|
||||
FILESGROUPS+= FILES ${TESTGROUP} ${TESTGROUP}EXE
|
||||
|
||||
${TESTGROUP}= ${TESTFILES}
|
||||
@ -25,7 +24,6 @@ ${TESTWRAPPER}.sh: ${GENTEST} ${EXCLUDE} ${${TESTGROUP}}
|
||||
sh ${GENTEST} -e ${EXCLUDE} ${TESTGROUP} ${${TESTGROUP}:S/ */ /} > ${.TARGET}
|
||||
|
||||
CLEANFILES+= ${TESTWRAPPER}.sh
|
||||
.endif # !defined(_RECURSING_PROGS)
|
||||
|
||||
.PATH: ${TESTSRC}
|
||||
|
||||
|
@ -1,3 +1,40 @@
|
||||
2015-10-20 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* Makefile (MAKE_VERSION): 20151020
|
||||
Merge with NetBSD make, pick up
|
||||
o var.c: fix uninitialized var
|
||||
|
||||
2015-10-12 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* var.c: the conditional expressions used with ':?' can be
|
||||
expensive, if already discarding do not evaluate or expand
|
||||
anything.
|
||||
|
||||
2015-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* Makefile (MAKE_VERSION): 20151010
|
||||
Merge with NetBSD make, pick up
|
||||
o Add Boolean wantit flag to Var_Subst and Var_Parse
|
||||
when FALSE we know we are discarding the result and can
|
||||
skip operations like Cmd_Exec.
|
||||
|
||||
2015-10-09 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* Makefile (MAKE_VERSION): 20151009
|
||||
Merge with NetBSD make, pick up
|
||||
o var.c: don't check for NULL before free()
|
||||
o meta.c: meta_oodate, do not hard code ignore of makeDependfile
|
||||
|
||||
2015-09-10 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* Makefile (MAKE_VERSION): 20150910
|
||||
Merge with NetBSD make, pick up
|
||||
o main.c: with -w print Enter/Leaving messages for objdir too
|
||||
if necessary.
|
||||
o centralize shell metachar handling
|
||||
|
||||
* FILES: add metachar.[ch]
|
||||
|
||||
2015-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* Makefile (MAKE_VERSION): 20150606
|
||||
|
@ -71,6 +71,8 @@ make_malloc.h
|
||||
makefile.in
|
||||
meta.c
|
||||
meta.h
|
||||
metachar.c
|
||||
metachar.h
|
||||
missing/sys/cdefs.h
|
||||
mkdeps.sh
|
||||
nonints.h
|
||||
|
@ -1,7 +1,7 @@
|
||||
# $Id: Makefile,v 1.39 2015/06/07 15:54:37 sjg Exp $
|
||||
# $Id: Makefile,v 1.44 2015/10/20 21:41:40 sjg Exp $
|
||||
|
||||
# Base version on src date
|
||||
MAKE_VERSION= 20150606
|
||||
MAKE_VERSION= 20151020
|
||||
|
||||
PROG= bmake
|
||||
|
||||
@ -18,6 +18,7 @@ SRCS= \
|
||||
make.c \
|
||||
make_malloc.c \
|
||||
meta.c \
|
||||
metachar.c \
|
||||
parse.c \
|
||||
str.c \
|
||||
strlist.c \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $ */
|
||||
/* $NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -69,14 +69,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $";
|
||||
static char rcsid[] = "$NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $");
|
||||
__RCSID("$NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -310,7 +310,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
|
||||
void *freeIt;
|
||||
char *result;
|
||||
|
||||
result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
|
||||
result = Var_Parse(cp, ctxt, TRUE, TRUE, &length, &freeIt);
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
if (result == var_Error) {
|
||||
@ -325,7 +325,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
|
||||
|
||||
*cp++ = '\0';
|
||||
if (subLibName) {
|
||||
libName = Var_Subst(NULL, libName, ctxt, TRUE);
|
||||
libName = Var_Subst(NULL, libName, ctxt, TRUE, TRUE);
|
||||
}
|
||||
|
||||
|
||||
@ -351,7 +351,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
|
||||
void *freeIt;
|
||||
char *result;
|
||||
|
||||
result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
|
||||
result = Var_Parse(cp, ctxt, TRUE, TRUE, &length, &freeIt);
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
if (result == var_Error) {
|
||||
@ -404,7 +404,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
|
||||
char *oldMemName = memName;
|
||||
size_t sz;
|
||||
|
||||
memName = Var_Subst(NULL, memName, ctxt, TRUE);
|
||||
memName = Var_Subst(NULL, memName, ctxt, TRUE, TRUE);
|
||||
|
||||
/*
|
||||
* Now form an archive spec and recurse to deal with nested
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $ */
|
||||
/* $NetBSD: compat.c,v 1.101 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -70,14 +70,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $";
|
||||
static char rcsid[] = "$NetBSD: compat.c,v 1.101 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $");
|
||||
__RCSID("$NetBSD: compat.c,v 1.101 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -111,37 +111,14 @@ __RCSID("$NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $");
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
#include "job.h"
|
||||
#include "metachar.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* The following array is used to make a fast determination of which
|
||||
* characters are interpreted specially by the shell. If a command
|
||||
* contains any of these characters, it is executed by the shell, not
|
||||
* directly by us.
|
||||
*/
|
||||
|
||||
static char meta[256];
|
||||
|
||||
static GNode *curTarg = NULL;
|
||||
static GNode *ENDNode;
|
||||
static void CompatInterrupt(int);
|
||||
|
||||
static void
|
||||
Compat_Init(void)
|
||||
{
|
||||
const char *cp;
|
||||
|
||||
Shell_Init(); /* setup default shell */
|
||||
|
||||
for (cp = "~#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) {
|
||||
meta[(unsigned char) *cp] = 1;
|
||||
}
|
||||
/*
|
||||
* The null character serves as a sentinel in the string.
|
||||
*/
|
||||
meta[0] = 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* CompatInterrupt --
|
||||
@ -236,7 +213,7 @@ CompatRunCommand(void *cmdp, void *gnp)
|
||||
doIt = FALSE;
|
||||
|
||||
cmdNode = Lst_Member(gn->commands, cmd);
|
||||
cmdStart = Var_Subst(NULL, cmd, gn, FALSE);
|
||||
cmdStart = Var_Subst(NULL, cmd, gn, FALSE, TRUE);
|
||||
|
||||
/*
|
||||
* brk_string will return an argv with a NULL in av[0], thus causing
|
||||
@ -271,8 +248,8 @@ CompatRunCommand(void *cmdp, void *gnp)
|
||||
break;
|
||||
case '+':
|
||||
doIt = TRUE;
|
||||
if (!meta[0]) /* we came here from jobs */
|
||||
Compat_Init();
|
||||
if (!shellName) /* we came here from jobs */
|
||||
Shell_Init();
|
||||
break;
|
||||
}
|
||||
cmd++;
|
||||
@ -300,11 +277,13 @@ CompatRunCommand(void *cmdp, void *gnp)
|
||||
* Search for meta characters in the command. If there are no meta
|
||||
* characters, there's no need to execute a shell to execute the
|
||||
* command.
|
||||
*
|
||||
* Additionally variable assignments and empty commands
|
||||
* go to the shell. Therefore treat '=' and ':' like shell
|
||||
* meta characters as documented in make(1).
|
||||
*/
|
||||
for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
|
||||
continue;
|
||||
}
|
||||
useShell = (*cp != '\0');
|
||||
|
||||
useShell = needshell(cmd, FALSE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -512,8 +491,8 @@ Compat_Make(void *gnp, void *pgnp)
|
||||
GNode *gn = (GNode *)gnp;
|
||||
GNode *pgn = (GNode *)pgnp;
|
||||
|
||||
if (!meta[0]) /* we came here from jobs */
|
||||
Compat_Init();
|
||||
if (!shellName) /* we came here from jobs */
|
||||
Shell_Init();
|
||||
if (gn->made == UNMADE && (gn == pgn || (pgn->type & OP_MADE) == 0)) {
|
||||
/*
|
||||
* First mark ourselves to be made, then apply whatever transformations
|
||||
@ -693,7 +672,8 @@ Compat_Run(Lst targs)
|
||||
GNode *gn = NULL;/* Current root target */
|
||||
int errors; /* Number of targets not remade due to errors */
|
||||
|
||||
Compat_Init();
|
||||
if (!shellName)
|
||||
Shell_Init();
|
||||
|
||||
if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
||||
bmake_signal(SIGINT, CompatInterrupt);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cond.c,v 1.68 2015/05/05 21:51:09 sjg Exp $ */
|
||||
/* $NetBSD: cond.c,v 1.69 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -70,14 +70,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: cond.c,v 1.68 2015/05/05 21:51:09 sjg Exp $";
|
||||
static char rcsid[] = "$NetBSD: cond.c,v 1.69 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: cond.c,v 1.68 2015/05/05 21:51:09 sjg Exp $");
|
||||
__RCSID("$NetBSD: cond.c,v 1.69 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -289,7 +289,7 @@ CondGetArg(char **linePtr, char **argPtr, const char *func)
|
||||
int len;
|
||||
void *freeIt;
|
||||
|
||||
cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &freeIt);
|
||||
cp2 = Var_Parse(cp, VAR_CMD, TRUE, TRUE, &len, &freeIt);
|
||||
Buf_AddBytes(&buf, strlen(cp2), cp2);
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
@ -571,7 +571,7 @@ CondGetString(Boolean doEval, Boolean *quoted, void **freeIt, Boolean strictLHS)
|
||||
case '$':
|
||||
/* if we are in quotes, then an undefined variable is ok */
|
||||
str = Var_Parse(condExpr, VAR_CMD, (qt ? 0 : doEval),
|
||||
&len, freeIt);
|
||||
TRUE, &len, freeIt);
|
||||
if (str == var_Error) {
|
||||
if (*freeIt) {
|
||||
free(*freeIt);
|
||||
@ -823,7 +823,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
|
||||
/* We do all the work here and return the result as the length */
|
||||
*argPtr = NULL;
|
||||
|
||||
val = Var_Parse(cp - 1, VAR_CMD, FALSE, &length, &freeIt);
|
||||
val = Var_Parse(cp - 1, VAR_CMD, FALSE, TRUE, &length, &freeIt);
|
||||
/*
|
||||
* Advance *linePtr to beyond the closing ). Note that
|
||||
* we subtract one because 'length' is calculated from 'cp - 1'.
|
||||
|
@ -1,11 +1,11 @@
|
||||
dnl
|
||||
dnl RCSid:
|
||||
dnl $Id: configure.in,v 1.53 2014/11/06 01:49:40 sjg Exp $
|
||||
dnl $Id: configure.in,v 1.54 2015/10/10 04:17:10 sjg Exp $
|
||||
dnl
|
||||
dnl Process this file with autoconf to produce a configure script
|
||||
dnl
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT([bmake], [20140214], [sjg@NetBSD.org])
|
||||
AC_INIT([bmake], [20151009], [sjg@NetBSD.org])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
dnl make srcdir absolute
|
||||
@ -105,6 +105,7 @@ AC_CHECK_HEADERS( \
|
||||
ar.h \
|
||||
err.h \
|
||||
fcntl.h \
|
||||
limits.h \
|
||||
paths.h \
|
||||
poll.h \
|
||||
ranlib.h \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: for.c,v 1.49 2012/06/03 04:29:40 sjg Exp $ */
|
||||
/* $NetBSD: for.c,v 1.50 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, The Regents of the University of California.
|
||||
@ -30,14 +30,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: for.c,v 1.49 2012/06/03 04:29:40 sjg Exp $";
|
||||
static char rcsid[] = "$NetBSD: for.c,v 1.50 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: for.c,v 1.49 2012/06/03 04:29:40 sjg Exp $");
|
||||
__RCSID("$NetBSD: for.c,v 1.50 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -216,7 +216,7 @@ For_Eval(char *line)
|
||||
* We can't do the escapes here - because we don't know whether
|
||||
* we are substuting into ${...} or $(...).
|
||||
*/
|
||||
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
|
||||
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE, TRUE);
|
||||
|
||||
/*
|
||||
* Split into words allowing for quoted strings.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: job.c,v 1.180 2015/04/16 13:31:03 joerg Exp $ */
|
||||
/* $NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -70,14 +70,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: job.c,v 1.180 2015/04/16 13:31:03 joerg Exp $";
|
||||
static char rcsid[] = "$NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: job.c,v 1.180 2015/04/16 13:31:03 joerg Exp $");
|
||||
__RCSID("$NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -731,7 +731,7 @@ JobPrintCommand(void *cmdp, void *jobp)
|
||||
|
||||
numCommands += 1;
|
||||
|
||||
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE);
|
||||
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE, TRUE);
|
||||
|
||||
cmdTemplate = "%s\n";
|
||||
|
||||
@ -919,7 +919,7 @@ JobPrintCommand(void *cmdp, void *jobp)
|
||||
static int
|
||||
JobSaveCommand(void *cmd, void *gn)
|
||||
{
|
||||
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, FALSE);
|
||||
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, FALSE, TRUE);
|
||||
(void)Lst_AtEnd(postCommands->commands, cmd);
|
||||
return(0);
|
||||
}
|
||||
@ -2211,7 +2211,8 @@ Job_SetPrefix(void)
|
||||
Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL, 0);
|
||||
}
|
||||
|
||||
targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}", VAR_GLOBAL, 0);
|
||||
targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}",
|
||||
VAR_GLOBAL, FALSE, TRUE);
|
||||
}
|
||||
|
||||
/*-
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: main.c,v 1.232 2015/03/26 22:20:42 sjg Exp $ */
|
||||
/* $NetBSD: main.c,v 1.234 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -69,7 +69,7 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: main.c,v 1.232 2015/03/26 22:20:42 sjg Exp $";
|
||||
static char rcsid[] = "$NetBSD: main.c,v 1.234 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.232 2015/03/26 22:20:42 sjg Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.234 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -172,6 +172,7 @@ Boolean keepgoing; /* -k flag */
|
||||
Boolean queryFlag; /* -q flag */
|
||||
Boolean touchFlag; /* -t flag */
|
||||
Boolean enterFlag; /* -w flag */
|
||||
Boolean enterFlagObj; /* -w and objdir != srcdir */
|
||||
Boolean ignoreErrors; /* -i flag */
|
||||
Boolean beSilent; /* -s flag */
|
||||
Boolean oldVars; /* variable substitution style */
|
||||
@ -722,7 +723,7 @@ Main_SetObjdir(const char *path)
|
||||
/* expand variable substitutions */
|
||||
if (strchr(path, '$') != 0) {
|
||||
snprintf(buf, MAXPATHLEN, "%s", path);
|
||||
path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
|
||||
path = p = Var_Subst(NULL, buf, VAR_GLOBAL, FALSE, TRUE);
|
||||
}
|
||||
|
||||
if (path[0] != '/') {
|
||||
@ -741,6 +742,8 @@ Main_SetObjdir(const char *path)
|
||||
setenv("PWD", objdir, 1);
|
||||
Dir_InitDot();
|
||||
rc = TRUE;
|
||||
if (enterFlag && strcmp(objdir, curdir) != 0)
|
||||
enterFlagObj = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -803,7 +806,8 @@ MakeMode(const char *mode)
|
||||
char *mp = NULL;
|
||||
|
||||
if (!mode)
|
||||
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
|
||||
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}",
|
||||
VAR_GLOBAL, FALSE, TRUE);
|
||||
|
||||
if (mode && *mode) {
|
||||
if (strstr(mode, "compat")) {
|
||||
@ -1249,7 +1253,7 @@ main(int argc, char **argv)
|
||||
(char *)Lst_Datum(ln));
|
||||
} else {
|
||||
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
|
||||
VAR_CMD, 0);
|
||||
VAR_CMD, FALSE, TRUE);
|
||||
if (p1) {
|
||||
(void)str2Lst_Append(makefiles, p1, NULL);
|
||||
(void)Lst_Find(makefiles, NULL, ReadMakefile);
|
||||
@ -1260,12 +1264,15 @@ main(int argc, char **argv)
|
||||
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
|
||||
if (!noBuiltins || !printVars) {
|
||||
makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
|
||||
VAR_CMD, 0);
|
||||
VAR_CMD, FALSE, TRUE);
|
||||
doing_depend = TRUE;
|
||||
(void)ReadMakefile(makeDependfile, NULL);
|
||||
doing_depend = FALSE;
|
||||
}
|
||||
|
||||
if (enterFlagObj)
|
||||
printf("%s: Entering directory `%s'\n", progname, objdir);
|
||||
|
||||
MakeMode(NULL);
|
||||
|
||||
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
|
||||
@ -1295,7 +1302,7 @@ main(int argc, char **argv)
|
||||
*/
|
||||
static char VPATH[] = "${VPATH}";
|
||||
|
||||
vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
|
||||
vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE, TRUE);
|
||||
path = vpath;
|
||||
do {
|
||||
/* skip to end of directory */
|
||||
@ -1342,14 +1349,16 @@ main(int argc, char **argv)
|
||||
char *value;
|
||||
|
||||
if (strchr(var, '$')) {
|
||||
value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
|
||||
value = p1 = Var_Subst(NULL, var, VAR_GLOBAL,
|
||||
FALSE, TRUE);
|
||||
} else if (expandVars) {
|
||||
char tmp[128];
|
||||
|
||||
if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp)))
|
||||
Fatal("%s: variable name too big: %s",
|
||||
progname, var);
|
||||
value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL,
|
||||
FALSE, TRUE);
|
||||
} else {
|
||||
value = Var_Value(var, VAR_GLOBAL, &p1);
|
||||
}
|
||||
@ -1406,6 +1415,8 @@ main(int argc, char **argv)
|
||||
|
||||
Trace_Log(MAKEEND, 0);
|
||||
|
||||
if (enterFlagObj)
|
||||
printf("%s: Leaving directory `%s'\n", progname, objdir);
|
||||
if (enterFlag)
|
||||
printf("%s: Leaving directory `%s'\n", progname, curdir);
|
||||
|
||||
@ -1885,7 +1896,7 @@ PrintOnError(GNode *gn, const char *s)
|
||||
}
|
||||
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
|
||||
sizeof(tmp) - 1);
|
||||
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
|
||||
if (cp) {
|
||||
if (*cp)
|
||||
printf("%s", cp);
|
||||
@ -1914,7 +1925,7 @@ Main_ExportMAKEFLAGS(Boolean first)
|
||||
|
||||
strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
|
||||
sizeof(tmp));
|
||||
s = Var_Subst(NULL, tmp, VAR_CMD, 0);
|
||||
s = Var_Subst(NULL, tmp, VAR_CMD, FALSE, TRUE);
|
||||
if (s && *s) {
|
||||
#ifdef POSIX
|
||||
setenv("MAKEFLAGS", s, 1);
|
||||
@ -1936,7 +1947,8 @@ getTmpdir(void)
|
||||
* Honor $TMPDIR but only if it is valid.
|
||||
* Ensure it ends with /.
|
||||
*/
|
||||
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
|
||||
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
|
||||
FALSE, TRUE);
|
||||
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
|
||||
free(tmpdir);
|
||||
tmpdir = bmake_strdup(_PATH_TMP);
|
||||
@ -1991,7 +2003,7 @@ getBoolean(const char *name, Boolean bf)
|
||||
char *cp;
|
||||
|
||||
if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) {
|
||||
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
|
||||
|
||||
if (cp) {
|
||||
switch(*cp) {
|
||||
|
@ -52,7 +52,7 @@ do_link() {
|
||||
}
|
||||
|
||||
BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o for.o getopt hash.o \
|
||||
job.o make.o make_malloc.o parse.o sigcompat.o str.o strlist.o \
|
||||
job.o make.o make_malloc.o metachar.o parse.o sigcompat.o str.o strlist.o \
|
||||
suff.o targ.o trace.o var.o util.o"
|
||||
|
||||
LST_OBJECTS="lstAppend.o lstDupl.o lstInit.o lstOpen.o \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: make.c,v 1.91 2014/10/18 08:33:30 snj Exp $ */
|
||||
/* $NetBSD: make.c,v 1.92 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -69,14 +69,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: make.c,v 1.91 2014/10/18 08:33:30 snj Exp $";
|
||||
static char rcsid[] = "$NetBSD: make.c,v 1.92 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: make.c,v 1.91 2014/10/18 08:33:30 snj Exp $");
|
||||
__RCSID("$NetBSD: make.c,v 1.92 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -485,7 +485,7 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
|
||||
if (gn->name)
|
||||
free(gn->name);
|
||||
}
|
||||
gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE);
|
||||
gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE, TRUE);
|
||||
if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) {
|
||||
/* See if we have a target for this node. */
|
||||
tgn = Targ_FindNode(gn->name, TARG_NOCREATE);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: make.h,v 1.95 2014/09/07 20:55:34 joerg Exp $ */
|
||||
/* $NetBSD: make.h,v 1.96 2015/09/21 21:50:16 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -519,8 +519,15 @@ int str2Lst_Append(Lst, char *, const char *);
|
||||
#define MAX(a, b) ((a > b) ? a : b)
|
||||
#endif
|
||||
|
||||
/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN BMAKE_PATH_MAX
|
||||
#endif
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAXPATHLEN
|
||||
#endif
|
||||
|
||||
#endif /* _MAKE_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: meta.c,v 1.38 2015/04/11 05:24:30 sjg Exp $ */
|
||||
/* $NetBSD: meta.c,v 1.40 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Implement 'meta' mode.
|
||||
@ -324,7 +324,7 @@ is_submake(void *cmdp, void *gnp)
|
||||
}
|
||||
cp = strchr(cmd, '$');
|
||||
if ((cp)) {
|
||||
mp = Var_Subst(NULL, cmd, gn, FALSE);
|
||||
mp = Var_Subst(NULL, cmd, gn, FALSE, TRUE);
|
||||
cmd = mp;
|
||||
}
|
||||
cp2 = strstr(cmd, p_make);
|
||||
@ -367,7 +367,7 @@ printCMD(void *cmdp, void *mfpp)
|
||||
char *cp = NULL;
|
||||
|
||||
if (strchr(cmd, '$')) {
|
||||
cmd = cp = Var_Subst(NULL, cmd, mfp->gn, FALSE);
|
||||
cmd = cp = Var_Subst(NULL, cmd, mfp->gn, FALSE, TRUE);
|
||||
}
|
||||
fprintf(mfp->fp, "CMD %s\n", cmd);
|
||||
if (cp)
|
||||
@ -462,7 +462,7 @@ meta_create(BuildMon *pbm, GNode *gn)
|
||||
char *mp;
|
||||
|
||||
/* Describe the target we are building */
|
||||
mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, 0);
|
||||
mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, FALSE, TRUE);
|
||||
if (*mp)
|
||||
fprintf(stdout, "%s\n", mp);
|
||||
free(mp);
|
||||
@ -605,7 +605,8 @@ meta_mode_init(const char *make_mode)
|
||||
* We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
|
||||
*/
|
||||
metaBailiwick = Lst_Init(FALSE);
|
||||
cp = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}", VAR_GLOBAL, 0);
|
||||
cp = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}", VAR_GLOBAL,
|
||||
FALSE, TRUE);
|
||||
if (cp) {
|
||||
str2Lst_Append(metaBailiwick, cp, NULL);
|
||||
}
|
||||
@ -616,7 +617,8 @@ meta_mode_init(const char *make_mode)
|
||||
Var_Append(MAKE_META_IGNORE_PATHS,
|
||||
"/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL);
|
||||
cp = Var_Subst(NULL,
|
||||
"${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL, 0);
|
||||
"${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL,
|
||||
FALSE, TRUE);
|
||||
if (cp) {
|
||||
str2Lst_Append(metaIgnorePaths, cp, NULL);
|
||||
}
|
||||
@ -727,7 +729,8 @@ meta_job_output(Job *job, char *cp, const char *nl)
|
||||
if (!meta_prefix) {
|
||||
char *cp2;
|
||||
|
||||
meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", VAR_GLOBAL, 0);
|
||||
meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}",
|
||||
VAR_GLOBAL, FALSE, TRUE);
|
||||
if ((cp2 = strchr(meta_prefix, '$')))
|
||||
meta_prefix_len = cp2 - meta_prefix;
|
||||
else
|
||||
@ -1209,16 +1212,6 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cp = strrchr(p, '/'))) {
|
||||
cp++;
|
||||
/*
|
||||
* We don't normally expect to see this,
|
||||
* but we do expect it to change.
|
||||
*/
|
||||
if (strcmp(cp, makeDependfile) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rest of the record is the file name.
|
||||
* Check if it's not an absolute path.
|
||||
@ -1322,7 +1315,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
if (DEBUG(META))
|
||||
fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno);
|
||||
}
|
||||
cmd = Var_Subst(NULL, cmd, gn, TRUE);
|
||||
cmd = Var_Subst(NULL, cmd, gn, TRUE, TRUE);
|
||||
|
||||
if ((cp = strchr(cmd, '\n'))) {
|
||||
int n;
|
||||
|
88
contrib/bmake/metachar.c
Normal file
88
contrib/bmake/metachar.c
Normal file
@ -0,0 +1,88 @@
|
||||
/* $NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#if defined(MAKE_NATIVE) || defined(HAVE_NBTOOL_CONFIG_H)
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
|
||||
#if defined(__RCSID) && !defined(lint)
|
||||
__RCSID("$NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $");
|
||||
#endif
|
||||
|
||||
#include "metachar.h"
|
||||
/*
|
||||
* The following array is used to make a fast determination of which
|
||||
* characters are interpreted specially by the shell. If a command
|
||||
* contains any of these characters, it is executed by the shell, not
|
||||
* directly by us.
|
||||
*
|
||||
* perhaps move it to ctype?
|
||||
*/
|
||||
|
||||
unsigned char _metachar[128] = {
|
||||
// nul soh stx etx eot enq ack bel
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
// bs ht nl vt np cr so si
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
// dle dc1 dc2 dc3 dc4 nak syn etb
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// can em sub esc fs gs rs us
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// sp ! " # $ % & '
|
||||
0, 1, 1, 1, 1, 0, 1, 1,
|
||||
// ( ) * + , - . /
|
||||
1, 1, 1, 0, 0, 0, 0, 0,
|
||||
// 0 1 2 3 4 5 6 7
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 8 9 : ; < = > ?
|
||||
0, 0, 0, 1, 1, 0, 1, 1,
|
||||
// @ A B C D E F G
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// H I J K L M N O
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// P Q R S T U V W
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// X Y Z [ \ ] ^ _
|
||||
0, 0, 0, 1, 1, 1, 1, 0,
|
||||
// ` a b c d e f g
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
// h i j k l m n o
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// p q r s t u v w
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// x y z { | } ~ del
|
||||
0, 0, 0, 1, 1, 1, 1, 0,
|
||||
};
|
||||
|
@ -1,8 +1,11 @@
|
||||
/* $NetBSD: s3c24x0var.h,v 1.1 2003/07/31 19:49:44 bsh Exp $ */
|
||||
/* $NetBSD: metachar.h,v 1.4 2015/06/21 20:26:02 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 Genetec corporation. All rights reserved.
|
||||
* Written by Hiroyuki Bessho for Genetec corporation.
|
||||
* Copyright (c) 2015 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -12,14 +15,11 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of Genetec corporation may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
@ -27,25 +27,35 @@
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#ifndef _METACHAR_H
|
||||
#define _METACHAR_H
|
||||
|
||||
#ifndef _ARM_S3C24X0VAR_H_
|
||||
#define _ARM_S3C24X0VAR_H_
|
||||
#include <ctype.h>
|
||||
|
||||
#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
|
||||
extern unsigned char _metachar[];
|
||||
|
||||
struct s3c24x0_softc {
|
||||
struct s3c2xx0_softc sc_sx;
|
||||
#define ismeta(c) _metachar[(c) & 0x7f]
|
||||
|
||||
bus_space_handle_t sc_timer_ioh; /* Timer control registers */
|
||||
};
|
||||
static inline int
|
||||
hasmeta(const char *cmd)
|
||||
{
|
||||
while (!ismeta(*cmd))
|
||||
cmd++;
|
||||
|
||||
void s3c24x0_clock_freq(struct s3c2xx0_softc *);
|
||||
void s3c2410_clock_freq2(vm_offset_t, int *, int *, int *);
|
||||
void s3c2440_clock_freq2(vm_offset_t, int *, int *, int *);
|
||||
return *cmd != '\0';
|
||||
}
|
||||
|
||||
void s3c24x0_sleep(int);
|
||||
static inline int
|
||||
needshell(const char *cmd, int white)
|
||||
{
|
||||
while (!ismeta(*cmd) && *cmd != ':' && *cmd != '=') {
|
||||
if (white && isspace((unsigned char)*cmd))
|
||||
break;
|
||||
cmd++;
|
||||
}
|
||||
|
||||
#endif /* _ARM_S3C24X0VAR_H_ */
|
||||
return *cmd != '\0';
|
||||
}
|
||||
|
||||
#endif /* _METACHAR_H */
|
@ -1,3 +1,48 @@
|
||||
2015-10-20 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20151020
|
||||
|
||||
* dirdeps.mk: Add logic for
|
||||
make -f dirdeps.mk some/dir.${TARGET_SPEC}
|
||||
|
||||
2015-10-14 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20151010
|
||||
|
||||
2015-10-02 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* meta.stage.mk: use staging: ${STAGE_TARGETS:...
|
||||
to have stage_lins run last in non-jobs mode.
|
||||
Use .ORDER only for jobs mode.
|
||||
|
||||
2015-09-02 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* rst2htm.mk: allow for per target flags etc.
|
||||
|
||||
2015-09-01 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20150901
|
||||
|
||||
* doc.mk: create dir if needed use DOC_INSTALL_OWN
|
||||
|
||||
2015-06-15 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20150615
|
||||
|
||||
* auto.obj.mk: allow use of MAKEOBJDIRPREFIX too.
|
||||
Follow make's normal precedence rules.
|
||||
|
||||
* gendirdeps.mk: allow customization of the header.
|
||||
eg. for FreeBSD:
|
||||
GENDIRDEPS_HEADER= echo '\# ${FreeBSD:L:@v@$$$v$$ @:M*F*}';
|
||||
|
||||
* meta.autodep.mk: ignore dirdeps.cache*
|
||||
|
||||
* meta.stage.mk: when bootstrapping options it can be handy to
|
||||
throw warnings rather than errors for staging conflicts.
|
||||
|
||||
* meta.sys.mk: include local.meta.sys.mk for customization
|
||||
|
||||
2015-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20150606
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: auto.obj.mk,v 1.10 2015/04/16 16:59:00 sjg Exp $
|
||||
# $Id: auto.obj.mk,v 1.11 2015/06/16 06:28:21 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2004, Simon J. Gerraty
|
||||
#
|
||||
@ -40,7 +40,10 @@ MKOBJDIRS= auto
|
||||
.if !defined(NOOBJ) && !defined(NO_OBJ) && ${MKOBJDIRS:Uno} == auto
|
||||
# Use __objdir here so it is easier to tweak without impacting
|
||||
# the logic.
|
||||
__objdir?= ${MAKEOBJDIR}
|
||||
.if !empty(MAKEOBJDIRPREFIX) && exists(${MAKEOBJDIRPREFIX})
|
||||
__objdir?= ${MAKEOBJDIRPREFIX}${.CURDIR}
|
||||
.endif
|
||||
__objdir?= ${MAKEOBJDIR:Uobj}
|
||||
__objdir:= ${__objdir:tA}
|
||||
.if ${.OBJDIR} != ${__objdir}
|
||||
# We need to chdir, make the directory if needed
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: dirdeps.mk,v 1.54 2015/06/08 20:55:11 sjg Exp $
|
||||
# $Id: dirdeps.mk,v 1.55 2015/10/20 22:04:53 sjg Exp $
|
||||
|
||||
# Copyright (c) 2010-2013, Juniper Networks, Inc.
|
||||
# All rights reserved.
|
||||
@ -242,6 +242,21 @@ DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
|
||||
DEP_MACHINE := ${_DEP_TARGET_SPEC}
|
||||
.endif
|
||||
|
||||
.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != ""
|
||||
# This little trick let's us do
|
||||
#
|
||||
# mk -f dirdeps.mk some/dir.${TARGET_SPEC}
|
||||
#
|
||||
all:
|
||||
${.TARGETS:Nall}: all
|
||||
DIRDEPS := ${.TARGETS:M*/*}
|
||||
# so that -DNO_DIRDEPS works
|
||||
DEP_RELDIR := ${DIRDEPS:R:[1]}
|
||||
# disable DIRDEPS_CACHE as it does not like this trick
|
||||
MK_DIRDEPS_CACHE = no
|
||||
.endif
|
||||
|
||||
|
||||
# pickup customizations
|
||||
# as below you can use !target(_DIRDEP_USE) to protect things
|
||||
# which should only be done once.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: doc.mk,v 1.4 2012/11/11 22:37:02 sjg Exp $
|
||||
# $Id: doc.mk,v 1.5 2015/09/08 06:15:31 sjg Exp $
|
||||
|
||||
.if !target(__${.PARSEFILE}__)
|
||||
__${.PARSEFILE}__:
|
||||
@ -47,17 +47,19 @@ install:
|
||||
.else
|
||||
FILES?= ${SRCS}
|
||||
install:
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
|
||||
Makefile ${FILES} ${EXTRA} ${DESTDIR}${BINDIR}/${DIR}
|
||||
test -d ${DESTDIR}${DOCDIR}/${DIR} || \
|
||||
${INSTALL} -d ${DOC_INSTALL_OWN} -m ${DIRMODE} ${DESTDIR}${DOCDIR}/${DIR}
|
||||
${INSTALL} ${COPY} ${DOC_INSTALL_OWN} -m ${DOCMODE} \
|
||||
Makefile ${FILES} ${EXTRA} ${DESTDIR}${DOCDIR}/${DIR}
|
||||
.endif
|
||||
|
||||
spell: ${SRCS}
|
||||
spell ${SRCS} | sort | comm -23 - spell.ok > paper.spell
|
||||
|
||||
BINDIR?= /usr/share/doc
|
||||
BINGRP?= bin
|
||||
BINOWN?= bin
|
||||
BINMODE?= 444
|
||||
|
||||
.include <own.mk>
|
||||
|
||||
.if !empty(DOCOWN)
|
||||
DOC_INSTALL_OWN?= -o ${DOCOWN} -g ${DOGGRP}
|
||||
.endif
|
||||
|
||||
.endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: gendirdeps.mk,v 1.27 2015/06/08 20:55:11 sjg Exp $
|
||||
# $Id: gendirdeps.mk,v 1.29 2015/10/03 05:00:46 sjg Exp $
|
||||
|
||||
# Copyright (c) 2010-2013, Juniper Networks, Inc.
|
||||
# All rights reserved.
|
||||
@ -157,7 +157,7 @@ M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX}
|
||||
.endif
|
||||
|
||||
# we are only interested in the dirs
|
||||
# sepecifically those we read something from.
|
||||
# specifically those we read something from.
|
||||
# we canonicalize them to keep things simple
|
||||
# if we are using a split-fs sandbox, it gets a little messier.
|
||||
_objtop := ${_OBJTOP:tA}
|
||||
@ -310,7 +310,7 @@ CAT_DEPEND ?= .depend
|
||||
# The sed command at the end of the stream, allows for the filters
|
||||
# to output _{VAR} tokens which we will turn into proper ${VAR} references.
|
||||
${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
|
||||
@(echo '# Autogenerated - do NOT edit!'; echo; \
|
||||
@(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
|
||||
echo 'DIRDEPS = \'; \
|
||||
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
|
||||
${_include_src_dirdeps} \
|
||||
@ -330,7 +330,7 @@ DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
|
||||
all: ${_DEPENDFILE}
|
||||
|
||||
${_DEPENDFILE}: ${MAKEFILE} ${_this}
|
||||
@(echo '# Autogenerated - do NOT edit!'; echo; \
|
||||
@(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
|
||||
echo 'DIRDEPS = \'; \
|
||||
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
|
||||
echo '.include <dirdeps.mk>'; \
|
||||
|
@ -1,5 +1,5 @@
|
||||
# RCSid:
|
||||
# $Id: host-target.mk,v 1.7 2014/05/16 17:54:52 sjg Exp $
|
||||
# $Id: host-target.mk,v 1.9 2015/09/10 18:42:57 sjg Exp $
|
||||
|
||||
# Host platform information; may be overridden
|
||||
.if !defined(_HOST_OSNAME)
|
||||
@ -10,16 +10,25 @@ _HOST_OSNAME != uname -s
|
||||
_HOST_OSREL != uname -r
|
||||
.export _HOST_OSREL
|
||||
.endif
|
||||
.if !defined(_HOST_MACHINE)
|
||||
_HOST_MACHINE != uname -m
|
||||
.export _HOST_MACHINE
|
||||
.endif
|
||||
.if !defined(_HOST_ARCH)
|
||||
# for NetBSD prefer $MACHINE (amd64 rather than x86_64)
|
||||
.if ${_HOST_OSNAME:NNetBSD} == ""
|
||||
_HOST_ARCH := ${_HOST_MACHINE}
|
||||
.else
|
||||
_HOST_ARCH != uname -p 2> /dev/null || uname -m
|
||||
# uname -p may produce garbage on linux
|
||||
.if ${_HOST_ARCH:[\#]} > 1
|
||||
_HOST_ARCH != uname -m
|
||||
_HOST_ARCH := ${_HOST_MACHINE}
|
||||
.endif
|
||||
.endif
|
||||
.export _HOST_ARCH
|
||||
.endif
|
||||
.if !defined(HOST_MACHINE)
|
||||
HOST_MACHINE != uname -m
|
||||
HOST_MACHINE := ${_HOST_MACHINE}
|
||||
.export HOST_MACHINE
|
||||
.endif
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
||||
# Simon J. Gerraty <sjg@crufty.net>
|
||||
|
||||
# RCSid:
|
||||
# $Id: install-mk,v 1.112 2015/06/08 20:55:11 sjg Exp $
|
||||
# $Id: install-mk,v 1.115 2015/10/20 22:04:53 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 1994 Simon J. Gerraty
|
||||
#
|
||||
@ -70,7 +70,7 @@
|
||||
# sjg@crufty.net
|
||||
#
|
||||
|
||||
MK_VERSION=20150606
|
||||
MK_VERSION=20151020
|
||||
OWNER=
|
||||
GROUP=
|
||||
MODE=444
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: meta.autodep.mk,v 1.36 2014/08/02 23:10:29 sjg Exp $
|
||||
# $Id: meta.autodep.mk,v 1.37 2015/06/16 06:29:17 sjg Exp $
|
||||
|
||||
#
|
||||
# @(#) Copyright (c) 2010, Simon J. Gerraty
|
||||
@ -97,6 +97,8 @@ UPDATE_DEPENDFILE = no
|
||||
# for example the result of running configure
|
||||
# just make sure this is not empty
|
||||
META_FILE_FILTER ?= N.meta
|
||||
# never consider these
|
||||
META_FILE_FILTER += Ndirdeps.cache*
|
||||
|
||||
.if !empty(DPADD)
|
||||
# if we have any non-libs in DPADD,
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: meta.stage.mk,v 1.35 2015/05/20 06:40:33 sjg Exp $
|
||||
# $Id: meta.stage.mk,v 1.40 2015/10/04 17:36:54 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2011, Simon J. Gerraty
|
||||
#
|
||||
@ -23,6 +23,8 @@ _dirdep = ${RELDIR}.${MACHINE}
|
||||
_dirdep = ${RELDIR}
|
||||
.endif
|
||||
|
||||
CLEANFILES+= .dirdep
|
||||
|
||||
# this allows us to trace dependencies back to their src dir
|
||||
.dirdep:
|
||||
@echo '${_dirdep}' > $@
|
||||
@ -59,14 +61,23 @@ LN_CP_SCRIPT = LnCp() { \
|
||||
ln $$1 $$2 2> /dev/null || \
|
||||
cp -p $$1 $$2; }
|
||||
|
||||
# a staging conflict should cause an error
|
||||
# a warning is handy when bootstapping different options.
|
||||
STAGE_CONFLICT?= ERROR
|
||||
.if ${STAGE_CONFLICT:tl} == "error"
|
||||
STAGE_CONFLICT_ACTION= exit 1;
|
||||
.else
|
||||
STAGE_CONFLICT_ACTION=
|
||||
.endif
|
||||
|
||||
# it is an error for more than one src dir to try and stage
|
||||
# the same file
|
||||
STAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \
|
||||
t=$$1; \
|
||||
if [ -s $$t.dirdep ]; then \
|
||||
cmp -s .dirdep $$t.dirdep && return; \
|
||||
echo "ERROR: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
|
||||
exit 1; \
|
||||
echo "${STAGE_CONFLICT}: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
|
||||
${STAGE_CONFLICT_ACTION} \
|
||||
fi; \
|
||||
LnCp .dirdep $$t.dirdep || exit 1; }
|
||||
|
||||
@ -124,7 +135,7 @@ _STAGE_AS_BASENAME_USE: .USE ${.TARGET:T}
|
||||
|
||||
.if !empty(STAGE_INCSDIR)
|
||||
STAGE_TARGETS += stage_incs
|
||||
STAGE_INCS ?= ${.ALLSRC:N.dirdep}
|
||||
STAGE_INCS ?= ${.ALLSRC:N.dirdep:Nstage_*}
|
||||
|
||||
stage_includes: stage_incs
|
||||
stage_incs: .dirdep
|
||||
@ -135,7 +146,7 @@ stage_incs: .dirdep
|
||||
.if !empty(STAGE_LIBDIR)
|
||||
STAGE_TARGETS += stage_libs
|
||||
|
||||
STAGE_LIBS ?= ${.ALLSRC:N.dirdep}
|
||||
STAGE_LIBS ?= ${.ALLSRC:N.dirdep:Nstage_*}
|
||||
|
||||
stage_libs: .dirdep
|
||||
@${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS}
|
||||
@ -167,8 +178,8 @@ CLEANFILES += ${STAGE_SETS:@s@stage*$s@}
|
||||
|
||||
# some makefiles need to populate multiple directories
|
||||
.for s in ${STAGE_SETS:O:u}
|
||||
STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep}
|
||||
STAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep}
|
||||
STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
|
||||
STAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
|
||||
STAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP}
|
||||
STAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP}
|
||||
|
||||
@ -214,7 +225,7 @@ STAGE_TARGETS += stage_as
|
||||
# each ${file} will be staged as ${STAGE_AS_${file:T}}
|
||||
# one could achieve the same with SYMLINKS
|
||||
.for s in ${STAGE_AS_SETS:O:u}
|
||||
STAGE_AS.$s ?= ${.ALLSRC:N.dirdep}
|
||||
STAGE_AS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
|
||||
|
||||
stage_as: stage_as.$s
|
||||
stage_as.$s: .dirdep
|
||||
@ -227,13 +238,15 @@ stage_as.$s: .dirdep
|
||||
CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes
|
||||
|
||||
# stage_*links usually needs to follow any others.
|
||||
# for non-jobs mode the order here matters
|
||||
staging: ${STAGE_TARGETS:N*_links} ${STAGE_TARGETS:M*_links}
|
||||
|
||||
.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:M*_links} != ""
|
||||
# the above isn't sufficient
|
||||
.for t in ${STAGE_TARGETS:N*links:O:u}
|
||||
.ORDER: $t stage_links
|
||||
.ORDER: $t stage_symlinks
|
||||
.endfor
|
||||
|
||||
# make sure this exists
|
||||
staging:
|
||||
.endif
|
||||
|
||||
# generally we want staging to wait until everything else is done
|
||||
STAGING_WAIT ?= .WAIT
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: meta.sys.mk,v 1.21 2015/06/01 22:43:49 sjg Exp $
|
||||
# $Id: meta.sys.mk,v 1.22 2015/06/16 06:31:05 sjg Exp $
|
||||
|
||||
#
|
||||
# @(#) Copyright (c) 2010, Simon J. Gerraty
|
||||
@ -20,6 +20,10 @@
|
||||
.if ${MAKE_VERSION:U0} > 20100901
|
||||
.if !target(.ERROR)
|
||||
|
||||
.-include "local.meta.sys.mk"
|
||||
|
||||
# absoulte path to what we are reading.
|
||||
_PARSEDIR = ${.PARSEDIR:tA}
|
||||
|
||||
META_MODE += meta verbose
|
||||
.MAKE.MODE ?= ${META_MODE}
|
||||
@ -69,6 +73,7 @@ MACHINE = host
|
||||
# for example, if using Makefild.depend for multiple machines,
|
||||
# allowing only MACHINE0 to update can keep things simple.
|
||||
MACHINE0 := ${MACHINE}
|
||||
.export MACHINE0
|
||||
|
||||
.if defined(PYTHON) && exists(${PYTHON})
|
||||
# we prefer the python version of this - it is much faster
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: own.mk,v 1.28 2015/04/16 16:59:00 sjg Exp $
|
||||
# $Id: own.mk,v 1.29 2015/09/08 06:15:31 sjg Exp $
|
||||
|
||||
.if !target(__${.PARSEFILE}__)
|
||||
__${.PARSEFILE}__:
|
||||
@ -133,7 +133,9 @@ USERGRP!= id -g
|
||||
.for x in BIN CONF DOC INFO KMOD LIB MAN NLS SHARE
|
||||
$xOWN= ${USER}
|
||||
$xGRP= ${USERGRP}
|
||||
$x_INSTALL_OWN=
|
||||
.endfor
|
||||
PROG_INSTALL_OWN=
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@ -143,6 +145,7 @@ BINGRP?= ${ROOT_GROUP}
|
||||
BINOWN?= root
|
||||
BINMODE?= 555
|
||||
NONBINMODE?= 444
|
||||
DIRMODE?= 755
|
||||
|
||||
# Define MANZ to have the man pages compressed (gzip)
|
||||
#MANZ= 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: rst2htm.mk,v 1.9 2014/02/22 01:52:41 sjg Exp $
|
||||
# $Id: rst2htm.mk,v 1.10 2015/09/08 22:17:46 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2009, Simon J. Gerraty
|
||||
#
|
||||
@ -26,7 +26,12 @@ RST2PDF ?= rst2pdf
|
||||
RST2S5 ?= rst2s5.py
|
||||
# the following will run RST2S5 if the target name contains the word 'slides'
|
||||
# otherwise it uses RST2HTML
|
||||
RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5} ${RST2S5_FLAGS}:${RST2HTML} ${RST2HTML_FLAGS}}
|
||||
RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5}:${RST2HTML}}
|
||||
RST2HTM_SLIDES_FLAGS ?= ${RST2S5_FLAGS}
|
||||
RST2HTM_DOC_FLAGS ?= ${RST2HTML_FLAGS}
|
||||
RST2HTM_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2HTM_SLIDES_FLAGS}:${RST2HTM_DOC_FLAGS}}
|
||||
|
||||
RST2PDF_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2PDF_SLIDES_FLAGS}:${RST2PDF_DOC_FLAGS}}
|
||||
|
||||
RST_SUFFIXES ?= .rst .txt
|
||||
|
||||
@ -37,10 +42,10 @@ html: ${HTMFILES}
|
||||
.SUFFIXES: ${RST_SUFFIXES} .htm .pdf
|
||||
|
||||
${RST_SUFFIXES:@s@$s.htm@}:
|
||||
${RST2HTM} ${.IMPSRC} ${.TARGET}
|
||||
${RST2HTM} ${RST2HTM_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET}
|
||||
|
||||
${RST_SUFFIXES:@s@$s.pdf@}:
|
||||
${RST2PDF} ${.IMPSRC} ${.TARGET}
|
||||
${RST2PDF} ${RST2PDF_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET}
|
||||
|
||||
.for s in ${RSTSRCS:O:u}
|
||||
${s:R:T}.htm: $s
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nonints.h,v 1.68 2015/05/05 21:51:09 sjg Exp $ */
|
||||
/* $NetBSD: nonints.h,v 1.69 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -184,8 +184,8 @@ void Var_Set(const char *, const char *, GNode *, int);
|
||||
void Var_Append(const char *, const char *, GNode *);
|
||||
Boolean Var_Exists(const char *, GNode *);
|
||||
char *Var_Value(const char *, GNode *, char **);
|
||||
char *Var_Parse(const char *, GNode *, Boolean, int *, void **);
|
||||
char *Var_Subst(const char *, const char *, GNode *, Boolean);
|
||||
char *Var_Parse(const char *, GNode *, Boolean, Boolean, int *, void **);
|
||||
char *Var_Subst(const char *, const char *, GNode *, Boolean, Boolean);
|
||||
char *Var_GetTail(const char *);
|
||||
char *Var_GetHead(const char *);
|
||||
void Var_Init(void);
|
||||
|
@ -17,7 +17,7 @@
|
||||
# Simon J. Gerraty <sjg@crufty.net>
|
||||
|
||||
# RCSid:
|
||||
# $Id: os.sh,v 1.46 2014/05/19 16:38:09 sjg Exp $
|
||||
# $Id: os.sh,v 1.47 2015/09/10 05:53:10 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 1994 Simon J. Gerraty
|
||||
#
|
||||
@ -137,7 +137,10 @@ SunOS)
|
||||
# NetBSD at least has good backward compatibility
|
||||
# so NetBSD/i386 is good enough
|
||||
case $OS in
|
||||
NetBSD) SHARE_ARCH=$OS/${MACHINE_ARCH:-$MACHINE};;
|
||||
NetBSD)
|
||||
HOST_ARCH=$MACHINE
|
||||
SHARE_ARCH=$OS/$HOST
|
||||
;;
|
||||
OpenBSD)
|
||||
arch=`Which arch /usr/bin:/usr/ucb:$PATH`
|
||||
MACHINE_ARCH=`$arch -s`
|
||||
@ -203,13 +206,14 @@ esac
|
||||
|
||||
TMP_DIRS=${TMP_DIRS:-"/tmp /var/tmp"}
|
||||
MACHINE_ARCH=${MACHINE_ARCH:-$MACHINE}
|
||||
HOST_ARCH=${HOST_ARCH:-$MACHINE_ARCH}
|
||||
# we mount server:/share/arch/$SHARE_ARCH as /usr/local
|
||||
SHARE_ARCH=${SHARE_ARCH:-$OS/$OSMAJOR.X/$MACHINE_ARCH}
|
||||
SHARE_ARCH=${SHARE_ARCH:-$OS/$OSMAJOR.X/$HOST_ARCH}
|
||||
LN=${LN:-ln}
|
||||
TR=${TR:-tr}
|
||||
|
||||
# Some people like have /share/$HOST_TARGET/bin etc.
|
||||
HOST_TARGET=`echo ${OS}${OSMAJOR}-${MACHINE_ARCH} | toLower`
|
||||
HOST_TARGET=`echo ${OS}${OSMAJOR}-$HOST_ARCH | toLower`
|
||||
export HOST_TARGET
|
||||
|
||||
case `echo -n .` in -n*) N=; C="\c";; *) N=-n; C=;; esac
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland Exp $ */
|
||||
/* $NetBSD: parse.c,v 1.205 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -69,14 +69,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland Exp $";
|
||||
static char rcsid[] = "$NetBSD: parse.c,v 1.205 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland Exp $");
|
||||
__RCSID("$NetBSD: parse.c,v 1.205 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -812,7 +812,7 @@ ParseMessage(char *line)
|
||||
while (isspace((u_char)*line))
|
||||
line++;
|
||||
|
||||
line = Var_Subst(NULL, line, VAR_CMD, 0);
|
||||
line = Var_Subst(NULL, line, VAR_CMD, FALSE, TRUE);
|
||||
Parse_Error(mtype, "%s", line);
|
||||
free(line);
|
||||
|
||||
@ -1229,7 +1229,7 @@ ParseDoDependency(char *line)
|
||||
int length;
|
||||
void *freeIt;
|
||||
|
||||
(void)Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
|
||||
(void)Var_Parse(cp, VAR_CMD, TRUE, TRUE, &length, &freeIt);
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
cp += length-1;
|
||||
@ -1944,7 +1944,7 @@ Parse_DoVar(char *line, GNode *ctxt)
|
||||
if (!Var_Exists(line, ctxt))
|
||||
Var_Set(line, "", ctxt, 0);
|
||||
|
||||
cp = Var_Subst(NULL, cp, ctxt, FALSE);
|
||||
cp = Var_Subst(NULL, cp, ctxt, FALSE, TRUE);
|
||||
oldVars = oldOldVars;
|
||||
freeCp = TRUE;
|
||||
|
||||
@ -1959,7 +1959,7 @@ Parse_DoVar(char *line, GNode *ctxt)
|
||||
* expansion on the whole thing. The resulting string will need
|
||||
* freeing when we're done, so set freeCmd to TRUE.
|
||||
*/
|
||||
cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
|
||||
cp = Var_Subst(NULL, cp, VAR_CMD, TRUE, TRUE);
|
||||
freeCp = TRUE;
|
||||
}
|
||||
|
||||
@ -2298,7 +2298,7 @@ ParseDoInclude(char *line)
|
||||
* Substitute for any variables in the file name before trying to
|
||||
* find the thing.
|
||||
*/
|
||||
file = Var_Subst(NULL, file, VAR_CMD, FALSE);
|
||||
file = Var_Subst(NULL, file, VAR_CMD, FALSE, TRUE);
|
||||
|
||||
Parse_include_file(file, endc == '>', silent);
|
||||
free(file);
|
||||
@ -2524,7 +2524,7 @@ ParseTraditionalInclude(char *line)
|
||||
* Substitute for any variables in the file name before trying to
|
||||
* find the thing.
|
||||
*/
|
||||
all_files = Var_Subst(NULL, file, VAR_CMD, FALSE);
|
||||
all_files = Var_Subst(NULL, file, VAR_CMD, FALSE, TRUE);
|
||||
|
||||
if (*file == '\0') {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
@ -2592,7 +2592,7 @@ ParseGmakeExport(char *line)
|
||||
/*
|
||||
* Expand the value before putting it in the environment.
|
||||
*/
|
||||
value = Var_Subst(NULL, value, VAR_CMD, FALSE);
|
||||
value = Var_Subst(NULL, value, VAR_CMD, FALSE, TRUE);
|
||||
setenv(variable, value, 1);
|
||||
}
|
||||
#endif
|
||||
@ -3141,7 +3141,7 @@ Parse_File(const char *name, int fd)
|
||||
* variables expanded before being parsed. Tell the variable
|
||||
* module to complain if some variable is undefined...
|
||||
*/
|
||||
line = Var_Subst(NULL, line, VAR_CMD, TRUE);
|
||||
line = Var_Subst(NULL, line, VAR_CMD, TRUE, TRUE);
|
||||
|
||||
/*
|
||||
* Need a non-circular list for the target nodes
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $ */
|
||||
/* $NetBSD: suff.c,v 1.74 2015/10/11 04:51:24 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -69,14 +69,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $";
|
||||
static char rcsid[] = "$NetBSD: suff.c,v 1.74 2015/10/11 04:51:24 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $");
|
||||
__RCSID("$NetBSD: suff.c,v 1.74 2015/10/11 04:51:24 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -1543,7 +1543,7 @@ SuffExpandChildren(LstNode cln, GNode *pgn)
|
||||
if (DEBUG(SUFF)) {
|
||||
fprintf(debug_file, "Expanding \"%s\"...", cgn->name);
|
||||
}
|
||||
cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
|
||||
cp = Var_Subst(NULL, cgn->name, pgn, TRUE, TRUE);
|
||||
|
||||
if (cp != NULL) {
|
||||
Lst members = Lst_Init(FALSE);
|
||||
@ -1596,7 +1596,7 @@ SuffExpandChildren(LstNode cln, GNode *pgn)
|
||||
int len;
|
||||
void *freeIt;
|
||||
|
||||
junk = Var_Parse(cp, pgn, TRUE, &len, &freeIt);
|
||||
junk = Var_Parse(cp, pgn, TRUE, TRUE, &len, &freeIt);
|
||||
if (junk != var_Error) {
|
||||
cp += len - 1;
|
||||
}
|
||||
|
@ -1,2 +1,20 @@
|
||||
|
||||
:D expanded when var set
|
||||
true
|
||||
TRUE
|
||||
:U expanded when var undef
|
||||
true
|
||||
TRUE
|
||||
:D skipped if var undef
|
||||
|
||||
:U skipped when var set
|
||||
is set
|
||||
:? only lhs when value true
|
||||
true
|
||||
TRUE
|
||||
:? only rhs when value false
|
||||
false
|
||||
FALSE
|
||||
do not evaluate or expand :? if discarding
|
||||
is set
|
||||
exit status 0
|
||||
|
@ -1,8 +1,42 @@
|
||||
# $Id: varmisc.mk,v 1.2 2014/08/30 22:25:14 sjg Exp $
|
||||
# $Id: varmisc.mk,v 1.5 2015/10/12 17:10:48 sjg Exp $
|
||||
#
|
||||
# Miscellaneous variable tests.
|
||||
|
||||
all: unmatched_var_paren
|
||||
all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none
|
||||
|
||||
unmatched_var_paren:
|
||||
@echo ${foo::=foo-text}
|
||||
|
||||
True = ${echo true >&2:L:sh}TRUE
|
||||
False= ${echo false >&2:L:sh}FALSE
|
||||
|
||||
VSET= is set
|
||||
.undef UNDEF
|
||||
|
||||
U_false:
|
||||
@echo :U skipped when var set
|
||||
@echo ${VSET:U${False}}
|
||||
|
||||
D_false:
|
||||
@echo :D skipped if var undef
|
||||
@echo ${UNDEF:D${False}}
|
||||
|
||||
U_true:
|
||||
@echo :U expanded when var undef
|
||||
@echo ${UNDEF:U${True}}
|
||||
|
||||
D_true:
|
||||
@echo :D expanded when var set
|
||||
@echo ${VSET:D${True}}
|
||||
|
||||
Q_lhs:
|
||||
@echo :? only lhs when value true
|
||||
@echo ${1:L:?${True}:${False}}
|
||||
|
||||
Q_rhs:
|
||||
@echo :? only rhs when value false
|
||||
@echo ${0:L:?${True}:${False}}
|
||||
|
||||
NQ_none:
|
||||
@echo do not evaluate or expand :? if discarding
|
||||
@echo ${VSET:U${1:L:?${True}:${False}}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $ */
|
||||
/* $NetBSD: var.c,v 1.199 2015/10/20 21:30:57 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -69,14 +69,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $";
|
||||
static char rcsid[] = "$NetBSD: var.c,v 1.199 2015/10/20 21:30:57 sjg Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $");
|
||||
__RCSID("$NetBSD: var.c,v 1.199 2015/10/20 21:30:57 sjg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
@ -138,6 +138,7 @@ __RCSID("$NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $");
|
||||
#include "buf.h"
|
||||
#include "dir.h"
|
||||
#include "job.h"
|
||||
#include "metachar.h"
|
||||
|
||||
extern int makelevel;
|
||||
/*
|
||||
@ -541,7 +542,7 @@ Var_Delete(const char *name, GNode *ctxt)
|
||||
char *cp;
|
||||
|
||||
if (strchr(name, '$')) {
|
||||
cp = Var_Subst(NULL, name, VAR_GLOBAL, 0);
|
||||
cp = Var_Subst(NULL, name, VAR_GLOBAL, FALSE, TRUE);
|
||||
} else {
|
||||
cp = (char *)name;
|
||||
}
|
||||
@ -632,7 +633,7 @@ Var_Export1(const char *name, int parent)
|
||||
}
|
||||
n = snprintf(tmp, sizeof(tmp), "${%s}", name);
|
||||
if (n < (int)sizeof(tmp)) {
|
||||
val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
val = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
|
||||
setenv(name, val, 1);
|
||||
free(val);
|
||||
}
|
||||
@ -700,7 +701,7 @@ Var_ExportVars(void)
|
||||
int ac;
|
||||
int i;
|
||||
|
||||
val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
val = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
|
||||
av = brk_string(val, &ac, FALSE, &as);
|
||||
for (i = 0; i < ac; i++) {
|
||||
Var_Export1(av[i], 0);
|
||||
@ -738,7 +739,7 @@ Var_Export(char *str, int isExport)
|
||||
} else {
|
||||
track = VAR_EXPORT_PARENT;
|
||||
}
|
||||
val = Var_Subst(NULL, str, VAR_GLOBAL, 0);
|
||||
val = Var_Subst(NULL, str, VAR_GLOBAL, FALSE, TRUE);
|
||||
av = brk_string(val, &ac, FALSE, &as);
|
||||
for (i = 0; i < ac; i++) {
|
||||
name = av[i];
|
||||
@ -826,7 +827,7 @@ Var_UnExport(char *str)
|
||||
/* Using .MAKE.EXPORTED */
|
||||
n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
|
||||
if (n < (int)sizeof(tmp)) {
|
||||
vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
if (vlist) {
|
||||
@ -856,7 +857,7 @@ Var_UnExport(char *str)
|
||||
n = snprintf(tmp, sizeof(tmp),
|
||||
"${" MAKE_EXPORTED ":N%s}", v->name);
|
||||
if (n < (int)sizeof(tmp)) {
|
||||
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
||||
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
|
||||
Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
|
||||
free(cp);
|
||||
}
|
||||
@ -911,7 +912,7 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
|
||||
* point in searching them all just to save a bit of memory...
|
||||
*/
|
||||
if (strchr(name, '$') != NULL) {
|
||||
expanded_name = Var_Subst(NULL, name, ctxt, 0);
|
||||
expanded_name = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
|
||||
if (expanded_name[0] == 0) {
|
||||
if (DEBUG(VAR)) {
|
||||
fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
|
||||
@ -982,7 +983,6 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
|
||||
|
||||
|
||||
out:
|
||||
if (expanded_name != NULL)
|
||||
free(expanded_name);
|
||||
if (v != NULL)
|
||||
VarFreeEnv(v, TRUE);
|
||||
@ -1023,7 +1023,7 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
|
||||
char *expanded_name = NULL;
|
||||
|
||||
if (strchr(name, '$') != NULL) {
|
||||
expanded_name = Var_Subst(NULL, name, ctxt, 0);
|
||||
expanded_name = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
|
||||
if (expanded_name[0] == 0) {
|
||||
if (DEBUG(VAR)) {
|
||||
fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
|
||||
@ -1061,7 +1061,6 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
|
||||
Hash_SetValue(h, v);
|
||||
}
|
||||
}
|
||||
if (expanded_name != NULL)
|
||||
free(expanded_name);
|
||||
}
|
||||
|
||||
@ -1089,12 +1088,10 @@ Var_Exists(const char *name, GNode *ctxt)
|
||||
char *cp;
|
||||
|
||||
if ((cp = strchr(name, '$')) != NULL) {
|
||||
cp = Var_Subst(NULL, name, ctxt, FALSE);
|
||||
cp = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
|
||||
}
|
||||
v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
|
||||
if (cp != NULL) {
|
||||
free(cp);
|
||||
}
|
||||
if (v == NULL) {
|
||||
return(FALSE);
|
||||
} else {
|
||||
@ -1389,7 +1386,7 @@ VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
|
||||
addSpace = TRUE;
|
||||
|
||||
if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
|
||||
varexp = Var_Subst(NULL, pat->rhs, ctx, 0);
|
||||
varexp = Var_Subst(NULL, pat->rhs, ctx, FALSE, TRUE);
|
||||
Str_SYSVSubst(buf, varexp, ptr, len);
|
||||
free(varexp);
|
||||
} else {
|
||||
@ -1809,7 +1806,7 @@ VarLoopExpand(GNode *ctx MAKE_ATTR_UNUSED,
|
||||
|
||||
if (word && *word) {
|
||||
Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
|
||||
s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum);
|
||||
s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum, TRUE);
|
||||
if (s != NULL && *s != '\0') {
|
||||
if (addSpace && *s != '\n')
|
||||
Buf_AddByte(buf, ' ');
|
||||
@ -2190,9 +2187,8 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
|
||||
* delimiter, assume it's a variable
|
||||
* substitution and recurse.
|
||||
*/
|
||||
cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
|
||||
cp2 = Var_Parse(cp, ctxt, errnum, TRUE, &len, &freeIt);
|
||||
Buf_AddBytes(&buf, strlen(cp2), cp2);
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
cp += len - 1;
|
||||
} else {
|
||||
@ -2246,7 +2242,7 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* VarQuote --
|
||||
* Quote shell meta-characters in the string
|
||||
* Quote shell meta-characters and space characters in the string
|
||||
*
|
||||
* Results:
|
||||
* The quoted string
|
||||
@ -2261,29 +2257,25 @@ VarQuote(char *str)
|
||||
{
|
||||
|
||||
Buffer buf;
|
||||
/* This should cover most shells :-( */
|
||||
static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
|
||||
const char *newline;
|
||||
size_t len, nlen;
|
||||
size_t nlen;
|
||||
|
||||
if ((newline = Shell_GetNewline()) == NULL)
|
||||
newline = "\\\n";
|
||||
nlen = strlen(newline);
|
||||
|
||||
Buf_Init(&buf, 0);
|
||||
while (*str != '\0') {
|
||||
if ((len = strcspn(str, meta)) != 0) {
|
||||
Buf_AddBytes(&buf, len, str);
|
||||
str += len;
|
||||
} else if (*str == '\n') {
|
||||
|
||||
for (; *str != '\0'; str++) {
|
||||
if (*str == '\n') {
|
||||
Buf_AddBytes(&buf, nlen, newline);
|
||||
++str;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (isspace((unsigned char)*str) || ismeta((unsigned char)*str))
|
||||
Buf_AddByte(&buf, '\\');
|
||||
Buf_AddByte(&buf, *str);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
str = Buf_Destroy(&buf, FALSE);
|
||||
if (DEBUG(VAR))
|
||||
fprintf(debug_file, "QuoteMeta: [%s]\n", str);
|
||||
@ -2468,7 +2460,7 @@ VarStrftime(const char *fmt, int zulu)
|
||||
static char *
|
||||
ApplyModifiers(char *nstr, const char *tstr,
|
||||
int startc, int endc,
|
||||
Var *v, GNode *ctxt, Boolean errnum,
|
||||
Var *v, GNode *ctxt, Boolean errnum, Boolean wantit,
|
||||
int *lengthPtr, void **freePtr)
|
||||
{
|
||||
const char *start;
|
||||
@ -2499,7 +2491,7 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
int rlen;
|
||||
int c;
|
||||
|
||||
rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
|
||||
rval = Var_Parse(tstr, ctxt, errnum, wantit, &rlen, &freeIt);
|
||||
|
||||
/*
|
||||
* If we have not parsed up to endc or ':',
|
||||
@ -2509,7 +2501,6 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
(c = tstr[rlen]) != '\0' &&
|
||||
c != ':' &&
|
||||
c != endc) {
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
goto apply_mods;
|
||||
}
|
||||
@ -2526,16 +2517,14 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
|
||||
nstr = ApplyModifiers(nstr, rval,
|
||||
0, 0,
|
||||
v, ctxt, errnum, &used, freePtr);
|
||||
v, ctxt, errnum, wantit, &used, freePtr);
|
||||
if (nstr == var_Error
|
||||
|| (nstr == varNoError && errnum == 0)
|
||||
|| strlen(rval) != (size_t) used) {
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
goto out; /* error already reported */
|
||||
}
|
||||
}
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
if (*tstr == ':')
|
||||
tstr++;
|
||||
@ -2565,6 +2554,7 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
char *sv_name;
|
||||
VarPattern pattern;
|
||||
int how;
|
||||
int flags;
|
||||
|
||||
if (v->name[0] == 0)
|
||||
goto bad_modifier;
|
||||
@ -2600,8 +2590,9 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
delim = startc == PROPEN ? PRCLOSE : BRCLOSE;
|
||||
pattern.flags = 0;
|
||||
|
||||
flags = (wantit) ? 0 : VAR_NOSUBST;
|
||||
pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
|
||||
&cp, delim, NULL,
|
||||
&cp, delim, &flags,
|
||||
&pattern.rightLen,
|
||||
NULL);
|
||||
if (v->flags & VAR_JUNK) {
|
||||
@ -2615,6 +2606,7 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
termc = *--cp;
|
||||
delim = '\0';
|
||||
|
||||
if (wantit) {
|
||||
switch (how) {
|
||||
case '+':
|
||||
Var_Append(v->name, pattern.rhs, v_ctxt);
|
||||
@ -2625,7 +2617,6 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
Error(emsg, nstr);
|
||||
else
|
||||
Var_Set(v->name, newStr, v_ctxt, 0);
|
||||
if (newStr)
|
||||
free(newStr);
|
||||
break;
|
||||
case '?':
|
||||
@ -2636,6 +2627,7 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
Var_Set(v->name, pattern.rhs, v_ctxt, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(UNCONST(pattern.rhs));
|
||||
newStr = varNoError;
|
||||
break;
|
||||
@ -2676,8 +2668,15 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
case 'U':
|
||||
{
|
||||
Buffer buf; /* Buffer for patterns */
|
||||
int wantit; /* want data in buffer */
|
||||
int wantit_; /* want data in buffer */
|
||||
|
||||
if (wantit) {
|
||||
if (*tstr == 'U')
|
||||
wantit_ = ((v->flags & VAR_JUNK) != 0);
|
||||
else
|
||||
wantit_ = ((v->flags & VAR_JUNK) == 0);
|
||||
} else
|
||||
wantit_ = wantit;
|
||||
/*
|
||||
* Pass through tstr looking for 1) escaped delimiters,
|
||||
* '$'s and backslashes (place the escaped character in
|
||||
@ -2706,9 +2705,8 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
int len;
|
||||
void *freeIt;
|
||||
|
||||
cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
|
||||
cp2 = Var_Parse(cp, ctxt, errnum, wantit_, &len, &freeIt);
|
||||
Buf_AddBytes(&buf, strlen(cp2), cp2);
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
cp += len - 1;
|
||||
} else {
|
||||
@ -2718,13 +2716,9 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
|
||||
termc = *cp;
|
||||
|
||||
if (*tstr == 'U')
|
||||
wantit = ((v->flags & VAR_JUNK) != 0);
|
||||
else
|
||||
wantit = ((v->flags & VAR_JUNK) == 0);
|
||||
if ((v->flags & VAR_JUNK) != 0)
|
||||
v->flags |= VAR_KEEP;
|
||||
if (wantit) {
|
||||
if (wantit_) {
|
||||
newStr = Buf_Destroy(&buf, FALSE);
|
||||
} else {
|
||||
newStr = nstr;
|
||||
@ -2769,14 +2763,17 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
pattern.flags = 0;
|
||||
|
||||
delim = '!';
|
||||
|
||||
emsg = NULL;
|
||||
cp = ++tstr;
|
||||
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
|
||||
&cp, delim,
|
||||
NULL, &pattern.rightLen,
|
||||
NULL)) == NULL)
|
||||
goto cleanup;
|
||||
if (wantit)
|
||||
newStr = Cmd_Exec(pattern.rhs, &emsg);
|
||||
else
|
||||
newStr = varNoError;
|
||||
free(UNCONST(pattern.rhs));
|
||||
if (emsg)
|
||||
Error(emsg, nstr);
|
||||
@ -3152,7 +3149,7 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
* expand it.
|
||||
*/
|
||||
cp2 = pattern;
|
||||
pattern = Var_Subst(NULL, cp2, ctxt, errnum);
|
||||
pattern = Var_Subst(NULL, cp2, ctxt, errnum, TRUE);
|
||||
free(cp2);
|
||||
}
|
||||
if (DEBUG(VAR))
|
||||
@ -3238,15 +3235,32 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
{
|
||||
VarPattern pattern;
|
||||
Boolean value;
|
||||
int cond_rc;
|
||||
int lhs_flags, rhs_flags;
|
||||
|
||||
/* find ':', and then substitute accordingly */
|
||||
|
||||
if (wantit) {
|
||||
cond_rc = Cond_EvalExpression(NULL, v->name, &value, 0, FALSE);
|
||||
if (cond_rc == COND_INVALID) {
|
||||
lhs_flags = rhs_flags = VAR_NOSUBST;
|
||||
} else if (value) {
|
||||
lhs_flags = 0;
|
||||
rhs_flags = VAR_NOSUBST;
|
||||
} else {
|
||||
lhs_flags = VAR_NOSUBST;
|
||||
rhs_flags = 0;
|
||||
}
|
||||
} else {
|
||||
/* we are just consuming and discarding */
|
||||
cond_rc = value = 0;
|
||||
lhs_flags = rhs_flags = VAR_NOSUBST;
|
||||
}
|
||||
pattern.flags = 0;
|
||||
|
||||
cp = ++tstr;
|
||||
delim = ':';
|
||||
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
|
||||
&cp, delim, NULL,
|
||||
&cp, delim, &lhs_flags,
|
||||
&pattern.leftLen,
|
||||
NULL)) == NULL)
|
||||
goto cleanup;
|
||||
@ -3254,15 +3268,14 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
/* BROPEN or PROPEN */
|
||||
delim = endc;
|
||||
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
|
||||
&cp, delim, NULL,
|
||||
&cp, delim, &rhs_flags,
|
||||
&pattern.rightLen,
|
||||
NULL)) == NULL)
|
||||
goto cleanup;
|
||||
|
||||
termc = *--cp;
|
||||
delim = '\0';
|
||||
if (Cond_EvalExpression(NULL, v->name, &value, 0, FALSE)
|
||||
== COND_INVALID) {
|
||||
if (cond_rc == COND_INVALID) {
|
||||
Error("Bad conditional expression `%s' in %s?%s:%s",
|
||||
v->name, v->name, pattern.lhs, pattern.rhs);
|
||||
goto cleanup;
|
||||
@ -3424,9 +3437,12 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
case 's':
|
||||
if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
|
||||
const char *emsg;
|
||||
if (wantit) {
|
||||
newStr = Cmd_Exec(nstr, &emsg);
|
||||
if (emsg)
|
||||
Error(emsg, nstr);
|
||||
} else
|
||||
newStr = varNoError;
|
||||
cp = tstr + 2;
|
||||
termc = *cp;
|
||||
break;
|
||||
@ -3547,10 +3563,8 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
if (delim != '\0')
|
||||
Error("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
if (*freePtr) {
|
||||
free(*freePtr);
|
||||
*freePtr = NULL;
|
||||
}
|
||||
return (var_Error);
|
||||
}
|
||||
|
||||
@ -3565,6 +3579,7 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
* str The string to parse
|
||||
* ctxt The context for the variable
|
||||
* errnum TRUE if undefined variables are an error
|
||||
* wantit TRUE if we actually want the result
|
||||
* lengthPtr OUT: The length of the specification
|
||||
* freePtr OUT: Non-NULL if caller should free *freePtr
|
||||
*
|
||||
@ -3583,8 +3598,9 @@ ApplyModifiers(char *nstr, const char *tstr,
|
||||
*/
|
||||
/* coverity[+alloc : arg-*4] */
|
||||
char *
|
||||
Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
void **freePtr)
|
||||
Var_Parse(const char *str, GNode *ctxt,
|
||||
Boolean errnum, Boolean wantit,
|
||||
int *lengthPtr, void **freePtr)
|
||||
{
|
||||
const char *tstr; /* Pointer into str */
|
||||
Var *v; /* Variable in invocation */
|
||||
@ -3689,11 +3705,10 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
if (*tstr == '$') {
|
||||
int rlen;
|
||||
void *freeIt;
|
||||
char *rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
|
||||
char *rval = Var_Parse(tstr, ctxt, errnum, wantit, &rlen, &freeIt);
|
||||
if (rval != NULL) {
|
||||
Buf_AddBytes(&buf, strlen(rval), rval);
|
||||
}
|
||||
if (freeIt)
|
||||
free(freeIt);
|
||||
tstr += rlen - 1;
|
||||
}
|
||||
@ -3837,7 +3852,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
*/
|
||||
nstr = Buf_GetAll(&v->val, NULL);
|
||||
if (strchr(nstr, '$') != NULL) {
|
||||
nstr = Var_Subst(NULL, nstr, ctxt, errnum);
|
||||
nstr = Var_Subst(NULL, nstr, ctxt, errnum, wantit);
|
||||
*freePtr = nstr;
|
||||
}
|
||||
|
||||
@ -3850,7 +3865,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
extraFree = NULL;
|
||||
if (extramodifiers != NULL) {
|
||||
nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
|
||||
v, ctxt, errnum, &used, &extraFree);
|
||||
v, ctxt, errnum, wantit, &used, &extraFree);
|
||||
}
|
||||
|
||||
if (haveModifier) {
|
||||
@ -3858,11 +3873,9 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
tstr++;
|
||||
|
||||
nstr = ApplyModifiers(nstr, tstr, startc, endc,
|
||||
v, ctxt, errnum, &used, freePtr);
|
||||
v, ctxt, errnum, wantit, &used, freePtr);
|
||||
tstr += used;
|
||||
if (extraFree) {
|
||||
free(extraFree);
|
||||
}
|
||||
} else {
|
||||
*freePtr = extraFree;
|
||||
}
|
||||
@ -3924,6 +3937,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
* str the string which to substitute
|
||||
* ctxt the context wherein to find variables
|
||||
* undefErr TRUE if undefineds are an error
|
||||
* wantit TRUE if we actually want the result
|
||||
*
|
||||
* Results:
|
||||
* The resulting string.
|
||||
@ -3933,7 +3947,8 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
char *
|
||||
Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
|
||||
Var_Subst(const char *var, const char *str, GNode *ctxt,
|
||||
Boolean undefErr, Boolean wantit)
|
||||
{
|
||||
Buffer buf; /* Buffer for forming things */
|
||||
char *val; /* Value to substitute for a variable */
|
||||
@ -4031,7 +4046,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
|
||||
continue;
|
||||
}
|
||||
|
||||
val = Var_Parse(str, ctxt, undefErr, &length, &freeIt);
|
||||
val = Var_Parse(str, ctxt, undefErr, wantit, &length, &freeIt);
|
||||
|
||||
/*
|
||||
* When we come down here, val should either point to the
|
||||
@ -4079,12 +4094,10 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
|
||||
Buf_AddBytes(&buf, length, val);
|
||||
trailingBslash = length > 0 && val[length - 1] == '\\';
|
||||
}
|
||||
if (freeIt) {
|
||||
free(freeIt);
|
||||
freeIt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Buf_DestroyCompact(&buf);
|
||||
}
|
||||
|
@ -2580,6 +2580,21 @@ arm_elf_osabi_sniffer (bfd *abfd)
|
||||
osabi = GDB_OSABI_ARM_EABI_V2;
|
||||
break;
|
||||
|
||||
case EF_ARM_EABI_VER3:
|
||||
case EF_ARM_EABI_VER4:
|
||||
case EF_ARM_EABI_VER5:
|
||||
/*
|
||||
* GDB does not support these EABI versions. Fallback
|
||||
* to the highest known to make the KGDB working with
|
||||
* kernel ELF image.
|
||||
*/
|
||||
osabi = GDB_OSABI_ARM_EABI_V2;
|
||||
printf ("\n%s:%d "
|
||||
"arm_elf_osabi_sniffer: Unsupported ARM EABI "
|
||||
"version 0x%x, falling back to 0x%x\n",
|
||||
__FILE__, __LINE__, eflags, EF_ARM_EABI_VER2);
|
||||
break;
|
||||
|
||||
case EF_ARM_EABI_UNKNOWN:
|
||||
/* Assume GNU tools. */
|
||||
osabi = GDB_OSABI_ARM_APCS;
|
||||
|
@ -780,7 +780,6 @@
|
||||
.ds doc-str-Lb-libfetch File Transfer Library for URLs (libfetch, \-lfetch)
|
||||
.ds doc-str-Lb-libform Curses Form Library (libform, \-lform)
|
||||
.ds doc-str-Lb-libgeom Userland API Library for kernel GEOM subsystem (libgeom, \-lgeom)
|
||||
.ds doc-str-Lb-libgpib General-Purpose Instrument Bus (GPIB) library (libgpib, \-lgpib)
|
||||
.ds doc-str-Lb-libi386 i386 Architecture Library (libi386, \-li386)
|
||||
.ds doc-str-Lb-libintl Internationalized Message Handling Library (libintl, \-lintl)
|
||||
.ds doc-str-Lb-libipsec IPsec Policy Control Library (libipsec, \-lipsec)
|
||||
|
@ -1732,8 +1732,6 @@ and their results are:
|
||||
.Lb libform
|
||||
.It Li libgeom
|
||||
.Lb libgeom
|
||||
.It Li libgpib
|
||||
.Lb libgpib
|
||||
.It Li libi386
|
||||
.Lb libi386
|
||||
.It Li libintl
|
||||
|
@ -4,6 +4,32 @@ brevity. Much more detail can be found in the git revision history:
|
||||
|
||||
https://github.com/jemalloc/jemalloc
|
||||
|
||||
* 4.0.4 (October 24, 2015)
|
||||
|
||||
This bugfix release fixes another xallocx() regression. No other regressions
|
||||
have come to light in over a month, so this is likely a good starting point
|
||||
for people who prefer to wait for "dot one" releases with all the major issues
|
||||
shaken out.
|
||||
|
||||
Bug fixes:
|
||||
- Fix xallocx(..., MALLOCX_ZERO to zero the last full trailing page of large
|
||||
allocations that have been randomly assigned an offset of 0 when
|
||||
--enable-cache-oblivious configure option is enabled.
|
||||
|
||||
* 4.0.3 (September 24, 2015)
|
||||
|
||||
This bugfix release continues the trend of xallocx() and heap profiling fixes.
|
||||
|
||||
Bug fixes:
|
||||
- Fix xallocx(..., MALLOCX_ZERO) to zero all trailing bytes of large
|
||||
allocations when --enable-cache-oblivious configure option is enabled.
|
||||
- Fix xallocx(..., MALLOCX_ZERO) to zero trailing bytes of huge allocations
|
||||
when resizing from/to a size class that is not a multiple of the chunk size.
|
||||
- Fix prof_tctx_dump_iter() to filter out nodes that were created after heap
|
||||
profile dumping started.
|
||||
- Work around a potentially bad thread-specific data initialization
|
||||
interaction with NPTL (glibc's pthreads implementation).
|
||||
|
||||
* 4.0.2 (September 21, 2015)
|
||||
|
||||
This bugfix release addresses a few bugs specific to heap profiling.
|
||||
|
@ -1,5 +1,5 @@
|
||||
diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in
|
||||
index 8fc774b..fdbef95 100644
|
||||
index 26a5e14..2a801b7 100644
|
||||
--- a/doc/jemalloc.xml.in
|
||||
+++ b/doc/jemalloc.xml.in
|
||||
@@ -53,11 +53,23 @@
|
||||
@ -47,7 +47,7 @@ index 8fc774b..fdbef95 100644
|
||||
+ </refsect1>
|
||||
</refentry>
|
||||
diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in
|
||||
index 8536a3e..0c2a81f 100644
|
||||
index 654cd08..ad5382d 100644
|
||||
--- a/include/jemalloc/internal/jemalloc_internal.h.in
|
||||
+++ b/include/jemalloc/internal/jemalloc_internal.h.in
|
||||
@@ -8,6 +8,9 @@
|
||||
|
@ -1 +1 @@
|
||||
4.0.2-0-g486d249fb4715fd3de679b6c2a04f7e657883111
|
||||
4.0.4-0-g91010a9e2ebfc84b1ac1ed7fdde3bfed4f65f180
|
||||
|
@ -2,12 +2,12 @@
|
||||
.\" Title: JEMALLOC
|
||||
.\" Author: Jason Evans
|
||||
.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
|
||||
.\" Date: 09/21/2015
|
||||
.\" Date: 10/24/2015
|
||||
.\" Manual: User Manual
|
||||
.\" Source: jemalloc 4.0.2-0-g486d249fb4715fd3de679b6c2a04f7e657883111
|
||||
.\" Source: jemalloc 4.0.4-0-g91010a9e2ebfc84b1ac1ed7fdde3bfed4f65f180
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "JEMALLOC" "3" "09/21/2015" "jemalloc 4.0.2-0-g486d249fb471" "User Manual"
|
||||
.TH "JEMALLOC" "3" "10/24/2015" "jemalloc 4.0.4-0-g91010a9e2ebf" "User Manual"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@ -31,7 +31,7 @@
|
||||
jemalloc \- general purpose memory allocation functions
|
||||
.SH "LIBRARY"
|
||||
.PP
|
||||
This manual describes jemalloc 4\&.0\&.2\-0\-g486d249fb4715fd3de679b6c2a04f7e657883111\&. More information can be found at the
|
||||
This manual describes jemalloc 4\&.0\&.4\-0\-g91010a9e2ebfc84b1ac1ed7fdde3bfed4f65f180\&. More information can be found at the
|
||||
\m[blue]\fBjemalloc website\fR\m[]\&\s-2\u[1]\d\s+2\&.
|
||||
.PP
|
||||
The following configuration options are enabled in libc\*(Aqs built\-in jemalloc:
|
||||
@ -1041,7 +1041,7 @@ Flush calling thread\*(Aqs thread\-specific cache (tcache)\&. This interface rel
|
||||
.PP
|
||||
"thread\&.prof\&.name" (\fBconst char *\fR) r\- or \-w [\fB\-\-enable\-prof\fR]
|
||||
.RS 4
|
||||
Get/set the descriptive name associated with the calling thread in memory profile dumps\&. An internal copy of the name string is created, so the input string need not be maintained after this interface completes execution\&. The output string of this interface should be copied for non\-ephemeral uses, because multiple implementation details can cause asynchronous string deallocation\&. Furthermore, each invocation of this interface can only read or write; simultaneous read/write is not supported due to string lifetime limitations\&. The name string must nil\-terminated and comprised only of characters in the sets recognized by
|
||||
Get/set the descriptive name associated with the calling thread in memory profile dumps\&. An internal copy of the name string is created, so the input string need not be maintained after this interface completes execution\&. The output string of this interface should be copied for non\-ephemeral uses, because multiple implementation details can cause asynchronous string deallocation\&. Furthermore, each invocation of this interface can only read or write; simultaneous read/write is not supported due to string lifetime limitations\&. The name string must be nil\-terminated and comprised only of characters in the sets recognized by
|
||||
\fBisgraph\fR(3)
|
||||
and
|
||||
\fBisblank\fR(3)\&.
|
||||
|
@ -314,6 +314,10 @@ typedef unsigned szind_t;
|
||||
#define PAGE ((size_t)(1U << LG_PAGE))
|
||||
#define PAGE_MASK ((size_t)(PAGE - 1))
|
||||
|
||||
/* Return the page base address for the page containing address a. */
|
||||
#define PAGE_ADDR2BASE(a) \
|
||||
((void *)((uintptr_t)(a) & ~PAGE_MASK))
|
||||
|
||||
/* Return the smallest pagesize multiple that is >= s. */
|
||||
#define PAGE_CEILING(s) \
|
||||
(((s) + PAGE_MASK) & ~PAGE_MASK)
|
||||
|
@ -79,12 +79,12 @@ extern "C" {
|
||||
#include <limits.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define JEMALLOC_VERSION "4.0.2-0-g486d249fb4715fd3de679b6c2a04f7e657883111"
|
||||
#define JEMALLOC_VERSION "4.0.4-0-g91010a9e2ebfc84b1ac1ed7fdde3bfed4f65f180"
|
||||
#define JEMALLOC_VERSION_MAJOR 4
|
||||
#define JEMALLOC_VERSION_MINOR 0
|
||||
#define JEMALLOC_VERSION_BUGFIX 2
|
||||
#define JEMALLOC_VERSION_BUGFIX 4
|
||||
#define JEMALLOC_VERSION_NREV 0
|
||||
#define JEMALLOC_VERSION_GID "486d249fb4715fd3de679b6c2a04f7e657883111"
|
||||
#define JEMALLOC_VERSION_GID "91010a9e2ebfc84b1ac1ed7fdde3bfed4f65f180"
|
||||
|
||||
# define MALLOCX_LG_ALIGN(la) (la)
|
||||
# if LG_SIZEOF_PTR == 2
|
||||
|
@ -2679,6 +2679,22 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
|
||||
if (arena_run_split_large(arena, run, splitsize, zero))
|
||||
goto label_fail;
|
||||
|
||||
if (config_cache_oblivious && zero) {
|
||||
/*
|
||||
* Zero the trailing bytes of the original allocation's
|
||||
* last page, since they are in an indeterminate state.
|
||||
* There will always be trailing bytes, because ptr's
|
||||
* offset from the beginning of the run is a multiple of
|
||||
* CACHELINE in [0 .. PAGE).
|
||||
*/
|
||||
void *zbase = (void *)((uintptr_t)ptr + oldsize);
|
||||
void *zpast = PAGE_ADDR2BASE((void *)((uintptr_t)zbase +
|
||||
PAGE));
|
||||
size_t nzero = (uintptr_t)zpast - (uintptr_t)zbase;
|
||||
assert(nzero > 0);
|
||||
memset(zbase, 0, nzero);
|
||||
}
|
||||
|
||||
size = oldsize + splitsize;
|
||||
npages = (size + large_pad) >> LG_PAGE;
|
||||
|
||||
|
@ -133,7 +133,7 @@ huge_ralloc_no_move_similar(void *ptr, size_t oldsize, size_t usize_min,
|
||||
extent_node_t *node;
|
||||
arena_t *arena;
|
||||
chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
|
||||
bool zeroed;
|
||||
bool pre_zeroed, post_zeroed;
|
||||
|
||||
/* Increase usize to incorporate extra. */
|
||||
for (usize = usize_min; usize < usize_max && (usize_next = s2u(usize+1))
|
||||
@ -145,26 +145,27 @@ huge_ralloc_no_move_similar(void *ptr, size_t oldsize, size_t usize_min,
|
||||
|
||||
node = huge_node_get(ptr);
|
||||
arena = extent_node_arena_get(node);
|
||||
pre_zeroed = extent_node_zeroed_get(node);
|
||||
|
||||
/* Fill if necessary (shrinking). */
|
||||
if (oldsize > usize) {
|
||||
size_t sdiff = oldsize - usize;
|
||||
if (config_fill && unlikely(opt_junk_free)) {
|
||||
memset((void *)((uintptr_t)ptr + usize), 0x5a, sdiff);
|
||||
zeroed = false;
|
||||
post_zeroed = false;
|
||||
} else {
|
||||
zeroed = !chunk_purge_wrapper(arena, &chunk_hooks, ptr,
|
||||
CHUNK_CEILING(oldsize), usize, sdiff);
|
||||
post_zeroed = !chunk_purge_wrapper(arena, &chunk_hooks,
|
||||
ptr, CHUNK_CEILING(oldsize), usize, sdiff);
|
||||
}
|
||||
} else
|
||||
zeroed = true;
|
||||
post_zeroed = pre_zeroed;
|
||||
|
||||
malloc_mutex_lock(&arena->huge_mtx);
|
||||
/* Update the size of the huge allocation. */
|
||||
assert(extent_node_size_get(node) != usize);
|
||||
extent_node_size_set(node, usize);
|
||||
/* Clear node's zeroed field if zeroing failed above. */
|
||||
extent_node_zeroed_set(node, extent_node_zeroed_get(node) && zeroed);
|
||||
/* Update zeroed. */
|
||||
extent_node_zeroed_set(node, post_zeroed);
|
||||
malloc_mutex_unlock(&arena->huge_mtx);
|
||||
|
||||
arena_chunk_ralloc_huge_similar(arena, ptr, oldsize, usize);
|
||||
@ -172,7 +173,7 @@ huge_ralloc_no_move_similar(void *ptr, size_t oldsize, size_t usize_min,
|
||||
/* Fill if necessary (growing). */
|
||||
if (oldsize < usize) {
|
||||
if (zero || (config_fill && unlikely(opt_zero))) {
|
||||
if (!zeroed) {
|
||||
if (!pre_zeroed) {
|
||||
memset((void *)((uintptr_t)ptr + oldsize), 0,
|
||||
usize - oldsize);
|
||||
}
|
||||
@ -190,10 +191,11 @@ huge_ralloc_no_move_shrink(void *ptr, size_t oldsize, size_t usize)
|
||||
arena_t *arena;
|
||||
chunk_hooks_t chunk_hooks;
|
||||
size_t cdiff;
|
||||
bool zeroed;
|
||||
bool pre_zeroed, post_zeroed;
|
||||
|
||||
node = huge_node_get(ptr);
|
||||
arena = extent_node_arena_get(node);
|
||||
pre_zeroed = extent_node_zeroed_get(node);
|
||||
chunk_hooks = chunk_hooks_get(arena);
|
||||
|
||||
assert(oldsize > usize);
|
||||
@ -209,21 +211,21 @@ huge_ralloc_no_move_shrink(void *ptr, size_t oldsize, size_t usize)
|
||||
if (config_fill && unlikely(opt_junk_free)) {
|
||||
huge_dalloc_junk((void *)((uintptr_t)ptr + usize),
|
||||
sdiff);
|
||||
zeroed = false;
|
||||
post_zeroed = false;
|
||||
} else {
|
||||
zeroed = !chunk_purge_wrapper(arena, &chunk_hooks,
|
||||
post_zeroed = !chunk_purge_wrapper(arena, &chunk_hooks,
|
||||
CHUNK_ADDR2BASE((uintptr_t)ptr + usize),
|
||||
CHUNK_CEILING(oldsize),
|
||||
CHUNK_ADDR2OFFSET((uintptr_t)ptr + usize), sdiff);
|
||||
}
|
||||
} else
|
||||
zeroed = true;
|
||||
post_zeroed = pre_zeroed;
|
||||
|
||||
malloc_mutex_lock(&arena->huge_mtx);
|
||||
/* Update the size of the huge allocation. */
|
||||
extent_node_size_set(node, usize);
|
||||
/* Clear node's zeroed field if zeroing failed above. */
|
||||
extent_node_zeroed_set(node, extent_node_zeroed_get(node) && zeroed);
|
||||
/* Update zeroed. */
|
||||
extent_node_zeroed_set(node, post_zeroed);
|
||||
malloc_mutex_unlock(&arena->huge_mtx);
|
||||
|
||||
/* Zap the excess chunks. */
|
||||
|
@ -1102,11 +1102,23 @@ prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg)
|
||||
{
|
||||
bool propagate_err = *(bool *)arg;
|
||||
|
||||
switch (tctx->state) {
|
||||
case prof_tctx_state_initializing:
|
||||
case prof_tctx_state_nominal:
|
||||
/* Not captured by this dump. */
|
||||
break;
|
||||
case prof_tctx_state_dumping:
|
||||
case prof_tctx_state_purgatory:
|
||||
if (prof_dump_printf(propagate_err,
|
||||
" t%"FMTu64": %"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]\n",
|
||||
tctx->thr_uid, tctx->dump_cnts.curobjs, tctx->dump_cnts.curbytes,
|
||||
tctx->dump_cnts.accumobjs, tctx->dump_cnts.accumbytes))
|
||||
" t%"FMTu64": %"FMTu64": %"FMTu64" [%"FMTu64": "
|
||||
"%"FMTu64"]\n", tctx->thr_uid, tctx->dump_cnts.curobjs,
|
||||
tctx->dump_cnts.curbytes, tctx->dump_cnts.accumobjs,
|
||||
tctx->dump_cnts.accumbytes))
|
||||
return (tctx);
|
||||
break;
|
||||
default:
|
||||
not_reached();
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,9 @@ tsd_cleanup(void *arg)
|
||||
tsd_t *tsd = (tsd_t *)arg;
|
||||
|
||||
switch (tsd->state) {
|
||||
case tsd_state_uninitialized:
|
||||
/* Do nothing. */
|
||||
break;
|
||||
case tsd_state_nominal:
|
||||
#define O(n, t) \
|
||||
n##_cleanup(tsd);
|
||||
|
260
contrib/libucl/CMakeLists.txt
Normal file
260
contrib/libucl/CMakeLists.txt
Normal file
@ -0,0 +1,260 @@
|
||||
PROJECT(libucl C)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR)
|
||||
|
||||
SET(LIBUCL_VERSION_MAJOR 0)
|
||||
SET(LIBUCL_VERSION_MINOR 5)
|
||||
SET(LIBUCL_VERSION_PATCH 0)
|
||||
|
||||
SET(LIBUCL_VERSION
|
||||
"${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}")
|
||||
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
INCLUDE(FindOpenSSL)
|
||||
|
||||
OPTION(ENABLE_URL_INCLUDE "Enable urls in ucl includes (requires libcurl or libfetch) [default: OFF]" OFF)
|
||||
OPTION(ENABLE_URL_SIGN "Enable signatures check in ucl includes (requires openssl) [default: OFF]" OFF)
|
||||
OPTION(BUILD_SHARED_LIBS "Build Shared Libraries [default: OFF]" OFF)
|
||||
OPTION(ENABLE_LUA "Enable lua support [default: OFF]" OFF)
|
||||
OPTION(ENABLE_LUAJIT "Enable luajit support [default: OFF]" OFF)
|
||||
|
||||
# Find lua installation
|
||||
MACRO(FindLua)
|
||||
# Find lua libraries
|
||||
UNSET(LUA_INCLUDE_DIR CACHE)
|
||||
UNSET(LUA_LIBRARY CACHE)
|
||||
CMAKE_PARSE_ARGUMENTS(LUA "" "VERSION_MAJOR;VERSION_MINOR;ROOT" "" ${ARGN})
|
||||
|
||||
IF(NOT LUA_VERSION_MAJOR OR NOT LUA_VERSION_MINOR)
|
||||
MESSAGE(FATAL_ERROR "Invalid FindLua invocation: ${ARGN}")
|
||||
ENDIF()
|
||||
|
||||
IF(ENABLE_LUAJIT MATCHES "ON")
|
||||
MESSAGE(STATUS "Check for luajit ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}")
|
||||
FIND_PATH(LUA_INCLUDE_DIR luajit.h
|
||||
HINTS
|
||||
"${RSPAMD_SEARCH_PATH}" "${LUA_ROOT}"
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES "include/luajit-2.0"
|
||||
"include/luajit${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"include/luajit${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"include/luajit-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"include/luajit"
|
||||
"include/lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"include/lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"include/lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
include/lua include
|
||||
PATHS ${RSPAMD_DEFAULT_INCLUDE_PATHS}
|
||||
)
|
||||
FIND_LIBRARY(LUA_LIBRARY
|
||||
NAMES luajit
|
||||
"luajit-2.0"
|
||||
"luajit2.0"
|
||||
"luajit${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"luajit${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"luajit-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
HINTS
|
||||
"${RSPAMD_SEARCH_PATH}" "${LUA_ROOT}"
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${RSPAMD_DEFAULT_LIBRARY_PATHS}
|
||||
DOC "Lua library"
|
||||
)
|
||||
|
||||
IF(NOT LUA_LIBRARY OR NOT LUA_INCLUDE_DIR)
|
||||
MESSAGE(STATUS "Fallback from luajit to plain lua")
|
||||
SET(ENABLE_LUAJIT "OFF")
|
||||
MESSAGE(STATUS "Check for lua ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}")
|
||||
FIND_PATH(LUA_INCLUDE_DIR lua.h
|
||||
HINTS
|
||||
"${RSPAMD_SEARCH_PATH}" "${LUA_ROOT}"
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES "include/lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"include/lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"include/lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
include/lua include
|
||||
PATHS ${RSPAMD_DEFAULT_INCLUDE_PATHS}
|
||||
)
|
||||
FIND_LIBRARY(LUA_LIBRARY
|
||||
NAMES lua
|
||||
"lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
HINTS
|
||||
"${RSPAMD_SEARCH_PATH}" "${LUA_ROOT}"
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${RSPAMD_DEFAULT_LIBRARY_PATHS}
|
||||
DOC "Lua library"
|
||||
)
|
||||
ENDIF()
|
||||
ELSE(ENABLE_LUAJIT MATCHES "ON")
|
||||
MESSAGE(STATUS "Check for lua ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}")
|
||||
FIND_PATH(LUA_INCLUDE_DIR lua.h
|
||||
HINTS
|
||||
"${RSPAMD_SEARCH_PATH}" "${LUA_ROOT}"
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES "include/lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"include/lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"include/lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
include/lua include
|
||||
PATHS ${RSPAMD_DEFAULT_INCLUDE_PATHS}
|
||||
)
|
||||
FIND_LIBRARY(LUA_LIBRARY
|
||||
NAMES lua
|
||||
"lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}"
|
||||
"lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
"lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}"
|
||||
HINTS
|
||||
"${RSPAMD_SEARCH_PATH}" "${LUA_ROOT}"
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${RSPAMD_DEFAULT_LIBRARY_PATHS}
|
||||
DOC "Lua library"
|
||||
)
|
||||
ENDIF(ENABLE_LUAJIT MATCHES "ON")
|
||||
|
||||
IF(LUA_LIBRARY AND LUA_INCLUDE_DIR)
|
||||
SET(LUA_FOUND 1)
|
||||
IF(NOT LUA_VERSION_MAJOR OR NOT LUA_VERSION_MINOR)
|
||||
SET(LUA_VERSION_MAJOR ${LUA_VERSION_MAJOR})
|
||||
SET(LUA_VERSION_MINOR ${LUA_VERSION_MINOR})
|
||||
ENDIF(NOT LUA_VERSION_MAJOR OR NOT LUA_VERSION_MINOR)
|
||||
IF(ENABLE_LUAJIT MATCHES "ON")
|
||||
MESSAGE(STATUS "Found luajit ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}")
|
||||
ELSE(ENABLE_LUAJIT MATCHES "ON")
|
||||
MESSAGE(STATUS "Found lua ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}")
|
||||
ENDIF(ENABLE_LUAJIT MATCHES "ON")
|
||||
ENDIF(LUA_LIBRARY AND LUA_INCLUDE_DIR)
|
||||
ENDMACRO()
|
||||
|
||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt)
|
||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
|
||||
IF(ENABLE_URL_INCLUDE MATCHES "ON")
|
||||
FIND_LIBRARY(LIBFETCH_LIBRARY NAMES fetch PATHS PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
DOC "Path where the libfetch library can be found")
|
||||
IF(LIBFETCH_LIBRARY)
|
||||
FIND_FILE(HAVE_FETCH_H NAMES fetch.h PATHS /usr/include
|
||||
/opt/include
|
||||
/usr/local/include
|
||||
DOC "Path to libfetch header")
|
||||
ELSE(LIBFETCH_LIBRARY)
|
||||
# Try to find libcurl
|
||||
ProcessPackage(CURL libcurl)
|
||||
IF(NOT CURL_FOUND)
|
||||
MESSAGE(WARNING "Neither libcurl nor libfetch were found, no support of URL includes in configuration")
|
||||
ENDIF(NOT CURL_FOUND)
|
||||
ENDIF(LIBFETCH_LIBRARY)
|
||||
ENDIF(ENABLE_URL_INCLUDE MATCHES "ON")
|
||||
|
||||
SET(CMAKE_C_WARN_FLAGS "")
|
||||
CHECK_C_COMPILER_FLAG(-Wall SUPPORT_WALL)
|
||||
CHECK_C_COMPILER_FLAG(-W SUPPORT_W)
|
||||
CHECK_C_COMPILER_FLAG(-Wno-unused-parameter SUPPORT_WPARAM)
|
||||
CHECK_C_COMPILER_FLAG(-Wno-pointer-sign SUPPORT_WPOINTER_SIGN)
|
||||
CHECK_C_COMPILER_FLAG(-Wstrict-prototypes SUPPORT_WSTRICT_PROTOTYPES)
|
||||
IF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES SunPro)
|
||||
CHECK_C_COMPILER_FLAG("-std=c99" SUPPORT_STD_FLAG)
|
||||
ENDIF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES SunPro)
|
||||
IF(SUPPORT_W)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -W")
|
||||
ENDIF(SUPPORT_W)
|
||||
IF(SUPPORT_WALL)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wall")
|
||||
ENDIF(SUPPORT_WALL)
|
||||
IF(SUPPORT_WPARAM)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wno-unused-parameter")
|
||||
ENDIF(SUPPORT_WPARAM)
|
||||
IF(SUPPORT_WPOINTER_SIGN)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wno-pointer-sign")
|
||||
ENDIF(SUPPORT_WPOINTER_SIGN)
|
||||
IF(SUPPORT_WSTRICT_PROTOTYPES)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wstrict-prototypes")
|
||||
ENDIF(SUPPORT_WSTRICT_PROTOTYPES)
|
||||
IF(SUPPORT_STD_FLAG)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -std=c99")
|
||||
ENDIF(SUPPORT_STD_FLAG)
|
||||
|
||||
IF(ENABLE_URL_SIGN MATCHES "ON")
|
||||
IF(OPENSSL_FOUND)
|
||||
SET(HAVE_OPENSSL 1)
|
||||
INCLUDE_DIRECTORIES("${OPENSSL_INCLUDE_DIR}")
|
||||
ENDIF(OPENSSL_FOUND)
|
||||
ENDIF(ENABLE_URL_SIGN MATCHES "ON")
|
||||
|
||||
INCLUDE_DIRECTORIES("src")
|
||||
INCLUDE_DIRECTORIES("include")
|
||||
INCLUDE_DIRECTORIES("uthash")
|
||||
INCLUDE_DIRECTORIES("klib")
|
||||
|
||||
SET(UCLSRC src/ucl_util.c
|
||||
src/ucl_parser.c
|
||||
src/ucl_emitter.c
|
||||
src/ucl_emitter_streamline.c
|
||||
src/ucl_emitter_utils.c
|
||||
src/ucl_hash.c
|
||||
src/ucl_schema.c
|
||||
src/ucl_msgpack.c
|
||||
src/ucl_sexp.c
|
||||
src/xxhash.c)
|
||||
|
||||
|
||||
SET (LIB_TYPE STATIC)
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
SET (LIB_TYPE SHARED)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
ADD_LIBRARY(ucl ${LIB_TYPE} ${UCLSRC})
|
||||
SET_TARGET_PROPERTIES(ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR})
|
||||
|
||||
IF(ENABLE_LUA MATCHES "ON")
|
||||
IF(ENABLE_LUAJIT MATCHES "ON")
|
||||
FindLua(VERSION_MAJOR "5" VERSION_MINOR "1" ROOT "${LUA_ROOT}")
|
||||
IF(NOT LUA_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Lua not found, lua support is required")
|
||||
ELSE(NOT LUA_FOUND)
|
||||
INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}")
|
||||
ENDIF(NOT LUA_FOUND)
|
||||
ELSE(ENABLE_LUAJIT MATCHES "ON")
|
||||
FindLua(VERSION_MAJOR "5" VERSION_MINOR "2" ROOT "${LUA_ROOT}")
|
||||
IF(NOT LUA_FOUND)
|
||||
FindLua(VERSION_MAJOR "5" VERSION_MINOR "1" ROOT "${LUA_ROOT}")
|
||||
ENDIF(NOT LUA_FOUND)
|
||||
IF(NOT LUA_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Lua not found, lua support is required")
|
||||
ELSE(NOT LUA_FOUND)
|
||||
INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}")
|
||||
ENDIF(NOT LUA_FOUND)
|
||||
ENDIF(ENABLE_LUAJIT MATCHES "ON")
|
||||
SET(UCL_LUA_SRC lua/lua_ucl.c)
|
||||
ADD_LIBRARY(lua-ucl ${LIB_TYPE} ${UCL_LUA_SRC})
|
||||
IF(ENABLE_LUAJIT MATCHES "ON")
|
||||
TARGET_LINK_LIBRARIES(lua-ucl "${LUAJIT_LIBRARY}")
|
||||
ELSE(ENABLE_LUAJIT MATCHES "ON")
|
||||
TARGET_LINK_LIBRARIES(lua-ucl "${LUA_LIBRARY}")
|
||||
ENDIF(ENABLE_LUAJIT MATCHES "ON")
|
||||
TARGET_LINK_LIBRARIES(lua-ucl ucl)
|
||||
SET_TARGET_PROPERTIES(lua-ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR})
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_FETCH_H)
|
||||
TARGET_LINK_LIBRARIES(ucl fetch)
|
||||
ELSE(HAVE_FETCH_H)
|
||||
IF(CURL_FOUND)
|
||||
TARGET_LINK_LIBRARIES(ucl ${CURL_LIBRARIES})
|
||||
ENDIF(CURL_FOUND)
|
||||
ENDIF(HAVE_FETCH_H)
|
||||
IF(ENABLE_URL_SIGN MATCHES "ON")
|
||||
IF(OPENSSL_FOUND)
|
||||
TARGET_LINK_LIBRARIES(ucl ${OPENSSL_LIBRARIES})
|
||||
ENDIF(OPENSSL_FOUND)
|
||||
ENDIF(ENABLE_URL_SIGN MATCHES "ON")
|
@ -32,3 +32,8 @@
|
||||
### Libucl 0.7.2
|
||||
|
||||
- Fixed serious bugs in schema and arrays iteration
|
||||
|
||||
### Libucl 0.7.3
|
||||
|
||||
- Fixed a bug with macroes that come after an empty object
|
||||
- Fixed a bug in include processing when an incorrect variable has been destroyed (use-after-free)
|
||||
|
@ -262,7 +262,20 @@ parser is created but before any configurations are parsed.
|
||||
all files that matches the specified pattern (normally the format of patterns is defined in `glob` manual page
|
||||
for your operating system). This option is meaningless for URL includes.
|
||||
* `url` (default: **true**) - allow URL includes.
|
||||
* `path` (default: empty) - A UCL_ARRAY of directories to search for the include file.
|
||||
Search ends after the first patch, unless `glob` is true, then all matches are included.
|
||||
* `prefix` (default false) - Put included contents inside an object, instead
|
||||
of loading them into the root. If no `key` is provided, one is automatically generated based on each files basename()
|
||||
* `key` (default: <empty string>) - Key to load contents of include into. If
|
||||
the key already exists, it must be the correct type
|
||||
* `target` (default: object) - Specify if the `prefix` `key` should be an
|
||||
object or an array.
|
||||
* `priority` (default: 0) - specify priority for the include (see below).
|
||||
* `duplicate` (default: 'append') - specify policy of duplicates resolving:
|
||||
- `append` - default strategy, if we have new object of higher priority then it replaces old one, if we have new object with less priority it is ignored completely, and if we have two duplicate objects with the same priority then we have a multi-value key (implicit array)
|
||||
- `merge` - if we have object or array, then new keys are merged inside, if we have a plain object then an implicit array is formed (regardeless of priorities)
|
||||
- `error` - create error on duplicate keys and stop parsing
|
||||
- `rewrite` - always rewrite an old value with new one (ignoring priorities)
|
||||
|
||||
Priorities are used by UCL parser to manage the policy of objects rewriting during including other files
|
||||
as following:
|
||||
|
@ -1,127 +0,0 @@
|
||||
PROJECT(libucl C)
|
||||
|
||||
SET(LIBUCL_VERSION_MAJOR 0)
|
||||
SET(LIBUCL_VERSION_MINOR 5)
|
||||
SET(LIBUCL_VERSION_PATCH 0)
|
||||
|
||||
SET(LIBUCL_VERSION "${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}")
|
||||
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
INCLUDE(FindOpenSSL)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR)
|
||||
|
||||
OPTION(ENABLE_URL_INCLUDE "Enable urls in ucl includes (requires libcurl or libfetch) [default: OFF]" OFF)
|
||||
OPTION(ENABLE_URL_SIGN "Enable signatures check in ucl includes (requires openssl) [default: OFF]" OFF)
|
||||
OPTION(BUILD_SHARED_LIBS "Build Shared Libraries [default: OFF]" OFF)
|
||||
|
||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt)
|
||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
|
||||
IF(ENABLE_URL_INCLUDE MATCHES "ON")
|
||||
FIND_LIBRARY(LIBFETCH_LIBRARY NAMES fetch PATHS PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
DOC "Path where the libfetch library can be found")
|
||||
IF(LIBFETCH_LIBRARY)
|
||||
FIND_FILE(HAVE_FETCH_H NAMES fetch.h PATHS /usr/include
|
||||
/opt/include
|
||||
/usr/local/include
|
||||
DOC "Path to libfetch header")
|
||||
ELSE(LIBFETCH_LIBRARY)
|
||||
# Try to find libcurl
|
||||
ProcessPackage(CURL libcurl)
|
||||
IF(NOT CURL_FOUND)
|
||||
MESSAGE(WARNING "Neither libcurl nor libfetch were found, no support of URL includes in configuration")
|
||||
ENDIF(NOT CURL_FOUND)
|
||||
ENDIF(LIBFETCH_LIBRARY)
|
||||
ENDIF(ENABLE_URL_INCLUDE MATCHES "ON")
|
||||
|
||||
SET(CMAKE_C_WARN_FLAGS "")
|
||||
CHECK_C_COMPILER_FLAG(-Wall SUPPORT_WALL)
|
||||
CHECK_C_COMPILER_FLAG(-W SUPPORT_W)
|
||||
CHECK_C_COMPILER_FLAG(-Wno-unused-parameter SUPPORT_WPARAM)
|
||||
CHECK_C_COMPILER_FLAG(-Wno-pointer-sign SUPPORT_WPOINTER_SIGN)
|
||||
CHECK_C_COMPILER_FLAG(-Wstrict-prototypes SUPPORT_WSTRICT_PROTOTYPES)
|
||||
IF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES SunPro)
|
||||
CHECK_C_COMPILER_FLAG("-std=c99" SUPPORT_STD_FLAG)
|
||||
ENDIF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES SunPro)
|
||||
IF(SUPPORT_W)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -W")
|
||||
ENDIF(SUPPORT_W)
|
||||
IF(SUPPORT_WALL)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wall")
|
||||
ENDIF(SUPPORT_WALL)
|
||||
IF(SUPPORT_WPARAM)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wno-unused-parameter")
|
||||
ENDIF(SUPPORT_WPARAM)
|
||||
IF(SUPPORT_WPOINTER_SIGN)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wno-pointer-sign")
|
||||
ENDIF(SUPPORT_WPOINTER_SIGN)
|
||||
IF(SUPPORT_WSTRICT_PROTOTYPES)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wstrict-prototypes")
|
||||
ENDIF(SUPPORT_WSTRICT_PROTOTYPES)
|
||||
IF(SUPPORT_STD_FLAG)
|
||||
SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -std=c99")
|
||||
ENDIF(SUPPORT_STD_FLAG)
|
||||
|
||||
IF(ENABLE_URL_SIGN MATCHES "ON")
|
||||
IF(OPENSSL_FOUND)
|
||||
SET(HAVE_OPENSSL 1)
|
||||
INCLUDE_DIRECTORIES("${OPENSSL_INCLUDE_DIR}")
|
||||
ENDIF(OPENSSL_FOUND)
|
||||
ENDIF(ENABLE_URL_SIGN MATCHES "ON")
|
||||
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../src")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../uthash")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../klib")
|
||||
|
||||
SET(UCLSRC ../src/ucl_util.c
|
||||
../src/ucl_parser.c
|
||||
../src/ucl_emitter.c
|
||||
../src/ucl_emitter_streamline.c
|
||||
../src/ucl_emitter_utils.c
|
||||
../src/ucl_hash.c
|
||||
../src/ucl_schema.c
|
||||
../src/xxhash.c)
|
||||
|
||||
|
||||
SET (LIB_TYPE STATIC)
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
SET (LIB_TYPE SHARED)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
ADD_LIBRARY(ucl ${LIB_TYPE} ${UCLSRC})
|
||||
SET_TARGET_PROPERTIES(ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR})
|
||||
|
||||
IF(WITH_LUA)
|
||||
SET(UCL_LUA_SRC ../lua/lua_ucl.c)
|
||||
ADD_LIBRARY(lua-ucl ${LIB_TYPE} ${UCL_LUA_SRC})
|
||||
IF(ENABLE_LUAJIT MATCHES "ON")
|
||||
TARGET_LINK_LIBRARIES(lua-ucl "${LUAJIT_LIBRARY}")
|
||||
ELSE(ENABLE_LUAJIT MATCHES "ON")
|
||||
TARGET_LINK_LIBRARIES(lua-ucl "${LUA_LIBRARY}")
|
||||
ENDIF(ENABLE_LUAJIT MATCHES "ON")
|
||||
TARGET_LINK_LIBRARIES(lua-ucl ucl)
|
||||
SET_TARGET_PROPERTIES(lua-ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR})
|
||||
ENDIF(WITH_LUA)
|
||||
|
||||
IF(HAVE_FETCH_H)
|
||||
TARGET_LINK_LIBRARIES(ucl fetch)
|
||||
ELSE(HAVE_FETCH_H)
|
||||
IF(CURL_FOUND)
|
||||
TARGET_LINK_LIBRARIES(ucl ${CURL_LIBRARIES})
|
||||
ENDIF(CURL_FOUND)
|
||||
ENDIF(HAVE_FETCH_H)
|
||||
IF(ENABLE_URL_SIGN MATCHES "ON")
|
||||
IF(OPENSSL_FOUND)
|
||||
TARGET_LINK_LIBRARIES(ucl ${OPENSSL_LIBRARIES})
|
||||
ENDIF(OPENSSL_FOUND)
|
||||
ENDIF(ENABLE_URL_SIGN MATCHES "ON")
|
@ -1,7 +1,7 @@
|
||||
m4_define([maj_ver], [0])
|
||||
m4_define([med_ver], [7])
|
||||
m4_define([min_ver], [2])
|
||||
m4_define([so_version], [5:0:1])
|
||||
m4_define([min_ver], [3])
|
||||
m4_define([so_version], [5:0:2])
|
||||
m4_define([ucl_version], [maj_ver.med_ver.min_ver])
|
||||
|
||||
AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])
|
||||
@ -47,6 +47,7 @@ AC_CHECK_HEADERS_ONCE([libgen.h])
|
||||
AC_CHECK_HEADERS_ONCE([stdio.h])
|
||||
AC_CHECK_HEADERS_ONCE([float.h])
|
||||
AC_CHECK_HEADERS_ONCE([math.h])
|
||||
AC_CHECK_HEADERS_ONCE([endian.h sys/endian.h machine/endian.h])
|
||||
|
||||
dnl Example of default-disabled feature
|
||||
AC_ARG_ENABLE([urls], AS_HELP_STRING([--enable-urls],
|
||||
|
@ -16,7 +16,7 @@ if not res then
|
||||
else
|
||||
local obj = parser:get_object()
|
||||
local got = ucl.to_format(obj, 'json')
|
||||
endif
|
||||
end
|
||||
|
||||
local table = {
|
||||
str = 'value',
|
||||
@ -25,6 +25,7 @@ local table = {
|
||||
func = function ()
|
||||
return 'huh'
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
print(ucl.to_format(table, 'ucl'))
|
||||
@ -115,6 +116,7 @@ local table = {
|
||||
func = function ()
|
||||
return 'huh'
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
print(ucl.to_format(table, 'ucl'))
|
||||
|
26
contrib/libucl/examples/ucl_cpp.cc
Normal file
26
contrib/libucl/examples/ucl_cpp.cc
Normal file
@ -0,0 +1,26 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ucl++.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::string input, err;
|
||||
|
||||
input.assign((std::istreambuf_iterator<char>(std::cin)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
auto obj = ucl::Ucl::parse(input, err);
|
||||
|
||||
if (obj) {
|
||||
std::cout << obj.dump(UCL_EMIT_CONFIG) << std::endl;
|
||||
|
||||
for (const auto &o : obj) {
|
||||
std::cout << o.dump(UCL_EMIT_CONFIG) << std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error: " << err << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
422
contrib/libucl/include/ucl++.h
Normal file
422
contrib/libucl/include/ucl++.h
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Vsevolod Stakhov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <strstream>
|
||||
|
||||
#include "ucl.h"
|
||||
|
||||
// C++11 API inspired by json11: https://github.com/dropbox/json11/
|
||||
|
||||
namespace ucl {
|
||||
|
||||
struct ucl_map_construct_t { };
|
||||
constexpr ucl_map_construct_t ucl_map_construct = ucl_map_construct_t();
|
||||
struct ucl_array_construct_t { };
|
||||
constexpr ucl_array_construct_t ucl_array_construct = ucl_array_construct_t();
|
||||
|
||||
class Ucl final {
|
||||
private:
|
||||
|
||||
struct ucl_deleter {
|
||||
void operator() (ucl_object_t *obj) {
|
||||
ucl_object_unref (obj);
|
||||
}
|
||||
};
|
||||
|
||||
static int
|
||||
append_char (unsigned char c, size_t nchars, void *ud)
|
||||
{
|
||||
std::string *out = reinterpret_cast<std::string *>(ud);
|
||||
|
||||
out->append (nchars, (char)c);
|
||||
|
||||
return nchars;
|
||||
}
|
||||
static int
|
||||
append_len (unsigned const char *str, size_t len, void *ud)
|
||||
{
|
||||
std::string *out = reinterpret_cast<std::string *>(ud);
|
||||
|
||||
out->append ((const char *)str, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
static int
|
||||
append_int (int64_t elt, void *ud)
|
||||
{
|
||||
std::string *out = reinterpret_cast<std::string *>(ud);
|
||||
auto nstr = std::to_string (elt);
|
||||
|
||||
out->append (nstr);
|
||||
|
||||
return nstr.size ();
|
||||
}
|
||||
static int
|
||||
append_double (double elt, void *ud)
|
||||
{
|
||||
std::string *out = reinterpret_cast<std::string *>(ud);
|
||||
auto nstr = std::to_string (elt);
|
||||
|
||||
out->append (nstr);
|
||||
|
||||
return nstr.size ();
|
||||
}
|
||||
|
||||
static struct ucl_emitter_functions default_emit_funcs()
|
||||
{
|
||||
struct ucl_emitter_functions func = {
|
||||
Ucl::append_char,
|
||||
Ucl::append_len,
|
||||
Ucl::append_int,
|
||||
Ucl::append_double,
|
||||
nullptr,
|
||||
nullptr
|
||||
};
|
||||
|
||||
return func;
|
||||
};
|
||||
|
||||
std::unique_ptr<ucl_object_t, ucl_deleter> obj;
|
||||
|
||||
public:
|
||||
class const_iterator {
|
||||
private:
|
||||
struct ucl_iter_deleter {
|
||||
void operator() (ucl_object_iter_t it) {
|
||||
ucl_object_iterate_free (it);
|
||||
}
|
||||
};
|
||||
std::shared_ptr<void> it;
|
||||
std::unique_ptr<Ucl> cur;
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
const_iterator(const Ucl &obj) {
|
||||
it = std::shared_ptr<void>(ucl_object_iterate_new (obj.obj.get()),
|
||||
ucl_iter_deleter());
|
||||
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
|
||||
}
|
||||
|
||||
const_iterator() {}
|
||||
const_iterator(const const_iterator &other) {
|
||||
it = other.it;
|
||||
}
|
||||
~const_iterator() {}
|
||||
|
||||
const_iterator& operator=(const const_iterator &other) {
|
||||
it = other.it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const const_iterator &other) const
|
||||
{
|
||||
if (cur && other.cur) {
|
||||
return cur->obj.get() == other.cur->obj.get();
|
||||
}
|
||||
|
||||
return !cur && !other.cur;
|
||||
}
|
||||
|
||||
bool operator!=(const const_iterator &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const_iterator& operator++()
|
||||
{
|
||||
if (it) {
|
||||
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
|
||||
}
|
||||
|
||||
if (!*cur) {
|
||||
it.reset ();
|
||||
cur.reset ();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Ucl& operator*() const
|
||||
{
|
||||
return *cur;
|
||||
}
|
||||
const Ucl* operator->() const
|
||||
{
|
||||
return cur.get();
|
||||
}
|
||||
};
|
||||
|
||||
// We grab ownership if get non-const ucl_object_t
|
||||
Ucl(ucl_object_t *other) {
|
||||
obj.reset (other);
|
||||
}
|
||||
|
||||
// Shared ownership
|
||||
Ucl(const ucl_object_t *other) {
|
||||
obj.reset (ucl_object_ref (other));
|
||||
}
|
||||
|
||||
Ucl(const Ucl &other) {
|
||||
obj.reset (ucl_object_ref (other.obj.get()));
|
||||
}
|
||||
|
||||
Ucl(Ucl &&other) {
|
||||
obj.swap (other.obj);
|
||||
}
|
||||
|
||||
Ucl() noexcept {
|
||||
obj.reset (ucl_object_typed_new (UCL_NULL));
|
||||
}
|
||||
Ucl(std::nullptr_t) noexcept {
|
||||
obj.reset (ucl_object_typed_new (UCL_NULL));
|
||||
}
|
||||
Ucl(double value) {
|
||||
obj.reset (ucl_object_typed_new (UCL_FLOAT));
|
||||
obj->value.dv = value;
|
||||
}
|
||||
Ucl(int64_t value) {
|
||||
obj.reset (ucl_object_typed_new (UCL_INT));
|
||||
obj->value.iv = value;
|
||||
}
|
||||
Ucl(bool value) {
|
||||
obj.reset (ucl_object_typed_new (UCL_BOOLEAN));
|
||||
obj->value.iv = static_cast<int64_t>(value);
|
||||
}
|
||||
Ucl(const std::string &value) {
|
||||
obj.reset (ucl_object_fromstring_common (value.data (), value.size (),
|
||||
UCL_STRING_RAW));
|
||||
}
|
||||
Ucl(const char * value) {
|
||||
obj.reset (ucl_object_fromstring_common (value, 0, UCL_STRING_RAW));
|
||||
}
|
||||
|
||||
// Implicit constructor: anything with a to_json() function.
|
||||
template <class T, class = decltype(&T::to_ucl)>
|
||||
Ucl(const T & t) : Ucl(t.to_ucl()) {}
|
||||
|
||||
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
|
||||
template <class M, typename std::enable_if<
|
||||
std::is_constructible<std::string, typename M::key_type>::value
|
||||
&& std::is_constructible<Ucl, typename M::mapped_type>::value,
|
||||
int>::type = 0>
|
||||
Ucl(const M & m) {
|
||||
obj.reset (ucl_object_typed_new (UCL_OBJECT));
|
||||
auto cobj = obj.get ();
|
||||
|
||||
for (const auto &e : m) {
|
||||
ucl_object_insert_key (cobj, ucl_object_ref (e.second.obj.get()),
|
||||
e.first.data (), e.first.size (), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
|
||||
template <class V, typename std::enable_if<
|
||||
std::is_constructible<Ucl, typename V::value_type>::value,
|
||||
int>::type = 0>
|
||||
Ucl(const V & v) {
|
||||
obj.reset (ucl_object_typed_new (UCL_ARRAY));
|
||||
auto cobj = obj.get ();
|
||||
|
||||
for (const auto &e : v) {
|
||||
ucl_array_append (cobj, ucl_object_ref (e.obj.get()));
|
||||
}
|
||||
}
|
||||
|
||||
ucl_type_t type () const {
|
||||
if (obj) {
|
||||
return ucl_object_type (obj.get ());
|
||||
}
|
||||
return UCL_NULL;
|
||||
}
|
||||
|
||||
const std::string key () const {
|
||||
std::string res;
|
||||
|
||||
if (obj->key) {
|
||||
res.assign (obj->key, obj->keylen);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
double number_value () const
|
||||
{
|
||||
if (obj) {
|
||||
return ucl_object_todouble (obj.get());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int64_t int_value () const
|
||||
{
|
||||
if (obj) {
|
||||
return ucl_object_toint (obj.get());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bool_value () const
|
||||
{
|
||||
if (obj) {
|
||||
return ucl_object_toboolean (obj.get());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string string_value () const
|
||||
{
|
||||
std::string res;
|
||||
|
||||
if (obj) {
|
||||
res.assign (ucl_object_tostring (obj.get()));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const Ucl operator[] (size_t i) const
|
||||
{
|
||||
if (type () == UCL_ARRAY) {
|
||||
return Ucl (ucl_array_find_index (obj.get(), i));
|
||||
}
|
||||
|
||||
return Ucl (nullptr);
|
||||
}
|
||||
|
||||
const Ucl operator[](const std::string &key) const
|
||||
{
|
||||
if (type () == UCL_OBJECT) {
|
||||
return Ucl (ucl_object_find_keyl (obj.get(),
|
||||
key.data (), key.size ()));
|
||||
}
|
||||
|
||||
return Ucl (nullptr);
|
||||
}
|
||||
// Serialize.
|
||||
void dump (std::string &out, ucl_emitter_t type = UCL_EMIT_JSON) const
|
||||
{
|
||||
struct ucl_emitter_functions cbdata;
|
||||
|
||||
cbdata = Ucl::default_emit_funcs();
|
||||
cbdata.ud = reinterpret_cast<void *>(&out);
|
||||
|
||||
ucl_object_emit_full (obj.get(), type, &cbdata);
|
||||
}
|
||||
|
||||
std::string dump (ucl_emitter_t type = UCL_EMIT_JSON) const
|
||||
{
|
||||
std::string out;
|
||||
|
||||
dump (out, type);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static Ucl parse (const std::string & in, std::string & err)
|
||||
{
|
||||
auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
|
||||
|
||||
if (!ucl_parser_add_chunk (parser, (const unsigned char *)in.data (),
|
||||
in.size ())) {
|
||||
err.assign (ucl_parser_get_error (parser));
|
||||
ucl_parser_free (parser);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto obj = ucl_parser_get_object (parser);
|
||||
ucl_parser_free (parser);
|
||||
|
||||
// Obj will handle ownership
|
||||
return Ucl (obj);
|
||||
}
|
||||
|
||||
static Ucl parse (const char * in, std::string & err)
|
||||
{
|
||||
if (in) {
|
||||
return parse (std::string(in), err);
|
||||
} else {
|
||||
err = "null input";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static Ucl parse (std::istream &ifs, std::string &err)
|
||||
{
|
||||
return Ucl::parse (std::string(std::istreambuf_iterator<char>(ifs),
|
||||
std::istreambuf_iterator<char>()), err);
|
||||
}
|
||||
|
||||
bool operator== (const Ucl &rhs) const
|
||||
{
|
||||
return ucl_object_compare (obj.get(), rhs.obj.get ()) == 0;
|
||||
}
|
||||
bool operator< (const Ucl &rhs) const
|
||||
{
|
||||
return ucl_object_compare (obj.get(), rhs.obj.get ()) < 0;
|
||||
}
|
||||
bool operator!= (const Ucl &rhs) const { return !(*this == rhs); }
|
||||
bool operator<= (const Ucl &rhs) const { return !(rhs < *this); }
|
||||
bool operator> (const Ucl &rhs) const { return (rhs < *this); }
|
||||
bool operator>= (const Ucl &rhs) const { return !(*this < rhs); }
|
||||
|
||||
operator bool () const
|
||||
{
|
||||
if (!obj || type() == UCL_NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type () == UCL_BOOLEAN) {
|
||||
return bool_value ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(*this);
|
||||
}
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(*this);
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2013, Vsevolod Stakhov
|
||||
/* Copyright (c) 2013-2015, Vsevolod Stakhov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -135,7 +135,9 @@ typedef enum ucl_emitter {
|
||||
UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */
|
||||
UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */
|
||||
UCL_EMIT_CONFIG, /**< Emit human readable config format */
|
||||
UCL_EMIT_YAML /**< Emit embedded YAML format */
|
||||
UCL_EMIT_YAML, /**< Emit embedded YAML format */
|
||||
UCL_EMIT_MSGPACK, /**< Emit msgpack output */
|
||||
UCL_EMIT_MAX /**< Unsupported emitter type */
|
||||
} ucl_emitter_t;
|
||||
|
||||
/**
|
||||
@ -145,6 +147,7 @@ typedef enum ucl_emitter {
|
||||
* UCL still has to perform copying implicitly.
|
||||
*/
|
||||
typedef enum ucl_parser_flags {
|
||||
UCL_PARSER_DEFAULT = 0x0, /**< No special flags */
|
||||
UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */
|
||||
UCL_PARSER_ZEROCOPY = 0x2, /**< Parse input in zero-copy mode if possible */
|
||||
UCL_PARSER_NO_TIME = 0x4, /**< Do not parse time and treat time values as strings */
|
||||
@ -155,6 +158,7 @@ typedef enum ucl_parser_flags {
|
||||
* String conversion flags, that are used in #ucl_object_fromstring_common function.
|
||||
*/
|
||||
typedef enum ucl_string_flags {
|
||||
UCL_STRING_RAW = 0x0, /**< Treat string as is */
|
||||
UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */
|
||||
UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */
|
||||
UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */
|
||||
@ -172,14 +176,35 @@ typedef enum ucl_string_flags {
|
||||
* Basic flags for an object
|
||||
*/
|
||||
typedef enum ucl_object_flags {
|
||||
UCL_OBJECT_ALLOCATED_KEY = 0x1, /**< An object has key allocated internally */
|
||||
UCL_OBJECT_ALLOCATED_VALUE = 0x2, /**< An object has a string value allocated internally */
|
||||
UCL_OBJECT_NEED_KEY_ESCAPE = 0x4, /**< The key of an object need to be escaped on output */
|
||||
UCL_OBJECT_EPHEMERAL = 0x8, /**< Temporary object that does not need to be freed really */
|
||||
UCL_OBJECT_MULTILINE = 0x10, /**< String should be displayed as multiline string */
|
||||
UCL_OBJECT_MULTIVALUE = 0x20 /**< Object is a key with multiple values */
|
||||
UCL_OBJECT_ALLOCATED_KEY = (1 << 0), /**< An object has key allocated internally */
|
||||
UCL_OBJECT_ALLOCATED_VALUE = (1 << 1), /**< An object has a string value allocated internally */
|
||||
UCL_OBJECT_NEED_KEY_ESCAPE = (1 << 2), /**< The key of an object need to be escaped on output */
|
||||
UCL_OBJECT_EPHEMERAL = (1 << 3), /**< Temporary object that does not need to be freed really */
|
||||
UCL_OBJECT_MULTILINE = (1 << 4), /**< String should be displayed as multiline string */
|
||||
UCL_OBJECT_MULTIVALUE = (1 << 5), /**< Object is a key with multiple values */
|
||||
UCL_OBJECT_INHERITED = (1 << 6), /**< Object has been inherited from another */
|
||||
UCL_OBJECT_BINARY = (1 << 7) /**< Object contains raw binary data */
|
||||
} ucl_object_flags_t;
|
||||
|
||||
/**
|
||||
* Duplicate policy types
|
||||
*/
|
||||
enum ucl_duplicate_strategy {
|
||||
UCL_DUPLICATE_APPEND = 0, /**< Default policy to merge based on priorities */
|
||||
UCL_DUPLICATE_MERGE, /**< Merge new object with old one */
|
||||
UCL_DUPLICATE_REWRITE, /**< Rewrite old keys */
|
||||
UCL_DUPLICATE_ERROR /**< Stop parsing on duplicate found */
|
||||
};
|
||||
|
||||
/**
|
||||
* Input format type
|
||||
*/
|
||||
enum ucl_parse_type {
|
||||
UCL_PARSE_UCL = 0, /**< Default ucl format */
|
||||
UCL_PARSE_MSGPACK, /**< Message pack input format */
|
||||
UCL_PARSE_CSEXP /**< Canonical S-expressions */
|
||||
};
|
||||
|
||||
/**
|
||||
* UCL object structure. Please mention that the most of fields should not be touched by
|
||||
* UCL users. In future, this structure may be converted to private one.
|
||||
@ -495,6 +520,15 @@ UCL_EXTERN ucl_object_t* ucl_array_pop_first (ucl_object_t *top);
|
||||
UCL_EXTERN const ucl_object_t* ucl_array_find_index (const ucl_object_t *top,
|
||||
unsigned int index);
|
||||
|
||||
/**
|
||||
* Return the index of `elt` in the array `top`
|
||||
* @param top object to get a key from (must be of type UCL_ARRAY)
|
||||
* @param elt element to find index of (must NOT be NULL)
|
||||
* @return index of `elt` in the array `top or (unsigned int)-1 if `elt` is not found
|
||||
*/
|
||||
UCL_EXTERN unsigned int ucl_array_index_of (ucl_object_t *top,
|
||||
ucl_object_t *elt);
|
||||
|
||||
/**
|
||||
* Replace an element in an array with a different element, returning the object
|
||||
* that was replaced. This object is not released, caller must unref the
|
||||
@ -611,6 +645,19 @@ UCL_EXTERN const char* ucl_object_tolstring (const ucl_object_t *obj, size_t *tl
|
||||
UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj,
|
||||
const char *key);
|
||||
|
||||
/**
|
||||
* Return object identified by a key in the specified object, if the first key is
|
||||
* not found then look for the next one. This process is repeated unless
|
||||
* the next argument in the list is not NULL. So, `ucl_object_find_any_key(obj, key, NULL)`
|
||||
* is equal to `ucl_object_find_key(obj, key)`
|
||||
* @param obj object to get a key from (must be of type UCL_OBJECT)
|
||||
* @param key key to search
|
||||
* @param ... list of alternative keys to search (NULL terminated)
|
||||
* @return object matching the specified key or NULL if key was not found
|
||||
*/
|
||||
UCL_EXTERN const ucl_object_t* ucl_object_find_any_key (const ucl_object_t *obj,
|
||||
const char *key, ...);
|
||||
|
||||
/**
|
||||
* Return object identified by a fixed size key in the specified object
|
||||
* @param obj object to get a key from (must be of type UCL_OBJECT)
|
||||
@ -630,6 +677,16 @@ UCL_EXTERN const ucl_object_t* ucl_object_find_keyl (const ucl_object_t *obj,
|
||||
UCL_EXTERN const ucl_object_t *ucl_lookup_path (const ucl_object_t *obj,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Return object identified by object notation string using arbitrary delimiter
|
||||
* @param obj object to search in
|
||||
* @param path dot.notation.path to the path to lookup. May use numeric .index on arrays
|
||||
* @param sep the sepatorator to use in place of . (incase keys have . in them)
|
||||
* @return object matched the specified path or NULL if path is not found
|
||||
*/
|
||||
UCL_EXTERN const ucl_object_t *ucl_lookup_path_char (const ucl_object_t *obj,
|
||||
const char *path, char sep);
|
||||
|
||||
/**
|
||||
* Returns a key of an object as a NULL terminated string
|
||||
* @param obj CL object
|
||||
@ -683,7 +740,7 @@ UCL_EXTERN int ucl_object_compare (const ucl_object_t *o1,
|
||||
* @param cmp
|
||||
*/
|
||||
UCL_EXTERN void ucl_object_array_sort (ucl_object_t *ar,
|
||||
int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2));
|
||||
int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2));
|
||||
|
||||
/**
|
||||
* Get the priority for specific UCL object
|
||||
@ -769,6 +826,21 @@ typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *arguments,
|
||||
void* ud);
|
||||
|
||||
/**
|
||||
* Context dependent macro handler for a parser
|
||||
* @param data the content of macro
|
||||
* @param len the length of content
|
||||
* @param arguments arguments object
|
||||
* @param context previously parsed context
|
||||
* @param ud opaque user data
|
||||
* @param err error pointer
|
||||
* @return true if macro has been parsed
|
||||
*/
|
||||
typedef bool (*ucl_context_macro_handler) (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *arguments,
|
||||
const ucl_object_t *context,
|
||||
void* ud);
|
||||
|
||||
/* Opaque parser */
|
||||
struct ucl_parser;
|
||||
|
||||
@ -779,6 +851,15 @@ struct ucl_parser;
|
||||
*/
|
||||
UCL_EXTERN struct ucl_parser* ucl_parser_new (int flags);
|
||||
|
||||
/**
|
||||
* Sets the default priority for the parser applied to chunks that does not
|
||||
* specify priority explicitly
|
||||
* @param parser parser object
|
||||
* @param prio default priority (0 .. 16)
|
||||
* @return true if parser's default priority was set
|
||||
*/
|
||||
UCL_EXTERN bool ucl_parser_set_default_priority (struct ucl_parser *parser,
|
||||
unsigned prio);
|
||||
/**
|
||||
* Register new handler for a macro
|
||||
* @param parser parser object
|
||||
@ -786,9 +867,22 @@ UCL_EXTERN struct ucl_parser* ucl_parser_new (int flags);
|
||||
* @param handler handler (it is called immediately after macro is parsed)
|
||||
* @param ud opaque user data for a handler
|
||||
*/
|
||||
UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
|
||||
UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
|
||||
const char *macro,
|
||||
ucl_macro_handler handler, void* ud);
|
||||
|
||||
/**
|
||||
* Register new context dependent handler for a macro
|
||||
* @param parser parser object
|
||||
* @param macro macro name (without leading dot)
|
||||
* @param handler handler (it is called immediately after macro is parsed)
|
||||
* @param ud opaque user data for a handler
|
||||
*/
|
||||
UCL_EXTERN void ucl_parser_register_context_macro (struct ucl_parser *parser,
|
||||
const char *macro,
|
||||
ucl_context_macro_handler handler,
|
||||
void* ud);
|
||||
|
||||
/**
|
||||
* Handler to detect unregistered variables
|
||||
* @param data variable data
|
||||
@ -842,6 +936,21 @@ UCL_EXTERN bool ucl_parser_add_chunk (struct ucl_parser *parser,
|
||||
UCL_EXTERN bool ucl_parser_add_chunk_priority (struct ucl_parser *parser,
|
||||
const unsigned char *data, size_t len, unsigned priority);
|
||||
|
||||
/**
|
||||
* Full version of ucl_add_chunk with priority and duplicate strategy
|
||||
* @param parser parser structure
|
||||
* @param data the pointer to the beginning of a chunk
|
||||
* @param len the length of a chunk
|
||||
* @param priority the desired priority of a chunk (only 4 least significant bits
|
||||
* are considered for this parameter)
|
||||
* @param strat duplicates merging strategy
|
||||
* @param parse_type input format
|
||||
* @return true if chunk has been added and false in case of error
|
||||
*/
|
||||
UCL_EXTERN bool ucl_parser_add_chunk_full (struct ucl_parser *parser,
|
||||
const unsigned char *data, size_t len, unsigned priority,
|
||||
enum ucl_duplicate_strategy strat, enum ucl_parse_type parse_type);
|
||||
|
||||
/**
|
||||
* Load ucl object from a string
|
||||
* @param parser parser structure
|
||||
@ -852,6 +961,18 @@ UCL_EXTERN bool ucl_parser_add_chunk_priority (struct ucl_parser *parser,
|
||||
UCL_EXTERN bool ucl_parser_add_string (struct ucl_parser *parser,
|
||||
const char *data,size_t len);
|
||||
|
||||
/**
|
||||
* Load ucl object from a string
|
||||
* @param parser parser structure
|
||||
* @param data the pointer to the string
|
||||
* @param len the length of the string, if `len` is 0 then `data` must be zero-terminated string
|
||||
* @param priority the desired priority of a chunk (only 4 least significant bits
|
||||
* are considered for this parameter)
|
||||
* @return true if string has been added and false in case of error
|
||||
*/
|
||||
UCL_EXTERN bool ucl_parser_add_string_priority (struct ucl_parser *parser,
|
||||
const char *data, size_t len, unsigned priority);
|
||||
|
||||
/**
|
||||
* Load and add data from a file
|
||||
* @param parser parser structure
|
||||
@ -862,6 +983,18 @@ UCL_EXTERN bool ucl_parser_add_string (struct ucl_parser *parser,
|
||||
UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser,
|
||||
const char *filename);
|
||||
|
||||
/**
|
||||
* Load and add data from a file
|
||||
* @param parser parser structure
|
||||
* @param filename the name of file
|
||||
* @param err if *err is NULL it is set to parser error
|
||||
* @param priority the desired priority of a chunk (only 4 least significant bits
|
||||
* are considered for this parameter)
|
||||
* @return true if chunk has been added and false in case of error
|
||||
*/
|
||||
UCL_EXTERN bool ucl_parser_add_file_priority (struct ucl_parser *parser,
|
||||
const char *filename, unsigned priority);
|
||||
|
||||
/**
|
||||
* Load and add data from a file descriptor
|
||||
* @param parser parser structure
|
||||
@ -872,6 +1005,28 @@ UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser,
|
||||
UCL_EXTERN bool ucl_parser_add_fd (struct ucl_parser *parser,
|
||||
int fd);
|
||||
|
||||
/**
|
||||
* Load and add data from a file descriptor
|
||||
* @param parser parser structure
|
||||
* @param filename the name of file
|
||||
* @param err if *err is NULL it is set to parser error
|
||||
* @param priority the desired priority of a chunk (only 4 least significant bits
|
||||
* are considered for this parameter)
|
||||
* @return true if chunk has been added and false in case of error
|
||||
*/
|
||||
UCL_EXTERN bool ucl_parser_add_fd_priority (struct ucl_parser *parser,
|
||||
int fd, unsigned priority);
|
||||
|
||||
/**
|
||||
* Provide a UCL_ARRAY of paths to search for include files. The object is
|
||||
* copied so caller must unref the object.
|
||||
* @param parser parser structure
|
||||
* @param paths UCL_ARRAY of paths to search
|
||||
* @return true if the path search array was replaced in the parser
|
||||
*/
|
||||
UCL_EXTERN bool ucl_set_include_path (struct ucl_parser *parser,
|
||||
ucl_object_t *paths);
|
||||
|
||||
/**
|
||||
* Get a top object for a parser (refcount is increased)
|
||||
* @param parser parser structure
|
||||
@ -881,11 +1036,33 @@ UCL_EXTERN bool ucl_parser_add_fd (struct ucl_parser *parser,
|
||||
UCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser);
|
||||
|
||||
/**
|
||||
* Get the error string if failing
|
||||
* Get the error string if parsing has been failed
|
||||
* @param parser parser object
|
||||
* @return error description
|
||||
*/
|
||||
UCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser);
|
||||
|
||||
/**
|
||||
* Get the code of the last error
|
||||
* @param parser parser object
|
||||
* @return error code
|
||||
*/
|
||||
UCL_EXTERN int ucl_parser_get_error_code(struct ucl_parser *parser);
|
||||
|
||||
/**
|
||||
* Get the current column number within parser
|
||||
* @param parser parser object
|
||||
* @return current column number
|
||||
*/
|
||||
UCL_EXTERN unsigned ucl_parser_get_column(struct ucl_parser *parser);
|
||||
|
||||
/**
|
||||
* Get the current line number within parser
|
||||
* @param parser parser object
|
||||
* @return current line number
|
||||
*/
|
||||
UCL_EXTERN unsigned ucl_parser_get_linenum(struct ucl_parser *parser);
|
||||
|
||||
/**
|
||||
* Clear the error in the parser
|
||||
* @param parser parser object
|
||||
@ -993,6 +1170,17 @@ struct ucl_emitter_context {
|
||||
UCL_EXTERN unsigned char *ucl_object_emit (const ucl_object_t *obj,
|
||||
enum ucl_emitter emit_type);
|
||||
|
||||
/**
|
||||
* Emit object to a string that can contain `\0` inside
|
||||
* @param obj object
|
||||
* @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
|
||||
* #UCL_EMIT_CONFIG then emit config like object
|
||||
* @param len the resulting length
|
||||
* @return dump of an object (must be freed after using) or NULL in case of error
|
||||
*/
|
||||
UCL_EXTERN unsigned char *ucl_object_emit_len (const ucl_object_t *obj,
|
||||
enum ucl_emitter emit_type, size_t *len);
|
||||
|
||||
/**
|
||||
* Emit object to a string
|
||||
* @param obj object
|
||||
|
@ -89,7 +89,7 @@ int main() {
|
||||
|
||||
#define kv_concat(type, v1, v0) do { \
|
||||
if ((v1).m < (v0).n + (v1).n) kv_resize(type, v1, (v0).n + (v1).n); \
|
||||
memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * ((v0).n + (v1).n)); \
|
||||
memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n); \
|
||||
(v1).n = (v0).n + (v1).n; \
|
||||
} while (0)
|
||||
|
||||
|
@ -69,6 +69,7 @@ func = "huh";
|
||||
#define PARSER_META "ucl.parser.meta"
|
||||
#define EMITTER_META "ucl.emitter.meta"
|
||||
#define NULL_META "null.emitter.meta"
|
||||
#define OBJECT_META "ucl.object.meta"
|
||||
|
||||
static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj);
|
||||
static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, bool allow_array);
|
||||
@ -172,8 +173,21 @@ static int
|
||||
ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj)
|
||||
{
|
||||
const ucl_object_t *cur;
|
||||
ucl_object_iter_t it;
|
||||
int i = 1, nelt = 0;
|
||||
|
||||
if (obj->type == UCL_ARRAY) {
|
||||
nelt = obj->len;
|
||||
it = ucl_object_iterate_new (obj);
|
||||
lua_createtable (L, nelt, 0);
|
||||
|
||||
while ((cur = ucl_object_iterate_safe (it, true))) {
|
||||
ucl_object_push_lua (L, cur, false);
|
||||
lua_rawseti (L, -2, i);
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Optimize allocation by preallocation of table */
|
||||
LL_FOREACH (obj, cur) {
|
||||
nelt ++;
|
||||
@ -186,6 +200,7 @@ ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj)
|
||||
lua_rawseti (L, -2, i);
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -259,7 +274,7 @@ ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array)
|
||||
case UCL_OBJECT:
|
||||
return ucl_object_lua_push_object (L, obj, allow_array);
|
||||
case UCL_ARRAY:
|
||||
return ucl_object_lua_push_array (L, obj->value.av);
|
||||
return ucl_object_lua_push_array (L, obj);
|
||||
default:
|
||||
return ucl_object_lua_push_scalar (L, obj, allow_array);
|
||||
}
|
||||
@ -322,6 +337,7 @@ ucl_object_lua_fromtable (lua_State *L, int idx)
|
||||
if (obj != NULL) {
|
||||
ucl_array_append (top, obj);
|
||||
}
|
||||
lua_pop (L, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -445,6 +461,24 @@ ucl_object_lua_import (lua_State *L, int idx)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type)
|
||||
{
|
||||
unsigned char *result;
|
||||
|
||||
result = ucl_object_emit (obj, type);
|
||||
|
||||
if (result != NULL) {
|
||||
lua_pushstring (L, (const char *)result);
|
||||
free (result);
|
||||
}
|
||||
else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_ucl_parser_init (lua_State *L)
|
||||
{
|
||||
@ -474,6 +508,12 @@ lua_ucl_parser_get (lua_State *L, int index)
|
||||
return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META));
|
||||
}
|
||||
|
||||
static ucl_object_t *
|
||||
lua_ucl_object_get (lua_State *L, int index)
|
||||
{
|
||||
return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META));
|
||||
}
|
||||
|
||||
/***
|
||||
* @method parser:parse_file(name)
|
||||
* Parse UCL object from file.
|
||||
@ -579,6 +619,108 @@ lua_ucl_parser_get_object (lua_State *L)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
* @method parser:get_object_wrapped()
|
||||
* Get top object from parser and export it to userdata object without
|
||||
* unwrapping to lua.
|
||||
* @return {ucl.object or nil} ucl object wrapped variable
|
||||
*/
|
||||
static int
|
||||
lua_ucl_parser_get_object_wrapped (lua_State *L)
|
||||
{
|
||||
struct ucl_parser *parser;
|
||||
ucl_object_t *obj, **pobj;
|
||||
int ret = 1;
|
||||
|
||||
parser = lua_ucl_parser_get (L, 1);
|
||||
obj = ucl_parser_get_object (parser);
|
||||
|
||||
if (obj != NULL) {
|
||||
pobj = lua_newuserdata (L, sizeof (*pobj));
|
||||
*pobj = obj;
|
||||
luaL_getmetatable (L, OBJECT_META);
|
||||
lua_setmetatable (L, -2);
|
||||
}
|
||||
else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
* @method parser:validate(schema)
|
||||
* Validates the top object in the parser against schema. Schema might be
|
||||
* another object or a string that represents file to load schema from.
|
||||
*
|
||||
* @param {string/table} schema input schema
|
||||
* @return {result,err} two values: boolean result and the corresponding error
|
||||
*
|
||||
*/
|
||||
static int
|
||||
lua_ucl_parser_validate (lua_State *L)
|
||||
{
|
||||
struct ucl_parser *parser, *schema_parser;
|
||||
ucl_object_t *schema;
|
||||
const char *schema_file;
|
||||
struct ucl_schema_error err;
|
||||
|
||||
parser = lua_ucl_parser_get (L, 1);
|
||||
|
||||
if (parser && parser->top_obj) {
|
||||
if (lua_type (L, 2) == LUA_TTABLE) {
|
||||
schema = ucl_object_lua_import (L, 2);
|
||||
|
||||
if (schema == NULL) {
|
||||
lua_pushboolean (L, false);
|
||||
lua_pushstring (L, "cannot load schema from lua table");
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else if (lua_type (L, 2) == LUA_TSTRING) {
|
||||
schema_parser = ucl_parser_new (0);
|
||||
schema_file = luaL_checkstring (L, 2);
|
||||
|
||||
if (!ucl_parser_add_file (schema_parser, schema_file)) {
|
||||
lua_pushboolean (L, false);
|
||||
lua_pushfstring (L, "cannot parse schema file \"%s\": "
|
||||
"%s", schema_file, ucl_parser_get_error (parser));
|
||||
ucl_parser_free (schema_parser);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
schema = ucl_parser_get_object (schema_parser);
|
||||
ucl_parser_free (schema_parser);
|
||||
}
|
||||
else {
|
||||
lua_pushboolean (L, false);
|
||||
lua_pushstring (L, "invalid schema argument");
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!ucl_object_validate (schema, parser->top_obj, &err)) {
|
||||
lua_pushboolean (L, false);
|
||||
lua_pushfstring (L, "validation error: "
|
||||
"%s", err.msg);
|
||||
}
|
||||
else {
|
||||
lua_pushboolean (L, true);
|
||||
lua_pushnil (L);
|
||||
}
|
||||
|
||||
ucl_object_unref (schema);
|
||||
}
|
||||
else {
|
||||
lua_pushboolean (L, false);
|
||||
lua_pushstring (L, "invalid parser or empty top object");
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_ucl_parser_gc (lua_State *L)
|
||||
{
|
||||
@ -590,6 +732,161 @@ lua_ucl_parser_gc (lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***
|
||||
* @method object:unwrap()
|
||||
* Unwraps opaque ucl object to the native lua object (performing copying)
|
||||
* @return {variant} any lua object
|
||||
*/
|
||||
static int
|
||||
lua_ucl_object_unwrap (lua_State *L)
|
||||
{
|
||||
ucl_object_t *obj;
|
||||
|
||||
obj = lua_ucl_object_get (L, 1);
|
||||
|
||||
if (obj) {
|
||||
ucl_object_push_lua (L, obj, true);
|
||||
}
|
||||
else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***
|
||||
* @method object:tostring(type)
|
||||
* Unwraps opaque ucl object to string (json by default). Optionally you can
|
||||
* specify output format:
|
||||
*
|
||||
* - `json` - fine printed json
|
||||
* - `json-compact` - compacted json
|
||||
* - `config` - fine printed configuration
|
||||
* - `ucl` - same as `config`
|
||||
* - `yaml` - embedded yaml
|
||||
* @param {string} type optional
|
||||
* @return {string} string representation of the opaque ucl object
|
||||
*/
|
||||
static int
|
||||
lua_ucl_object_tostring (lua_State *L)
|
||||
{
|
||||
ucl_object_t *obj;
|
||||
enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
|
||||
|
||||
obj = lua_ucl_object_get (L, 1);
|
||||
|
||||
if (obj) {
|
||||
if (lua_gettop (L) > 1) {
|
||||
if (lua_type (L, 2) == LUA_TSTRING) {
|
||||
const char *strtype = lua_tostring (L, 2);
|
||||
|
||||
if (strcasecmp (strtype, "json") == 0) {
|
||||
format = UCL_EMIT_JSON;
|
||||
}
|
||||
else if (strcasecmp (strtype, "json-compact") == 0) {
|
||||
format = UCL_EMIT_JSON_COMPACT;
|
||||
}
|
||||
else if (strcasecmp (strtype, "yaml") == 0) {
|
||||
format = UCL_EMIT_YAML;
|
||||
}
|
||||
else if (strcasecmp (strtype, "config") == 0 ||
|
||||
strcasecmp (strtype, "ucl") == 0) {
|
||||
format = UCL_EMIT_CONFIG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lua_ucl_to_string (L, obj, format);
|
||||
}
|
||||
else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***
|
||||
* @method object:validate(schema, path)
|
||||
* Validates the given ucl object using schema object represented as another
|
||||
* opaque ucl object. You can also specify path in the form `#/path/def` to
|
||||
* specify the specific schema element to perform validation.
|
||||
*
|
||||
* @param {ucl.object} schema schema object
|
||||
* @param {string} path optional path for validation procedure
|
||||
* @return {result,err} two values: boolean result and the corresponding error
|
||||
*/
|
||||
static int
|
||||
lua_ucl_object_validate (lua_State *L)
|
||||
{
|
||||
ucl_object_t *obj, *schema;
|
||||
const ucl_object_t *schema_elt;
|
||||
bool res = false;
|
||||
struct ucl_schema_error err;
|
||||
const char *path = NULL;
|
||||
|
||||
obj = lua_ucl_object_get (L, 1);
|
||||
schema = lua_ucl_object_get (L, 2);
|
||||
|
||||
if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) {
|
||||
if (lua_gettop (L) > 2 && lua_type (L, 3) == LUA_TSTRING) {
|
||||
path = lua_tostring (L, 3);
|
||||
if (path[0] == '#') {
|
||||
path ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (path) {
|
||||
schema_elt = ucl_lookup_path_char (schema, path, '/');
|
||||
}
|
||||
else {
|
||||
/* Use the top object */
|
||||
schema_elt = schema;
|
||||
}
|
||||
|
||||
if (schema_elt) {
|
||||
res = ucl_object_validate (schema_elt, obj, &err);
|
||||
|
||||
if (res) {
|
||||
lua_pushboolean (L, res);
|
||||
lua_pushnil (L);
|
||||
}
|
||||
else {
|
||||
lua_pushboolean (L, res);
|
||||
lua_pushfstring (L, "validation error: %s", err.msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_pushboolean (L, res);
|
||||
|
||||
if (path) {
|
||||
lua_pushfstring (L, "cannot find the requested path: %s", path);
|
||||
}
|
||||
else {
|
||||
/* Should not be reached */
|
||||
lua_pushstring (L, "unknown error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_pushboolean (L, res);
|
||||
lua_pushstring (L, "invalid object or schema");
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_ucl_object_gc (lua_State *L)
|
||||
{
|
||||
ucl_object_t *obj;
|
||||
|
||||
obj = lua_ucl_object_get (L, 1);
|
||||
|
||||
ucl_object_unref (obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lua_ucl_parser_mt (lua_State *L)
|
||||
{
|
||||
@ -610,25 +907,45 @@ lua_ucl_parser_mt (lua_State *L)
|
||||
lua_pushcfunction (L, lua_ucl_parser_get_object);
|
||||
lua_setfield (L, -2, "get_object");
|
||||
|
||||
lua_pushcfunction (L, lua_ucl_parser_get_object_wrapped);
|
||||
lua_setfield (L, -2, "get_object_wrapped");
|
||||
|
||||
lua_pushcfunction (L, lua_ucl_parser_validate);
|
||||
lua_setfield (L, -2, "validate");
|
||||
|
||||
lua_pop (L, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type)
|
||||
static void
|
||||
lua_ucl_object_mt (lua_State *L)
|
||||
{
|
||||
unsigned char *result;
|
||||
luaL_newmetatable (L, OBJECT_META);
|
||||
|
||||
result = ucl_object_emit (obj, type);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
if (result != NULL) {
|
||||
lua_pushstring (L, (const char *)result);
|
||||
free (result);
|
||||
}
|
||||
else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
lua_pushcfunction (L, lua_ucl_object_gc);
|
||||
lua_setfield (L, -2, "__gc");
|
||||
|
||||
return 1;
|
||||
lua_pushcfunction (L, lua_ucl_object_tostring);
|
||||
lua_setfield (L, -2, "__tostring");
|
||||
|
||||
lua_pushcfunction (L, lua_ucl_object_tostring);
|
||||
lua_setfield (L, -2, "tostring");
|
||||
|
||||
lua_pushcfunction (L, lua_ucl_object_unwrap);
|
||||
lua_setfield (L, -2, "unwrap");
|
||||
|
||||
lua_pushcfunction (L, lua_ucl_object_unwrap);
|
||||
lua_setfield (L, -2, "tolua");
|
||||
|
||||
lua_pushcfunction (L, lua_ucl_object_validate);
|
||||
lua_setfield (L, -2, "validate");
|
||||
|
||||
lua_pushstring (L, OBJECT_META);
|
||||
lua_setfield (L, -2, "class");
|
||||
|
||||
lua_pop (L, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -774,6 +1091,7 @@ luaopen_ucl (lua_State *L)
|
||||
{
|
||||
lua_ucl_parser_mt (L);
|
||||
lua_ucl_null_mt (L);
|
||||
lua_ucl_object_mt (L);
|
||||
|
||||
/* Create the refs weak table: */
|
||||
lua_createtable (L, 0, 2);
|
||||
|
664
contrib/libucl/m4/ax_lua.m4
Normal file
664
contrib/libucl/m4/ax_lua.m4
Normal file
@ -0,0 +1,664 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_lua.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Detect a Lua interpreter, optionally specifying a minimum and maximum
|
||||
# version number. Set up important Lua paths, such as the directories in
|
||||
# which to install scripts and modules (shared libraries).
|
||||
#
|
||||
# Also detect Lua headers and libraries. The Lua version contained in the
|
||||
# header is checked to match the Lua interpreter version exactly. When
|
||||
# searching for Lua libraries, the version number is used as a suffix.
|
||||
# This is done with the goal of supporting multiple Lua installs (5.1,
|
||||
# 5.2, and 5.3 side-by-side).
|
||||
#
|
||||
# A note on compatibility with previous versions: This file has been
|
||||
# mostly rewritten for serial 18. Most developers should be able to use
|
||||
# these macros without needing to modify configure.ac. Care has been taken
|
||||
# to preserve each macro's behavior, but there are some differences:
|
||||
#
|
||||
# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as
|
||||
# AX_PROG_LUA with no arguments.
|
||||
#
|
||||
# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h
|
||||
# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore
|
||||
# unnecessary, so it is deprecated and does not expand to anything.
|
||||
#
|
||||
# 3) The configure flag --with-lua-suffix no longer exists; the user
|
||||
# should instead specify the LUA precious variable on the command line.
|
||||
# See the AX_PROG_LUA description for details.
|
||||
#
|
||||
# Please read the macro descriptions below for more information.
|
||||
#
|
||||
# This file was inspired by Andrew Dalke's and James Henstridge's
|
||||
# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4
|
||||
# (serial 17). Basically, this file is a mash-up of those two files. I
|
||||
# like to think it combines the best of the two!
|
||||
#
|
||||
# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua
|
||||
# paths. Adds precious variable LUA, which may contain the path of the Lua
|
||||
# interpreter. If LUA is blank, the user's path is searched for an
|
||||
# suitable interpreter.
|
||||
#
|
||||
# If MINIMUM-VERSION is supplied, then only Lua interpreters with a
|
||||
# version number greater or equal to MINIMUM-VERSION will be accepted. If
|
||||
# TOO-BIG-VERSION is also supplied, then only Lua interpreters with a
|
||||
# version number greater or equal to MINIMUM-VERSION and less than
|
||||
# TOO-BIG-VERSION will be accepted.
|
||||
#
|
||||
# The Lua version number, LUA_VERSION, is found from the interpreter, and
|
||||
# substituted. LUA_PLATFORM is also found, but not currently supported (no
|
||||
# standard representation).
|
||||
#
|
||||
# Finally, the macro finds four paths:
|
||||
#
|
||||
# luadir Directory to install Lua scripts.
|
||||
# pkgluadir $luadir/$PACKAGE
|
||||
# luaexecdir Directory to install Lua modules.
|
||||
# pkgluaexecdir $luaexecdir/$PACKAGE
|
||||
#
|
||||
# These paths are found based on $prefix, $exec_prefix, Lua's
|
||||
# package.path, and package.cpath. The first path of package.path
|
||||
# beginning with $prefix is selected as luadir. The first path of
|
||||
# package.cpath beginning with $exec_prefix is used as luaexecdir. This
|
||||
# should work on all reasonable Lua installations. If a path cannot be
|
||||
# determined, a default path is used. Of course, the user can override
|
||||
# these later when invoking make.
|
||||
#
|
||||
# luadir Default: $prefix/share/lua/$LUA_VERSION
|
||||
# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION
|
||||
#
|
||||
# These directories can be used by Automake as install destinations. The
|
||||
# variable name minus 'dir' needs to be used as a prefix to the
|
||||
# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES.
|
||||
#
|
||||
# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is
|
||||
# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT-
|
||||
# FOUND is blank, then it will default to printing an error. To prevent
|
||||
# the default behavior, give ':' as an action.
|
||||
#
|
||||
# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be
|
||||
# expanded before this macro. Adds precious variable LUA_INCLUDE, which
|
||||
# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If
|
||||
# LUA_INCLUDE is blank, then this macro will attempt to find suitable
|
||||
# flags.
|
||||
#
|
||||
# LUA_INCLUDE can be used by Automake to compile Lua modules or
|
||||
# executables with embedded interpreters. The *_CPPFLAGS variables should
|
||||
# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE).
|
||||
#
|
||||
# This macro searches for the header lua.h (and others). The search is
|
||||
# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE.
|
||||
# If the search is unsuccessful, then some common directories are tried.
|
||||
# If the headers are then found, then LUA_INCLUDE is set accordingly.
|
||||
#
|
||||
# The paths automatically searched are:
|
||||
#
|
||||
# * /usr/include/luaX.Y
|
||||
# * /usr/include/lua/X.Y
|
||||
# * /usr/include/luaXY
|
||||
# * /usr/local/include/luaX.Y
|
||||
# * /usr/local/include/lua-X.Y
|
||||
# * /usr/local/include/lua/X.Y
|
||||
# * /usr/local/include/luaXY
|
||||
#
|
||||
# (Where X.Y is the Lua version number, e.g. 5.1.)
|
||||
#
|
||||
# The Lua version number found in the headers is always checked to match
|
||||
# the Lua interpreter's version number. Lua headers with mismatched
|
||||
# version numbers are not accepted.
|
||||
#
|
||||
# If headers are found, then ACTION-IF-FOUND is performed, otherwise
|
||||
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
|
||||
# it will default to printing an error. To prevent the default behavior,
|
||||
# set the action to ':'.
|
||||
#
|
||||
# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be
|
||||
# expanded before this macro. Adds precious variable LUA_LIB, which may
|
||||
# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank,
|
||||
# then this macro will attempt to find suitable flags.
|
||||
#
|
||||
# LUA_LIB can be used by Automake to link Lua modules or executables with
|
||||
# embedded interpreters. The *_LIBADD and *_LDADD variables should be used
|
||||
# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB).
|
||||
#
|
||||
# This macro searches for the Lua library. More technically, it searches
|
||||
# for a library containing the function lua_load. The search is performed
|
||||
# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB.
|
||||
#
|
||||
# If the search determines that some linker flags are missing, then those
|
||||
# flags will be added to LUA_LIB.
|
||||
#
|
||||
# If libraries are found, then ACTION-IF-FOUND is performed, otherwise
|
||||
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
|
||||
# it will default to printing an error. To prevent the default behavior,
|
||||
# set the action to ':'.
|
||||
#
|
||||
# AX_LUA_READLINE: Search for readline headers and libraries. Requires the
|
||||
# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the
|
||||
# Autoconf Archive.
|
||||
#
|
||||
# If a readline compatible library is found, then ACTION-IF-FOUND is
|
||||
# performed, otherwise ACTION-IF-NOT-FOUND is performed.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2015 Reuben Thomas <rrt@sc3d.org>
|
||||
# Copyright (c) 2014 Tim Perkins <tprk77@gmail.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 3 of the License, 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, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 39
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
|
||||
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_PROG_LUA],
|
||||
[
|
||||
dnl Check for required tools.
|
||||
AC_REQUIRE([AC_PROG_GREP])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
|
||||
dnl Make LUA a precious variable.
|
||||
AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
|
||||
|
||||
dnl Find a Lua interpreter.
|
||||
m4_define_default([_AX_LUA_INTERPRETER_LIST],
|
||||
[lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50])
|
||||
|
||||
m4_if([$1], [],
|
||||
[ dnl No version check is needed. Find any Lua interpreter.
|
||||
AS_IF([test "x$LUA" = 'x'],
|
||||
[AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
|
||||
ax_display_LUA='lua'
|
||||
|
||||
AS_IF([test "x$LUA" != 'x:'],
|
||||
[ dnl At least check if this is a Lua interpreter.
|
||||
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
|
||||
_AX_LUA_CHK_IS_INTRP([$LUA],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([not a Lua interpreter])
|
||||
])
|
||||
])
|
||||
],
|
||||
[ dnl A version check is needed.
|
||||
AS_IF([test "x$LUA" != 'x'],
|
||||
[ dnl Check if this is a Lua interpreter.
|
||||
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
|
||||
_AX_LUA_CHK_IS_INTRP([$LUA],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([not a Lua interpreter])
|
||||
])
|
||||
dnl Check the version.
|
||||
m4_if([$2], [],
|
||||
[_ax_check_text="whether $LUA version >= $1"],
|
||||
[_ax_check_text="whether $LUA version >= $1, < $2"])
|
||||
AC_MSG_CHECKING([$_ax_check_text])
|
||||
_AX_LUA_CHK_VER([$LUA], [$1], [$2],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([version is out of range for specified LUA])])
|
||||
ax_display_LUA=$LUA
|
||||
],
|
||||
[ dnl Try each interpreter until we find one that satisfies VERSION.
|
||||
m4_if([$2], [],
|
||||
[_ax_check_text="for a Lua interpreter with version >= $1"],
|
||||
[_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
|
||||
AC_CACHE_CHECK([$_ax_check_text],
|
||||
[ax_cv_pathless_LUA],
|
||||
[ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
|
||||
test "x$ax_cv_pathless_LUA" = 'xnone' && break
|
||||
_AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
|
||||
_AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
|
||||
done
|
||||
])
|
||||
dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
|
||||
AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
|
||||
[LUA=':'],
|
||||
[AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
|
||||
ax_display_LUA=$ax_cv_pathless_LUA
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "x$LUA" = 'x:'],
|
||||
[ dnl Run any user-specified action, or abort.
|
||||
m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
|
||||
],
|
||||
[ dnl Query Lua for its version number.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA version],
|
||||
[ax_cv_lua_version],
|
||||
[ dnl Get the interpreter version in X.Y format. This should work for
|
||||
dnl interpreters version 5.0 and beyond.
|
||||
ax_cv_lua_version=[`$LUA -e '
|
||||
-- return a version number in X.Y format
|
||||
local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)")
|
||||
print(ver)'`]
|
||||
])
|
||||
AS_IF([test "x$ax_cv_lua_version" = 'x'],
|
||||
[AC_MSG_ERROR([invalid Lua version number])])
|
||||
AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
|
||||
AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`])
|
||||
|
||||
dnl The following check is not supported:
|
||||
dnl At times (like when building shared libraries) you may want to know
|
||||
dnl which OS platform Lua thinks this is.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA platform],
|
||||
[ax_cv_lua_platform],
|
||||
[ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]])
|
||||
AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
|
||||
|
||||
dnl Use the values of $prefix and $exec_prefix for the corresponding
|
||||
dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
|
||||
dnl variables so they can be overridden if need be. However, the general
|
||||
dnl consensus is that you shouldn't need this ability.
|
||||
AC_SUBST([LUA_PREFIX], ['${prefix}'])
|
||||
AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
|
||||
|
||||
dnl Lua provides no way to query the script directory, and instead
|
||||
dnl provides LUA_PATH. However, we should be able to make a safe educated
|
||||
dnl guess. If the built-in search path contains a directory which is
|
||||
dnl prefixed by $prefix, then we can store scripts there. The first
|
||||
dnl matching path will be used.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA script directory],
|
||||
[ax_cv_lua_luadir],
|
||||
[ AS_IF([test "x$prefix" = 'xNONE'],
|
||||
[ax_lua_prefix=$ac_default_prefix],
|
||||
[ax_lua_prefix=$prefix])
|
||||
|
||||
dnl Initialize to the default path.
|
||||
ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
|
||||
|
||||
dnl Try to find a path with the prefix.
|
||||
_AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script])
|
||||
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
|
||||
[ dnl Fix the prefix.
|
||||
_ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'`
|
||||
ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
|
||||
$SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"`
|
||||
])
|
||||
])
|
||||
AC_SUBST([luadir], [$ax_cv_lua_luadir])
|
||||
AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
|
||||
|
||||
dnl Lua provides no way to query the module directory, and instead
|
||||
dnl provides LUA_PATH. However, we should be able to make a safe educated
|
||||
dnl guess. If the built-in search path contains a directory which is
|
||||
dnl prefixed by $exec_prefix, then we can store modules there. The first
|
||||
dnl matching path will be used.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA module directory],
|
||||
[ax_cv_lua_luaexecdir],
|
||||
[ AS_IF([test "x$exec_prefix" = 'xNONE'],
|
||||
[ax_lua_exec_prefix=$ax_lua_prefix],
|
||||
[ax_lua_exec_prefix=$exec_prefix])
|
||||
|
||||
dnl Initialize to the default path.
|
||||
ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
|
||||
|
||||
dnl Try to find a path with the prefix.
|
||||
_AX_LUA_FND_PRFX_PTH([$LUA],
|
||||
[$ax_lua_exec_prefix], [module])
|
||||
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
|
||||
[ dnl Fix the prefix.
|
||||
_ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'`
|
||||
ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
|
||||
$SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"`
|
||||
])
|
||||
])
|
||||
AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
|
||||
AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
|
||||
|
||||
dnl Run any user specified action.
|
||||
$3
|
||||
])
|
||||
])
|
||||
|
||||
dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
|
||||
AC_DEFUN([AX_WITH_LUA],
|
||||
[
|
||||
AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]])
|
||||
AX_PROG_LUA
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
|
||||
[
|
||||
dnl A minimal Lua factorial to prove this is an interpreter. This should work
|
||||
dnl for Lua interpreters version 5.0 and beyond.
|
||||
_ax_lua_factorial=[`$1 2>/dev/null -e '
|
||||
-- a simple factorial
|
||||
function fact (n)
|
||||
if n == 0 then
|
||||
return 1
|
||||
else
|
||||
return n * fact(n-1)
|
||||
end
|
||||
end
|
||||
print("fact(5) is " .. fact(5))'`]
|
||||
AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'],
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
|
||||
dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([_AX_LUA_CHK_VER],
|
||||
[
|
||||
dnl Check that the Lua version is within the bounds. Only the major and minor
|
||||
dnl version numbers are considered. This should work for Lua interpreters
|
||||
dnl version 5.0 and beyond.
|
||||
_ax_lua_good_version=[`$1 -e '
|
||||
-- a script to compare versions
|
||||
function verstr2num(verstr)
|
||||
local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)")
|
||||
if majorver and minorver then
|
||||
return tonumber(majorver) * 100 + tonumber(minorver)
|
||||
end
|
||||
end
|
||||
local minver = verstr2num("$2")
|
||||
local _, _, trimver = string.find(_VERSION, "^Lua (.*)")
|
||||
local ver = verstr2num(trimver)
|
||||
local maxver = verstr2num("$3") or 1e9
|
||||
if minver <= ver and ver < maxver then
|
||||
print("yes")
|
||||
else
|
||||
print("no")
|
||||
end'`]
|
||||
AS_IF([test "x$_ax_lua_good_version" = "xyes"],
|
||||
[$4], [$5])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR)
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
|
||||
[
|
||||
dnl Get the script or module directory by querying the Lua interpreter,
|
||||
dnl filtering on the given prefix, and selecting the shallowest path. If no
|
||||
dnl path is found matching the prefix, the result will be an empty string.
|
||||
dnl The third argument determines the type of search, it can be 'script' or
|
||||
dnl 'module'. Supplying 'script' will perform the search with package.path
|
||||
dnl and LUA_PATH, and supplying 'module' will search with package.cpath and
|
||||
dnl LUA_CPATH. This is done for compatibility with Lua 5.0.
|
||||
|
||||
ax_lua_prefixed_path=[`$1 -e '
|
||||
-- get the path based on search type
|
||||
local searchtype = "$3"
|
||||
local paths = ""
|
||||
if searchtype == "script" then
|
||||
paths = (package and package.path) or LUA_PATH
|
||||
elseif searchtype == "module" then
|
||||
paths = (package and package.cpath) or LUA_CPATH
|
||||
end
|
||||
-- search for the prefix
|
||||
local prefix = "'$2'"
|
||||
local minpath = ""
|
||||
local mindepth = 1e9
|
||||
string.gsub(paths, "(@<:@^;@:>@+)",
|
||||
function (path)
|
||||
path = string.gsub(path, "%?.*$", "")
|
||||
path = string.gsub(path, "/@<:@^/@:>@*$", "")
|
||||
if string.find(path, prefix) then
|
||||
local depth = string.len(string.gsub(path, "@<:@^/@:>@", ""))
|
||||
if depth < mindepth then
|
||||
minpath = path
|
||||
mindepth = depth
|
||||
end
|
||||
end
|
||||
end)
|
||||
print(minpath)'`]
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_LUA_HEADERS],
|
||||
[
|
||||
dnl Check for LUA_VERSION.
|
||||
AC_MSG_CHECKING([if LUA_VERSION is defined])
|
||||
AS_IF([test "x$LUA_VERSION" != 'x'],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
|
||||
])
|
||||
|
||||
dnl Make LUA_INCLUDE a precious variable.
|
||||
AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
|
||||
|
||||
dnl Some default directories to search.
|
||||
LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'`
|
||||
m4_define_default([_AX_LUA_INCLUDE_LIST],
|
||||
[ /usr/include/lua$LUA_VERSION \
|
||||
/usr/include/lua-$LUA_VERSION \
|
||||
/usr/include/lua/$LUA_VERSION \
|
||||
/usr/include/lua$LUA_SHORT_VERSION \
|
||||
/usr/local/include/lua$LUA_VERSION \
|
||||
/usr/local/include/lua-$LUA_VERSION \
|
||||
/usr/local/include/lua/$LUA_VERSION \
|
||||
/usr/local/include/lua$LUA_SHORT_VERSION \
|
||||
])
|
||||
|
||||
dnl Try to find the headers.
|
||||
_ax_lua_saved_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
|
||||
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
|
||||
CPPFLAGS=$_ax_lua_saved_cppflags
|
||||
|
||||
dnl Try some other directories if LUA_INCLUDE was not set.
|
||||
AS_IF([test "x$LUA_INCLUDE" = 'x' &&
|
||||
test "x$ac_cv_header_lua_h" != 'xyes'],
|
||||
[ dnl Try some common include paths.
|
||||
for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
|
||||
test ! -d "$_ax_include_path" && continue
|
||||
|
||||
AC_MSG_CHECKING([for Lua headers in])
|
||||
AC_MSG_RESULT([$_ax_include_path])
|
||||
|
||||
AS_UNSET([ac_cv_header_lua_h])
|
||||
AS_UNSET([ac_cv_header_lualib_h])
|
||||
AS_UNSET([ac_cv_header_lauxlib_h])
|
||||
AS_UNSET([ac_cv_header_luaconf_h])
|
||||
|
||||
_ax_lua_saved_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
|
||||
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
|
||||
CPPFLAGS=$_ax_lua_saved_cppflags
|
||||
|
||||
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
|
||||
[ LUA_INCLUDE="-I$_ax_include_path"
|
||||
break
|
||||
])
|
||||
done
|
||||
])
|
||||
|
||||
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
|
||||
[ dnl Make a program to print LUA_VERSION defined in the header.
|
||||
dnl TODO It would be really nice if we could do this without compiling a
|
||||
dnl program, then it would work when cross compiling. But I'm not sure how
|
||||
dnl to do this reliably. For now, assume versions match when cross compiling.
|
||||
|
||||
AS_IF([test "x$cross_compiling" != 'xyes'],
|
||||
[ AC_CACHE_CHECK([for Lua header version],
|
||||
[ax_cv_lua_header_version],
|
||||
[ _ax_lua_saved_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
|
||||
AC_RUN_IFELSE(
|
||||
[ AC_LANG_SOURCE([[
|
||||
#include <lua.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
if(argc > 1) printf("%s", LUA_VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
]])
|
||||
],
|
||||
[ ax_cv_lua_header_version=`./conftest$EXEEXT p | \
|
||||
$SED -n "s|^Lua \(@<:@0-9@:>@\{1,\}\.@<:@0-9@:>@\{1,\}\).\{0,\}|\1|p"`
|
||||
],
|
||||
[ax_cv_lua_header_version='unknown'])
|
||||
CPPFLAGS=$_ax_lua_saved_cppflags
|
||||
])
|
||||
|
||||
dnl Compare this to the previously found LUA_VERSION.
|
||||
AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
|
||||
AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
|
||||
[ AC_MSG_RESULT([yes])
|
||||
ax_header_version_match='yes'
|
||||
],
|
||||
[ AC_MSG_RESULT([no])
|
||||
ax_header_version_match='no'
|
||||
])
|
||||
],
|
||||
[ AC_MSG_WARN([cross compiling so assuming header version number matches])
|
||||
ax_header_version_match='yes'
|
||||
])
|
||||
])
|
||||
|
||||
dnl Was LUA_INCLUDE specified?
|
||||
AS_IF([test "x$ax_header_version_match" != 'xyes' &&
|
||||
test "x$LUA_INCLUDE" != 'x'],
|
||||
[AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
|
||||
|
||||
dnl Test the final result and run user code.
|
||||
AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
|
||||
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
|
||||
])
|
||||
|
||||
dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
|
||||
AC_DEFUN([AX_LUA_HEADERS_VERSION],
|
||||
[
|
||||
AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_LUA_LIBS],
|
||||
[
|
||||
dnl TODO Should this macro also check various -L flags?
|
||||
|
||||
dnl Check for LUA_VERSION.
|
||||
AC_MSG_CHECKING([if LUA_VERSION is defined])
|
||||
AS_IF([test "x$LUA_VERSION" != 'x'],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
|
||||
])
|
||||
|
||||
dnl Make LUA_LIB a precious variable.
|
||||
AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
|
||||
|
||||
AS_IF([test "x$LUA_LIB" != 'x'],
|
||||
[ dnl Check that LUA_LIBS works.
|
||||
_ax_lua_saved_libs=$LIBS
|
||||
LIBS="$LUA_LIB $LIBS"
|
||||
AC_SEARCH_LIBS([lua_load], [],
|
||||
[_ax_found_lua_libs='yes'],
|
||||
[_ax_found_lua_libs='no'])
|
||||
LIBS=$_ax_lua_saved_libs
|
||||
|
||||
dnl Check the result.
|
||||
AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
|
||||
[AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
|
||||
],
|
||||
[ dnl First search for extra libs.
|
||||
_ax_lua_extra_libs=''
|
||||
|
||||
_ax_lua_saved_libs=$LIBS
|
||||
LIBS="$LUA_LIB $LIBS"
|
||||
AC_SEARCH_LIBS([exp], [m])
|
||||
AC_SEARCH_LIBS([dlopen], [dl])
|
||||
LIBS=$_ax_lua_saved_libs
|
||||
|
||||
AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
|
||||
test "x$ac_cv_search_exp" != 'xnone required'],
|
||||
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
|
||||
|
||||
AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
|
||||
test "x$ac_cv_search_dlopen" != 'xnone required'],
|
||||
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
|
||||
|
||||
dnl Try to find the Lua libs.
|
||||
_ax_lua_saved_libs=$LIBS
|
||||
LIBS="$LUA_LIB $LIBS"
|
||||
AC_SEARCH_LIBS([lua_load],
|
||||
[ lua$LUA_VERSION \
|
||||
lua$LUA_SHORT_VERSION \
|
||||
lua-$LUA_VERSION \
|
||||
lua-$LUA_SHORT_VERSION \
|
||||
lua \
|
||||
],
|
||||
[_ax_found_lua_libs='yes'],
|
||||
[_ax_found_lua_libs='no'],
|
||||
[$_ax_lua_extra_libs])
|
||||
LIBS=$_ax_lua_saved_libs
|
||||
|
||||
AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
|
||||
test "x$ac_cv_search_lua_load" != 'xnone required'],
|
||||
[LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
|
||||
])
|
||||
|
||||
dnl Test the result and run user code.
|
||||
AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
|
||||
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_LUA_READLINE],
|
||||
[
|
||||
AX_LIB_READLINE
|
||||
AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
|
||||
test "x$ac_cv_header_readline_history_h" != 'x'],
|
||||
[ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
|
||||
$1
|
||||
],
|
||||
[$2])
|
||||
])
|
37
contrib/libucl/python/setup.py
Normal file
37
contrib/libucl/python/setup.py
Normal file
@ -0,0 +1,37 @@
|
||||
import distutils.ccompiler
|
||||
import distutils.sysconfig
|
||||
from distutils.core import setup, Extension
|
||||
import os
|
||||
|
||||
|
||||
compiler = distutils.ccompiler.new_compiler()
|
||||
search_paths=[os.path.expanduser('~/{}'), '/opt/local/{}', '/usr/local/{}', '/usr/{}']
|
||||
lib_paths = [ a.format("lib") for a in search_paths]
|
||||
inc_paths = [ a.format("include") for a in search_paths]
|
||||
|
||||
uclmodule = Extension('ucl',
|
||||
include_dirs = inc_paths,
|
||||
library_dirs = lib_paths,
|
||||
libraries = ['ucl'],
|
||||
sources = ['src/uclmodule.c'],
|
||||
runtime_library_dirs = lib_paths,
|
||||
language='c')
|
||||
|
||||
setup(name='ucl',
|
||||
version='1.0',
|
||||
description='ucl parser and emmitter',
|
||||
ext_modules = [uclmodule],
|
||||
author="Eitan Adler",
|
||||
author_email="lists@eitanadler.com",
|
||||
url="https://github.com/vstakhov/libucl/",
|
||||
license="MIT",
|
||||
classifiers=["Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: DFSG approved",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: C",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
]
|
||||
)
|
156
contrib/libucl/python/src/uclmodule.c
Normal file
156
contrib/libucl/python/src/uclmodule.c
Normal file
@ -0,0 +1,156 @@
|
||||
// Attempts to load a UCL structure from a string
|
||||
#include <ucl.h>
|
||||
#include <Python.h>
|
||||
|
||||
static PyObject*
|
||||
_basic_ucl_type(ucl_object_t const * const obj) {
|
||||
if (obj->type == UCL_INT) {
|
||||
return Py_BuildValue("L", (long long)ucl_object_toint (obj));
|
||||
}
|
||||
else if (obj->type == UCL_FLOAT) {
|
||||
return Py_BuildValue("d", ucl_object_todouble (obj));
|
||||
}
|
||||
else if (obj->type == UCL_STRING) {
|
||||
return Py_BuildValue("s", ucl_object_tostring (obj));
|
||||
}
|
||||
else if (obj->type == UCL_BOOLEAN) {
|
||||
// maybe used 'p' here?
|
||||
return Py_BuildValue("s", ucl_object_tostring_forced (obj));
|
||||
}
|
||||
else if (obj->type == UCL_TIME) {
|
||||
return Py_BuildValue("d", ucl_object_todouble (obj));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_iterate_valid_ucl(ucl_object_t const * obj) {
|
||||
const ucl_object_t *tmp;
|
||||
ucl_object_iter_t it = NULL;
|
||||
|
||||
tmp = obj;
|
||||
|
||||
while ((obj = ucl_iterate_object (tmp, &it, false))) {
|
||||
|
||||
PyObject* val;
|
||||
|
||||
val = _basic_ucl_type(obj);
|
||||
if (!val) {
|
||||
PyObject* key = NULL;
|
||||
if (obj->key != NULL) {
|
||||
key = Py_BuildValue("s", ucl_object_key(obj));
|
||||
}
|
||||
|
||||
PyObject* ret;
|
||||
ret = PyDict_New();
|
||||
if (obj->type == UCL_OBJECT) {
|
||||
val = PyDict_New();
|
||||
const ucl_object_t *cur;
|
||||
ucl_object_iter_t it_obj = NULL;
|
||||
while ((cur = ucl_iterate_object (obj, &it_obj, true))) {
|
||||
PyObject* keyobj = Py_BuildValue("s",ucl_object_key(cur));
|
||||
PyDict_SetItem(val, keyobj, _iterate_valid_ucl(cur));
|
||||
}
|
||||
}
|
||||
else if (obj->type == UCL_ARRAY) {
|
||||
val = PyList_New(0);
|
||||
const ucl_object_t *cur;
|
||||
ucl_object_iter_t it_obj = NULL;
|
||||
while ((cur = ucl_iterate_object (obj, &it_obj, true))) {
|
||||
PyList_Append(val, _iterate_valid_ucl(cur));
|
||||
}
|
||||
}
|
||||
else if (obj->type == UCL_USERDATA) {
|
||||
// XXX: this should be
|
||||
// PyBytes_FromStringAndSize; where is the
|
||||
// length from?
|
||||
val = PyBytes_FromString(obj->value.ud);
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_SystemError, "unhandled type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_internal_load_ucl(char* uclstr) {
|
||||
PyObject* ret;
|
||||
|
||||
struct ucl_parser *parser = ucl_parser_new (UCL_PARSER_NO_TIME);
|
||||
|
||||
bool r = ucl_parser_add_string(parser, uclstr, 0);
|
||||
if (r) {
|
||||
if (ucl_parser_get_error (parser)) {
|
||||
PyErr_SetString(PyExc_ValueError, ucl_parser_get_error(parser));
|
||||
ucl_parser_free(parser);
|
||||
ret = NULL;
|
||||
goto return_with_parser;
|
||||
} else {
|
||||
ucl_object_t* uclobj = ucl_parser_get_object(parser);
|
||||
ret = _iterate_valid_ucl(uclobj);
|
||||
ucl_object_unref(uclobj);
|
||||
goto return_with_parser;
|
||||
}
|
||||
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, ucl_parser_get_error (parser));
|
||||
ret = NULL;
|
||||
goto return_with_parser;
|
||||
}
|
||||
|
||||
return_with_parser:
|
||||
ucl_parser_free(parser);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
ucl_load(PyObject *self, PyObject *args) {
|
||||
char* uclstr;
|
||||
if (PyArg_ParseTuple(args, "z", &uclstr)) {
|
||||
if (!uclstr) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return _internal_load_ucl(uclstr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
ucl_validate(PyObject *self, PyObject *args) {
|
||||
char *uclstr, *schema;
|
||||
if (PyArg_ParseTuple(args, "zz", &uclstr, &schema)) {
|
||||
if (!uclstr || !schema) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
PyErr_SetString(PyExc_NotImplementedError, "schema validation is not yet supported");
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyMethodDef uclMethods[] = {
|
||||
{"load", ucl_load, METH_VARARGS, "Load UCL from stream"},
|
||||
{"validate", ucl_validate, METH_VARARGS, "Validate ucl stream against schema"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static struct PyModuleDef uclmodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"ucl",
|
||||
NULL,
|
||||
-1,
|
||||
uclMethods
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_ucl(void) {
|
||||
return PyModule_Create(&uclmodule);
|
||||
}
|
||||
#else
|
||||
void initucl(void) {
|
||||
Py_InitModule("ucl", uclMethods);
|
||||
}
|
||||
#endif
|
6
contrib/libucl/python/test.sh
Executable file
6
contrib/libucl/python/test.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
set -xe
|
||||
python3.4 setup.py build_ext --inplace
|
||||
./test_uclmodule.py -v
|
||||
rm -rfv build
|
||||
rm ucl.so
|
100
contrib/libucl/python/test_uclmodule.py
Executable file
100
contrib/libucl/python/test_uclmodule.py
Executable file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python
|
||||
import json
|
||||
import unittest
|
||||
import ucl
|
||||
import sys
|
||||
|
||||
if sys.version_info[:2] == (2, 7):
|
||||
unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
|
||||
|
||||
|
||||
class TestUcl(unittest.TestCase):
|
||||
def test_no_args(self):
|
||||
with self.assertRaises(TypeError):
|
||||
ucl.load()
|
||||
|
||||
def test_multi_args(self):
|
||||
with self.assertRaises(TypeError):
|
||||
ucl.load(0,0)
|
||||
|
||||
def test_none(self):
|
||||
r = ucl.load(None)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
def test_int(self):
|
||||
r = ucl.load("a : 1")
|
||||
self.assertEqual(ucl.load("a : 1"), { "a" : 1 } )
|
||||
|
||||
def test_braced_int(self):
|
||||
self.assertEqual(ucl.load("{a : 1}"), { "a" : 1 } )
|
||||
|
||||
def test_nested_int(self):
|
||||
self.assertEqual(ucl.load("a : { b : 1 }"), { "a" : { "b" : 1 } })
|
||||
|
||||
def test_str(self):
|
||||
self.assertEqual(ucl.load("a : b"), {"a" : "b"})
|
||||
|
||||
def test_float(self):
|
||||
self.assertEqual(ucl.load("a : 1.1"), {"a" : 1.1})
|
||||
|
||||
def test_empty_ucl(self):
|
||||
r = ucl.load("{}")
|
||||
self.assertEqual(r, {})
|
||||
|
||||
def test_single_brace(self):
|
||||
self.assertEqual(ucl.load("{"), {})
|
||||
|
||||
def test_single_back_brace(self):
|
||||
ucl.load("}")
|
||||
|
||||
def test_single_square_forward(self):
|
||||
self.assertEqual(ucl.load("["), [])
|
||||
|
||||
def test_invalid_ucl(self):
|
||||
with self.assertRaisesRegex(ValueError, "unfinished key$"):
|
||||
ucl.load('{ "var"')
|
||||
|
||||
def test_comment_ignored(self):
|
||||
self.assertEqual(ucl.load("{/*1*/}"), {})
|
||||
|
||||
def test_1_in(self):
|
||||
with open("../tests/basic/1.in", "r") as in1:
|
||||
self.assertEqual(ucl.load(in1.read()), {'key1': 'value'})
|
||||
|
||||
def test_every_type(self):
|
||||
totest="""{
|
||||
"key1": value;
|
||||
"key2": value2;
|
||||
"key3": "value;"
|
||||
"key4": 1.0,
|
||||
"key5": -0xdeadbeef
|
||||
"key6": 0xdeadbeef.1
|
||||
"key7": 0xreadbeef
|
||||
"key8": -1e-10,
|
||||
"key9": 1
|
||||
"key10": true
|
||||
"key11": no
|
||||
"key12": yes
|
||||
}"""
|
||||
correct = {
|
||||
'key1': 'value',
|
||||
'key2': 'value2',
|
||||
'key3': 'value;',
|
||||
'key4': 1.0,
|
||||
'key5': -3735928559,
|
||||
'key6': '0xdeadbeef.1',
|
||||
'key7': '0xreadbeef',
|
||||
'key8': -1e-10,
|
||||
'key9': 1,
|
||||
'key10': 'true',
|
||||
'key11': 'false',
|
||||
'key12': 'true',
|
||||
}
|
||||
self.assertEqual(ucl.load(totest), correct)
|
||||
|
||||
def test_validation_useless(self):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
ucl.validate("","")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -11,6 +11,8 @@ libucl_la_SOURCES= ucl_emitter.c \
|
||||
ucl_parser.c \
|
||||
ucl_schema.c \
|
||||
ucl_util.c \
|
||||
ucl_msgpack.c \
|
||||
ucl_sexp.c \
|
||||
xxhash.c
|
||||
libucl_la_CFLAGS= $(libucl_common_cflags) \
|
||||
@CURL_CFLAGS@
|
||||
@ -20,7 +22,8 @@ libucl_la_LIBADD= @LIBFETCH_LIBS@ \
|
||||
@LIBREGEX_LIB@ \
|
||||
@CURL_LIBS@
|
||||
|
||||
include_HEADERS= $(top_srcdir)/include/ucl.h
|
||||
include_HEADERS= $(top_srcdir)/include/ucl.h \
|
||||
$(top_srcdir)/include/ucl++.h
|
||||
noinst_HEADERS= ucl_internal.h \
|
||||
xxhash.h \
|
||||
ucl_hash.h \
|
||||
|
@ -44,6 +44,13 @@
|
||||
|
||||
|
||||
#define TREE_DELTA_MAX 1
|
||||
#ifndef _HU_FUNCTION
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define _HU_FUNCTION(x) __attribute__((__unused__)) x
|
||||
# else
|
||||
# define _HU_FUNCTION(x) x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define TREE_ENTRY(type) \
|
||||
struct { \
|
||||
@ -68,9 +75,9 @@
|
||||
|
||||
#define TREE_DEFINE(node, field) \
|
||||
\
|
||||
struct node *TREE_BALANCE_##node##_##field(struct node *); \
|
||||
static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *); \
|
||||
\
|
||||
struct node *TREE_ROTL_##node##_##field(struct node *self) \
|
||||
static struct node *_HU_FUNCTION(TREE_ROTL_##node##_##field)(struct node *self) \
|
||||
{ \
|
||||
struct node *r= self->field.avl_right; \
|
||||
self->field.avl_right= r->field.avl_left; \
|
||||
@ -78,7 +85,7 @@
|
||||
return TREE_BALANCE_##node##_##field(r); \
|
||||
} \
|
||||
\
|
||||
struct node *TREE_ROTR_##node##_##field(struct node *self) \
|
||||
static struct node *_HU_FUNCTION(TREE_ROTR_##node##_##field)(struct node *self) \
|
||||
{ \
|
||||
struct node *l= self->field.avl_left; \
|
||||
self->field.avl_left= l->field.avl_right; \
|
||||
@ -86,7 +93,7 @@
|
||||
return TREE_BALANCE_##node##_##field(l); \
|
||||
} \
|
||||
\
|
||||
struct node *TREE_BALANCE_##node##_##field(struct node *self) \
|
||||
static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *self) \
|
||||
{ \
|
||||
int delta= TREE_DELTA(self, field); \
|
||||
\
|
||||
@ -111,7 +118,7 @@
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
struct node *TREE_INSERT_##node##_##field \
|
||||
static struct node *_HU_FUNCTION(TREE_INSERT_##node##_##field) \
|
||||
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
|
||||
{ \
|
||||
if (!self) \
|
||||
@ -123,7 +130,7 @@
|
||||
return TREE_BALANCE_##node##_##field(self); \
|
||||
} \
|
||||
\
|
||||
struct node *TREE_FIND_##node##_##field \
|
||||
static struct node *_HU_FUNCTION(TREE_FIND_##node##_##field) \
|
||||
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
|
||||
{ \
|
||||
if (!self) \
|
||||
@ -136,7 +143,7 @@
|
||||
return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
|
||||
} \
|
||||
\
|
||||
struct node *TREE_MOVE_RIGHT(struct node *self, struct node *rhs) \
|
||||
static struct node *_HU_FUNCTION(TREE_MOVE_RIGHT)(struct node *self, struct node *rhs) \
|
||||
{ \
|
||||
if (!self) \
|
||||
return rhs; \
|
||||
@ -144,7 +151,7 @@
|
||||
return TREE_BALANCE_##node##_##field(self); \
|
||||
} \
|
||||
\
|
||||
struct node *TREE_REMOVE_##node##_##field \
|
||||
static struct node *_HU_FUNCTION(TREE_REMOVE_##node##_##field) \
|
||||
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
|
||||
{ \
|
||||
if (!self) return 0; \
|
||||
@ -163,7 +170,7 @@
|
||||
return TREE_BALANCE_##node##_##field(self); \
|
||||
} \
|
||||
\
|
||||
void TREE_FORWARD_APPLY_ALL_##node##_##field \
|
||||
static void _HU_FUNCTION(TREE_FORWARD_APPLY_ALL_##node##_##field) \
|
||||
(struct node *self, void (*function)(struct node *node, void *data), void *data) \
|
||||
{ \
|
||||
if (self) \
|
||||
@ -174,7 +181,7 @@
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void TREE_REVERSE_APPLY_ALL_##node##_##field \
|
||||
static void _HU_FUNCTION(TREE_REVERSE_APPLY_ALL_##node##_##field) \
|
||||
(struct node *self, void (*function)(struct node *node, void *data), void *data) \
|
||||
{ \
|
||||
if (self) \
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include "ucl_internal.h"
|
||||
|
||||
static const unsigned int ucl_chartable[255] = {
|
||||
static const unsigned int ucl_chartable[256] = {
|
||||
UCL_CHARACTER_VALUE_END, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
|
||||
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
|
||||
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
|
||||
@ -255,6 +255,7 @@ UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
|
||||
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
|
||||
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
|
||||
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
|
||||
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
|
||||
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,7 @@ UCL_EMIT_TYPE_OPS(json);
|
||||
UCL_EMIT_TYPE_OPS(json_compact);
|
||||
UCL_EMIT_TYPE_OPS(config);
|
||||
UCL_EMIT_TYPE_OPS(yaml);
|
||||
UCL_EMIT_TYPE_OPS(msgpack);
|
||||
|
||||
#define UCL_EMIT_TYPE_CONTENT(type) { \
|
||||
.ucl_emitter_write_elt = ucl_emit_ ## type ## _elt, \
|
||||
@ -71,12 +72,12 @@ UCL_EMIT_TYPE_OPS(yaml);
|
||||
.ucl_emitter_end_array = ucl_emit_ ## type ##_end_array \
|
||||
}
|
||||
|
||||
|
||||
const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = {
|
||||
[UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json),
|
||||
[UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact),
|
||||
[UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config),
|
||||
[UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml)
|
||||
[UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml),
|
||||
[UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack)
|
||||
};
|
||||
|
||||
/*
|
||||
@ -469,19 +470,150 @@ UCL_EMIT_TYPE_IMPL(json_compact, true)
|
||||
UCL_EMIT_TYPE_IMPL(config, false)
|
||||
UCL_EMIT_TYPE_IMPL(yaml, false)
|
||||
|
||||
static void
|
||||
ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
|
||||
const ucl_object_t *obj, bool first, bool print_key)
|
||||
{
|
||||
ucl_object_iter_t it;
|
||||
struct ucl_object_userdata *ud;
|
||||
const char *ud_out;
|
||||
const ucl_object_t *cur, *celt;
|
||||
|
||||
switch (obj->type) {
|
||||
case UCL_INT:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj));
|
||||
break;
|
||||
|
||||
case UCL_FLOAT:
|
||||
case UCL_TIME:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj));
|
||||
break;
|
||||
|
||||
case UCL_BOOLEAN:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj));
|
||||
break;
|
||||
|
||||
case UCL_STRING:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
|
||||
if (obj->flags & UCL_OBJECT_BINARY) {
|
||||
ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv,
|
||||
obj->len);
|
||||
}
|
||||
else {
|
||||
ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
|
||||
}
|
||||
break;
|
||||
|
||||
case UCL_NULL:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
ucl_emitter_print_null_msgpack (ctx);
|
||||
break;
|
||||
|
||||
case UCL_OBJECT:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
ucl_emit_msgpack_start_obj (ctx, obj, print_key);
|
||||
it = NULL;
|
||||
|
||||
while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
|
||||
LL_FOREACH (cur, celt) {
|
||||
ucl_emit_msgpack_elt (ctx, celt, false, true);
|
||||
/* XXX:
|
||||
* in msgpack the length of objects is encoded within a single elt
|
||||
* so in case of multi-value keys we are using merely the first
|
||||
* element ignoring others
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UCL_ARRAY:
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
ucl_emit_msgpack_start_array (ctx, obj, print_key);
|
||||
it = NULL;
|
||||
|
||||
while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
|
||||
ucl_emit_msgpack_elt (ctx, cur, false, false);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UCL_USERDATA:
|
||||
ud = (struct ucl_object_userdata *)obj;
|
||||
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
|
||||
|
||||
if (ud->emitter) {
|
||||
ud_out = ud->emitter (obj->value.ud);
|
||||
if (ud_out == NULL) {
|
||||
ud_out = "null";
|
||||
}
|
||||
}
|
||||
ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
|
||||
const ucl_object_t *obj, bool print_key)
|
||||
{
|
||||
ucl_emitter_print_object_msgpack (ctx, obj->len);
|
||||
}
|
||||
|
||||
static void
|
||||
ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
|
||||
const ucl_object_t *obj, bool print_key)
|
||||
{
|
||||
ucl_emitter_print_array_msgpack (ctx, obj->len);
|
||||
}
|
||||
|
||||
static void
|
||||
ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx,
|
||||
const ucl_object_t *obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx,
|
||||
const ucl_object_t *obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
|
||||
{
|
||||
return ucl_object_emit_len (obj, emit_type, NULL);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
|
||||
size_t *outlen)
|
||||
{
|
||||
unsigned char *res = NULL;
|
||||
struct ucl_emitter_functions *func;
|
||||
UT_string *s;
|
||||
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
func = ucl_object_emit_memory_funcs ((void **)&res);
|
||||
s = func->ud;
|
||||
|
||||
if (func != NULL) {
|
||||
ucl_object_emit_full (obj, emit_type, func);
|
||||
|
||||
if (outlen != NULL) {
|
||||
*outlen = s->i;
|
||||
}
|
||||
|
||||
ucl_object_emit_funcs_free (func);
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,12 @@ static const struct ucl_emitter_context ucl_standard_emitters[] = {
|
||||
.id = UCL_EMIT_YAML,
|
||||
.func = NULL,
|
||||
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML]
|
||||
},
|
||||
[UCL_EMIT_MSGPACK] = {
|
||||
.name = "msgpack",
|
||||
.id = UCL_EMIT_MSGPACK,
|
||||
.func = NULL,
|
||||
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_MSGPACK]
|
||||
}
|
||||
};
|
||||
|
||||
@ -73,7 +79,7 @@ static const struct ucl_emitter_context ucl_standard_emitters[] = {
|
||||
const struct ucl_emitter_context *
|
||||
ucl_emit_get_standard_context (enum ucl_emitter emit_type)
|
||||
{
|
||||
if (emit_type >= UCL_EMIT_JSON && emit_type <= UCL_EMIT_YAML) {
|
||||
if (emit_type >= UCL_EMIT_JSON && emit_type < UCL_EMIT_MAX) {
|
||||
return &ucl_standard_emitters[emit_type];
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,9 @@
|
||||
#include "khash.h"
|
||||
#include "kvec.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
struct ucl_hash_elt {
|
||||
const ucl_object_t *obj;
|
||||
size_t ar_idx;
|
||||
@ -37,11 +40,78 @@ struct ucl_hash_struct {
|
||||
bool caseless;
|
||||
};
|
||||
|
||||
static uint64_t
|
||||
ucl_hash_seed (void)
|
||||
{
|
||||
static uint64_t seed;
|
||||
|
||||
if (seed == 0) {
|
||||
#ifdef UCL_RANDOM_FUNCTION
|
||||
seed = UCL_RANDOM_FUNCTION;
|
||||
#else
|
||||
/* Not very random but can be useful for our purposes */
|
||||
seed = time (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
static const unsigned char lc_map[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
#if (defined(WORD_BIT) && WORD_BIT == 64) || \
|
||||
(defined(__WORDSIZE) && __WORDSIZE == 64) || \
|
||||
defined(__x86_64__) || \
|
||||
defined(__amd64__)
|
||||
#define UCL64_BIT_HASH 1
|
||||
#endif
|
||||
|
||||
#ifdef UCL64_BIT_HASH
|
||||
static inline uint32_t
|
||||
ucl_hash_func (const ucl_object_t *o)
|
||||
{
|
||||
return XXH32 (o->key, o->keylen, 0xdeadbeef);
|
||||
return XXH64 (o->key, o->keylen, ucl_hash_seed ());
|
||||
}
|
||||
#else
|
||||
static inline uint32_t
|
||||
ucl_hash_func (const ucl_object_t *o)
|
||||
{
|
||||
return XXH32 (o->key, o->keylen, ucl_hash_seed ());
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
|
||||
@ -56,33 +126,91 @@ ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
|
||||
KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1,
|
||||
ucl_hash_func, ucl_hash_equal)
|
||||
|
||||
#ifdef UCL64_BIT_HASH
|
||||
static inline uint32_t
|
||||
ucl_hash_caseless_func (const ucl_object_t *o)
|
||||
{
|
||||
void *xxh = XXH32_init (0xdeadbeef);
|
||||
char hash_buf[64], *c;
|
||||
const char *p;
|
||||
ssize_t remain = o->keylen;
|
||||
unsigned len = o->keylen;
|
||||
unsigned leftover = o->keylen % 4;
|
||||
unsigned fp, i;
|
||||
const uint8_t* s = (const uint8_t*)o->key;
|
||||
union {
|
||||
struct {
|
||||
unsigned char c1, c2, c3, c4;
|
||||
} c;
|
||||
uint32_t pp;
|
||||
} u;
|
||||
XXH64_state_t st;
|
||||
|
||||
p = o->key;
|
||||
c = &hash_buf[0];
|
||||
fp = len - leftover;
|
||||
XXH64_reset (&st, ucl_hash_seed ());
|
||||
|
||||
while (remain > 0) {
|
||||
*c++ = tolower (*p++);
|
||||
|
||||
if (c - &hash_buf[0] == sizeof (hash_buf)) {
|
||||
XXH32_update (xxh, hash_buf, sizeof (hash_buf));
|
||||
c = &hash_buf[0];
|
||||
}
|
||||
remain --;
|
||||
for (i = 0; i != fp; i += 4) {
|
||||
u.c.c1 = s[i], u.c.c2 = s[i + 1], u.c.c3 = s[i + 2], u.c.c4 = s[i + 3];
|
||||
u.c.c1 = lc_map[u.c.c1];
|
||||
u.c.c2 = lc_map[u.c.c2];
|
||||
u.c.c3 = lc_map[u.c.c3];
|
||||
u.c.c4 = lc_map[u.c.c4];
|
||||
XXH64_update (&st, &u.pp, sizeof (u));
|
||||
}
|
||||
|
||||
if (c - &hash_buf[0] != 0) {
|
||||
XXH32_update (xxh, hash_buf, c - &hash_buf[0]);
|
||||
u.pp = 0;
|
||||
switch (leftover) {
|
||||
case 3:
|
||||
u.c.c3 = lc_map[(unsigned char)s[i++]];
|
||||
case 2:
|
||||
u.c.c2 = lc_map[(unsigned char)s[i++]];
|
||||
case 1:
|
||||
u.c.c1 = lc_map[(unsigned char)s[i]];
|
||||
XXH64_update (&st, &u.pp, leftover);
|
||||
break;
|
||||
}
|
||||
|
||||
return XXH32_digest (xxh);
|
||||
return XXH64_digest (&st);
|
||||
}
|
||||
#else
|
||||
static inline uint32_t
|
||||
ucl_hash_caseless_func (const ucl_object_t *o)
|
||||
{
|
||||
unsigned len = o->keylen;
|
||||
unsigned leftover = o->keylen % 4;
|
||||
unsigned fp, i;
|
||||
const uint8_t* s = (const uint8_t*)o->key;
|
||||
union {
|
||||
struct {
|
||||
unsigned char c1, c2, c3, c4;
|
||||
} c;
|
||||
uint32_t pp;
|
||||
} u;
|
||||
XXH32_state_t st;
|
||||
|
||||
fp = len - leftover;
|
||||
XXH32_reset (&st, ucl_hash_seed ());
|
||||
|
||||
for (i = 0; i != fp; i += 4) {
|
||||
u.c.c1 = s[i], u.c.c2 = s[i + 1], u.c.c3 = s[i + 2], u.c.c4 = s[i + 3];
|
||||
u.c.c1 = lc_map[u.c.c1];
|
||||
u.c.c2 = lc_map[u.c.c2];
|
||||
u.c.c3 = lc_map[u.c.c3];
|
||||
u.c.c4 = lc_map[u.c.c4];
|
||||
XXH32_update (&st, &u.pp, sizeof (u));
|
||||
}
|
||||
|
||||
u.pp = 0;
|
||||
switch (leftover) {
|
||||
case 3:
|
||||
u.c.c3 = lc_map[(unsigned char)s[i++]];
|
||||
case 2:
|
||||
u.c.c2 = lc_map[(unsigned char)s[i++]];
|
||||
case 1:
|
||||
u.c.c1 = lc_map[(unsigned char)s[i]];
|
||||
XXH32_update (&st, &u.pp, leftover);
|
||||
break;
|
||||
}
|
||||
|
||||
return XXH32_digest (&st);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
|
||||
@ -254,6 +382,11 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
|
||||
|
||||
if (it == NULL) {
|
||||
it = UCL_ALLOC (sizeof (*it));
|
||||
|
||||
if (it == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
it->cur = &hashlin->ar.a[0];
|
||||
it->end = it->cur + hashlin->ar.n;
|
||||
}
|
||||
@ -336,7 +469,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
|
||||
k = kh_get (ucl_hash_caseless_node, h, obj);
|
||||
if (k != kh_end (h)) {
|
||||
elt = &kh_value (h, k);
|
||||
kv_A (hashlin->ar, elt->ar_idx) = NULL;
|
||||
kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
|
||||
kh_del (ucl_hash_caseless_node, h, k);
|
||||
}
|
||||
}
|
||||
@ -346,7 +479,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
|
||||
k = kh_get (ucl_hash_node, h, obj);
|
||||
if (k != kh_end (h)) {
|
||||
elt = &kh_value (h, k);
|
||||
kv_A (hashlin->ar, elt->ar_idx) = NULL;
|
||||
kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
|
||||
kh_del (ucl_hash_node, h, k);
|
||||
}
|
||||
}
|
||||
|
@ -145,15 +145,19 @@ enum ucl_character_type {
|
||||
|
||||
struct ucl_macro {
|
||||
char *name;
|
||||
union {
|
||||
ucl_macro_handler handler;
|
||||
ucl_context_macro_handler context_handler;
|
||||
} h;
|
||||
void* ud;
|
||||
bool is_context;
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct ucl_stack {
|
||||
ucl_object_t *obj;
|
||||
struct ucl_stack *next;
|
||||
int level;
|
||||
uint64_t level;
|
||||
};
|
||||
|
||||
struct ucl_chunk {
|
||||
@ -164,6 +168,8 @@ struct ucl_chunk {
|
||||
unsigned int line;
|
||||
unsigned int column;
|
||||
unsigned priority;
|
||||
enum ucl_duplicate_strategy strategy;
|
||||
enum ucl_parse_type parse_type;
|
||||
struct ucl_chunk *next;
|
||||
};
|
||||
|
||||
@ -191,8 +197,12 @@ struct ucl_parser {
|
||||
enum ucl_parser_state prev_state;
|
||||
unsigned int recursion;
|
||||
int flags;
|
||||
unsigned default_priority;
|
||||
int err_code;
|
||||
ucl_object_t *top_obj;
|
||||
ucl_object_t *cur_obj;
|
||||
ucl_object_t *trash_objs;
|
||||
ucl_object_t *includepaths;
|
||||
char *cur_file;
|
||||
struct ucl_macro *macroes;
|
||||
struct ucl_stack *stack;
|
||||
@ -220,13 +230,21 @@ size_t ucl_unescape_json_string (char *str, size_t len);
|
||||
* Handle include macro
|
||||
* @param data include data
|
||||
* @param len length of data
|
||||
* @param args UCL object representing arguments to the macro
|
||||
* @param ud user data
|
||||
* @param err error ptr
|
||||
* @return
|
||||
*/
|
||||
bool ucl_include_handler (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *args, void* ud);
|
||||
|
||||
/**
|
||||
* Handle tryinclude macro
|
||||
* @param data include data
|
||||
* @param len length of data
|
||||
* @param args UCL object representing arguments to the macro
|
||||
* @param ud user data
|
||||
* @return
|
||||
*/
|
||||
bool ucl_try_include_handler (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *args, void* ud);
|
||||
|
||||
@ -234,17 +252,52 @@ bool ucl_try_include_handler (const unsigned char *data, size_t len,
|
||||
* Handle includes macro
|
||||
* @param data include data
|
||||
* @param len length of data
|
||||
* @param args UCL object representing arguments to the macro
|
||||
* @param ud user data
|
||||
* @param err error ptr
|
||||
* @return
|
||||
*/
|
||||
bool ucl_includes_handler (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *args, void* ud);
|
||||
|
||||
/**
|
||||
* Handle priority macro
|
||||
* @param data include data
|
||||
* @param len length of data
|
||||
* @param args UCL object representing arguments to the macro
|
||||
* @param ud user data
|
||||
* @return
|
||||
*/
|
||||
bool ucl_priority_handler (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *args, void* ud);
|
||||
|
||||
/**
|
||||
* Handle load macro
|
||||
* @param data include data
|
||||
* @param len length of data
|
||||
* @param args UCL object representing arguments to the macro
|
||||
* @param ud user data
|
||||
* @return
|
||||
*/
|
||||
bool ucl_load_handler (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *args, void* ud);
|
||||
/**
|
||||
* Handle inherit macro
|
||||
* @param data include data
|
||||
* @param len length of data
|
||||
* @param args UCL object representing arguments to the macro
|
||||
* @param ctx the current context object
|
||||
* @param ud user data
|
||||
* @return
|
||||
*/
|
||||
bool ucl_inherit_handler (const unsigned char *data, size_t len,
|
||||
const ucl_object_t *args, const ucl_object_t *ctx, void* ud);
|
||||
|
||||
size_t ucl_strlcpy (char *dst, const char *src, size_t siz);
|
||||
size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
|
||||
size_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz);
|
||||
|
||||
char *ucl_strnstr (const char *s, const char *find, int len);
|
||||
char *ucl_strncasestr (const char *s, const char *find, int len);
|
||||
|
||||
#ifdef __GNUC__
|
||||
static inline void
|
||||
@ -252,9 +305,10 @@ ucl_create_err (UT_string **err, const char *fmt, ...)
|
||||
__attribute__ (( format( printf, 2, 3) ));
|
||||
#endif
|
||||
|
||||
#undef UCL_FATAL_ERRORS
|
||||
|
||||
static inline void
|
||||
ucl_create_err (UT_string **err, const char *fmt, ...)
|
||||
|
||||
{
|
||||
if (*err == NULL) {
|
||||
utstring_new (*err);
|
||||
@ -263,6 +317,10 @@ ucl_create_err (UT_string **err, const char *fmt, ...)
|
||||
utstring_printf_va (*err, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
#ifdef UCL_FATAL_ERRORS
|
||||
assert (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,7 +369,7 @@ ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t l
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (ret && obj != NULL) {
|
||||
obj->type = UCL_BOOLEAN;
|
||||
obj->value.iv = val;
|
||||
}
|
||||
@ -396,4 +454,89 @@ unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
|
||||
*/
|
||||
bool ucl_maybe_long_string (const ucl_object_t *obj);
|
||||
|
||||
/**
|
||||
* Print integer to the msgpack output
|
||||
* @param ctx
|
||||
* @param val
|
||||
*/
|
||||
void ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx,
|
||||
int64_t val);
|
||||
/**
|
||||
* Print integer to the msgpack output
|
||||
* @param ctx
|
||||
* @param val
|
||||
*/
|
||||
void ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx,
|
||||
double val);
|
||||
/**
|
||||
* Print double to the msgpack output
|
||||
* @param ctx
|
||||
* @param val
|
||||
*/
|
||||
void ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx,
|
||||
bool val);
|
||||
/**
|
||||
* Print string to the msgpack output
|
||||
* @param ctx
|
||||
* @param s
|
||||
* @param len
|
||||
*/
|
||||
void ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
|
||||
const char *s, size_t len);
|
||||
|
||||
/**
|
||||
* Print binary string to the msgpack output
|
||||
* @param ctx
|
||||
* @param s
|
||||
* @param len
|
||||
*/
|
||||
void ucl_emitter_print_binary_string_msgpack (struct ucl_emitter_context *ctx,
|
||||
const char *s, size_t len);
|
||||
|
||||
/**
|
||||
* Print array preamble for msgpack
|
||||
* @param ctx
|
||||
* @param len
|
||||
*/
|
||||
void ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* Print object preamble for msgpack
|
||||
* @param ctx
|
||||
* @param len
|
||||
*/
|
||||
void ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx,
|
||||
size_t len);
|
||||
/**
|
||||
* Print NULL to the msgpack output
|
||||
* @param ctx
|
||||
*/
|
||||
void ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx);
|
||||
/**
|
||||
* Print object's key if needed to the msgpack output
|
||||
* @param print_key
|
||||
* @param ctx
|
||||
* @param obj
|
||||
*/
|
||||
void ucl_emitter_print_key_msgpack (bool print_key,
|
||||
struct ucl_emitter_context *ctx,
|
||||
const ucl_object_t *obj);
|
||||
|
||||
/**
|
||||
* Add new element to an object using the current merge strategy and priority
|
||||
* @param parser
|
||||
* @param nobj
|
||||
* @return
|
||||
*/
|
||||
bool ucl_parser_process_object_element (struct ucl_parser *parser,
|
||||
ucl_object_t *nobj);
|
||||
|
||||
/**
|
||||
* Parse msgpack chunk
|
||||
* @param parser
|
||||
* @return
|
||||
*/
|
||||
bool ucl_parse_msgpack (struct ucl_parser *parser);
|
||||
|
||||
#endif /* UCL_INTERNAL_H_ */
|
||||
|
1600
contrib/libucl/src/ucl_msgpack.c
Normal file
1600
contrib/libucl/src/ucl_msgpack.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -67,6 +67,7 @@ ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **e
|
||||
else {
|
||||
filename = "<unknown>";
|
||||
}
|
||||
|
||||
if (chunk->pos < chunk->end) {
|
||||
if (isgraph (*chunk->pos)) {
|
||||
fmt_string = "error while parsing %s: "
|
||||
@ -84,6 +85,8 @@ ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **e
|
||||
ucl_create_err (err, "error while parsing %s: at the end of chunk: %s",
|
||||
filename, str);
|
||||
}
|
||||
|
||||
parser->err_code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -513,7 +516,7 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser,
|
||||
/* Copy string */
|
||||
*dst = UCL_ALLOC (in_len + 1);
|
||||
if (*dst == NULL) {
|
||||
ucl_set_err (parser, 0, "cannot allocate memory for a string",
|
||||
ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for a string",
|
||||
&parser->err);
|
||||
return false;
|
||||
}
|
||||
@ -559,7 +562,8 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser,
|
||||
* @return
|
||||
*/
|
||||
static inline ucl_object_t *
|
||||
ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_array, int level)
|
||||
ucl_parser_add_container (ucl_object_t *obj, struct ucl_parser *parser,
|
||||
bool is_array, int level)
|
||||
{
|
||||
struct ucl_stack *st;
|
||||
|
||||
@ -570,7 +574,9 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra
|
||||
else {
|
||||
obj->type = UCL_OBJECT;
|
||||
}
|
||||
if (obj->value.ov == NULL) {
|
||||
obj->value.ov = ucl_hash_create (parser->flags & UCL_PARSER_KEY_LOWERCASE);
|
||||
}
|
||||
parser->state = UCL_STATE_KEY;
|
||||
}
|
||||
else {
|
||||
@ -585,7 +591,7 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra
|
||||
|
||||
st = UCL_ALLOC (sizeof (struct ucl_stack));
|
||||
if (st == NULL) {
|
||||
ucl_set_err (parser, 0, "cannot allocate memory for an object",
|
||||
ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for an object",
|
||||
&parser->err);
|
||||
ucl_object_unref (obj);
|
||||
return NULL;
|
||||
@ -835,6 +841,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
|
||||
return EINVAL;
|
||||
|
||||
set_obj:
|
||||
if (obj != NULL) {
|
||||
if (allow_double && (need_double || is_time)) {
|
||||
if (!is_time) {
|
||||
obj->type = UCL_FLOAT;
|
||||
@ -848,6 +855,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
|
||||
obj->type = UCL_INT;
|
||||
obj->value.iv = is_neg ? (-lv) : lv;
|
||||
}
|
||||
}
|
||||
*pos = p;
|
||||
return 0;
|
||||
}
|
||||
@ -856,6 +864,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
|
||||
* Parse possible number
|
||||
* @param parser
|
||||
* @param chunk
|
||||
* @param obj
|
||||
* @return true if a number has been parsed
|
||||
*/
|
||||
static bool
|
||||
@ -875,7 +884,8 @@ ucl_lex_number (struct ucl_parser *parser,
|
||||
return true;
|
||||
}
|
||||
else if (ret == ERANGE) {
|
||||
ucl_set_err (parser, ERANGE, "numeric value out of range", &parser->err);
|
||||
ucl_set_err (parser, UCL_ESYNTAX, "numeric value out of range",
|
||||
&parser->err);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -885,6 +895,9 @@ ucl_lex_number (struct ucl_parser *parser,
|
||||
* Parse quoted string with possible escapes
|
||||
* @param parser
|
||||
* @param chunk
|
||||
* @param need_unescape
|
||||
* @param ucl_escape
|
||||
* @param var_expand
|
||||
* @return true if a string has been parsed
|
||||
*/
|
||||
static bool
|
||||
@ -971,6 +984,7 @@ ucl_parser_append_elt (struct ucl_parser *parser, ucl_hash_t *cont,
|
||||
/* Implicit array */
|
||||
top->flags |= UCL_OBJECT_MULTIVALUE;
|
||||
DL_APPEND (top, elt);
|
||||
parser->stack->obj->len ++;
|
||||
}
|
||||
else {
|
||||
if ((top->flags & UCL_OBJECT_MULTIVALUE) != 0) {
|
||||
@ -979,34 +993,127 @@ ucl_parser_append_elt (struct ucl_parser *parser, ucl_hash_t *cont,
|
||||
}
|
||||
else {
|
||||
/* Convert to an array */
|
||||
ucl_hash_delete (cont, top);
|
||||
nobj = ucl_object_typed_new (UCL_ARRAY);
|
||||
nobj->key = top->key;
|
||||
nobj->keylen = top->keylen;
|
||||
nobj->flags |= UCL_OBJECT_MULTIVALUE;
|
||||
ucl_array_append (nobj, top);
|
||||
ucl_array_append (nobj, elt);
|
||||
ucl_hash_insert (cont, nobj, nobj->key, nobj->keylen);
|
||||
ucl_hash_replace (cont, top, nobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj)
|
||||
{
|
||||
ucl_hash_t *container;
|
||||
ucl_object_t *tobj;
|
||||
|
||||
container = parser->stack->obj->value.ov;
|
||||
|
||||
tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj));
|
||||
if (tobj == NULL) {
|
||||
container = ucl_hash_insert_object (container, nobj,
|
||||
parser->flags & UCL_PARSER_KEY_LOWERCASE);
|
||||
nobj->prev = nobj;
|
||||
nobj->next = NULL;
|
||||
parser->stack->obj->len ++;
|
||||
}
|
||||
else {
|
||||
unsigned priold = ucl_object_get_priority (tobj),
|
||||
prinew = ucl_object_get_priority (nobj);
|
||||
switch (parser->chunks->strategy) {
|
||||
|
||||
case UCL_DUPLICATE_APPEND:
|
||||
/*
|
||||
* The logic here is the following:
|
||||
*
|
||||
* - if we have two objects with the same priority, then we form an
|
||||
* implicit or explicit array
|
||||
* - if a new object has bigger priority, then we overwrite an old one
|
||||
* - if a new object has lower priority, then we ignore it
|
||||
*/
|
||||
|
||||
|
||||
/* Special case for inherited objects */
|
||||
if (tobj->flags & UCL_OBJECT_INHERITED) {
|
||||
prinew = priold + 1;
|
||||
}
|
||||
|
||||
if (priold == prinew) {
|
||||
ucl_parser_append_elt (parser, container, tobj, nobj);
|
||||
}
|
||||
else if (priold > prinew) {
|
||||
/*
|
||||
* We add this new object to a list of trash objects just to ensure
|
||||
* that it won't come to any real object
|
||||
* XXX: rather inefficient approach
|
||||
*/
|
||||
DL_APPEND (parser->trash_objs, nobj);
|
||||
}
|
||||
else {
|
||||
ucl_hash_replace (container, tobj, nobj);
|
||||
ucl_object_unref (tobj);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UCL_DUPLICATE_REWRITE:
|
||||
/* We just rewrite old values regardless of priority */
|
||||
ucl_hash_replace (container, tobj, nobj);
|
||||
ucl_object_unref (tobj);
|
||||
|
||||
break;
|
||||
|
||||
case UCL_DUPLICATE_ERROR:
|
||||
ucl_create_err (&parser->err, "error while parsing %s: "
|
||||
"line: %d, column: %d: duplicate element for key '%s' "
|
||||
"has been found",
|
||||
parser->cur_file ? parser->cur_file : "<unknown>",
|
||||
parser->chunks->line, parser->chunks->column, nobj->key);
|
||||
return false;
|
||||
|
||||
case UCL_DUPLICATE_MERGE:
|
||||
/*
|
||||
* Here we do have some old object so we just push it on top of objects stack
|
||||
*/
|
||||
if (tobj->type == UCL_OBJECT || tobj->type == UCL_ARRAY) {
|
||||
ucl_object_unref (nobj);
|
||||
nobj = tobj;
|
||||
}
|
||||
else {
|
||||
/* For other types we create implicit array as usual */
|
||||
ucl_parser_append_elt (parser, container, tobj, nobj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parser->stack->obj->value.ov = container;
|
||||
parser->cur_obj = nobj;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a key in an object
|
||||
* @param parser
|
||||
* @param chunk
|
||||
* @param next_key
|
||||
* @param end_of_object
|
||||
* @return true if a key has been parsed
|
||||
*/
|
||||
static bool
|
||||
ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_key, bool *end_of_object)
|
||||
ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk,
|
||||
bool *next_key, bool *end_of_object)
|
||||
{
|
||||
const unsigned char *p, *c = NULL, *end, *t;
|
||||
const char *key = NULL;
|
||||
bool got_quote = false, got_eq = false, got_semicolon = false,
|
||||
need_unescape = false, ucl_escape = false, var_expand = false,
|
||||
got_content = false, got_sep = false;
|
||||
ucl_object_t *nobj, *tobj;
|
||||
ucl_hash_t *container;
|
||||
ucl_object_t *nobj;
|
||||
ssize_t keylen;
|
||||
|
||||
p = chunk->pos;
|
||||
@ -1191,47 +1298,17 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
|
||||
return false;
|
||||
}
|
||||
|
||||
container = parser->stack->obj->value.ov;
|
||||
nobj->key = key;
|
||||
nobj->keylen = keylen;
|
||||
tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj));
|
||||
if (tobj == NULL) {
|
||||
container = ucl_hash_insert_object (container, nobj,
|
||||
parser->flags & UCL_PARSER_KEY_LOWERCASE);
|
||||
nobj->prev = nobj;
|
||||
nobj->next = NULL;
|
||||
parser->stack->obj->len ++;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* The logic here is the following:
|
||||
*
|
||||
* - if we have two objects with the same priority, then we form an
|
||||
* implicit or explicit array
|
||||
* - if a new object has bigger priority, then we overwrite an old one
|
||||
* - if a new object has lower priority, then we ignore it
|
||||
*/
|
||||
unsigned priold = ucl_object_get_priority (tobj),
|
||||
prinew = ucl_object_get_priority (nobj);
|
||||
if (priold == prinew) {
|
||||
ucl_parser_append_elt (parser, container, tobj, nobj);
|
||||
}
|
||||
else if (priold > prinew) {
|
||||
ucl_object_unref (nobj);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ucl_hash_replace (container, tobj, nobj);
|
||||
ucl_object_unref (tobj);
|
||||
}
|
||||
|
||||
if (!ucl_parser_process_object_element (parser, nobj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ucl_escape) {
|
||||
nobj->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
|
||||
}
|
||||
parser->stack->obj->value.ov = container;
|
||||
|
||||
parser->cur_obj = nobj;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1240,6 +1317,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
|
||||
* Parse a cl string
|
||||
* @param parser
|
||||
* @param chunk
|
||||
* @param var_expand
|
||||
* @param need_unescape
|
||||
* @return true if a key has been parsed
|
||||
*/
|
||||
static bool
|
||||
@ -1309,6 +1388,8 @@ ucl_parse_string_value (struct ucl_parser *parser,
|
||||
* @param chunk
|
||||
* @param term
|
||||
* @param term_len
|
||||
* @param beg
|
||||
* @param var_expand
|
||||
* @return size of multiline string or 0 in case of error
|
||||
*/
|
||||
static int
|
||||
@ -1360,8 +1441,8 @@ ucl_parse_multiline_string (struct ucl_parser *parser,
|
||||
return len;
|
||||
}
|
||||
|
||||
static ucl_object_t*
|
||||
ucl_get_value_object (struct ucl_parser *parser)
|
||||
static inline ucl_object_t*
|
||||
ucl_parser_get_container (struct ucl_parser *parser)
|
||||
{
|
||||
ucl_object_t *t, *obj = NULL;
|
||||
|
||||
@ -1373,7 +1454,12 @@ ucl_get_value_object (struct ucl_parser *parser)
|
||||
/* Object must be allocated */
|
||||
obj = ucl_object_new_full (UCL_NULL, parser->chunks->priority);
|
||||
t = parser->stack->obj;
|
||||
ucl_array_append (t, obj);
|
||||
|
||||
if (!ucl_array_append (t, obj)) {
|
||||
ucl_object_unref (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parser->cur_obj = obj;
|
||||
}
|
||||
else {
|
||||
@ -1417,42 +1503,51 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
c = p;
|
||||
switch (*p) {
|
||||
case '"':
|
||||
obj = ucl_get_value_object (parser);
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape, &var_expand)) {
|
||||
|
||||
if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape,
|
||||
&var_expand)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
obj = ucl_parser_get_container (parser);
|
||||
str_len = chunk->pos - c - 2;
|
||||
obj->type = UCL_STRING;
|
||||
if ((str_len = ucl_copy_or_store_ptr (parser, c + 1, &obj->trash_stack[UCL_TRASH_VALUE],
|
||||
&obj->value.sv, str_len, need_unescape, false, var_expand)) == -1) {
|
||||
if ((str_len = ucl_copy_or_store_ptr (parser, c + 1,
|
||||
&obj->trash_stack[UCL_TRASH_VALUE],
|
||||
&obj->value.sv, str_len, need_unescape, false,
|
||||
var_expand)) == -1) {
|
||||
return false;
|
||||
}
|
||||
obj->len = str_len;
|
||||
|
||||
parser->state = UCL_STATE_AFTER_VALUE;
|
||||
p = chunk->pos;
|
||||
|
||||
return true;
|
||||
break;
|
||||
case '{':
|
||||
obj = ucl_get_value_object (parser);
|
||||
obj = ucl_parser_get_container (parser);
|
||||
/* We have a new object */
|
||||
obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level);
|
||||
obj = ucl_parser_add_container (obj, parser, false, parser->stack->level);
|
||||
if (obj == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
|
||||
return true;
|
||||
break;
|
||||
case '[':
|
||||
obj = ucl_get_value_object (parser);
|
||||
obj = ucl_parser_get_container (parser);
|
||||
/* We have a new array */
|
||||
obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level);
|
||||
obj = ucl_parser_add_container (obj, parser, true, parser->stack->level);
|
||||
if (obj == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
|
||||
return true;
|
||||
break;
|
||||
case ']':
|
||||
@ -1466,7 +1561,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
obj = ucl_get_value_object (parser);
|
||||
obj = ucl_parser_get_container (parser);
|
||||
/* We have something like multiline value, which must be <<[A-Z]+\n */
|
||||
if (chunk->end - p > 3) {
|
||||
if (memcmp (p, "<<", 2) == 0) {
|
||||
@ -1488,13 +1583,19 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
"unterminated multiline value", &parser->err);
|
||||
return false;
|
||||
}
|
||||
|
||||
obj->type = UCL_STRING;
|
||||
if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
|
||||
&obj->value.sv, str_len - 1, false, false, var_expand)) == -1) {
|
||||
obj->flags |= UCL_OBJECT_MULTILINE;
|
||||
if ((str_len = ucl_copy_or_store_ptr (parser, c,
|
||||
&obj->trash_stack[UCL_TRASH_VALUE],
|
||||
&obj->value.sv, str_len - 1, false,
|
||||
false, var_expand)) == -1) {
|
||||
return false;
|
||||
}
|
||||
obj->len = str_len;
|
||||
|
||||
parser->state = UCL_STATE_AFTER_VALUE;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1503,8 +1604,9 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
default:
|
||||
parse_string:
|
||||
if (obj == NULL) {
|
||||
obj = ucl_get_value_object (parser);
|
||||
obj = ucl_parser_get_container (parser);
|
||||
}
|
||||
|
||||
/* Parse atom */
|
||||
if (ucl_test_character (*p, UCL_CHARACTER_VALUE_DIGIT_START)) {
|
||||
if (!ucl_lex_number (parser, chunk, obj)) {
|
||||
@ -1519,7 +1621,8 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
/* Fallback to normal string */
|
||||
}
|
||||
|
||||
if (!ucl_parse_string_value (parser, chunk, &var_expand, &need_unescape)) {
|
||||
if (!ucl_parse_string_value (parser, chunk, &var_expand,
|
||||
&need_unescape)) {
|
||||
return false;
|
||||
}
|
||||
/* Cut trailing spaces */
|
||||
@ -1530,7 +1633,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
}
|
||||
str_len = chunk->pos - c - stripped_spaces;
|
||||
if (str_len <= 0) {
|
||||
ucl_set_err (parser, 0, "string value must not be empty",
|
||||
ucl_set_err (parser, UCL_ESYNTAX, "string value must not be empty",
|
||||
&parser->err);
|
||||
return false;
|
||||
}
|
||||
@ -1540,7 +1643,8 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
}
|
||||
else if (!ucl_maybe_parse_boolean (obj, c, str_len)) {
|
||||
obj->type = UCL_STRING;
|
||||
if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
|
||||
if ((str_len = ucl_copy_or_store_ptr (parser, c,
|
||||
&obj->trash_stack[UCL_TRASH_VALUE],
|
||||
&obj->value.sv, str_len, need_unescape,
|
||||
false, var_expand)) == -1) {
|
||||
return false;
|
||||
@ -1652,6 +1756,9 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
|
||||
* Handle macro data
|
||||
* @param parser
|
||||
* @param chunk
|
||||
* @param marco
|
||||
* @param macro_start
|
||||
* @param macro_len
|
||||
* @return
|
||||
*/
|
||||
static bool
|
||||
@ -1790,6 +1897,7 @@ ucl_parse_macro_arguments (struct ucl_parser *parser,
|
||||
if (chunk->remain == 0) {
|
||||
goto restore_chunk;
|
||||
}
|
||||
args_len ++;
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
break;
|
||||
case 99:
|
||||
@ -1842,8 +1950,6 @@ ucl_parse_macro_arguments (struct ucl_parser *parser,
|
||||
/**
|
||||
* Handle the main states of rcl parser
|
||||
* @param parser parser structure
|
||||
* @param data the pointer to the beginning of a chunk
|
||||
* @param len the length of a chunk
|
||||
* @return true if chunk has been parsed and false in case of error
|
||||
*/
|
||||
static bool
|
||||
@ -1858,17 +1964,6 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
bool next_key = false, end_of_object = false, ret;
|
||||
|
||||
if (parser->top_obj == NULL) {
|
||||
if (*chunk->pos == '[') {
|
||||
obj = ucl_add_parser_stack (NULL, parser, true, 0);
|
||||
}
|
||||
else {
|
||||
obj = ucl_add_parser_stack (NULL, parser, false, 0);
|
||||
}
|
||||
if (obj == NULL) {
|
||||
return false;
|
||||
}
|
||||
parser->top_obj = obj;
|
||||
parser->cur_obj = obj;
|
||||
parser->state = UCL_STATE_INIT;
|
||||
}
|
||||
|
||||
@ -1892,7 +1987,9 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
UCL_CHARACTER_WHITESPACE_UNSAFE)) {
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
}
|
||||
|
||||
p = chunk->pos;
|
||||
|
||||
if (*p == '[') {
|
||||
parser->state = UCL_STATE_VALUE;
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
@ -1903,6 +2000,23 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser->top_obj == NULL) {
|
||||
if (parser->state == UCL_STATE_VALUE) {
|
||||
obj = ucl_parser_add_container (NULL, parser, true, 0);
|
||||
}
|
||||
else {
|
||||
obj = ucl_parser_add_container (NULL, parser, false, 0);
|
||||
}
|
||||
|
||||
if (obj == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parser->top_obj = obj;
|
||||
parser->cur_obj = obj;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case UCL_STATE_KEY:
|
||||
@ -1936,7 +2050,7 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
else if (parser->state != UCL_STATE_MACRO_NAME) {
|
||||
if (next_key && parser->stack->obj->type == UCL_OBJECT) {
|
||||
/* Parse more keys and nest objects accordingly */
|
||||
obj = ucl_add_parser_stack (parser->cur_obj, parser, false,
|
||||
obj = ucl_parser_add_container (parser->cur_obj, parser, false,
|
||||
parser->stack->level + 1);
|
||||
if (obj == NULL) {
|
||||
return false;
|
||||
@ -1967,6 +2081,7 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
parser->state = UCL_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parser->stack != NULL) {
|
||||
if (parser->stack->obj->type == UCL_OBJECT) {
|
||||
parser->state = UCL_STATE_KEY;
|
||||
@ -1987,14 +2102,20 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
*p != '(') {
|
||||
ucl_chunk_skipc (chunk, p);
|
||||
}
|
||||
else if (p - c > 0) {
|
||||
else {
|
||||
if (p - c > 0) {
|
||||
/* We got macro name */
|
||||
macro_len = (size_t) (p - c);
|
||||
HASH_FIND (hh, parser->macroes, c, macro_len, macro);
|
||||
if (macro == NULL) {
|
||||
ucl_create_err (&parser->err, "error on line %d at column %d: "
|
||||
ucl_create_err (&parser->err,
|
||||
"error on line %d at column %d: "
|
||||
"unknown macro: '%.*s', character: '%c'",
|
||||
chunk->line, chunk->column, (int)(p - c), c, *chunk->pos);
|
||||
chunk->line,
|
||||
chunk->column,
|
||||
(int) (p - c),
|
||||
c,
|
||||
*chunk->pos);
|
||||
parser->state = UCL_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
@ -2002,6 +2123,16 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
SKIP_SPACES_COMMENTS(parser, chunk, p);
|
||||
parser->state = UCL_STATE_MACRO;
|
||||
}
|
||||
else {
|
||||
/* We have invalid macro name */
|
||||
ucl_create_err (&parser->err,
|
||||
"error on line %d at column %d: invalid macro name",
|
||||
chunk->line,
|
||||
chunk->column);
|
||||
parser->state = UCL_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UCL_STATE_MACRO:
|
||||
if (*chunk->pos == '(') {
|
||||
@ -2024,14 +2155,36 @@ ucl_state_machine (struct ucl_parser *parser)
|
||||
macro_start, macro_len);
|
||||
parser->state = parser->prev_state;
|
||||
if (macro_escaped == NULL) {
|
||||
ret = macro->handler (macro_start, macro_len, macro_args,
|
||||
if (macro->is_context) {
|
||||
ret = macro->h.context_handler (macro_start, macro_len,
|
||||
macro_args,
|
||||
parser->top_obj,
|
||||
macro->ud);
|
||||
}
|
||||
else {
|
||||
ret = macro->handler (macro_escaped, macro_len, macro_args,
|
||||
ret = macro->h.handler (macro_start, macro_len, macro_args,
|
||||
macro->ud);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (macro->is_context) {
|
||||
ret = macro->h.context_handler (macro_escaped, macro_len,
|
||||
macro_args,
|
||||
parser->top_obj,
|
||||
macro->ud);
|
||||
}
|
||||
else {
|
||||
ret = macro->h.handler (macro_escaped, macro_len, macro_args,
|
||||
macro->ud);
|
||||
}
|
||||
|
||||
UCL_FREE (macro_len + 1, macro_escaped);
|
||||
}
|
||||
|
||||
/*
|
||||
* Chunk can be modified within macro handler
|
||||
*/
|
||||
chunk = parser->chunks;
|
||||
p = chunk->pos;
|
||||
if (macro_args) {
|
||||
ucl_object_unref (macro_args);
|
||||
@ -2061,13 +2214,18 @@ ucl_parser_new (int flags)
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (new, 0, sizeof (struct ucl_parser));
|
||||
|
||||
ucl_parser_register_macro (new, "include", ucl_include_handler, new);
|
||||
ucl_parser_register_macro (new, "try_include", ucl_try_include_handler, new);
|
||||
ucl_parser_register_macro (new, "includes", ucl_includes_handler, new);
|
||||
ucl_parser_register_macro (new, "priority", ucl_priority_handler, new);
|
||||
ucl_parser_register_macro (new, "load", ucl_load_handler, new);
|
||||
ucl_parser_register_context_macro (new, "inherit", ucl_inherit_handler, new);
|
||||
|
||||
new->flags = flags;
|
||||
new->includepaths = NULL;
|
||||
|
||||
/* Initial assumption about filevars */
|
||||
ucl_parser_set_filevars (new, NULL, false);
|
||||
@ -2075,6 +2233,17 @@ ucl_parser_new (int flags)
|
||||
return new;
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_set_default_priority (struct ucl_parser *parser, unsigned prio)
|
||||
{
|
||||
if (parser == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parser->default_priority = prio;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
|
||||
@ -2085,17 +2254,42 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
|
||||
if (macro == NULL || handler == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
new = UCL_ALLOC (sizeof (struct ucl_macro));
|
||||
if (new == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset (new, 0, sizeof (struct ucl_macro));
|
||||
new->handler = handler;
|
||||
new->h.handler = handler;
|
||||
new->name = strdup (macro);
|
||||
new->ud = ud;
|
||||
HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
|
||||
}
|
||||
|
||||
void
|
||||
ucl_parser_register_context_macro (struct ucl_parser *parser, const char *macro,
|
||||
ucl_context_macro_handler handler, void* ud)
|
||||
{
|
||||
struct ucl_macro *new;
|
||||
|
||||
if (macro == NULL || handler == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
new = UCL_ALLOC (sizeof (struct ucl_macro));
|
||||
if (new == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset (new, 0, sizeof (struct ucl_macro));
|
||||
new->h.context_handler = handler;
|
||||
new->name = strdup (macro);
|
||||
new->ud = ud;
|
||||
new->is_context = true;
|
||||
HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
|
||||
}
|
||||
|
||||
void
|
||||
ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
|
||||
const char *value)
|
||||
@ -2159,11 +2353,16 @@ ucl_parser_set_variables_handler (struct ucl_parser *parser,
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_add_chunk_priority (struct ucl_parser *parser, const unsigned char *data,
|
||||
size_t len, unsigned priority)
|
||||
ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
|
||||
size_t len, unsigned priority, enum ucl_duplicate_strategy strat,
|
||||
enum ucl_parse_type parse_type)
|
||||
{
|
||||
struct ucl_chunk *chunk;
|
||||
|
||||
if (parser == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL) {
|
||||
ucl_create_err (&parser->err, "invalid chunk added");
|
||||
return false;
|
||||
@ -2185,14 +2384,24 @@ ucl_parser_add_chunk_priority (struct ucl_parser *parser, const unsigned char *d
|
||||
chunk->line = 1;
|
||||
chunk->column = 0;
|
||||
chunk->priority = priority;
|
||||
chunk->strategy = strat;
|
||||
chunk->parse_type = parse_type;
|
||||
LL_PREPEND (parser->chunks, chunk);
|
||||
parser->recursion ++;
|
||||
|
||||
if (parser->recursion > UCL_MAX_RECURSION) {
|
||||
ucl_create_err (&parser->err, "maximum include nesting limit is reached: %d",
|
||||
parser->recursion);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (parse_type) {
|
||||
default:
|
||||
case UCL_PARSE_UCL:
|
||||
return ucl_state_machine (parser);
|
||||
case UCL_PARSE_MSGPACK:
|
||||
return ucl_parse_msgpack (parser);
|
||||
}
|
||||
}
|
||||
|
||||
ucl_create_err (&parser->err, "a parser is in an invalid state");
|
||||
@ -2201,15 +2410,33 @@ ucl_parser_add_chunk_priority (struct ucl_parser *parser, const unsigned char *d
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
|
||||
size_t len)
|
||||
ucl_parser_add_chunk_priority (struct ucl_parser *parser,
|
||||
const unsigned char *data, size_t len, unsigned priority)
|
||||
{
|
||||
return ucl_parser_add_chunk_priority (parser, data, len, 0);
|
||||
/* We dereference parser, so this check is essential */
|
||||
if (parser == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ucl_parser_add_chunk_full (parser, data, len,
|
||||
priority, UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_add_string (struct ucl_parser *parser, const char *data,
|
||||
ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
|
||||
size_t len)
|
||||
{
|
||||
if (parser == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ucl_parser_add_chunk_full (parser, data, len,
|
||||
parser->default_priority, UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_add_string_priority (struct ucl_parser *parser, const char *data,
|
||||
size_t len, unsigned priority)
|
||||
{
|
||||
if (data == NULL) {
|
||||
ucl_create_err (&parser->err, "invalid string added");
|
||||
@ -2219,5 +2446,40 @@ ucl_parser_add_string (struct ucl_parser *parser, const char *data,
|
||||
len = strlen (data);
|
||||
}
|
||||
|
||||
return ucl_parser_add_chunk (parser, (const unsigned char *)data, len);
|
||||
return ucl_parser_add_chunk_priority (parser,
|
||||
(const unsigned char *)data, len, priority);
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_parser_add_string (struct ucl_parser *parser, const char *data,
|
||||
size_t len)
|
||||
{
|
||||
if (parser == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ucl_parser_add_string_priority (parser,
|
||||
(const unsigned char *)data, len, parser->default_priority);
|
||||
}
|
||||
|
||||
bool
|
||||
ucl_set_include_path (struct ucl_parser *parser, ucl_object_t *paths)
|
||||
{
|
||||
if (parser == NULL || paths == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parser->includepaths == NULL) {
|
||||
parser->includepaths = ucl_object_copy (paths);
|
||||
}
|
||||
else {
|
||||
ucl_object_unref (parser->includepaths);
|
||||
parser->includepaths = ucl_object_copy (paths);
|
||||
}
|
||||
|
||||
if (parser->includepaths == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
224
contrib/libucl/src/ucl_sexp.c
Normal file
224
contrib/libucl/src/ucl_sexp.c
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Vsevolod Stakhov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ucl.h>
|
||||
#include "ucl.h"
|
||||
#include "ucl_internal.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#define NEXT_STATE do { \
|
||||
if (p >= end) { \
|
||||
if (state != read_ebrace) { \
|
||||
ucl_create_err (&parser->err,\
|
||||
"extra data");\
|
||||
state = parse_err; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
switch (*p) { \
|
||||
case '(': \
|
||||
state = read_obrace; \
|
||||
break; \
|
||||
case ')': \
|
||||
state = read_ebrace; \
|
||||
break; \
|
||||
default: \
|
||||
len = 0; \
|
||||
mult = 1; \
|
||||
state = read_length; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
bool
|
||||
ucl_parse_csexp (struct ucl_parser *parser)
|
||||
{
|
||||
const unsigned char *p, *end;
|
||||
ucl_object_t *obj;
|
||||
struct ucl_stack *st;
|
||||
uint64_t len = 0, mult = 1;
|
||||
enum {
|
||||
start_parse,
|
||||
read_obrace,
|
||||
read_length,
|
||||
read_value,
|
||||
read_ebrace,
|
||||
parse_err
|
||||
} state = start_parse;
|
||||
|
||||
assert (parser != NULL);
|
||||
assert (parser->chunks != NULL);
|
||||
assert (parser->chunks->begin != NULL);
|
||||
assert (parser->chunks->remain != 0);
|
||||
|
||||
p = parser->chunks->begin;
|
||||
end = p + parser->chunks->remain;
|
||||
|
||||
while (p < end) {
|
||||
switch (state) {
|
||||
case start_parse:
|
||||
/* At this point we expect open brace */
|
||||
if (*p == '(') {
|
||||
state = read_obrace;
|
||||
}
|
||||
else {
|
||||
ucl_create_err (&parser->err, "bad starting character for "
|
||||
"sexp block: %x", (int)*p);
|
||||
state = parse_err;
|
||||
}
|
||||
break;
|
||||
|
||||
case read_obrace:
|
||||
st = calloc (1, sizeof (*st));
|
||||
|
||||
if (st == NULL) {
|
||||
ucl_create_err (&parser->err, "no memory");
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
|
||||
st->obj = ucl_object_typed_new (UCL_ARRAY);
|
||||
|
||||
if (st->obj == NULL) {
|
||||
ucl_create_err (&parser->err, "no memory");
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parser->stack == NULL) {
|
||||
/* We have no stack */
|
||||
parser->stack = st;
|
||||
|
||||
if (parser->top_obj == NULL) {
|
||||
parser->top_obj = st->obj;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Prepend new element to the stack */
|
||||
LL_PREPEND (parser->stack, st);
|
||||
}
|
||||
|
||||
p ++;
|
||||
NEXT_STATE;
|
||||
|
||||
break;
|
||||
|
||||
case read_length:
|
||||
if (*p == ':') {
|
||||
if (len == 0) {
|
||||
ucl_create_err (&parser->err, "zero length element");
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
|
||||
state = read_value;
|
||||
}
|
||||
else if (*p >= '0' && *p <= '9') {
|
||||
len += (*p - '0') * mult;
|
||||
mult *= 10;
|
||||
|
||||
if (len > UINT32_MAX) {
|
||||
ucl_create_err (&parser->err, "too big length of an "
|
||||
"element");
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ucl_create_err (&parser->err, "bad length character: %x",
|
||||
(int)*p);
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
|
||||
p ++;
|
||||
break;
|
||||
|
||||
case read_value:
|
||||
if ((uint64_t)(end - p) > len || len == 0) {
|
||||
ucl_create_err (&parser->err, "invalid length: %llu, %ld "
|
||||
"remain", (long long unsigned)len, (long)(end - p));
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
obj = ucl_object_typed_new (UCL_STRING);
|
||||
|
||||
obj->value.sv = (const char*)p;
|
||||
obj->len = len;
|
||||
obj->flags |= UCL_OBJECT_BINARY;
|
||||
|
||||
if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
|
||||
ucl_copy_value_trash (obj);
|
||||
}
|
||||
|
||||
ucl_array_append (parser->stack->obj, obj);
|
||||
p += len;
|
||||
NEXT_STATE;
|
||||
break;
|
||||
|
||||
case read_ebrace:
|
||||
if (parser->stack == NULL) {
|
||||
/* We have an extra end brace */
|
||||
ucl_create_err (&parser->err, "invalid length: %llu, %ld "
|
||||
"remain", (long long unsigned)len, (long)(end - p));
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
/* Pop the container */
|
||||
st = parser->stack;
|
||||
parser->stack = st->next;
|
||||
|
||||
if (parser->stack->obj->type == UCL_ARRAY) {
|
||||
ucl_array_append (parser->stack->obj, st->obj);
|
||||
}
|
||||
else {
|
||||
ucl_create_err (&parser->err, "bad container object, array "
|
||||
"expected");
|
||||
state = parse_err;
|
||||
continue;
|
||||
}
|
||||
|
||||
free (st);
|
||||
p++;
|
||||
NEXT_STATE;
|
||||
break;
|
||||
|
||||
case parse_err:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != read_ebrace) {
|
||||
ucl_create_err (&parser->err, "invalid finishing state: %d", state);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/*
|
||||
xxHash - Fast Hash algorithm
|
||||
Copyright (C) 2012-2013, Yann Collet.
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -28,6 +28,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
- public discussion board : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
|
||||
@ -58,7 +59,6 @@ You can contact the author at :
|
||||
// This option has no impact on Little_Endian CPU.
|
||||
#define XXH_FORCE_NATIVE_FORMAT 0
|
||||
|
||||
|
||||
//**************************************
|
||||
// Compiler Specific Options
|
||||
//**************************************
|
||||
@ -68,28 +68,30 @@ You can contact the author at :
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER // Visual Studio
|
||||
# define forceinline static __forceinline
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
# define forceinline static inline __attribute__((always_inline))
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define forceinline static inline
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
//**************************************
|
||||
// Includes & Memory related functions
|
||||
//**************************************
|
||||
#include "xxhash.h"
|
||||
// Modify the local functions below should you wish to use some other memory related routines
|
||||
// Modify the local functions below should you wish to use some other memory routines
|
||||
// for malloc(), free()
|
||||
#include <stdlib.h>
|
||||
forceinline void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
forceinline void XXH_free (void* p) { free(p); }
|
||||
static void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
static void XXH_free (void* p) { free(p); }
|
||||
// for memcpy()
|
||||
#include <string.h>
|
||||
forceinline void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
|
||||
static void* XXH_memcpy(void* dest, const void* src, size_t size)
|
||||
{
|
||||
return memcpy(dest,src,size);
|
||||
}
|
||||
|
||||
|
||||
//**************************************
|
||||
@ -107,7 +109,7 @@ forceinline void* XXH_memcpy(void* dest, const void* src, size_t size) { return
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
typedef uint64_t U64;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
@ -124,13 +126,21 @@ forceinline void* XXH_memcpy(void* dest, const void* src, size_t size) { return
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct _U32_S { U32 v; } _PACKED U32_S;
|
||||
typedef struct _U32_S
|
||||
{
|
||||
U32 v;
|
||||
} _PACKED U32_S;
|
||||
typedef struct _U64_S
|
||||
{
|
||||
U64 v;
|
||||
} _PACKED U64_S;
|
||||
|
||||
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#define A32(x) (((U32_S *)(x))->v)
|
||||
#define A64(x) (((U64_S *)(x))->v)
|
||||
|
||||
|
||||
//***************************************
|
||||
@ -141,20 +151,37 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
|
||||
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
# define XXH_rotl64(x,r) _rotl64(x,r)
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) // Visual Studio
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
#elif GCC_VERSION >= 403
|
||||
# define XXH_swap64 _byteswap_uint64
|
||||
#elif GCC_VERSION >= 403 || defined(__clang__)
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
# define XXH_swap64 __builtin_bswap64
|
||||
#else
|
||||
static inline U32 XXH_swap32 (U32 x) {
|
||||
static inline U32 XXH_swap32 (U32 x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );}
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
static inline U64 XXH_swap64 (U64 x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000ULL) |
|
||||
((x << 40) & 0x00ff000000000000ULL) |
|
||||
((x << 24) & 0x0000ff0000000000ULL) |
|
||||
((x << 8) & 0x000000ff00000000ULL) |
|
||||
((x >> 8) & 0x00000000ff000000ULL) |
|
||||
((x >> 24) & 0x0000000000ff0000ULL) |
|
||||
((x >> 40) & 0x000000000000ff00ULL) |
|
||||
((x >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -167,6 +194,11 @@ static inline U32 XXH_swap32 (U32 x) {
|
||||
#define PRIME32_4 668265263U
|
||||
#define PRIME32_5 374761393U
|
||||
|
||||
#define PRIME64_1 11400714785074694791ULL
|
||||
#define PRIME64_2 14029467366897019727ULL
|
||||
#define PRIME64_3 1609587929392839161ULL
|
||||
#define PRIME64_4 9650029242287828579ULL
|
||||
#define PRIME64_5 2870177450012600261ULL
|
||||
|
||||
//**************************************
|
||||
// Architecture Macros
|
||||
@ -189,28 +221,49 @@ typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
//****************************
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
forceinline U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr);
|
||||
return endian==XXH_littleEndian ? *(U32*)ptr : XXH_swap32(*(U32*)ptr);
|
||||
}
|
||||
|
||||
forceinline U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
|
||||
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? A64(ptr) : XXH_swap64(A64(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(U64*)ptr : XXH_swap64(*(U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
|
||||
//****************************
|
||||
// Simple Hash Functions
|
||||
//****************************
|
||||
forceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
const BYTE* bEnd = p + len;
|
||||
U32 h32;
|
||||
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL) { len=0; p=(const BYTE*)(size_t)16; }
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=16)
|
||||
@ -223,11 +276,24 @@ forceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_end
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
|
||||
v2 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
|
||||
v3 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
|
||||
v4 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
|
||||
} while (p<=limit);
|
||||
v1 += XXH_get32bits(p) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_get32bits(p) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_get32bits(p) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_get32bits(p) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
}
|
||||
@ -238,9 +304,9 @@ forceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_end
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p<=bEnd-4)
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_3;
|
||||
h32 += XXH_get32bits(p) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
@ -262,18 +328,19 @@ forceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_end
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32(const void* input, int len, U32 seed)
|
||||
unsigned int XXH32 (const void* input, size_t len, unsigned seed)
|
||||
{
|
||||
#if 0
|
||||
// Simple version, good for code maintenance, but unfortunately slow for small inputs
|
||||
void* state = XXH32_init(seed);
|
||||
XXH32_update(state, input, len);
|
||||
return XXH32_digest(state);
|
||||
XXH32_state_t state;
|
||||
XXH32_reset(&state, seed);
|
||||
XXH32_update(&state, input, len);
|
||||
return XXH32_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if (!(((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage
|
||||
if ((((size_t)input) & 3) == 0) // Input is aligned, let's leverage the speed advantage
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
@ -289,12 +356,152 @@ U32 XXH32(const void* input, int len, U32 seed)
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U64 h64;
|
||||
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
|
||||
|
||||
//****************************
|
||||
// Advanced Hash Functions
|
||||
//****************************
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)32;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct XXH_state32_t
|
||||
if (len>=32)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
U64 v2 = seed + PRIME64_2;
|
||||
U64 v3 = seed + 0;
|
||||
U64 v4 = seed - PRIME64_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
v2 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
v3 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
v4 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_get64bits(p);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
uint64_t XXH64 (const void* input, size_t len, uint64_t seed)
|
||||
{
|
||||
#if 0
|
||||
// Simple version, good for code maintenance, but unfortunately slow for small inputs
|
||||
XXH64_state_t state;
|
||||
XXH64_reset(&state, seed);
|
||||
XXH64_update(&state, input, len);
|
||||
return XXH64_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 7)==0) // Input is aligned, let's leverage the speed advantage
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Advanced Hash Functions
|
||||
****************************************************/
|
||||
|
||||
/*** Allocation ***/
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U32 seed;
|
||||
@ -302,21 +509,60 @@ struct XXH_state32_t
|
||||
U32 v2;
|
||||
U32 v3;
|
||||
U32 v4;
|
||||
int memsize;
|
||||
char memory[16];
|
||||
U32 mem32[4]; /* defined as U32 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U64 seed;
|
||||
U64 v1;
|
||||
U64 v2;
|
||||
U64 v3;
|
||||
U64 v4;
|
||||
U64 mem64[4]; /* defined as U64 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate64_t;
|
||||
|
||||
|
||||
XXH32_state_t* XXH32_createState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t)); // A compilation error here means XXH32_state_t is not large enough
|
||||
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
|
||||
}
|
||||
|
||||
void* XXH32_init (unsigned seed)
|
||||
{
|
||||
XXH32_state_t *st = XXH32_createState();
|
||||
XXH32_reset(st, seed);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
};
|
||||
|
||||
XXH64_state_t* XXH64_createState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t)); // A compilation error here means XXH64_state_t is not large enough
|
||||
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
|
||||
}
|
||||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
};
|
||||
|
||||
|
||||
int XXH32_sizeofState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); // A compilation error here means XXH32_SIZEOFSTATE is not large enough
|
||||
return sizeof(struct XXH_state32_t);
|
||||
}
|
||||
/*** Hash feed ***/
|
||||
|
||||
|
||||
XXH_errorcode XXH32_resetState(void* state_in, U32 seed)
|
||||
XXH_errorcode XXH32_reset(XXH32_state_t* state_in, U32 seed)
|
||||
{
|
||||
struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
|
||||
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state->v2 = seed + PRIME32_2;
|
||||
@ -327,18 +573,23 @@ XXH_errorcode XXH32_resetState(void* state_in, U32 seed)
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
void* XXH32_init (U32 seed)
|
||||
XXH_errorcode XXH64_reset(XXH64_state_t* state_in, uint64_t seed)
|
||||
{
|
||||
void* state = XXH_malloc (sizeof(struct XXH_state32_t));
|
||||
XXH32_resetState(state, seed);
|
||||
return state;
|
||||
XXH_istate64_t* state = (XXH_istate64_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
state->v2 = seed + PRIME64_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME64_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
forceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
|
||||
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
|
||||
XXH_istate32_t* state = (XXH_istate32_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
@ -350,20 +601,32 @@ forceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input
|
||||
|
||||
if (state->memsize + len < 16) // fill in tmp buffer
|
||||
{
|
||||
XXH_memcpy(state->memory + state->memsize, input, len);
|
||||
state->memsize += len;
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) // some data left from previous update
|
||||
{
|
||||
XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
|
||||
{
|
||||
const U32* p32 = (const U32*)state->memory;
|
||||
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
|
||||
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++;
|
||||
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
|
||||
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
|
||||
const U32* p32 = state->mem32;
|
||||
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v1 = XXH_rotl32(state->v1, 13);
|
||||
state->v1 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v2 = XXH_rotl32(state->v2, 13);
|
||||
state->v2 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v3 = XXH_rotl32(state->v3, 13);
|
||||
state->v3 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v4 = XXH_rotl32(state->v4, 13);
|
||||
state->v4 *= PRIME32_1;
|
||||
p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
@ -379,11 +642,24 @@ forceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
|
||||
v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
|
||||
v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
|
||||
v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
|
||||
} while (p<=limit);
|
||||
v1 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
@ -393,14 +669,14 @@ forceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->memory, p, bEnd-p);
|
||||
XXH_memcpy(state->mem32, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH32_update (void* state_in, const void* input, int len)
|
||||
XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
@ -412,11 +688,11 @@ XXH_errorcode XXH32_update (void* state_in, const void* input, int len)
|
||||
|
||||
|
||||
|
||||
forceinline U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
|
||||
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
|
||||
const BYTE * p = (const BYTE*)state->memory;
|
||||
BYTE* bEnd = (BYTE*)state->memory + state->memsize;
|
||||
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
BYTE* bEnd = (BYTE*)(state->mem32) + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->total_len >= 16)
|
||||
@ -430,9 +706,9 @@ forceinline U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess e
|
||||
|
||||
h32 += (U32) state->total_len;
|
||||
|
||||
while (p<=bEnd-4)
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3;
|
||||
h32 += XXH_readLE32(p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
@ -449,27 +725,217 @@ forceinline U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess e
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
#if 0
|
||||
XXH32_freeState((XXH32_state_t *)state_in);
|
||||
#endif
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32_intermediateDigest (void* state_in)
|
||||
U32 XXH32_digest (const XXH32_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
|
||||
return XXH32_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
|
||||
return XXH32_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32_digest (void* state_in)
|
||||
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
U32 h32 = XXH32_intermediateDigest(state_in);
|
||||
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
XXH_free(state_in);
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
return h32;
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 32) // fill in tmp buffer
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) // some data left from previous update
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
|
||||
{
|
||||
const U64* p64 = state->mem64;
|
||||
state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v1 = XXH_rotl64(state->v1, 31);
|
||||
state->v1 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v2 = XXH_rotl64(state->v2, 31);
|
||||
state->v2 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v3 = XXH_rotl64(state->v3, 31);
|
||||
state->v3 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v4 = XXH_rotl64(state->v4, 31);
|
||||
state->v4 *= PRIME64_1;
|
||||
p64++;
|
||||
}
|
||||
p += 32-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p+32 <= bEnd)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
p+=8;
|
||||
v2 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
p+=8;
|
||||
v3 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
p+=8;
|
||||
v4 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
p+=8;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem64, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
BYTE* bEnd = (BYTE*)state->mem64 + state->memsize;
|
||||
U64 h64;
|
||||
|
||||
if (state->total_len >= 32)
|
||||
{
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = state->seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) state->total_len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_readLE64(p, endian);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
#if 0
|
||||
XXH64_freeState((XXH64_state_t *)state_in);
|
||||
#endif
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
uint64_t XXH64_digest (const XXH64_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
xxHash - Fast Hash algorithm
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2013, Yann Collet.
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -56,109 +56,110 @@ Q.Score is a measure of quality of the hash function.
|
||||
It depends on successfully passing SMHasher test set.
|
||||
10 is a perfect score.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef LIBUCL_XXHASH_H
|
||||
#define LIBUCL_XXHASH_H
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
//****************************
|
||||
// Type
|
||||
//****************************
|
||||
/*****************************
|
||||
Includes
|
||||
*****************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/*****************************
|
||||
Type
|
||||
*****************************/
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Simple Hash Functions
|
||||
//****************************
|
||||
/*****************************
|
||||
Simple Hash Functions
|
||||
*****************************/
|
||||
|
||||
unsigned int XXH32 (const void* input, int len, unsigned int seed);
|
||||
unsigned int XXH32 (const void* input, size_t length, unsigned seed);
|
||||
uint64_t XXH64 (const void* input, size_t length, uint64_t seed);
|
||||
|
||||
/*
|
||||
XXH32() :
|
||||
Calculate the 32-bits hash of sequence of length "len" stored at memory address "input".
|
||||
The memory between input & input+len must be valid (allocated and read-accessible).
|
||||
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
|
||||
The memory between input & input+length must be valid (allocated and read-accessible).
|
||||
"seed" can be used to alter the result predictably.
|
||||
This function successfully passes all SMHasher tests.
|
||||
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
|
||||
Note that "len" is type "int", which means it is limited to 2^31-1.
|
||||
If your data is larger, use the advanced functions below.
|
||||
XXH64() :
|
||||
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Advanced Hash Functions
|
||||
//****************************
|
||||
|
||||
void* XXH32_init (unsigned int seed);
|
||||
XXH_errorcode XXH32_update (void* state, const void* input, int len);
|
||||
unsigned int XXH32_digest (void* state);
|
||||
/*****************************
|
||||
Advanced Hash Functions
|
||||
*****************************/
|
||||
typedef struct { int64_t ll[ 6]; } XXH32_state_t;
|
||||
typedef struct { int64_t ll[11]; } XXH64_state_t;
|
||||
|
||||
/*
|
||||
These functions calculate the xxhash of an input provided in several small packets,
|
||||
These structures allow static allocation of XXH states.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
|
||||
If you prefer dynamic allocation, please refer to functions below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Rspamd specific: we use the legacy method to free state when digest is obtained
|
||||
* !!!
|
||||
*/
|
||||
void * XXH32_init (unsigned seed);
|
||||
XXH32_state_t* XXH32_createState(void);
|
||||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
|
||||
|
||||
XXH64_state_t* XXH64_createState(void);
|
||||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions create and release memory for XXH state.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
*/
|
||||
|
||||
|
||||
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed);
|
||||
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned int XXH32_digest (const XXH32_state_t* statePtr);
|
||||
|
||||
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, uint64_t seed);
|
||||
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
|
||||
uint64_t XXH64_digest (const XXH64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions calculate the xxHash of an input provided in multiple smaller packets,
|
||||
as opposed to an input provided as a single block.
|
||||
|
||||
It must be started with :
|
||||
void* XXH32_init()
|
||||
The function returns a pointer which holds the state of calculation.
|
||||
XXH state space must first be allocated, using either static or dynamic method provided above.
|
||||
|
||||
This pointer must be provided as "void* state" parameter for XXH32_update().
|
||||
XXH32_update() can be called as many times as necessary.
|
||||
The user must provide a valid (allocated) input.
|
||||
Start a new hash by initializing state with a seed, using XXHnn_reset().
|
||||
|
||||
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
|
||||
Obviously, input must be valid, meaning allocated and read accessible.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
Note that "len" is type "int", which means it is limited to 2^31-1.
|
||||
If your data is larger, it is recommended to chunk your data into blocks
|
||||
of size for example 2^30 (1GB) to avoid any "int" overflow issue.
|
||||
|
||||
Finally, you can end the calculation anytime, by using XXH32_digest().
|
||||
This function returns the final 32-bits hash.
|
||||
You must provide the same "void* state" parameter created by XXH32_init().
|
||||
Memory will be freed by XXH32_digest().
|
||||
Finally, you can produce a hash anytime, by using XXHnn_digest().
|
||||
This function returns the final nn-bits hash.
|
||||
You can nonetheless continue feeding the hash state with more input,
|
||||
and therefore get some new hashes, by calling again XXHnn_digest().
|
||||
|
||||
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
|
||||
*/
|
||||
|
||||
|
||||
int XXH32_sizeofState(void);
|
||||
XXH_errorcode XXH32_resetState(void* state, unsigned int seed);
|
||||
|
||||
#define XXH32_SIZEOFSTATE 48
|
||||
typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
|
||||
/*
|
||||
These functions allow user application to make its own allocation for state.
|
||||
|
||||
XXH32_sizeofState() is used to know how much space must be allocated for the xxHash 32-bits state.
|
||||
Note that the state must be aligned to access 'long long' fields. Memory must be allocated and referenced by a pointer.
|
||||
This pointer must then be provided as 'state' into XXH32_resetState(), which initializes the state.
|
||||
|
||||
For static allocation purposes (such as allocation on stack, or freestanding systems without malloc()),
|
||||
use the structure XXH32_stateSpace_t, which will ensure that memory space is large enough and correctly aligned to access 'long long' fields.
|
||||
*/
|
||||
|
||||
|
||||
unsigned int XXH32_intermediateDigest (void* state);
|
||||
/*
|
||||
This function does the same as XXH32_digest(), generating a 32-bit hash,
|
||||
but preserve memory context.
|
||||
This way, it becomes possible to generate intermediate hashes, and then continue feeding data with XXH32_update().
|
||||
To free memory context, use XXH32_digest(), or free().
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Deprecated function names
|
||||
//****************************
|
||||
// The following translations are provided to ease code transition
|
||||
// You are encouraged to no longer this function names
|
||||
#define XXH32_feed XXH32_update
|
||||
#define XXH32_result XXH32_digest
|
||||
#define XXH32_getIntermediateResult XXH32_intermediateDigest
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,12 @@
|
||||
EXTRA_DIST = $(TESTS) basic schema generate.res streamline.res rcl_test.json.xz
|
||||
EXTRA_DIST = $(TESTS) basic schema generate.res \
|
||||
streamline.res rcl_test.json.xz
|
||||
|
||||
TESTS = basic.test \
|
||||
generate.test \
|
||||
schema.test \
|
||||
msgpack.test \
|
||||
speed.test \
|
||||
streamline.test
|
||||
msgpack.test
|
||||
TESTS_ENVIRONMENT = $(SH) \
|
||||
TEST_DIR=$(top_srcdir)/tests \
|
||||
TEST_OUT_DIR=$(top_builddir)/tests \
|
||||
@ -35,4 +37,9 @@ test_streamline_SOURCES = test_streamline.c
|
||||
test_streamline_LDADD = $(common_test_ldadd)
|
||||
test_streamline_CFLAGS = $(common_test_cflags)
|
||||
|
||||
check_PROGRAMS = test_basic test_speed test_generate test_schema test_streamline
|
||||
test_msgpack_SOURCES = test_msgpack.c
|
||||
test_msgpack_LDADD = $(common_test_ldadd)
|
||||
test_msgpack_CFLAGS = $(common_test_cflags)
|
||||
|
||||
check_PROGRAMS = test_basic test_speed test_generate test_schema test_streamline \
|
||||
test_msgpack
|
@ -1,7 +1,7 @@
|
||||
key = value_orig;
|
||||
|
||||
# test glob
|
||||
.include(glob=true) "${CURDIR}/include_dir/test*.conf"
|
||||
.include(glob=true,something="test") "${CURDIR}/include_dir/test*.conf"
|
||||
|
||||
.include(priority=1) "${CURDIR}/include_dir/pri1.conf"
|
||||
.include(priority=2) "${CURDIR}/include_dir/pri2.conf"
|
||||
|
24
contrib/libucl/tests/basic/15.in
Normal file
24
contrib/libucl/tests/basic/15.in
Normal file
@ -0,0 +1,24 @@
|
||||
# In this test we test include override bug
|
||||
|
||||
.include(priority = 1) "${CURDIR}/15.inc"
|
||||
|
||||
section = {
|
||||
value = "test";
|
||||
}
|
||||
|
||||
overrided = {
|
||||
value = "not-to-be-shown";
|
||||
}
|
||||
|
||||
/*
|
||||
BUGGED UCL:
|
||||
overrided {
|
||||
key = "overrided";
|
||||
}
|
||||
!!! So overrided has actually rewritten the previous key
|
||||
section {
|
||||
value {
|
||||
value = "not-to-be-shown";
|
||||
}
|
||||
}
|
||||
*/
|
3
contrib/libucl/tests/basic/15.inc
Normal file
3
contrib/libucl/tests/basic/15.inc
Normal file
@ -0,0 +1,3 @@
|
||||
overrided {
|
||||
key = "overrided";
|
||||
}
|
7
contrib/libucl/tests/basic/15.res
Normal file
7
contrib/libucl/tests/basic/15.res
Normal file
@ -0,0 +1,7 @@
|
||||
overrided {
|
||||
key = "overrided";
|
||||
}
|
||||
section {
|
||||
value = "test";
|
||||
}
|
||||
|
12
contrib/libucl/tests/basic/16.in
Normal file
12
contrib/libucl/tests/basic/16.in
Normal file
@ -0,0 +1,12 @@
|
||||
.include(priority = 1) "${CURDIR}/16.inc"
|
||||
|
||||
section = {
|
||||
value = "test";
|
||||
}
|
||||
|
||||
overrided = {
|
||||
value = "not-to-be-shown";
|
||||
}
|
||||
overrided = {
|
||||
value2 = "implicit-array";
|
||||
}
|
3
contrib/libucl/tests/basic/16.inc
Normal file
3
contrib/libucl/tests/basic/16.inc
Normal file
@ -0,0 +1,3 @@
|
||||
overrided {
|
||||
key = "overrided";
|
||||
}
|
7
contrib/libucl/tests/basic/16.res
Normal file
7
contrib/libucl/tests/basic/16.res
Normal file
@ -0,0 +1,7 @@
|
||||
overrided {
|
||||
key = "overrided";
|
||||
}
|
||||
section {
|
||||
value = "test";
|
||||
}
|
||||
|
2
contrib/libucl/tests/basic/17.in
Normal file
2
contrib/libucl/tests/basic/17.in
Normal file
@ -0,0 +1,2 @@
|
||||
# issue 74
|
||||
string that ends in slash\
|
2
contrib/libucl/tests/basic/17.res
Normal file
2
contrib/libucl/tests/basic/17.res
Normal file
@ -0,0 +1,2 @@
|
||||
string = "that ends in slash\\";
|
||||
|
10
contrib/libucl/tests/basic/18.in
Normal file
10
contrib/libucl/tests/basic/18.in
Normal file
@ -0,0 +1,10 @@
|
||||
defaults {
|
||||
key = "val"
|
||||
foo = "bar"
|
||||
many = "values here"
|
||||
}
|
||||
|
||||
mything {
|
||||
.inherit "defaults"
|
||||
key = "newval"
|
||||
}
|
11
contrib/libucl/tests/basic/18.res
Normal file
11
contrib/libucl/tests/basic/18.res
Normal file
@ -0,0 +1,11 @@
|
||||
defaults {
|
||||
key = "val";
|
||||
foo = "bar";
|
||||
many = "values here";
|
||||
}
|
||||
mything {
|
||||
key = "newval";
|
||||
foo = "bar";
|
||||
many = "values here";
|
||||
}
|
||||
|
8
contrib/libucl/tests/basic/19-append.inc
Normal file
8
contrib/libucl/tests/basic/19-append.inc
Normal file
@ -0,0 +1,8 @@
|
||||
okey_append = {
|
||||
key = value1;
|
||||
key1 = value2
|
||||
}
|
||||
|
||||
akey_append = ["value3"];
|
||||
|
||||
skey_append = "value4";
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user