mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
merging the name class change in the trunk into the new working branch
git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-dnsrrparams@430 e5f2f494-b856-4b98-b285-d166d9295462
This commit is contained in:
682
Makefile.in
682
Makefile.in
@@ -1,682 +0,0 @@
|
||||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||
depcomp install-sh missing
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-dvi-recursive install-exec-recursive \
|
||||
install-html-recursive install-info-recursive \
|
||||
install-pdf-recursive install-ps-recursive install-recursive \
|
||||
installcheck-recursive installdirs-recursive pdf-recursive \
|
||||
ps-recursive uninstall-recursive
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
|
||||
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
|
||||
distdir dist dist-all distcheck
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
am__remove_distdir = \
|
||||
{ test ! -d "$(distdir)" \
|
||||
|| { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
&& rm -fr "$(distdir)"; }; }
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
DIST_ARCHIVES = $(distdir).tar.gz
|
||||
GZIP_ENV = --best
|
||||
distuninstallcheck_listfiles = find . -type f -print
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
GTEST_INCLUDES = @GTEST_INCLUDES@
|
||||
GTEST_LDADD = @GTEST_LDADD@
|
||||
GTEST_LDFLAGS = @GTEST_LDFLAGS@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
SUBDIRS = src
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
am--refresh:
|
||||
@:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
|
||||
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
config.h: stamp-h1
|
||||
@if test ! -f $@; then \
|
||||
rm -f stamp-h1; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
|
||||
else :; fi
|
||||
|
||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||
$(srcdir)/config.h.in: $(am__configure_deps)
|
||||
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
-test -n "$(am__skip_mode_fix)" \
|
||||
|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r "$(distdir)"
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-bzip2: distdir
|
||||
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-lzma: distdir
|
||||
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-xz: distdir
|
||||
tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-shar: distdir
|
||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist dist-all: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lzma*) \
|
||||
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
|
||||
*.tar.xz*) \
|
||||
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir); chmod a+w $(distdir)
|
||||
mkdir $(distdir)/_build
|
||||
mkdir $(distdir)/_inst
|
||||
chmod a-w $(distdir)
|
||||
test -d $(distdir)/_build || exit 0; \
|
||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||
&& am__cwd=`pwd` \
|
||||
&& $(am__cd) $(distdir)/_build \
|
||||
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
|
||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||
distuninstallcheck \
|
||||
&& chmod -R a-w "$$dc_install_base" \
|
||||
&& ({ \
|
||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||
&& rm -rf "$$dc_destdir" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||
&& rm -rf $(DIST_ARCHIVES) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||
&& cd "$$am__cwd" \
|
||||
|| exit 1
|
||||
$(am__remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@$(am__cd) '$(distuninstallcheck_dir)' \
|
||||
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|
||||
|| { echo "ERROR: files left after uninstall:" ; \
|
||||
if test -n "$(DESTDIR)"; then \
|
||||
echo " (check DESTDIR support)"; \
|
||||
fi ; \
|
||||
$(distuninstallcheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
distcleancheck: distclean
|
||||
@if test '$(srcdir)' = . ; then \
|
||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||
$(distcleancheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \
|
||||
ctags-recursive install-am install-strip tags-recursive
|
||||
|
||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
||||
all all-am am--refresh check check-am clean clean-generic \
|
||||
ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
|
||||
dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
|
||||
distclean distclean-generic distclean-hdr distclean-tags \
|
||||
distcleancheck distdir distuninstallcheck dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs installdirs-am maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
|
||||
pdf-am ps ps-am tags tags-recursive uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
951
aclocal.m4
vendored
951
aclocal.m4
vendored
@@ -1,951 +0,0 @@
|
||||
# generated automatically by aclocal 1.11 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
|
||||
[m4_warning([this file was generated for autoconf 2.64.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically `autoreconf'.])])
|
||||
|
||||
# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_AUTOMAKE_VERSION(VERSION)
|
||||
# ----------------------------
|
||||
# Automake X.Y traces this macro to ensure aclocal.m4 has been
|
||||
# generated from the m4 files accompanying Automake X.Y.
|
||||
# (This private macro should not be called outside this file.)
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.11'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.11], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
# _AM_AUTOCONF_VERSION(VERSION)
|
||||
# -----------------------------
|
||||
# aclocal traces this macro to find the Autoconf version.
|
||||
# This is a private macro too. Using m4_define simplifies
|
||||
# the logic in aclocal, which can simply ignore this definition.
|
||||
m4_define([_AM_AUTOCONF_VERSION], [])
|
||||
|
||||
# AM_SET_CURRENT_AUTOMAKE_VERSION
|
||||
# -------------------------------
|
||||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.11])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
|
||||
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
|
||||
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
|
||||
#
|
||||
# Of course, Automake must honor this variable whenever it calls a
|
||||
# tool from the auxiliary directory. The problem is that $srcdir (and
|
||||
# therefore $ac_aux_dir as well) can be either absolute or relative,
|
||||
# depending on how configure is run. This is pretty annoying, since
|
||||
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
|
||||
# source directory, any form will work fine, but in subdirectories a
|
||||
# relative path needs to be adjusted first.
|
||||
#
|
||||
# $ac_aux_dir/missing
|
||||
# fails when called from a subdirectory if $ac_aux_dir is relative
|
||||
# $top_srcdir/$ac_aux_dir/missing
|
||||
# fails if $ac_aux_dir is absolute,
|
||||
# fails when called from a subdirectory in a VPATH build with
|
||||
# a relative $ac_aux_dir
|
||||
#
|
||||
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
|
||||
# are both prefixed by $srcdir. In an in-source build this is usually
|
||||
# harmless because $srcdir is `.', but things will broke when you
|
||||
# start a VPATH build or use an absolute $srcdir.
|
||||
#
|
||||
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
|
||||
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
|
||||
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
|
||||
# and then we would define $MISSING as
|
||||
# MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# This will work as long as MISSING is not called from configure, because
|
||||
# unfortunately $(top_srcdir) has no meaning in configure.
|
||||
# However there are other variables, like CC, which are often used in
|
||||
# configure, and could therefore not use this "fixed" $ac_aux_dir.
|
||||
#
|
||||
# Another solution, used here, is to always expand $ac_aux_dir to an
|
||||
# absolute PATH. The drawback is that using absolute paths prevent a
|
||||
# configured tree to be moved without reconfiguration.
|
||||
|
||||
AC_DEFUN([AM_AUX_DIR_EXPAND],
|
||||
[dnl Rely on autoconf to set up CDPATH properly.
|
||||
AC_PREREQ([2.50])dnl
|
||||
# expand $ac_aux_dir to an absolute path
|
||||
am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
])
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 9
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ(2.52)dnl
|
||||
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
m4_define([_AM_COND_VALUE_$1], [$2])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 10
|
||||
|
||||
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
|
||||
# written in clear, in which case automake, when reading aclocal.m4,
|
||||
# will think it sees a *use*, and therefore will trigger all it's
|
||||
# C support machinery. Also note that it means that autoscan, seeing
|
||||
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
|
||||
|
||||
|
||||
# _AM_DEPENDENCIES(NAME)
|
||||
# ----------------------
|
||||
# See how the compiler implements dependency checking.
|
||||
# NAME is "CC", "CXX", "GCJ", or "OBJC".
|
||||
# We try a few techniques and use that to set a single cache variable.
|
||||
#
|
||||
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
|
||||
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
|
||||
# dependency, and given that the user is not expected to run this macro,
|
||||
# just rely on AC_PROG_CC.
|
||||
AC_DEFUN([_AM_DEPENDENCIES],
|
||||
[AC_REQUIRE([AM_SET_DEPDIR])dnl
|
||||
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
|
||||
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
|
||||
AC_REQUIRE([AM_DEP_TRACK])dnl
|
||||
|
||||
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
|
||||
[$1], CXX, [depcc="$CXX" am_compiler_list=],
|
||||
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
|
||||
[$1], UPC, [depcc="$UPC" am_compiler_list=],
|
||||
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
|
||||
[depcc="$$1" am_compiler_list=])
|
||||
|
||||
AC_CACHE_CHECK([dependency style of $depcc],
|
||||
[am_cv_$1_dependencies_compiler_type],
|
||||
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
|
||||
# We make a subdir and do the tests there. Otherwise we can end up
|
||||
# making bogus files that we don't know about and never remove. For
|
||||
# instance it was reported that on HP-UX the gcc test will end up
|
||||
# making a dummy file named `D' -- because `-MD' means `put the output
|
||||
# in D'.
|
||||
mkdir conftest.dir
|
||||
# Copy depcomp to subdir because otherwise we won't find it if we're
|
||||
# using a relative directory.
|
||||
cp "$am_depcomp" conftest.dir
|
||||
cd conftest.dir
|
||||
# We will build objects and dependencies in a subdirectory because
|
||||
# it helps to detect inapplicable dependency modes. For instance
|
||||
# both Tru64's cc and ICC support -MD to output dependencies as a
|
||||
# side effect of compilation, but ICC will put the dependencies in
|
||||
# the current directory while Tru64 will put them in the object
|
||||
# directory.
|
||||
mkdir sub
|
||||
|
||||
am_cv_$1_dependencies_compiler_type=none
|
||||
if test "$am_compiler_list" = ""; then
|
||||
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
|
||||
fi
|
||||
am__universal=false
|
||||
m4_case([$1], [CC],
|
||||
[case " $depcc " in #(
|
||||
*\ -arch\ *\ -arch\ *) am__universal=true ;;
|
||||
esac],
|
||||
[CXX],
|
||||
[case " $depcc " in #(
|
||||
*\ -arch\ *\ -arch\ *) am__universal=true ;;
|
||||
esac])
|
||||
|
||||
for depmode in $am_compiler_list; do
|
||||
# Setup a source with many dependencies, because some compilers
|
||||
# like to wrap large dependency lists on column 80 (with \), and
|
||||
# we should not choose a depcomp mode which is confused by this.
|
||||
#
|
||||
# We need to recreate these files for each test, as the compiler may
|
||||
# overwrite some of them when testing with obscure command lines.
|
||||
# This happens at least with the AIX C compiler.
|
||||
: > sub/conftest.c
|
||||
for i in 1 2 3 4 5 6; do
|
||||
echo '#include "conftst'$i'.h"' >> sub/conftest.c
|
||||
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
|
||||
# Solaris 8's {/usr,}/bin/sh.
|
||||
touch sub/conftst$i.h
|
||||
done
|
||||
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
|
||||
|
||||
# We check with `-c' and `-o' for the sake of the "dashmstdout"
|
||||
# mode. It turns out that the SunPro C++ compiler does not properly
|
||||
# handle `-M -o', and we need to detect this. Also, some Intel
|
||||
# versions had trouble with output in subdirs
|
||||
am__obj=sub/conftest.${OBJEXT-o}
|
||||
am__minus_obj="-o $am__obj"
|
||||
case $depmode in
|
||||
gcc)
|
||||
# This depmode causes a compiler race in universal mode.
|
||||
test "$am__universal" = false || continue
|
||||
;;
|
||||
nosideeffect)
|
||||
# after this tag, mechanisms are not by side-effect, so they'll
|
||||
# only be used when explicitly requested
|
||||
if test "x$enable_dependency_tracking" = xyes; then
|
||||
continue
|
||||
else
|
||||
break
|
||||
fi
|
||||
;;
|
||||
msvisualcpp | msvcmsys)
|
||||
# This compiler won't grok `-c -o', but also, the minuso test has
|
||||
# not run yet. These depmodes are late enough in the game, and
|
||||
# so weak that their functioning should not be impacted.
|
||||
am__obj=conftest.${OBJEXT-o}
|
||||
am__minus_obj=
|
||||
;;
|
||||
none) break ;;
|
||||
esac
|
||||
if depmode=$depmode \
|
||||
source=sub/conftest.c object=$am__obj \
|
||||
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
|
||||
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
|
||||
>/dev/null 2>conftest.err &&
|
||||
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
|
||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||
# icc doesn't choke on unknown options, it will just issue warnings
|
||||
# or remarks (even with -Werror). So we grep stderr for any message
|
||||
# that says an option was ignored or not supported.
|
||||
# When given -MP, icc 7.0 and 7.1 complain thusly:
|
||||
# icc: Command line warning: ignoring option '-M'; no argument required
|
||||
# The diagnosis changed in icc 8.0:
|
||||
# icc: Command line remark: option '-MP' not supported
|
||||
if (grep 'ignoring option' conftest.err ||
|
||||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
||||
am_cv_$1_dependencies_compiler_type=$depmode
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
cd ..
|
||||
rm -rf conftest.dir
|
||||
else
|
||||
am_cv_$1_dependencies_compiler_type=none
|
||||
fi
|
||||
])
|
||||
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
|
||||
AM_CONDITIONAL([am__fastdep$1], [
|
||||
test "x$enable_dependency_tracking" != xno \
|
||||
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
|
||||
])
|
||||
|
||||
|
||||
# AM_SET_DEPDIR
|
||||
# -------------
|
||||
# Choose a directory name for dependency files.
|
||||
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
|
||||
AC_DEFUN([AM_SET_DEPDIR],
|
||||
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
|
||||
])
|
||||
|
||||
|
||||
# AM_DEP_TRACK
|
||||
# ------------
|
||||
AC_DEFUN([AM_DEP_TRACK],
|
||||
[AC_ARG_ENABLE(dependency-tracking,
|
||||
[ --disable-dependency-tracking speeds up one-time build
|
||||
--enable-dependency-tracking do not reject slow dependency extractors])
|
||||
if test "x$enable_dependency_tracking" != xno; then
|
||||
am_depcomp="$ac_aux_dir/depcomp"
|
||||
AMDEPBACKSLASH='\'
|
||||
fi
|
||||
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
|
||||
AC_SUBST([AMDEPBACKSLASH])dnl
|
||||
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
|
||||
])
|
||||
|
||||
# Generate code to set up dependency tracking. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
#serial 5
|
||||
|
||||
# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
# ------------------------------
|
||||
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[{
|
||||
# Autoconf 2.62 quotes --file arguments for eval, but not when files
|
||||
# are listed without --file. Let's play safe and only enable the eval
|
||||
# if we detect the quoting.
|
||||
case $CONFIG_FILES in
|
||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
||||
*) set x $CONFIG_FILES ;;
|
||||
esac
|
||||
shift
|
||||
for mf
|
||||
do
|
||||
# Strip MF so we end up with the name of the file.
|
||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile or not.
|
||||
# We used to match only the files named `Makefile.in', but
|
||||
# some people rename them; so instead we look at the file content.
|
||||
# Grep'ing the first line is not enough: some people post-process
|
||||
# each Makefile.in and add a new line on top of each file to say so.
|
||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
|
||||
dirpart=`AS_DIRNAME("$mf")`
|
||||
else
|
||||
continue
|
||||
fi
|
||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
||||
# from the Makefile without running `make'.
|
||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
||||
test -z "$DEPDIR" && continue
|
||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
||||
test -z "am__include" && continue
|
||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
||||
# When using ansi2knr, U may be empty or an underscore; expand it
|
||||
U=`sed -n 's/^U = //p' < "$mf"`
|
||||
# Find all dependency output files, they are included files with
|
||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
||||
# expansion.
|
||||
for file in `sed -n "
|
||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
|
||||
# Make sure the directory exists.
|
||||
test -f "$dirpart/$file" && continue
|
||||
fdir=`AS_DIRNAME(["$file"])`
|
||||
AS_MKDIR_P([$dirpart/$fdir])
|
||||
# echo "creating $dirpart/$file"
|
||||
echo '# dummy' > "$dirpart/$file"
|
||||
done
|
||||
done
|
||||
}
|
||||
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
|
||||
|
||||
# AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
# -----------------------------
|
||||
# This macro should only be invoked once -- use via AC_REQUIRE.
|
||||
#
|
||||
# This code is only required when automatic dependency tracking
|
||||
# is enabled. FIXME. This creates each `.P' file that we will
|
||||
# need in order to bootstrap the dependency handling code.
|
||||
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[AC_CONFIG_COMMANDS([depfiles],
|
||||
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
|
||||
])
|
||||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 16
|
||||
|
||||
# This macro actually does too much. Some checks are only needed if
|
||||
# your package does certain things. But this isn't really a big deal.
|
||||
|
||||
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
|
||||
# AM_INIT_AUTOMAKE([OPTIONS])
|
||||
# -----------------------------------------------
|
||||
# The call with PACKAGE and VERSION arguments is the old style
|
||||
# call (pre autoconf-2.50), which is being phased out. PACKAGE
|
||||
# and VERSION should now be passed to AC_INIT and removed from
|
||||
# the call to AM_INIT_AUTOMAKE.
|
||||
# We support both call styles for the transition. After
|
||||
# the next Automake release, Autoconf can make the AC_INIT
|
||||
# arguments mandatory, and then we can depend on a new Autoconf
|
||||
# release and drop the old call support.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[AC_PREREQ([2.62])dnl
|
||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
||||
dnl the ones we care about.
|
||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
||||
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
|
||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`"; then
|
||||
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
|
||||
# is not polluted with repeated "-I."
|
||||
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
|
||||
# test to see if srcdir already configured
|
||||
if test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
fi
|
||||
fi
|
||||
|
||||
# test whether we have cygpath
|
||||
if test -z "$CYGPATH_W"; then
|
||||
if (cygpath --version) >/dev/null 2>/dev/null; then
|
||||
CYGPATH_W='cygpath -w'
|
||||
else
|
||||
CYGPATH_W=echo
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([CYGPATH_W])
|
||||
|
||||
# Define the identity of the package.
|
||||
dnl Distinguish between old-style and new-style calls.
|
||||
m4_ifval([$2],
|
||||
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
|
||||
AC_SUBST([PACKAGE], [$1])dnl
|
||||
AC_SUBST([VERSION], [$2])],
|
||||
[_AM_SET_OPTIONS([$1])dnl
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
|
||||
|
||||
_AM_IF_OPTION([no-define],,
|
||||
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
|
||||
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
|
||||
|
||||
# Some tools Automake needs.
|
||||
AC_REQUIRE([AM_SANITY_CHECK])dnl
|
||||
AC_REQUIRE([AC_ARG_PROGRAM])dnl
|
||||
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
|
||||
AM_MISSING_PROG(AUTOCONF, autoconf)
|
||||
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
|
||||
AM_MISSING_PROG(AUTOHEADER, autoheader)
|
||||
AM_MISSING_PROG(MAKEINFO, makeinfo)
|
||||
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
|
||||
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
|
||||
# We need awk for the "check" target. The system "awk" is bad on
|
||||
# some platforms.
|
||||
AC_REQUIRE([AC_PROG_AWK])dnl
|
||||
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
|
||||
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
|
||||
[_AM_PROG_TAR([v7])])])
|
||||
_AM_IF_OPTION([no-dependencies],,
|
||||
[AC_PROVIDE_IFELSE([AC_PROG_CC],
|
||||
[_AM_DEPENDENCIES(CC)],
|
||||
[define([AC_PROG_CC],
|
||||
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_CXX],
|
||||
[_AM_DEPENDENCIES(CXX)],
|
||||
[define([AC_PROG_CXX],
|
||||
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
|
||||
[_AM_DEPENDENCIES(OBJC)],
|
||||
[define([AC_PROG_OBJC],
|
||||
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
|
||||
])
|
||||
_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
|
||||
dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
|
||||
dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
|
||||
dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
|
||||
AC_CONFIG_COMMANDS_PRE(dnl
|
||||
[m4_provide_if([_AM_COMPILER_EXEEXT],
|
||||
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
|
||||
])
|
||||
|
||||
dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
|
||||
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
|
||||
dnl mangled by Autoconf and run in a shell conditional statement.
|
||||
m4_define([_AC_COMPILER_EXEEXT],
|
||||
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
|
||||
|
||||
|
||||
# When config.status generates a header, we must update the stamp-h file.
|
||||
# This file resides in the same directory as the config header
|
||||
# that is generated. The stamp files are numbered to have different names.
|
||||
|
||||
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
|
||||
# loop where config.status creates the headers, so we can generate
|
||||
# our stamp files there.
|
||||
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
|
||||
[# Compute $1's index in $config_headers.
|
||||
_am_arg=$1
|
||||
_am_stamp_count=1
|
||||
for _am_header in $config_headers :; do
|
||||
case $_am_header in
|
||||
$_am_arg | $_am_arg:* )
|
||||
break ;;
|
||||
* )
|
||||
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
|
||||
esac
|
||||
done
|
||||
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_INSTALL_SH
|
||||
# ------------------
|
||||
# Define $install_sh.
|
||||
AC_DEFUN([AM_PROG_INSTALL_SH],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
if test x"${install_sh}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
|
||||
*)
|
||||
install_sh="\${SHELL} $am_aux_dir/install-sh"
|
||||
esac
|
||||
fi
|
||||
AC_SUBST(install_sh)])
|
||||
|
||||
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# Check whether the underlying file-system supports filenames
|
||||
# with a leading dot. For instance MS-DOS doesn't.
|
||||
AC_DEFUN([AM_SET_LEADING_DOT],
|
||||
[rm -rf .tst 2>/dev/null
|
||||
mkdir .tst 2>/dev/null
|
||||
if test -d .tst; then
|
||||
am__leading_dot=.
|
||||
else
|
||||
am__leading_dot=_
|
||||
fi
|
||||
rmdir .tst 2>/dev/null
|
||||
AC_SUBST([am__leading_dot])])
|
||||
|
||||
# Check to see how 'make' treats includes. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 4
|
||||
|
||||
# AM_MAKE_INCLUDE()
|
||||
# -----------------
|
||||
# Check to see how make treats includes.
|
||||
AC_DEFUN([AM_MAKE_INCLUDE],
|
||||
[am_make=${MAKE-make}
|
||||
cat > confinc << 'END'
|
||||
am__doit:
|
||||
@echo this is the am__doit target
|
||||
.PHONY: am__doit
|
||||
END
|
||||
# If we don't find an include directive, just comment out the code.
|
||||
AC_MSG_CHECKING([for style of include used by $am_make])
|
||||
am__include="#"
|
||||
am__quote=
|
||||
_am_result=none
|
||||
# First try GNU make style include.
|
||||
echo "include confinc" > confmf
|
||||
# Ignore all kinds of additional output from `make'.
|
||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
||||
*the\ am__doit\ target*)
|
||||
am__include=include
|
||||
am__quote=
|
||||
_am_result=GNU
|
||||
;;
|
||||
esac
|
||||
# Now try BSD make style include.
|
||||
if test "$am__include" = "#"; then
|
||||
echo '.include "confinc"' > confmf
|
||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
||||
*the\ am__doit\ target*)
|
||||
am__include=.include
|
||||
am__quote="\""
|
||||
_am_result=BSD
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_SUBST([am__include])
|
||||
AC_SUBST([am__quote])
|
||||
AC_MSG_RESULT([$_am_result])
|
||||
rm -f confinc confmf
|
||||
])
|
||||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 6
|
||||
|
||||
# AM_MISSING_PROG(NAME, PROGRAM)
|
||||
# ------------------------------
|
||||
AC_DEFUN([AM_MISSING_PROG],
|
||||
[AC_REQUIRE([AM_MISSING_HAS_RUN])
|
||||
$1=${$1-"${am_missing_run}$2"}
|
||||
AC_SUBST($1)])
|
||||
|
||||
|
||||
# AM_MISSING_HAS_RUN
|
||||
# ------------------
|
||||
# Define MISSING if not defined so far and test if it supports --run.
|
||||
# If it does, set am_missing_run to use it, otherwise, to nothing.
|
||||
AC_DEFUN([AM_MISSING_HAS_RUN],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([missing])dnl
|
||||
if test x"${MISSING+set}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
|
||||
*)
|
||||
MISSING="\${SHELL} $am_aux_dir/missing" ;;
|
||||
esac
|
||||
fi
|
||||
# Use eval to expand $SHELL
|
||||
if eval "$MISSING --run true"; then
|
||||
am_missing_run="$MISSING --run "
|
||||
else
|
||||
am_missing_run=
|
||||
AC_MSG_WARN([`missing' script is too old or missing])
|
||||
fi
|
||||
])
|
||||
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_MKDIR_P
|
||||
# ---------------
|
||||
# Check for `mkdir -p'.
|
||||
AC_DEFUN([AM_PROG_MKDIR_P],
|
||||
[AC_PREREQ([2.60])dnl
|
||||
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
|
||||
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
|
||||
dnl while keeping a definition of mkdir_p for backward compatibility.
|
||||
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
|
||||
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
|
||||
dnl Makefile.ins that do not define MKDIR_P, so we do our own
|
||||
dnl adjustment using top_builddir (which is defined more often than
|
||||
dnl MKDIR_P).
|
||||
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
|
||||
case $mkdir_p in
|
||||
[[\\/$]]* | ?:[[\\/]]*) ;;
|
||||
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
|
||||
esac
|
||||
])
|
||||
|
||||
# Helper functions for option handling. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 4
|
||||
|
||||
# _AM_MANGLE_OPTION(NAME)
|
||||
# -----------------------
|
||||
AC_DEFUN([_AM_MANGLE_OPTION],
|
||||
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
|
||||
|
||||
# _AM_SET_OPTION(NAME)
|
||||
# ------------------------------
|
||||
# Set option NAME. Presently that only means defining a flag for this option.
|
||||
AC_DEFUN([_AM_SET_OPTION],
|
||||
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
|
||||
|
||||
# _AM_SET_OPTIONS(OPTIONS)
|
||||
# ----------------------------------
|
||||
# OPTIONS is a space-separated list of Automake options.
|
||||
AC_DEFUN([_AM_SET_OPTIONS],
|
||||
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
|
||||
|
||||
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
|
||||
# -------------------------------------------
|
||||
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
||||
AC_DEFUN([_AM_IF_OPTION],
|
||||
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
|
||||
|
||||
# Check to make sure that the build environment is sane. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 5
|
||||
|
||||
# AM_SANITY_CHECK
|
||||
# ---------------
|
||||
AC_DEFUN([AM_SANITY_CHECK],
|
||||
[AC_MSG_CHECKING([whether build environment is sane])
|
||||
# Just in case
|
||||
sleep 1
|
||||
echo timestamp > conftest.file
|
||||
# Reject unsafe characters in $srcdir or the absolute working directory
|
||||
# name. Accept space and tab only in the latter.
|
||||
am_lf='
|
||||
'
|
||||
case `pwd` in
|
||||
*[[\\\"\#\$\&\'\`$am_lf]]*)
|
||||
AC_MSG_ERROR([unsafe absolute working directory name]);;
|
||||
esac
|
||||
case $srcdir in
|
||||
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
|
||||
AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
|
||||
esac
|
||||
|
||||
# Do `set' in a subshell so we don't clobber the current shell's
|
||||
# arguments. Must try -L first in case configure is actually a
|
||||
# symlink; some systems play weird games with the mod time of symlinks
|
||||
# (eg FreeBSD returns the mod time of the symlink's containing
|
||||
# directory).
|
||||
if (
|
||||
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
|
||||
if test "$[*]" = "X"; then
|
||||
# -L didn't work.
|
||||
set X `ls -t "$srcdir/configure" conftest.file`
|
||||
fi
|
||||
rm -f conftest.file
|
||||
if test "$[*]" != "X $srcdir/configure conftest.file" \
|
||||
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
|
||||
|
||||
# If neither matched, then we have a broken ls. This can happen
|
||||
# if, for instance, CONFIG_SHELL is bash and it inherits a
|
||||
# broken ls alias from the environment. This has actually
|
||||
# happened. Such a system could not be considered "sane".
|
||||
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
|
||||
alias in your environment])
|
||||
fi
|
||||
|
||||
test "$[2]" = conftest.file
|
||||
)
|
||||
then
|
||||
# Ok.
|
||||
:
|
||||
else
|
||||
AC_MSG_ERROR([newly created file is older than distributed files!
|
||||
Check your system clock])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)])
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_INSTALL_STRIP
|
||||
# ---------------------
|
||||
# One issue with vendor `install' (even GNU) is that you can't
|
||||
# specify the program used to strip binaries. This is especially
|
||||
# annoying in cross-compiling environments, where the build's strip
|
||||
# is unlikely to handle the host's binaries.
|
||||
# Fortunately install-sh will honor a STRIPPROG variable, so we
|
||||
# always use install-sh in `make install-strip', and initialize
|
||||
# STRIPPROG with the value of the STRIP variable (set by the user).
|
||||
AC_DEFUN([AM_PROG_INSTALL_STRIP],
|
||||
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
# Installed binaries are usually stripped using `strip' when the user
|
||||
# run `make install-strip'. However `strip' might not be the right
|
||||
# tool to use in cross-compilation environments, therefore Automake
|
||||
# will honor the `STRIP' environment variable to overrule this program.
|
||||
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
|
||||
if test "$cross_compiling" != no; then
|
||||
AC_CHECK_TOOL([STRIP], [strip], :)
|
||||
fi
|
||||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
||||
|
||||
# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Public sister of _AM_SUBST_NOTMAKE.
|
||||
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
|
||||
|
||||
# Check how to create a tarball. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# _AM_PROG_TAR(FORMAT)
|
||||
# --------------------
|
||||
# Check how to create a tarball in format FORMAT.
|
||||
# FORMAT should be one of `v7', `ustar', or `pax'.
|
||||
#
|
||||
# Substitute a variable $(am__tar) that is a command
|
||||
# writing to stdout a FORMAT-tarball containing the directory
|
||||
# $tardir.
|
||||
# tardir=directory && $(am__tar) > result.tar
|
||||
#
|
||||
# Substitute a variable $(am__untar) that extract such
|
||||
# a tarball read from stdin.
|
||||
# $(am__untar) < result.tar
|
||||
AC_DEFUN([_AM_PROG_TAR],
|
||||
[# Always define AMTAR for backward compatibility.
|
||||
AM_MISSING_PROG([AMTAR], [tar])
|
||||
m4_if([$1], [v7],
|
||||
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
|
||||
[m4_case([$1], [ustar],, [pax],,
|
||||
[m4_fatal([Unknown tar format])])
|
||||
AC_MSG_CHECKING([how to create a $1 tar archive])
|
||||
# Loop over all known methods to create a tar archive until one works.
|
||||
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
|
||||
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
|
||||
# Do not fold the above two line into one, because Tru64 sh and
|
||||
# Solaris sh will not grok spaces in the rhs of `-'.
|
||||
for _am_tool in $_am_tools
|
||||
do
|
||||
case $_am_tool in
|
||||
gnutar)
|
||||
for _am_tar in tar gnutar gtar;
|
||||
do
|
||||
AM_RUN_LOG([$_am_tar --version]) && break
|
||||
done
|
||||
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
|
||||
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
|
||||
am__untar="$_am_tar -xf -"
|
||||
;;
|
||||
plaintar)
|
||||
# Must skip GNU tar: if it does not support --format= it doesn't create
|
||||
# ustar tarball either.
|
||||
(tar --version) >/dev/null 2>&1 && continue
|
||||
am__tar='tar chf - "$$tardir"'
|
||||
am__tar_='tar chf - "$tardir"'
|
||||
am__untar='tar xf -'
|
||||
;;
|
||||
pax)
|
||||
am__tar='pax -L -x $1 -w "$$tardir"'
|
||||
am__tar_='pax -L -x $1 -w "$tardir"'
|
||||
am__untar='pax -r'
|
||||
;;
|
||||
cpio)
|
||||
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
|
||||
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
|
||||
am__untar='cpio -i -H $1 -d'
|
||||
;;
|
||||
none)
|
||||
am__tar=false
|
||||
am__tar_=false
|
||||
am__untar=false
|
||||
;;
|
||||
esac
|
||||
|
||||
# If the value was cached, stop now. We just wanted to have am__tar
|
||||
# and am__untar set.
|
||||
test -n "${am_cv_prog_tar_$1}" && break
|
||||
|
||||
# tar/untar a dummy directory, and stop if the command works
|
||||
rm -rf conftest.dir
|
||||
mkdir conftest.dir
|
||||
echo GrepMe > conftest.dir/file
|
||||
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
|
||||
rm -rf conftest.dir
|
||||
if test -s conftest.tar; then
|
||||
AM_RUN_LOG([$am__untar <conftest.tar])
|
||||
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
|
||||
fi
|
||||
done
|
||||
rm -rf conftest.dir
|
||||
|
||||
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
|
||||
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
|
||||
AC_SUBST([am__tar])
|
||||
AC_SUBST([am__untar])
|
||||
]) # _AM_PROG_TAR
|
||||
|
64
config.h.in
64
config.h.in
@@ -1,64 +0,0 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if stdbool.h conforms to C99. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#undef HAVE__BOOL
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
31
configure.ac
31
configure.ac
@@ -1,7 +1,7 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.64])
|
||||
AC_PREREQ([2.59])
|
||||
AC_INIT(bind, 10.0.0, bind10-bugs@isc.org)
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
AM_INIT_AUTOMAKE
|
||||
@@ -10,8 +10,11 @@ AC_CONFIG_HEADERS([config.h])
|
||||
# Checks for programs.
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AM_CONDITIONAL(GCC, test "$GCC" = yes)
|
||||
AC_PROG_RANLIB
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# Checks for header files.
|
||||
@@ -20,6 +23,18 @@ AC_PROG_RANLIB
|
||||
AC_HEADER_STDBOOL
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
# default compiler warning settings
|
||||
if test "X$GCC" = "Xyes"; then
|
||||
CXXFLAGS="-g -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare"
|
||||
fi
|
||||
|
||||
# produce PIC unless we disable share libraries. need this for python bindings.
|
||||
if test $enable_shared != "no" -a "X$GCC" = "Xyes"; then
|
||||
CXXFLAGS="$CXXFLAGS -fPIC"
|
||||
fi
|
||||
|
||||
AC_SUBST(CXXFLAGS)
|
||||
|
||||
#
|
||||
# Check availablity of gtest, which will be used for unit tests.
|
||||
#
|
||||
@@ -28,9 +43,17 @@ AC_ARG_WITH(gtest,
|
||||
gtest_path="$withval", gtest_path="no")
|
||||
if test "$gtest_path" != "no"
|
||||
then
|
||||
GTEST_INCLUDES="-I${gtest_path}/include"
|
||||
GTEST_LDFLAGS="-L${gtest_path}/lib"
|
||||
GTEST_LDADD="-lgtest"
|
||||
if test "$gtest_path" != "yes"
|
||||
then
|
||||
GTEST_INCLUDES="-I${gtest_path}/include"
|
||||
GTEST_LDFLAGS="-L${gtest_path}/lib"
|
||||
GTEST_LDADD="-lgtest"
|
||||
else
|
||||
# todo: check for default paths (/usr and /usr/local?)
|
||||
GTEST_INCLUDE="-I/usr/include"
|
||||
GTEST_LDFLAGS="-L/usr/lib"
|
||||
GTEST_LDADD="-lgtest"
|
||||
fi
|
||||
else
|
||||
GTEST_INCLUDES=
|
||||
GTEST_LDFLAGS=
|
||||
|
@@ -611,7 +611,7 @@ EXCLUDE_SYMLINKS = NO
|
||||
# against the file with absolute path, so to exclude all test directories
|
||||
# for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS = *unittest.h
|
||||
EXCLUDE_PATTERNS = *unittest*.h
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
|
524
src/Makefile.in
524
src/Makefile.in
@@ -1,524 +0,0 @@
|
||||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = src
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-dvi-recursive install-exec-recursive \
|
||||
install-html-recursive install-info-recursive \
|
||||
install-pdf-recursive install-ps-recursive install-recursive \
|
||||
installcheck-recursive installdirs-recursive pdf-recursive \
|
||||
ps-recursive uninstall-recursive
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
|
||||
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
|
||||
distdir
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
GTEST_INCLUDES = @GTEST_INCLUDES@
|
||||
GTEST_LDADD = @GTEST_LDADD@
|
||||
GTEST_LDFLAGS = @GTEST_LDFLAGS@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
SUBDIRS = lib
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign src/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
|
||||
install-am install-strip tags-recursive
|
||||
|
||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
||||
all all-am check check-am clean clean-generic ctags \
|
||||
ctags-recursive distclean distclean-generic distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
installdirs-am maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
|
||||
tags-recursive uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
@@ -1,524 +0,0 @@
|
||||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = src/lib
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-dvi-recursive install-exec-recursive \
|
||||
install-html-recursive install-info-recursive \
|
||||
install-pdf-recursive install-ps-recursive install-recursive \
|
||||
installcheck-recursive installdirs-recursive pdf-recursive \
|
||||
ps-recursive uninstall-recursive
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
|
||||
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
|
||||
distdir
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
GTEST_INCLUDES = @GTEST_INCLUDES@
|
||||
GTEST_LDADD = @GTEST_LDADD@
|
||||
GTEST_LDFLAGS = @GTEST_LDFLAGS@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
SUBDIRS = dns
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign src/lib/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
|
||||
install-am install-strip tags-recursive
|
||||
|
||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
||||
all all-am check check-am clean clean-generic ctags \
|
||||
ctags-recursive distclean distclean-generic distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
installdirs-am maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
|
||||
tags-recursive uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
@@ -1,13 +1,17 @@
|
||||
lib_LIBRARIES = libdns.a
|
||||
libdns_a_SOURCES = name.cc name.h
|
||||
lib_LTLIBRARIES = libdns.la
|
||||
libdns_la_SOURCES = buffer.h name.cc name.h messagerenderer.h messagerenderer.cc
|
||||
libdns_la_SOURCES += exceptions.h exceptions.cc
|
||||
|
||||
TESTS =
|
||||
if HAVE_GTEST
|
||||
TESTS += run_unittests
|
||||
run_unittests_SOURCES = run_unittests.cc
|
||||
run_unittests_SOURCES = unittest_util.h unittest_util.cc
|
||||
run_unittests_SOURCES += buffer_unittest.cc name_unittest.cc
|
||||
run_unittests_SOURCES += messagerenderer_unittest.cc exceptions_unittest.cc
|
||||
run_unittests_SOURCES += run_unittests.cc
|
||||
run_unittests_CPPFLAGS = $(GTEST_INCLUDES)
|
||||
run_unittests_LDFLAGS = $(GTEST_LDFLAGS)
|
||||
run_unittests_LDADD = ./libdns.a $(GTEST_LDADD)
|
||||
run_unittests_LDADD = .libs/libdns.a $(GTEST_LDADD)
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
401
src/lib/dns/cpp/buffer.h
Normal file
401
src/lib/dns/cpp/buffer.h
Normal file
@@ -0,0 +1,401 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#ifndef __BUFFER_H
|
||||
#define __BUFFER_H 1
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "exceptions.h"
|
||||
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if an out-of-range
|
||||
/// buffer operation is being performed.
|
||||
///
|
||||
class InvalidBufferPosition : public Exception {
|
||||
public:
|
||||
InvalidBufferPosition(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///\brief The \c InputBuffer class is a buffer abstraction for manipulating
|
||||
/// read-only data.
|
||||
///
|
||||
/// The main purpose of this class is to provide a safe placeholder for
|
||||
/// examining wire-format data received from a network.
|
||||
///
|
||||
/// Applications normally use this class only in a limited situation: as an
|
||||
/// interface between legacy I/O operation (such as receiving data from a BSD
|
||||
/// socket) and the rest of the BIND10 DNS library. One common usage of this
|
||||
/// class for an application would therefore be something like this:
|
||||
///
|
||||
/// \code unsigned char buf[1024];
|
||||
/// struct sockaddr addr;
|
||||
/// socklen_t addrlen = sizeof(addr);
|
||||
/// int cc = recvfrom(s, buf, sizeof(buf), 0, &addr, &addrlen);
|
||||
/// InputBuffer buffer(buf, cc);
|
||||
/// // pass the buffer to a DNS message object to parse the message \endcode
|
||||
///
|
||||
/// Other BIND10 DNS classes will then use methods of this class to get access
|
||||
/// to the data, but the application normally doesn't have to care about the
|
||||
/// details.
|
||||
///
|
||||
/// An \c InputBuffer object internally holds a reference to the given data,
|
||||
/// rather than make a local copy of the data. Also, it does not have an
|
||||
/// ownership of the given data. It is application's responsibility to ensure
|
||||
/// the data remains valid throughout the lifetime of the \c InputBuffer
|
||||
/// object. Likewise, this object generally assumes the data isn't modified
|
||||
/// throughout its lifetime; if the application modifies the data while this
|
||||
/// object retains a reference to it, the result is undefined. The application
|
||||
/// will also be responsible for releasing the data when it's not needed if it
|
||||
/// was dynamically acquired.
|
||||
///
|
||||
/// This is a deliberate design choice: although it's safer to make a local
|
||||
/// copy of the given data on construction, it would cause unacceptable
|
||||
/// performance overhead, especially considering that a DNS message can be
|
||||
/// as large as a few KB. Alternatively, we could allow the object to allocate
|
||||
/// memory internally and expose it to the application to store network data
|
||||
/// in it. This is also a bad design, however, in that we would effectively
|
||||
/// break the abstraction employed in the class, and do so by publishing
|
||||
/// "read-only" stuff as a writable memory region. Since there doesn't seem to
|
||||
/// be a perfect solution, we have adopted what we thought a "least bad" one.
|
||||
///
|
||||
/// Methods for reading data from the buffer generally work like an input
|
||||
/// stream: it begins with the head of the data, and once some length of data
|
||||
/// is read from the buffer, the next read operation will take place from the
|
||||
/// head of the unread data. An object of this class internally holds (a
|
||||
/// notion of) where the next read operation should start. We call it the
|
||||
/// <em>read position</em> in this document.
|
||||
class InputBuffer {
|
||||
public:
|
||||
///
|
||||
/// \name Constructors and Destructor
|
||||
//@{
|
||||
/// \brief Constructor from variable length of data.
|
||||
///
|
||||
/// It is caller's responsibility to ensure that the data is valid as long
|
||||
/// as the buffer exists.
|
||||
/// \param data A pointer to the data stored in the buffer.
|
||||
/// \param len The length of the data in bytes.
|
||||
InputBuffer(const void* data, size_t len) :
|
||||
position_(0), data_(static_cast<const uint8_t*>(data)), len_(len) {}
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Getter Methods
|
||||
//@{
|
||||
/// \brief Return the length of the data stored in the buffer.
|
||||
size_t getLength() const { return (len_); }
|
||||
/// \brief Return the current read position.
|
||||
size_t getPosition() const { return (position_); }
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Setter Methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Set the read position of the buffer to the given value.
|
||||
///
|
||||
/// The new position must be in the valid range of the buffer; otherwise
|
||||
/// an exception of class \c isc::dns::InvalidBufferPosition will be thrown.
|
||||
/// \param position The new position (offset from the beginning of the
|
||||
/// buffer).
|
||||
void setPosition(size_t position)
|
||||
{
|
||||
if (position > len_)
|
||||
dns_throw(InvalidBufferPosition, "position is too large");
|
||||
position_ = position;
|
||||
}
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Methods for reading data from the buffer.
|
||||
//@{
|
||||
/// \brief Read an unsigned 8-bit integer from the buffer and return it.
|
||||
///
|
||||
/// If the remaining length of the buffer is smaller than 8-bit, an
|
||||
/// exception of class \c isc::dns::InvalidBufferPosition will be thrown.
|
||||
uint8_t readUint8()
|
||||
{
|
||||
if (position_ + sizeof(uint8_t) > len_) {
|
||||
dns_throw(InvalidBufferPosition, "read beyond end of buffer");
|
||||
}
|
||||
|
||||
return (data_[position_++]);
|
||||
}
|
||||
/// \brief Read an unsigned 16-bit integer in network byte order from the
|
||||
/// buffer, convert it to host byte order, and return it.
|
||||
///
|
||||
/// If the remaining length of the buffer is smaller than 16-bit, an
|
||||
/// exception of class \c isc::dns::InvalidBufferPosition will be thrown.
|
||||
uint16_t readUint16()
|
||||
{
|
||||
uint16_t data;
|
||||
const uint8_t* cp;
|
||||
|
||||
if (position_ + sizeof(data) > len_) {
|
||||
dns_throw(InvalidBufferPosition, "read beyond end of buffer");
|
||||
}
|
||||
|
||||
cp = &data_[position_];
|
||||
data = ((unsigned int)(cp[0])) << 8;
|
||||
data |= ((unsigned int)(cp[1]));
|
||||
position_ += sizeof(data);
|
||||
|
||||
return (data);
|
||||
}
|
||||
/// \brief Read an unsigned 32-bit integer in network byte order from the
|
||||
/// buffer, convert it to host byte order, and return it.
|
||||
///
|
||||
/// If the remaining length of the buffer is smaller than 32-bit, an
|
||||
/// exception of class \c isc::dns::InvalidBufferPosition will be thrown.
|
||||
uint32_t readUint32()
|
||||
{
|
||||
uint32_t data;
|
||||
const uint8_t* cp;
|
||||
|
||||
if (position_ + sizeof(data) > len_) {
|
||||
dns_throw(InvalidBufferPosition, "read beyond end of buffer");
|
||||
}
|
||||
|
||||
cp = &data_[position_];
|
||||
data = ((unsigned int)(cp[0])) << 24;
|
||||
data |= ((unsigned int)(cp[1])) << 16;
|
||||
data |= ((unsigned int)(cp[2])) << 8;
|
||||
data |= ((unsigned int)(cp[3]));
|
||||
position_ += sizeof(data);
|
||||
|
||||
return (data);
|
||||
}
|
||||
/// \brief Read data of the specified length from the buffer and copy it to
|
||||
/// the caller supplied buffer.
|
||||
///
|
||||
/// The data is copied as stored in the buffer; no conversion is performed.
|
||||
/// If the remaining length of the buffer is smaller than the specified
|
||||
/// length, an exception of class \c isc::dns::InvalidBufferPosition will
|
||||
/// be thrown.
|
||||
void readData(void* data, size_t len)
|
||||
{
|
||||
if (position_ + len > len_) {
|
||||
dns_throw(InvalidBufferPosition, "read beyond end of buffer");
|
||||
}
|
||||
|
||||
memcpy(data, &data_[position_], len);
|
||||
position_ += len;
|
||||
}
|
||||
//@}
|
||||
|
||||
private:
|
||||
size_t position_;
|
||||
const uint8_t* data_;
|
||||
size_t len_;
|
||||
};
|
||||
|
||||
///
|
||||
///\brief The \c OutputBuffer class is a buffer abstraction for manipulating
|
||||
/// mutable data.
|
||||
///
|
||||
/// The main purpose of this class is to provide a safe workplace for
|
||||
/// constructing wire-format data to be sent out to a network. Here,
|
||||
/// <em>safe</em> means that it automatically allocates necessary memory and
|
||||
/// avoid buffer overrun.
|
||||
///
|
||||
/// Like for the \c InputBuffer class, applications normally use this class only
|
||||
/// in a limited situation. One common usage of this class for an application
|
||||
/// would be something like this:
|
||||
///
|
||||
/// \code OutputBuffer buffer(4096); // give a sufficiently large initial size
|
||||
/// // pass the buffer to a DNS message object to construct a wire-format
|
||||
/// // DNS message.
|
||||
/// struct sockaddr to;
|
||||
/// sendto(s, buffer.getData(), buffer.getLength(), 0, &to, sizeof(to));
|
||||
/// \endcode
|
||||
///
|
||||
/// where the \c getData() method gives a reference to the internal memory
|
||||
/// region stored in the \c buffer object. This is a suboptimal design in that
|
||||
/// it exposes an encapsulated "handle" of an object to its user.
|
||||
/// Unfortunately, there is no easy way to avoid this without involving
|
||||
/// expensive data copy if we want to use this object with a legacy API such as
|
||||
/// a BSD socket interface. And, indeed, this is one major purpose for this
|
||||
/// object. Applications should use this method only under such a special
|
||||
/// circumstance. It should also be noted that the memory region returned by
|
||||
/// \c getData() may be invalidated after a subsequent write operation.
|
||||
///
|
||||
/// An \c OutputBuffer class object automatically extends its memory region when
|
||||
/// data is written beyond the end of the current buffer. However, it will
|
||||
/// involve performance overhead such as reallocating more memory and copying
|
||||
/// data. It is therefore recommended to construct the buffer object with a
|
||||
/// sufficiently large initial size.
|
||||
/// The \c getCapacity() method provides the current maximum size of data
|
||||
/// (including the portion already written) that can be written into the buffer
|
||||
/// without causing memory reallocation.
|
||||
///
|
||||
/// Methods for writing data into the buffer generally work like an output
|
||||
/// stream: it begins with the head of the buffer, and once some length of data
|
||||
/// is written into the buffer, the next write operation will take place from
|
||||
/// the end of the buffer. Other methods to emulate "random access" are also
|
||||
/// provided (e.g., \c writeUint16At()). The normal write operations are
|
||||
/// normally exception-free as this class automatically extends the buffer
|
||||
/// when necessary. However, in extreme cases such as an attempt of writing
|
||||
/// multi-GB data, a separate exception (e.g., \c std::bad_alloc) may be thrown
|
||||
/// by the system. This also applies to the constructor with a very large
|
||||
/// initial size.
|
||||
///
|
||||
/// Note to developers: it may make more sense to introduce an abstract base
|
||||
/// class for the \c OutputBuffer and define the simple implementation as a
|
||||
/// a concrete derived class. That way we can provide flexibility for future
|
||||
/// extension such as more efficient buffer implementation or allowing users
|
||||
/// to have their own customized version without modifying the source code.
|
||||
/// We in fact considered that option, but at the moment chose the simpler
|
||||
/// approach with a single concrete class because it may make the
|
||||
/// implementation unnecessarily complicated while we were still not certain
|
||||
/// if we really want that flexibility. We may revisit the class design as
|
||||
/// we see more applications of the class. The same considerations apply to
|
||||
/// the \c InputBuffer and \c MessageRenderer classes.
|
||||
class OutputBuffer {
|
||||
public:
|
||||
///
|
||||
/// \name Constructors and Destructor
|
||||
///
|
||||
//@{
|
||||
/// \brief Constructor from the initial size of the buffer.
|
||||
///
|
||||
/// \param len The initial length of the buffer in bytes.
|
||||
OutputBuffer(size_t len) { data_.reserve(len); }
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Getter Methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Return the current capacity of the buffer.
|
||||
size_t getCapacity() const { return (data_.capacity()); }
|
||||
/// \brief Return a pointer to the head of the data stored in the buffer.
|
||||
///
|
||||
/// The caller can assume that the subsequent \c getLength() bytes are
|
||||
/// identical to the stored data of the buffer.
|
||||
///
|
||||
/// Note: The pointer returned by this method may be invalidated after a
|
||||
/// subsequent write operation.
|
||||
const void* getData() const { return (&data_[0]); }
|
||||
/// \brief Return the length of data written in the buffer.
|
||||
size_t getLength() const { return (data_.size()); }
|
||||
/// \brief Return the value of the buffer at the specified position.
|
||||
///
|
||||
/// \c pos must specify the valid position of the buffer; otherwise an
|
||||
/// exception class of \c InvalidBufferPosition will be thrown.
|
||||
///
|
||||
/// \param pos The position in the buffer to be returned.
|
||||
uint8_t operator[](size_t pos) const
|
||||
{
|
||||
if (pos >= data_.size()) {
|
||||
dns_throw(InvalidBufferPosition, "read at invalid position");
|
||||
}
|
||||
return (data_[pos]);
|
||||
}
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Methods for writing data into the buffer.
|
||||
///
|
||||
//@{
|
||||
/// \brief Insert a specified length of gap at the end of the buffer.
|
||||
///
|
||||
/// The caller should not assume any particular value to be inserted.
|
||||
/// This method is provided as a shortcut to make a hole in the buffer
|
||||
/// that is to be filled in later, e.g, by \ref writeUint16At().
|
||||
/// \param len The length of the gap to be inserted in bytes.
|
||||
void skip(size_t len) { data_.insert(data_.end(), len, 0); }
|
||||
/// \brief Clear buffer content.
|
||||
///
|
||||
/// This method can be used to re-initialize and reuse the buffer without
|
||||
/// constructing a new one.
|
||||
void clear() { data_.clear(); }
|
||||
/// \brief Write an unsigned 8-bit integer into the buffer.
|
||||
///
|
||||
/// \param data The 8-bit integer to be written into the buffer.
|
||||
void writeUint8(uint8_t data) { data_.push_back(data); }
|
||||
|
||||
/// \brief Write an unsigned 16-bit integer in host byte order into the
|
||||
/// buffer in network byte order.
|
||||
///
|
||||
/// \param data The 16-bit integer to be written into the buffer.
|
||||
void writeUint16(uint16_t data)
|
||||
{
|
||||
data_.push_back(static_cast<uint8_t>((data & 0xff00U) >> 8));
|
||||
data_.push_back(static_cast<uint8_t>(data & 0x00ffU));
|
||||
}
|
||||
/// \brief Write an unsigned 16-bit integer in host byte order at the
|
||||
/// specified position of the buffer in network byte order.
|
||||
///
|
||||
/// The buffer must have a sufficient room to store the given data at the
|
||||
/// given position, that is, <code>pos + 2 < getLength()</code>;
|
||||
/// otherwise an exception of class \c isc::dns::InvalidBufferPosition will
|
||||
/// be thrown.
|
||||
/// Note also that this method never extends the buffer.
|
||||
///
|
||||
/// \param data The 16-bit integer to be written into the buffer.
|
||||
/// \param pos The beginning position in the buffer to write the data.
|
||||
void writeUint16At(uint16_t data, size_t pos)
|
||||
{
|
||||
if (pos + sizeof(data) >= data_.size()) {
|
||||
dns_throw(InvalidBufferPosition, "write at invalid position");
|
||||
}
|
||||
|
||||
data_[pos] = static_cast<uint8_t>((data & 0xff00U) >> 8);
|
||||
data_[pos + 1] = static_cast<uint8_t>(data & 0x00ffU);
|
||||
}
|
||||
/// \brief Write an unsigned 32-bit integer in host byte order
|
||||
/// into the buffer in network byte order.
|
||||
///
|
||||
/// \param data The 32-bit integer to be written into the buffer.
|
||||
void writeUint32(uint32_t data)
|
||||
{
|
||||
data_.push_back(static_cast<uint8_t>((data & 0xff000000) >> 24));
|
||||
data_.push_back(static_cast<uint8_t>((data & 0x00ff0000) >> 16));
|
||||
data_.push_back(static_cast<uint8_t>((data & 0x0000ff00) >> 8));
|
||||
data_.push_back(static_cast<uint8_t>(data & 0x000000ff));
|
||||
}
|
||||
/// \brief Copy an arbitrary length of data into the buffer.
|
||||
///
|
||||
/// No conversion on the copied data is performed.
|
||||
///
|
||||
/// \param data A pointer to the data to be copied into the buffer.
|
||||
/// \param len The length of the data in bytes.
|
||||
void writeData(const void *data, size_t len)
|
||||
{
|
||||
const uint8_t* cp = static_cast<const uint8_t*>(data);
|
||||
data_.insert(data_.end(), cp, cp + len);
|
||||
}
|
||||
//@}
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // __BUFFER_H
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// End:
|
167
src/lib/dns/cpp/buffer_unittest.cc
Normal file
167
src/lib/dns/cpp/buffer_unittest.cc
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using isc::dns::InputBuffer;
|
||||
using isc::dns::OutputBuffer;
|
||||
|
||||
class BufferTest : public ::testing::Test {
|
||||
protected:
|
||||
BufferTest() : ibuffer(testdata, sizeof(testdata)), obuffer(0),
|
||||
expected_size(0)
|
||||
{
|
||||
data16 = (2 << 8) | 3;
|
||||
data32 = (4 << 24) | (5 << 16) | (6 << 8) | 7;
|
||||
}
|
||||
|
||||
InputBuffer ibuffer;
|
||||
OutputBuffer obuffer;
|
||||
static const uint8_t testdata[5];
|
||||
uint8_t vdata[sizeof(testdata)];
|
||||
size_t expected_size;
|
||||
uint16_t data16;
|
||||
uint32_t data32;
|
||||
};
|
||||
|
||||
const uint8_t BufferTest::testdata[5] = {1, 2, 3, 4, 5};
|
||||
|
||||
TEST_F(BufferTest, input_buffer_read)
|
||||
{
|
||||
EXPECT_EQ(5, ibuffer.getLength());
|
||||
EXPECT_EQ(1, ibuffer.readUint8());
|
||||
EXPECT_EQ(1, ibuffer.getPosition());
|
||||
data16 = ibuffer.readUint16();
|
||||
EXPECT_EQ((2 << 8) | 3, data16);
|
||||
EXPECT_EQ(3, ibuffer.getPosition());
|
||||
ibuffer.setPosition(1);
|
||||
EXPECT_EQ(1, ibuffer.getPosition());
|
||||
data32 = ibuffer.readUint32();
|
||||
EXPECT_EQ((2 << 24) | (3 << 16) | (4 << 8) | 5, data32);
|
||||
ibuffer.setPosition(0);
|
||||
memset(vdata, 0, sizeof(vdata));
|
||||
ibuffer.readData(vdata, sizeof(vdata));
|
||||
EXPECT_EQ(0, memcmp(vdata, testdata, sizeof(testdata)));
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, input_buffer_exception)
|
||||
{
|
||||
EXPECT_THROW(ibuffer.setPosition(6), isc::dns::InvalidBufferPosition);
|
||||
|
||||
ibuffer.setPosition(sizeof(testdata));
|
||||
EXPECT_THROW(ibuffer.readUint8(), isc::dns::InvalidBufferPosition);
|
||||
|
||||
ibuffer.setPosition(sizeof(testdata) - 1);
|
||||
EXPECT_THROW(ibuffer.readUint16(), isc::dns::InvalidBufferPosition);
|
||||
|
||||
ibuffer.setPosition(sizeof(testdata) - 3);
|
||||
EXPECT_THROW(ibuffer.readUint32(), isc::dns::InvalidBufferPosition);
|
||||
|
||||
ibuffer.setPosition(sizeof(testdata) - 4);
|
||||
EXPECT_THROW(ibuffer.readData(vdata, sizeof(vdata)),
|
||||
isc::dns::InvalidBufferPosition);
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, output_buffer_extend)
|
||||
{
|
||||
EXPECT_EQ(0, obuffer.getCapacity());
|
||||
EXPECT_EQ(0, obuffer.getLength());
|
||||
obuffer.writeUint8(10);
|
||||
EXPECT_LT(0, obuffer.getCapacity());
|
||||
EXPECT_EQ(1, obuffer.getLength());
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, output_buffer_write)
|
||||
{
|
||||
const uint8_t* cp;
|
||||
|
||||
obuffer.writeUint8(1);
|
||||
expected_size += sizeof(uint8_t);
|
||||
EXPECT_EQ(expected_size, obuffer.getLength());
|
||||
cp = static_cast<const uint8_t*>(obuffer.getData());
|
||||
EXPECT_EQ(1, *cp);
|
||||
|
||||
obuffer.writeUint16(data16);
|
||||
expected_size += sizeof(data16);
|
||||
cp = static_cast<const uint8_t*>(obuffer.getData());
|
||||
EXPECT_EQ(expected_size, obuffer.getLength());
|
||||
EXPECT_EQ(2, *(cp + 1));
|
||||
EXPECT_EQ(3, *(cp + 2));
|
||||
|
||||
obuffer.writeUint32(data32);
|
||||
expected_size += sizeof(data32);
|
||||
cp = static_cast<const uint8_t*>(obuffer.getData());
|
||||
EXPECT_EQ(expected_size, obuffer.getLength());
|
||||
EXPECT_EQ(4, *(cp + 3));
|
||||
EXPECT_EQ(5, *(cp + 4));
|
||||
EXPECT_EQ(6, *(cp + 5));
|
||||
EXPECT_EQ(7, *(cp + 6));
|
||||
|
||||
obuffer.writeData(testdata, sizeof(testdata));
|
||||
expected_size += sizeof(testdata);
|
||||
EXPECT_EQ(expected_size, obuffer.getLength());
|
||||
cp = static_cast<const uint8_t*>(obuffer.getData());
|
||||
EXPECT_EQ(0, memcmp(cp + 7, testdata, sizeof(testdata)));
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, output_buffer_writeat)
|
||||
{
|
||||
obuffer.writeUint32(data32);
|
||||
expected_size += sizeof(data32);
|
||||
obuffer.writeUint16At(data16, 1);
|
||||
EXPECT_EQ(expected_size, obuffer.getLength()); // length shouldn't change
|
||||
|
||||
const uint8_t* cp = static_cast<const uint8_t*>(obuffer.getData());
|
||||
EXPECT_EQ(2, *(cp + 1));
|
||||
EXPECT_EQ(3, *(cp + 2));
|
||||
|
||||
EXPECT_THROW(obuffer.writeUint16At(data16, 3),
|
||||
isc::dns::InvalidBufferPosition);
|
||||
EXPECT_THROW(obuffer.writeUint16At(data16, 4),
|
||||
isc::dns::InvalidBufferPosition);
|
||||
EXPECT_THROW(obuffer.writeUint16At(data16, 5),
|
||||
isc::dns::InvalidBufferPosition);
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, output_buffer_skip)
|
||||
{
|
||||
obuffer.skip(4);
|
||||
EXPECT_EQ(4, obuffer.getLength());
|
||||
|
||||
obuffer.skip(2);
|
||||
EXPECT_EQ(6, obuffer.getLength());
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, output_buffer_readat)
|
||||
{
|
||||
obuffer.writeData(testdata, sizeof(testdata));
|
||||
for (int i = 0; i < sizeof(testdata); i ++) {
|
||||
EXPECT_EQ(testdata[i], obuffer[i]);
|
||||
}
|
||||
EXPECT_THROW(obuffer[sizeof(testdata)], isc::dns::InvalidBufferPosition);
|
||||
}
|
||||
|
||||
TEST_F(BufferTest, output_buffer_clear)
|
||||
{
|
||||
obuffer.writeData(testdata, sizeof(testdata));
|
||||
obuffer.clear();
|
||||
EXPECT_EQ(0, obuffer.getLength());
|
||||
}
|
||||
}
|
45
src/lib/dns/cpp/exceptions.cc
Normal file
45
src/lib/dns/cpp/exceptions.cc
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "exceptions.h"
|
||||
|
||||
using isc::dns::Exception;
|
||||
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
|
||||
const char*
|
||||
Exception::what() const throw()
|
||||
{
|
||||
const char* whatstr = "isc::dns::Exception";
|
||||
|
||||
// XXX: even though it's very unlikely that c_str() throws an exception,
|
||||
// it's still not 100% guaranteed. To meet the exception specification
|
||||
// of this function, we catch any unexpected exception and fall back to
|
||||
// the pre-defined constant.
|
||||
try {
|
||||
whatstr = what_.c_str();
|
||||
} catch (...) {
|
||||
// no exception handling is necessary. just have to catch exceptions.
|
||||
}
|
||||
|
||||
return (whatstr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
117
src/lib/dns/cpp/exceptions.h
Normal file
117
src/lib/dns/cpp/exceptions.h
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#ifndef __EXCEPTIONS_H
|
||||
#define __EXCEPTIONS_H 1
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
|
||||
///
|
||||
/// This is a base class for exceptions thrown from the DNS library module.
|
||||
/// Normally, the exceptions are thrown via a convenient shortcut macro,
|
||||
/// @ref dns_throw, which automatically gives trivial parameters for the
|
||||
/// exception such as the file name and line number where the exception is
|
||||
/// triggered.
|
||||
///
|
||||
class Exception : public std::exception {
|
||||
public:
|
||||
///
|
||||
/// \name Constructors and Destructor
|
||||
///
|
||||
//@{
|
||||
/// \brief Constructor for a given type for exceptions with file name and
|
||||
/// file line number.
|
||||
///
|
||||
/// @param file the file name where the exception was thrown.
|
||||
/// @param line the line in @ref file where the exception was thrown.
|
||||
/// @param what a description (type) of the exception.
|
||||
Exception(const char* file, size_t line, const char* what) :
|
||||
file_(file), line_(line), what_(what) {}
|
||||
/// The destructor
|
||||
virtual ~Exception() throw() {}
|
||||
//@}
|
||||
private:
|
||||
///
|
||||
/// The assignment operator is intentionally disabled.
|
||||
///
|
||||
void operator=(const Exception& src);
|
||||
|
||||
public:
|
||||
///
|
||||
/// \name Methods Reimplemented against the Standard Exception Class
|
||||
///
|
||||
//@{
|
||||
/// \brief Returns a C-style character string of the cause of the exception.
|
||||
///
|
||||
/// Note: we normally don't use exception specifications, but this is an
|
||||
/// "exception" to that policy as it's enforced by the base class.
|
||||
///
|
||||
/// @return A C-style character string of the exception cause.
|
||||
virtual const char* what() const throw();
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Getter Methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Gets a string describing the cause of the exception.
|
||||
///
|
||||
/// @return the cause string.
|
||||
const std::string& getMessage() const { return (what_); }
|
||||
|
||||
/// \brief Gets the file name where the exception was thrown.
|
||||
///
|
||||
/// @return a C-style string of the file name.
|
||||
const char* getFile() const { return (file_); }
|
||||
|
||||
/// \brief Gets the line number of the file where the exception was thrown.
|
||||
///
|
||||
/// @return an integer specifying the line number.
|
||||
size_t getLine() const { return (line_); }
|
||||
//@}
|
||||
|
||||
private:
|
||||
const char* const file_;
|
||||
size_t line_;
|
||||
const std::string what_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if a parameter give
|
||||
/// to a method would refer to or modify out-of-range data.
|
||||
///
|
||||
class OutOfRange : public Exception {
|
||||
public:
|
||||
OutOfRange(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// A shortcut macro to insert known values into exception arguments.
|
||||
///
|
||||
#define dns_throw(type, args...) throw type(__FILE__, __LINE__, args)
|
||||
|
||||
}
|
||||
}
|
||||
#endif // __EXCEPTIONS_H
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// End:
|
52
src/lib/dns/cpp/exceptions_unittest.cc
Normal file
52
src/lib/dns/cpp/exceptions_unittest.cc
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "exceptions.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using isc::dns::Exception;
|
||||
|
||||
namespace {
|
||||
|
||||
class ExceptionTest : public ::testing::Test {
|
||||
protected:
|
||||
ExceptionTest() : teststring("test") {}
|
||||
const char* teststring;
|
||||
};
|
||||
|
||||
TEST_F(ExceptionTest, BasicMethods) {
|
||||
try {
|
||||
dns_throw(Exception, teststring);
|
||||
} catch (Exception& ex) {
|
||||
EXPECT_EQ(ex.getMessage(), std::string(teststring));
|
||||
EXPECT_EQ(ex.getFile(), std::string(__FILE__));
|
||||
EXPECT_EQ(ex.getLine(), __LINE__ - 4);
|
||||
}
|
||||
}
|
||||
|
||||
// Test to see if it works as a proper derived class of std::exception.
|
||||
TEST_F(ExceptionTest, StdInheritance) {
|
||||
try {
|
||||
dns_throw(Exception, teststring);
|
||||
} catch (std::exception& ex) {
|
||||
EXPECT_EQ(std::string(ex.what()), std::string(teststring));
|
||||
}
|
||||
}
|
||||
}
|
210
src/lib/dns/cpp/messagerenderer.cc
Normal file
210
src/lib/dns/cpp/messagerenderer.cc
Normal file
@@ -0,0 +1,210 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "name.h"
|
||||
#include "messagerenderer.h"
|
||||
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
|
||||
namespace { // hide internal-only names from the public namespaces
|
||||
///
|
||||
/// \brief The \c NameCompressNode class represents a pointer to a name
|
||||
/// rendered in the internal buffer for the \c MessageRendererImpl object.
|
||||
///
|
||||
/// A \c MessageRendererImpl object maintains a set of the \c NameCompressNode
|
||||
/// objects, and searches the set for the position of the longest match
|
||||
/// (ancestor) name against each new name to be rendered into the buffer.
|
||||
struct NameCompressNode {
|
||||
NameCompressNode(const OutputBuffer& buffer, size_t pos, size_t len) :
|
||||
buffer_(buffer), pos_(pos), len_(len) {}
|
||||
/// The buffer in which the corresponding name is rendered.
|
||||
const OutputBuffer& buffer_;
|
||||
/// The position (offset from the beginning) in the buffer where the
|
||||
/// name starts.
|
||||
uint16_t pos_;
|
||||
/// The length of the corresponding name.
|
||||
uint16_t len_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief The \c NameCompare class is a functor that gives ordering among
|
||||
/// \c NameCompressNode objects stored in \c MessageRendererImpl::nodeset_.
|
||||
///
|
||||
/// Its only public method as a functor, \c operator(), gives the ordering
|
||||
/// between two \c NameCompressNode objects in terms of equivalence, that is,
|
||||
/// returns whether one is "less than" the other.
|
||||
/// For our purpose we only need to distinguish two different names, so the
|
||||
/// ordering is different from the canonical DNS name order used in DNSSEC;
|
||||
/// basically, it gives the case-insensitive ordering of the two names as their
|
||||
/// textual representation.
|
||||
struct NameCompare : public std::binary_function<NameCompressNode,
|
||||
NameCompressNode,
|
||||
bool> {
|
||||
///
|
||||
/// Returns true if n1 < n2 as a result of case-insensitive comparison;
|
||||
/// otherwise return false.
|
||||
///
|
||||
/// The name corresponding to \c n1 or \c n2 may be compressed, in which
|
||||
/// case we must follow the compression pointer in the associated buffer.
|
||||
/// The helper private method \c nextPosition() gives the position in the
|
||||
/// buffer for the next character, taking into account compression.
|
||||
///
|
||||
bool operator()(const NameCompressNode& n1,
|
||||
const NameCompressNode& n2) const
|
||||
{
|
||||
if (n1.len_ < n2.len_) {
|
||||
return (true);
|
||||
} else if (n1.len_ > n2.len_) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t pos1 = n1.pos_;
|
||||
uint16_t pos2 = n2.pos_;
|
||||
uint16_t l1 = 0;
|
||||
uint16_t l2 = 0;
|
||||
for (uint16_t i = 0; i < n1.len_; i++, pos1++, pos2++) {
|
||||
pos1 = nextPosition(n1.buffer_, pos1, l1);
|
||||
pos2 = nextPosition(n2.buffer_, pos2, l2);
|
||||
if (tolower(n1.buffer_[pos1]) < tolower(n2.buffer_[pos2])) {
|
||||
return (true);
|
||||
} else if (tolower(n1.buffer_[pos1]) > tolower(n2.buffer_[pos2])) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t nextPosition(const OutputBuffer& buffer,
|
||||
uint16_t pos, uint16_t& llen) const
|
||||
{
|
||||
if (llen == 0) {
|
||||
int i = 0;
|
||||
|
||||
while ((buffer[pos] & Name::COMPRESS_POINTER_MARK8) ==
|
||||
Name::COMPRESS_POINTER_MARK8) {
|
||||
pos = (buffer[pos] & ~Name::COMPRESS_POINTER_MARK8) *
|
||||
256 + buffer[pos + 1];
|
||||
|
||||
// This loop should stop as long as the buffer has been
|
||||
// constructed validly and the search/insert argument is based
|
||||
// on a valid name, which is an assumption for this class.
|
||||
// But we'll abort if a bug could cause an infinite loop.
|
||||
i += 2;
|
||||
assert(i < Name::MAX_WIRE);
|
||||
}
|
||||
llen = buffer[pos];
|
||||
} else {
|
||||
--llen;
|
||||
}
|
||||
return (pos);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief The \c MessageRendererImpl class is the actual implementation of
|
||||
/// \c MessageRenderer.
|
||||
///
|
||||
/// The implementation is hidden from applications. We can refer to specific
|
||||
/// members of this class only within this file.
|
||||
///
|
||||
struct MessageRendererImpl {
|
||||
/// \brief Constructor from an output buffer.
|
||||
///
|
||||
/// \param buffer An \c OutputBuffer object to which wire format data is
|
||||
/// written.
|
||||
MessageRendererImpl(OutputBuffer& buffer) :
|
||||
buffer_(buffer), nbuffer_(Name::MAX_WIRE) {}
|
||||
/// The buffer that holds the entire DNS message.
|
||||
OutputBuffer& buffer_;
|
||||
/// A local working buffer to convert each given name into wire format.
|
||||
/// This could be a local variable of the \c writeName() method, but
|
||||
/// we keep it in the class so that we can reuse it and avoid construction
|
||||
/// overhead.
|
||||
OutputBuffer nbuffer_;
|
||||
/// A set of compression pointers.
|
||||
std::set<NameCompressNode, NameCompare> nodeset_;
|
||||
};
|
||||
|
||||
MessageRenderer::MessageRenderer(OutputBuffer& buffer) :
|
||||
impl_(new MessageRendererImpl(buffer))
|
||||
{}
|
||||
|
||||
MessageRenderer::~MessageRenderer()
|
||||
{
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void
|
||||
MessageRenderer::writeName(const Name& name, bool compress)
|
||||
{
|
||||
impl_->nbuffer_.clear();
|
||||
name.toWire(impl_->nbuffer_);
|
||||
|
||||
unsigned int i;
|
||||
std::set<NameCompressNode>::const_iterator n;
|
||||
|
||||
// Find the longest ancestor name in the rendered set that matches the
|
||||
// given name.
|
||||
for (i = 0; i < impl_->nbuffer_.getLength(); i += impl_->nbuffer_[i] + 1) {
|
||||
// skip the trailing null label
|
||||
if (impl_->nbuffer_[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
n = impl_->nodeset_.find(NameCompressNode(impl_->nbuffer_, i,
|
||||
impl_->nbuffer_.getLength() -
|
||||
i));
|
||||
if (n != impl_->nodeset_.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Record the current offset before extending the buffer.
|
||||
size_t offset = impl_->buffer_.getLength();
|
||||
// Write uncompress part...
|
||||
impl_->buffer_.writeData(impl_->nbuffer_.getData(),
|
||||
compress ? i : impl_->nbuffer_.getLength());
|
||||
if (compress && n != impl_->nodeset_.end()) {
|
||||
// ...and compression pointer if available.
|
||||
uint16_t pointer = (*n).pos_;
|
||||
pointer |= Name::COMPRESS_POINTER_MARK16;
|
||||
impl_->buffer_.writeUint16(pointer);
|
||||
}
|
||||
|
||||
// Finally, add to the set the newly rendered name and its ancestors that
|
||||
// have not been in the set.
|
||||
for (unsigned int j = 0; j < i; j += impl_->nbuffer_[j] + 1) {
|
||||
if (impl_->nbuffer_[j] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (offset + j > Name::MAX_COMPRESS_POINTER) {
|
||||
break;
|
||||
}
|
||||
impl_->nodeset_.insert(NameCompressNode(impl_->buffer_, offset + j,
|
||||
impl_->nbuffer_.getLength() -
|
||||
j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
118
src/lib/dns/cpp/messagerenderer.h
Normal file
118
src/lib/dns/cpp/messagerenderer.h
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#ifndef __MESSAGERENDERER_H
|
||||
#define __MESSAGERENDERER_H 1
|
||||
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
// forward declarations
|
||||
class OutputBuffer;
|
||||
class Name;
|
||||
class MessageRendererImpl;
|
||||
|
||||
///
|
||||
/// \brief The \c MessageRenderer class encapsulates implementation details
|
||||
/// of rendering a DNS message into a buffer in wire format.
|
||||
///
|
||||
/// In effect, it's simply responsible for name compression at least in the
|
||||
/// current implementation. A \c MessageRenderer class object manages the
|
||||
/// positions of names rendered in a buffer and uses that information to render
|
||||
/// subsequent names with compression.
|
||||
///
|
||||
/// This class is mainly intended to be used as a helper for a more
|
||||
/// comprehensive \c Message class internally; normal applications won't have
|
||||
/// to care about this class.
|
||||
///
|
||||
/// A \c MessageRenderer class object is constructed with a \c OutputBuffer
|
||||
/// object, which is the buffer into which the rendered data will be written.
|
||||
/// Normally the buffer is expected to be empty on construction, but it doesn't
|
||||
/// have to be so; the \c MessageRenderer object will start rendering from the
|
||||
/// end of the buffer at the time of construction. However, if the
|
||||
/// pre-existing portion of the buffer contains DNS names, these names won't
|
||||
/// be considered for name compression.
|
||||
///
|
||||
/// Once a \c MessageRenderer object is constructed with a buffer, it is
|
||||
/// generally expected that all rendering operations are performed via the
|
||||
/// \c MessageRenderer object. If the application modifies the buffer in
|
||||
/// parallel with the \c MessageRenderer, the result will be undefined.
|
||||
///
|
||||
/// Note to developers: we introduced a separate class for name compression
|
||||
/// because previous benchmark with BIND9 showed compression affects overall
|
||||
/// response performance very much. By having a separate class dedicated for
|
||||
/// this purpose, we'll be able to change the internal implementation of name
|
||||
/// compression in the future without affecting other part of the API and
|
||||
/// implementation. For the same reason, we adopt the "pimpl" idiom in the
|
||||
/// class definition (i.e., using a pointer to a \c MessageRendererImpl class,
|
||||
/// which is defined with the class implementation, not in the header file):
|
||||
/// we may want to modify the compression implementation without modifying the
|
||||
/// header file thereby requesting rebuild the package.
|
||||
///
|
||||
/// Furthermore, we may eventually want to allow other developers to develop
|
||||
/// and use their own compression implementation. Should such a case become
|
||||
/// realistic, we may want to make the \c MessageRendererImpl class an abstract
|
||||
/// base class and let concrete derived classes have their own implementations.
|
||||
/// At the moment we don't the strong need for it, so we rather avoid over
|
||||
/// abstraction and keep the definition simpler.
|
||||
class MessageRenderer {
|
||||
public:
|
||||
///
|
||||
/// \name Constructors and Destructor
|
||||
//@{
|
||||
/// \brief Constructor from an output buffer.
|
||||
///
|
||||
/// \param buffer An \c OutputBuffer object to which wire format data is
|
||||
/// written.
|
||||
MessageRenderer(OutputBuffer& buffer);
|
||||
/// \brief The default destructor.
|
||||
///
|
||||
/// The destructor does nothing on the given \c buffer on construction;
|
||||
/// in fact, it is expected that the user will use the resulting buffer
|
||||
/// for some post rendering purposes (e.g., send the data to the network).
|
||||
/// It's user's responsibility to do any necessary cleanup for the
|
||||
/// \c buffer.
|
||||
~MessageRenderer();
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Rendering Methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Write a \c Name object into the internal buffer in wire format,
|
||||
/// with or without name compression.
|
||||
///
|
||||
/// If the optional parameter \c compress is \c true, this method tries to
|
||||
/// compress the \c name if possible, searching the entire message that has
|
||||
/// been rendered. Otherwise name compression is omitted. Its default
|
||||
/// value is \c true.
|
||||
///
|
||||
/// Note: even if \c compress is \c true, the position of the \c name (and
|
||||
/// possibly its ancestor names) in the message is recorded and may be used
|
||||
/// for compressing subsequent names.
|
||||
///
|
||||
/// \param name A \c Name object to be written.
|
||||
/// \param compress A boolean indicating whether to enable name compression.
|
||||
void writeName(const Name& name, bool compress = true);
|
||||
private:
|
||||
MessageRendererImpl* impl_;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // __MESSAGERENDERER_H
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// End:
|
96
src/lib/dns/cpp/messagerenderer_unittest.cc
Normal file
96
src/lib/dns/cpp/messagerenderer_unittest.cc
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "name.h"
|
||||
#include "messagerenderer.h"
|
||||
|
||||
#include "unittest_util.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using isc::UnitTestUtil;
|
||||
using isc::dns::OutputBuffer;
|
||||
using isc::dns::Name;
|
||||
using isc::dns::MessageRenderer;
|
||||
|
||||
namespace {
|
||||
class MessageRendererTest : public ::testing::Test {
|
||||
protected:
|
||||
MessageRendererTest() : buffer(0), renderer(buffer) {}
|
||||
OutputBuffer buffer;
|
||||
MessageRenderer renderer;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
TEST_F(MessageRendererTest, toWire)
|
||||
{
|
||||
UnitTestUtil::readWireData("testdata/name_toWire1", data);
|
||||
renderer.writeName(Name("a.example.com."));
|
||||
renderer.writeName(Name("b.example.com."));
|
||||
renderer.writeName(Name("a.example.org."));
|
||||
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
|
||||
buffer.getLength(), &data[0], data.size());
|
||||
}
|
||||
|
||||
TEST_F(MessageRendererTest, toWireInLargeBuffer)
|
||||
{
|
||||
size_t offset = 0x3fff;
|
||||
buffer.skip(offset);
|
||||
|
||||
UnitTestUtil::readWireData("testdata/name_toWire2", data);
|
||||
renderer.writeName(Name("a.example.com."));
|
||||
renderer.writeName(Name("a.example.com."));
|
||||
renderer.writeName(Name("b.example.com."));
|
||||
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
|
||||
static_cast<const uint8_t*>(buffer.getData()) + offset,
|
||||
buffer.getLength() - offset,
|
||||
&data[0], data.size());
|
||||
}
|
||||
|
||||
TEST_F(MessageRendererTest, toWireWithUncompressed)
|
||||
{
|
||||
UnitTestUtil::readWireData("testdata/name_toWire3", data);
|
||||
renderer.writeName(Name("a.example.com."));
|
||||
renderer.writeName(Name("b.example.com."), false);
|
||||
renderer.writeName(Name("b.example.com."));
|
||||
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
|
||||
buffer.getLength(), &data[0], data.size());
|
||||
}
|
||||
|
||||
TEST_F(MessageRendererTest, toWirePointerChain)
|
||||
{
|
||||
UnitTestUtil::readWireData("testdata/name_toWire4", data);
|
||||
renderer.writeName(Name("a.example.com."));
|
||||
renderer.writeName(Name("b.example.com."));
|
||||
renderer.writeName(Name("b.example.com."));
|
||||
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
|
||||
buffer.getLength(), &data[0], data.size());
|
||||
}
|
||||
|
||||
TEST_F(MessageRendererTest, toWireCaseCompress)
|
||||
{
|
||||
UnitTestUtil::readWireData("testdata/name_toWire1", data);
|
||||
renderer.writeName(Name("a.example.com."));
|
||||
// this should match the first name in terms of compression:
|
||||
renderer.writeName(Name("b.exAmple.CoM."));
|
||||
renderer.writeName(Name("a.example.org."));
|
||||
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
|
||||
buffer.getLength(), &data[0], data.size());
|
||||
}
|
||||
}
|
@@ -14,421 +14,681 @@
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "name.h"
|
||||
#include "messagerenderer.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ISC::DNS;
|
||||
using isc::dns::NameComparisonResult;
|
||||
using isc::dns::MessageRenderer;
|
||||
|
||||
// quick hack exception classes: should be moved to an appropriate place soon.
|
||||
class ISCException {};
|
||||
class ISCUnexpected : public ISCException {};
|
||||
class ISCNoSpace : public ISCException {};
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
|
||||
class DNSException {};
|
||||
class DNSEmptyLabel : public DNSException {};
|
||||
class DNSLabelTooLong : public DNSException {};
|
||||
class DNSBadEscape : public DNSException {};
|
||||
class DNSBadLabelType : public DNSException {};
|
||||
namespace {
|
||||
///
|
||||
/// These are shortcut arrays for efficient character conversion.
|
||||
/// digitvalue converts a digit character to the corresponding integer.
|
||||
/// maptolower convert uppercase alphabets to their lowercase counterparts.
|
||||
/// A helper class and its only instance will initialize the arrays at startup
|
||||
/// time.
|
||||
///
|
||||
static char digitvalue[256];
|
||||
static unsigned char maptolower[256];
|
||||
|
||||
class Initializer {
|
||||
public:
|
||||
Initializer()
|
||||
{
|
||||
for (unsigned int i = 0; i < 256; i++) {
|
||||
if (i >= '0' && i<= '9') {
|
||||
digitvalue[i] = i - '0';
|
||||
} else {
|
||||
digitvalue[i] = -1;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < 256; i++) {
|
||||
if (i >= 'A' && i <= 'Z') {
|
||||
maptolower[i] = i - ('A' - 'a');
|
||||
} else {
|
||||
maptolower[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/// This object is defined only to call its constructor.
|
||||
static Initializer initialier;
|
||||
}
|
||||
|
||||
namespace {
|
||||
///
|
||||
/// Textual name parser states.
|
||||
///
|
||||
typedef enum {
|
||||
ft_init = 0,
|
||||
ft_start,
|
||||
ft_ordinary,
|
||||
ft_initialescape,
|
||||
ft_escape,
|
||||
ft_escdecimal,
|
||||
ft_at
|
||||
ft_init = 0, // begin of the name
|
||||
ft_start, // begin of a label
|
||||
ft_ordinary, // parsing an ordinary label
|
||||
ft_initialescape, // just found '\'
|
||||
ft_escape, // begin of handling a '\'-escaped sequence
|
||||
ft_escdecimal, // parsing a '\DDD' octet.
|
||||
|
||||
// Unused at this moment. We'll revisit this when we support master file
|
||||
// parser where @ is used to mean an origin name.
|
||||
ft_at
|
||||
} ft_state;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
fw_start = 0,
|
||||
fw_ordinary,
|
||||
fw_copy,
|
||||
fw_newcurrent
|
||||
} fw_state;
|
||||
|
||||
static char digitvalue[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
|
||||
};
|
||||
|
||||
static unsigned char maptolower[] = {
|
||||
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
|
||||
};
|
||||
|
||||
void
|
||||
Name::from_string(const string &namestring)
|
||||
Name::Name(const std::string &namestring, bool downcase)
|
||||
{
|
||||
char c;
|
||||
ft_state state;
|
||||
unsigned int value, count, pos, lpos;
|
||||
unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
|
||||
bool done;
|
||||
|
||||
offsets_.reserve(128);
|
||||
offsets_[0] = 0;
|
||||
|
||||
//
|
||||
// Initialize things to make the compiler happy; they're not required.
|
||||
//
|
||||
n1 = 0;
|
||||
n2 = 0;
|
||||
digits = 0;
|
||||
value = 0;
|
||||
count = 0;
|
||||
unsigned int digits = 0;
|
||||
unsigned int value = 0;
|
||||
unsigned int count = 0;
|
||||
|
||||
//
|
||||
// Set up the state machine.
|
||||
//
|
||||
pos = 0;
|
||||
tlen = namestring.length();
|
||||
tused = 0;
|
||||
nrem = 255;
|
||||
nused = 0;
|
||||
labels = 0;
|
||||
done = false;
|
||||
state = ft_init;
|
||||
std::string::const_iterator s = namestring.begin();
|
||||
std::string::const_iterator send = namestring.end();
|
||||
bool done = false;
|
||||
bool is_root = false;
|
||||
ft_state state = ft_init;
|
||||
|
||||
while (nrem > 0 && tlen > 0 && !done) {
|
||||
c = namestring[pos++];
|
||||
tlen--;
|
||||
tused++;
|
||||
std::vector<unsigned char> offsets;
|
||||
offsets.reserve(Name::MAX_LABELS);
|
||||
offsets.push_back(0);
|
||||
|
||||
std::string ndata;
|
||||
ndata.reserve(Name::MAX_WIRE);
|
||||
|
||||
// should we refactor this code using, e.g, the state pattern? Probably
|
||||
// not at this point, as this is based on proved code (derived from BIND9)
|
||||
// and it's less likely that we'll have more variations in the domain name
|
||||
// syntax. If this ever happens next time, we should consider refactor
|
||||
// the code, rather than adding more states and cases below.
|
||||
while (ndata.size() < Name::MAX_WIRE && s != send && !done) {
|
||||
unsigned char c = *s++;
|
||||
|
||||
switch (state) {
|
||||
case ft_init:
|
||||
/*
|
||||
* Is this the root name?
|
||||
*/
|
||||
//
|
||||
// Is this the root name?
|
||||
//
|
||||
if (c == '.') {
|
||||
if (tlen != 0)
|
||||
throw DNSEmptyLabel();
|
||||
labels++;
|
||||
ndata_.push_back(0);
|
||||
nrem--;
|
||||
nused++;
|
||||
if (s != send) {
|
||||
dns_throw(EmptyLabel, "non terminating empty label");
|
||||
}
|
||||
is_root = true;
|
||||
} else if (c == '@' && s == send) {
|
||||
// handle a single '@' as the root name.
|
||||
is_root = true;
|
||||
}
|
||||
|
||||
if (is_root) {
|
||||
ndata.push_back(0);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if (c == '@' && tlen == 0) {
|
||||
state = ft_at;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
// FALLTHROUGH
|
||||
case ft_start:
|
||||
ndata_.push_back(0); // dummy data
|
||||
nrem--;
|
||||
lpos = nused;
|
||||
nused++;
|
||||
ndata.push_back(0); // placeholder for the label length field
|
||||
count = 0;
|
||||
if (c == '\\') {
|
||||
state = ft_initialescape;
|
||||
break;
|
||||
}
|
||||
state = ft_ordinary;
|
||||
if (nrem == 0)
|
||||
throw ISCNoSpace();
|
||||
/* FALLTHROUGH */
|
||||
assert(ndata.size() < Name::MAX_WIRE);
|
||||
// FALLTHROUGH
|
||||
case ft_ordinary:
|
||||
if (c == '.') {
|
||||
if (count == 0)
|
||||
throw DNSEmptyLabel();
|
||||
ndata_[lpos] = count;
|
||||
labels++;
|
||||
//INSIST(labels <= 127);
|
||||
offsets_[labels] = nused;
|
||||
if (tlen == 0) {
|
||||
labels++;
|
||||
ndata_.push_back(0);
|
||||
nrem--;
|
||||
nused++;
|
||||
if (count == 0) {
|
||||
dns_throw(EmptyLabel, "duplicate period");
|
||||
}
|
||||
ndata.at(offsets.back()) = count;
|
||||
offsets.push_back(ndata.size());
|
||||
if (s == send) {
|
||||
ndata.push_back(0);
|
||||
done = true;
|
||||
}
|
||||
state = ft_start;
|
||||
} else if (c == '\\') {
|
||||
state = ft_escape;
|
||||
} else {
|
||||
if (count >= 63)
|
||||
throw DNSLabelTooLong();
|
||||
count++;
|
||||
ndata_.push_back(c);
|
||||
nrem--;
|
||||
nused++;
|
||||
if (++count > MAX_LABELLEN) {
|
||||
dns_throw(TooLongLabel, "label is too long");
|
||||
}
|
||||
ndata.push_back(downcase ? maptolower[c] : c);
|
||||
}
|
||||
break;
|
||||
case ft_initialescape:
|
||||
if (c == '[') {
|
||||
/*
|
||||
* This looks like a bitstring label, which
|
||||
* was deprecated. Intentionally drop it.
|
||||
*/
|
||||
throw DNSBadLabelType();
|
||||
// This looks like a bitstring label, which was deprecated.
|
||||
// Intentionally drop it.
|
||||
dns_throw(BadLabelType, "invalid label type");
|
||||
}
|
||||
state = ft_escape;
|
||||
/* FALLTHROUGH */
|
||||
// FALLTHROUGH
|
||||
case ft_escape:
|
||||
if (!isdigit(c & 0xff)) {
|
||||
if (count >= 63)
|
||||
throw DNSLabelTooLong();
|
||||
count++;
|
||||
ndata_.push_back(c);
|
||||
nrem--;
|
||||
nused++;
|
||||
if (++count > MAX_LABELLEN) {
|
||||
dns_throw(TooLongLabel, "label is too long");
|
||||
}
|
||||
ndata.push_back(downcase ? maptolower[c] : c);
|
||||
state = ft_ordinary;
|
||||
break;
|
||||
}
|
||||
digits = 0;
|
||||
value = 0;
|
||||
state = ft_escdecimal;
|
||||
/* FALLTHROUGH */
|
||||
// FALLTHROUGH
|
||||
case ft_escdecimal:
|
||||
if (!isdigit(c & 0xff))
|
||||
throw DNSBadEscape();
|
||||
if (!isdigit(c & 0xff)) {
|
||||
dns_throw(BadEscape, "mixture of escaped digit and non-digit");
|
||||
}
|
||||
value *= 10;
|
||||
value += digitvalue[(int)c];
|
||||
value += digitvalue[c];
|
||||
digits++;
|
||||
if (digits == 3) {
|
||||
if (value > 255)
|
||||
throw DNSBadEscape();
|
||||
if (count >= 63)
|
||||
throw DNSLabelTooLong();
|
||||
count++;
|
||||
ndata_.push_back(value);
|
||||
nrem--;
|
||||
nused++;
|
||||
if (value > 255) {
|
||||
dns_throw(BadEscape, "escaped decimal is too large");
|
||||
}
|
||||
if (++count > MAX_LABELLEN) {
|
||||
dns_throw(TooLongLabel, "label is too long");
|
||||
}
|
||||
ndata.push_back(downcase ? maptolower[value] : value);
|
||||
state = ft_ordinary;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("Unexpected state " + state);
|
||||
// impossible case
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) { // no trailing '.' was found.
|
||||
if (ndata.size() == Name::MAX_WIRE) {
|
||||
dns_throw(TooLongName, "name is too long for termination");
|
||||
}
|
||||
assert(s == send);
|
||||
if (state != ft_ordinary && state != ft_at) {
|
||||
dns_throw(IncompleteName, "incomplete textual name");
|
||||
}
|
||||
if (state == ft_ordinary) {
|
||||
assert(count != 0);
|
||||
ndata.at(offsets.back()) = count;
|
||||
|
||||
offsets.push_back(ndata.size());
|
||||
// add a trailing \0
|
||||
ndata.push_back('\0');
|
||||
}
|
||||
}
|
||||
|
||||
labelcount_ = offsets.size();
|
||||
assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
|
||||
ndata_.assign(ndata.data(), ndata.size());
|
||||
length_ = ndata_.size();
|
||||
offsets_.assign(offsets.begin(), offsets.end());
|
||||
}
|
||||
|
||||
namespace {
|
||||
///
|
||||
/// Wire-format name parser states.
|
||||
///
|
||||
typedef enum {
|
||||
fw_start = 0, // beginning of a label
|
||||
fw_ordinary, // inside an ordinary (non compressed) label
|
||||
fw_newcurrent // beginning of a compression pointer
|
||||
} fw_state;
|
||||
}
|
||||
|
||||
Name::Name(InputBuffer& buffer, bool downcase)
|
||||
{
|
||||
std::vector<unsigned char> offsets;
|
||||
offsets.reserve(Name::MAX_LABELS);
|
||||
|
||||
/*
|
||||
* Initialize things to make the compiler happy; they're not required.
|
||||
*/
|
||||
unsigned int n = 0;
|
||||
|
||||
//
|
||||
// Set up.
|
||||
//
|
||||
bool done = false;
|
||||
unsigned int nused = 0;
|
||||
bool seen_pointer = false;
|
||||
fw_state state = fw_start;
|
||||
|
||||
unsigned int cused = 0; // Bytes of compressed name data used
|
||||
unsigned int current = buffer.getPosition();
|
||||
unsigned int pos_begin = current;
|
||||
unsigned int biggest_pointer = current;
|
||||
|
||||
// Make the compiler happy; this is not required.
|
||||
// XXX: bad style in that we initialize it with a dummy value and define
|
||||
// it far from where it's used. But alternatives seemed even worse.
|
||||
unsigned int new_current = 0;
|
||||
|
||||
//
|
||||
// Note: The following code is not optimized for speed, but
|
||||
// rather for correctness. Speed will be addressed in the future.
|
||||
//
|
||||
while (current < buffer.getLength() && !done) {
|
||||
unsigned int c = buffer.readUint8();
|
||||
current++;
|
||||
if (!seen_pointer) {
|
||||
cused++;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case fw_start:
|
||||
if (c <= MAX_LABELLEN) {
|
||||
offsets.push_back(nused);
|
||||
if (nused + c + 1 > Name::MAX_WIRE) {
|
||||
dns_throw(TooLongName, "wire name is too long");
|
||||
}
|
||||
nused += c + 1;
|
||||
ndata_.push_back(c);
|
||||
if (c == 0) {
|
||||
done = true;
|
||||
}
|
||||
n = c;
|
||||
state = fw_ordinary;
|
||||
} else if ((c & COMPRESS_POINTER_MARK8) == COMPRESS_POINTER_MARK8) {
|
||||
//
|
||||
// Ordinary 14-bit pointer.
|
||||
//
|
||||
new_current = c & ~COMPRESS_POINTER_MARK8;
|
||||
n = 1;
|
||||
state = fw_newcurrent;
|
||||
} else {
|
||||
// this case includes local compression pointer, which hasn't
|
||||
// been standardized.
|
||||
dns_throw(BadLabelType, "unknown label character");
|
||||
}
|
||||
break;
|
||||
case fw_ordinary:
|
||||
if (downcase) {
|
||||
c = maptolower[c];
|
||||
}
|
||||
ndata_.push_back(c);
|
||||
if (--n == 0) {
|
||||
state = fw_start;
|
||||
}
|
||||
break;
|
||||
case fw_newcurrent:
|
||||
new_current *= 256;
|
||||
new_current += c;
|
||||
if (--n != 0) {
|
||||
break;
|
||||
}
|
||||
if (new_current >= biggest_pointer) {
|
||||
dns_throw(BadPointer, "bad compression pointer: out of range");
|
||||
}
|
||||
biggest_pointer = new_current;
|
||||
current = new_current;
|
||||
buffer.setPosition(current);
|
||||
seen_pointer = true;
|
||||
state = fw_start;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
if (nrem == 0)
|
||||
throw ISCNoSpace();
|
||||
//INSIST(tlen == 0);
|
||||
if (state != ft_ordinary && state != ft_at)
|
||||
throw runtime_error("Unexpected state " + state);
|
||||
if (state == ft_ordinary) {
|
||||
//INSIST(count != 0);
|
||||
ndata_[lpos] = count;
|
||||
labels++;
|
||||
//INSIST(labels <= 127);
|
||||
offsets_[labels] = nused;
|
||||
|
||||
// added a trailing \0
|
||||
ndata_.push_back('\0');
|
||||
++labels;
|
||||
++nused;
|
||||
offsets_[labels] = nused;
|
||||
}
|
||||
dns_throw(IncompleteName, "incomplete wire-format name");
|
||||
}
|
||||
|
||||
labels_ = labels;
|
||||
labelcount_ = offsets.size();
|
||||
length_ = nused;
|
||||
offsets_.assign(offsets.begin(), offsets.end());
|
||||
buffer.setPosition(pos_begin + cused);
|
||||
}
|
||||
|
||||
string
|
||||
Name::to_text(bool omit_final_dot) const
|
||||
void
|
||||
Name::toWire(OutputBuffer& buffer) const
|
||||
{
|
||||
string tdata;
|
||||
unsigned int nlen;
|
||||
unsigned char c;
|
||||
unsigned int count;
|
||||
unsigned int labels;
|
||||
bool saw_root = false;
|
||||
string::const_iterator iter_ndata;
|
||||
buffer.writeData(ndata_.data(), ndata_.size());
|
||||
}
|
||||
|
||||
/*
|
||||
* This function assumes the name is in proper uncompressed
|
||||
* wire format.
|
||||
*/
|
||||
iter_ndata = ndata_.begin();
|
||||
nlen = length_;
|
||||
labels = labels_;
|
||||
void
|
||||
Name::toWire(MessageRenderer& renderer) const
|
||||
{
|
||||
renderer.writeName(*this);
|
||||
}
|
||||
|
||||
if (labels == 0 && nlen == 0) {
|
||||
/*
|
||||
* Special handling for an empty name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The names of these booleans are misleading in this case.
|
||||
* This empty name is not necessarily from the root node of
|
||||
* the DNS root zone, nor is a final dot going to be included.
|
||||
* They need to be set this way, though, to keep the "@"
|
||||
* from being trounced.
|
||||
*/
|
||||
saw_root = true;
|
||||
omit_final_dot = false;
|
||||
tdata.push_back('@');
|
||||
|
||||
/*
|
||||
* Skip the while() loop.
|
||||
*/
|
||||
nlen = 0;
|
||||
} else if (nlen == 1 && labels == 1 && *iter_ndata == '\0') {
|
||||
/*
|
||||
* Special handling for the root label.
|
||||
*/
|
||||
saw_root = true;
|
||||
omit_final_dot = false;
|
||||
tdata.push_back('.');
|
||||
|
||||
/*
|
||||
* Skip the while() loop.
|
||||
*/
|
||||
nlen = 0;
|
||||
std::string
|
||||
Name::toText(bool omit_final_dot) const
|
||||
{
|
||||
if (length_ == 1) {
|
||||
//
|
||||
// Special handling for the root label. We ignore omit_final_dot.
|
||||
//
|
||||
assert(labelcount_ == 1 && ndata_[0] == '\0');
|
||||
return (".");
|
||||
}
|
||||
|
||||
while (labels > 0 && nlen > 0) {
|
||||
std::string::const_iterator np = ndata_.begin();
|
||||
std::string::const_iterator np_end = ndata_.end();
|
||||
unsigned int labels = labelcount_; // use for integrity check
|
||||
// init with an impossible value to catch error cases in the end:
|
||||
unsigned int count = MAX_LABELLEN + 1;
|
||||
|
||||
// result string: it will roughly have the same length as the wire format
|
||||
// name data. reserve that length to minimize reallocation.
|
||||
std::string result;
|
||||
result.reserve(length_);
|
||||
|
||||
while (np != np_end) {
|
||||
labels--;
|
||||
count = *iter_ndata++;
|
||||
nlen--;
|
||||
count = *np++;
|
||||
|
||||
if (count == 0) {
|
||||
saw_root = true;
|
||||
if (!omit_final_dot) {
|
||||
result.push_back('.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (count < 64) {
|
||||
//INSIST(nlen >= count);
|
||||
while (count > 0) {
|
||||
c = *iter_ndata;
|
||||
|
||||
if (count <= MAX_LABELLEN) {
|
||||
assert(np_end - np >= count);
|
||||
|
||||
if (!result.empty()) {
|
||||
// just after a non-empty label. add a separating dot.
|
||||
result.push_back('.');
|
||||
}
|
||||
|
||||
while (count-- > 0) {
|
||||
unsigned char c = *np++;
|
||||
switch (c) {
|
||||
case 0x22: /* '"' */
|
||||
case 0x28: /* '(' */
|
||||
case 0x29: /* ')' */
|
||||
case 0x2E: /* '.' */
|
||||
case 0x3B: /* ';' */
|
||||
case 0x5C: /* '\\' */
|
||||
/* Special modifiers in zone files. */
|
||||
case 0x40: /* '@' */
|
||||
case 0x24: /* '$' */
|
||||
tdata.push_back('\\');
|
||||
tdata.push_back(c);
|
||||
iter_ndata++;
|
||||
nlen--;
|
||||
case 0x22: // '"'
|
||||
case 0x28: // '('
|
||||
case 0x29: // ')'
|
||||
case 0x2E: // '.'
|
||||
case 0x3B: // ';'
|
||||
case 0x5C: // '\\'
|
||||
// Special modifiers in zone files.
|
||||
case 0x40: // '@'
|
||||
case 0x24: // '$'
|
||||
result.push_back('\\');
|
||||
result.push_back(c);
|
||||
break;
|
||||
default:
|
||||
if (c > 0x20 && c < 0x7f) {
|
||||
tdata.push_back(c);
|
||||
iter_ndata++;
|
||||
nlen--;
|
||||
// append printable characters intact
|
||||
result.push_back(c);
|
||||
} else {
|
||||
tdata.push_back(0x5c);
|
||||
tdata.push_back(0x30 + ((c / 100) % 10));
|
||||
tdata.push_back(0x30 + ((c / 10) % 10));
|
||||
tdata.push_back(0x30 + (c % 10));
|
||||
iter_ndata++;
|
||||
nlen--;
|
||||
// encode non-printable characters in the form of \DDD
|
||||
result.push_back(0x5c);
|
||||
result.push_back(0x30 + ((c / 100) % 10));
|
||||
result.push_back(0x30 + ((c / 10) % 10));
|
||||
result.push_back(0x30 + (c % 10));
|
||||
}
|
||||
}
|
||||
count--;
|
||||
}
|
||||
} else
|
||||
throw runtime_error("Unexpected label type " + count);
|
||||
// The following assumes names are absolute. If not, we
|
||||
// fix things up later. Note that this means that in some
|
||||
// cases one more byte of text buffer is required than is
|
||||
// needed in the final output.
|
||||
tdata.push_back('.');
|
||||
} else {
|
||||
dns_throw(BadLabelType, "unknown label type in name data");
|
||||
}
|
||||
}
|
||||
|
||||
if (nlen != 0)
|
||||
throw ISCNoSpace();
|
||||
assert(labels == 0);
|
||||
assert(count == 0); // a valid name must end with a 'dot'.
|
||||
|
||||
if (!saw_root || omit_final_dot)
|
||||
tdata.erase(tdata.end() - 1);
|
||||
|
||||
return (tdata);
|
||||
return (result);
|
||||
}
|
||||
|
||||
// Are 'this' name and 'other' equal?
|
||||
bool
|
||||
Name::operator==(const Name& other) const
|
||||
NameComparisonResult
|
||||
Name::compare(const Name& other) const
|
||||
{
|
||||
unsigned int l;
|
||||
unsigned char c, count;
|
||||
string::const_iterator label1, label2;
|
||||
// Determine the relative ordering under the DNSSEC order relation of
|
||||
// 'this' and 'other', and also determine the hierarchical relationship
|
||||
// of the names.
|
||||
|
||||
if (length_ != other.length_)
|
||||
return (false);
|
||||
unsigned int nlabels = 0;
|
||||
unsigned int l1 = labelcount_;
|
||||
unsigned int l2 = other.labelcount_;
|
||||
int ldiff = (int)l1 - (int)l2;
|
||||
unsigned int l = (ldiff < 0) ? l1 : l2;
|
||||
|
||||
l = labels_;
|
||||
|
||||
if (l != other.labels_)
|
||||
return (false);
|
||||
|
||||
label1 = ndata_.begin();
|
||||
label2 = other.ndata_.begin();
|
||||
while (l > 0) {
|
||||
l--;
|
||||
count = *label1++;
|
||||
if (count != *label2++)
|
||||
return (false);
|
||||
--l;
|
||||
--l1;
|
||||
--l2;
|
||||
size_t pos1 = offsets_[l1];
|
||||
size_t pos2 = other.offsets_[l2];
|
||||
unsigned int count1 = ndata_[pos1++];
|
||||
unsigned int count2 = other.ndata_[pos2++];
|
||||
|
||||
// We don't support any extended label types including now-obsolete
|
||||
// bitstring labels.
|
||||
assert(count1 <= MAX_LABELLEN && count2 <= MAX_LABELLEN);
|
||||
|
||||
int cdiff = (int)count1 - (int)count2;
|
||||
unsigned int count = (cdiff < 0) ? count1 : count2;
|
||||
|
||||
while (count > 0) {
|
||||
count--;
|
||||
c = maptolower[(unsigned char)*label1++]; // XXX should avoid cast
|
||||
if (c != maptolower[(unsigned char)*label2++])
|
||||
unsigned char label1 = ndata_[pos1];
|
||||
unsigned char label2 = other.ndata_[pos2];
|
||||
|
||||
int chdiff = (int)maptolower[label1] - (int)maptolower[label2];
|
||||
if (chdiff != 0) {
|
||||
return (NameComparisonResult(chdiff, nlabels,
|
||||
NameComparisonResult::COMMONANCESTOR));
|
||||
}
|
||||
--count;
|
||||
++pos1;
|
||||
++pos2;
|
||||
}
|
||||
if (cdiff != 0) {
|
||||
return (NameComparisonResult(cdiff, nlabels,
|
||||
NameComparisonResult::COMMONANCESTOR));
|
||||
}
|
||||
++nlabels;
|
||||
}
|
||||
|
||||
if (ldiff < 0) {
|
||||
return (NameComparisonResult(ldiff, nlabels,
|
||||
NameComparisonResult::SUPERDOMAIN));
|
||||
} else if (ldiff > 0) {
|
||||
return (NameComparisonResult(ldiff, nlabels,
|
||||
NameComparisonResult::SUBDOMAIN));
|
||||
}
|
||||
|
||||
return (NameComparisonResult(ldiff, nlabels, NameComparisonResult::EQUAL));
|
||||
}
|
||||
|
||||
bool
|
||||
Name::equals(const Name& other) const
|
||||
{
|
||||
if (length_ != other.length_ || labelcount_ != other.labelcount_) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
for (unsigned int l = labelcount_, pos = 0; l > 0; --l) {
|
||||
unsigned char count = ndata_[pos];
|
||||
if (count != other.ndata_[pos]) {
|
||||
return (false);
|
||||
}
|
||||
++pos;
|
||||
|
||||
while (count-- > 0) {
|
||||
unsigned char label1 = ndata_[pos];
|
||||
unsigned char label2 = other.ndata_[pos];
|
||||
|
||||
if (maptolower[label1] != maptolower[label2]) {
|
||||
return (false);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<<(ostream& os, const Name& name)
|
||||
bool
|
||||
Name::leq(const Name& other) const
|
||||
{
|
||||
os << name.to_text();
|
||||
return (compare(other).getOrder() <= 0);
|
||||
}
|
||||
|
||||
bool
|
||||
Name::geq(const Name& other) const
|
||||
{
|
||||
return (compare(other).getOrder() >= 0);
|
||||
}
|
||||
|
||||
bool
|
||||
Name::lthan(const Name& other) const
|
||||
{
|
||||
return (compare(other).getOrder() < 0);
|
||||
}
|
||||
|
||||
bool
|
||||
Name::gthan(const Name& other) const
|
||||
{
|
||||
return (compare(other).getOrder() > 0);
|
||||
}
|
||||
|
||||
bool
|
||||
Name::isWildcard() const
|
||||
{
|
||||
return (length_ >= 2 && ndata_[0] == 1 && ndata_[1] == '*');
|
||||
}
|
||||
|
||||
namespace { // hide the local class
|
||||
///
|
||||
/// A helper functor class to add an additional offset to an offset vector.
|
||||
///
|
||||
struct OffsetAdjuster : public std::binary_function<unsigned char,
|
||||
int, unsigned char> {
|
||||
unsigned char operator()(unsigned char ch, int offset) const
|
||||
{
|
||||
return (ch + offset);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Name
|
||||
Name::concatenate(const Name& suffix) const
|
||||
{
|
||||
assert(this->length_ > 0 && suffix.length_ > 0);
|
||||
assert(this->labelcount_ > 0 && suffix.labelcount_ > 0);
|
||||
|
||||
unsigned int length = this->length_ + suffix.length_ - 1;
|
||||
if (length > Name::MAX_WIRE) {
|
||||
dns_throw(TooLongName, "names are too long to concatenate");
|
||||
}
|
||||
|
||||
Name retname;
|
||||
retname.ndata_.reserve(length);
|
||||
retname.ndata_.assign(this->ndata_, 0, this->length_ - 1);
|
||||
retname.ndata_.insert(retname.ndata_.end(),
|
||||
suffix.ndata_.begin(), suffix.ndata_.end());
|
||||
assert(retname.ndata_.size() == length);
|
||||
retname.length_ = length;
|
||||
|
||||
//
|
||||
// Setup the offsets vector. Copy the offsets of this (prefix) name,
|
||||
// excluding that for the trailing dot, and append the offsets of the
|
||||
// suffix name with the additional offset of the length of the prefix.
|
||||
//
|
||||
unsigned int labels = this->labelcount_ + suffix.labelcount_ - 1;
|
||||
assert(labels <= Name::MAX_LABELS);
|
||||
retname.offsets_.reserve(labels);
|
||||
retname.offsets_.assign(&this->offsets_[0],
|
||||
&this->offsets_[0] + this->labelcount_ - 1);
|
||||
transform(suffix.offsets_.begin(), suffix.offsets_.end(),
|
||||
back_inserter(retname.offsets_),
|
||||
bind2nd(OffsetAdjuster(), this->length_ - 1));
|
||||
assert(retname.offsets_.size() == labels);
|
||||
retname.labelcount_ = labels;
|
||||
|
||||
return (retname);
|
||||
}
|
||||
|
||||
Name
|
||||
Name::split(unsigned int first, unsigned int n) const
|
||||
{
|
||||
if (n == 0 || first + n > labelcount_) {
|
||||
dns_throw(OutOfRange, "Name::split: invalid split range");
|
||||
}
|
||||
|
||||
Name retname;
|
||||
// If the specified range doesn't include the trailing dot, we need one
|
||||
// more label for that.
|
||||
unsigned int newlabels = (first + n == labelcount_) ? n : n + 1;
|
||||
|
||||
//
|
||||
// Set up offsets: copy the corresponding range of the original offsets
|
||||
// with subtracting an offset of the prefix length.
|
||||
//
|
||||
retname.offsets_.reserve(newlabels);
|
||||
transform(offsets_.begin() + first, offsets_.begin() + first + newlabels,
|
||||
back_inserter(retname.offsets_),
|
||||
bind2nd(OffsetAdjuster(), -offsets_[first]));
|
||||
|
||||
//
|
||||
// Set up the new name. At this point the tail of the new offsets specifies
|
||||
// the position of the trailing dot, which should be equal to the length of
|
||||
// the extracted portion excluding the dot. First copy that part from the
|
||||
// original name, and append the trailing dot explicitly.
|
||||
//
|
||||
retname.ndata_.reserve(retname.offsets_.back() + 1);
|
||||
retname.ndata_.assign(ndata_, offsets_[first], retname.offsets_.back());
|
||||
retname.ndata_.push_back(0);
|
||||
|
||||
retname.length_ = retname.ndata_.size();
|
||||
retname.labelcount_ = retname.offsets_.size();
|
||||
assert(retname.labelcount_ == newlabels);
|
||||
|
||||
return (retname);
|
||||
}
|
||||
|
||||
Name&
|
||||
Name::downcase()
|
||||
{
|
||||
unsigned int nlen = length_;
|
||||
unsigned int labels = labelcount_;
|
||||
unsigned int pos = 0;
|
||||
|
||||
while (labels > 0 && nlen > 0) {
|
||||
--labels;
|
||||
--nlen;
|
||||
|
||||
// we assume a valid name, and do abort() if the assumption fails
|
||||
// rather than throwing an exception.
|
||||
unsigned int count = ndata_.at(pos++);
|
||||
assert(count <= MAX_LABELLEN);
|
||||
assert(nlen >= count);
|
||||
|
||||
while (count > 0) {
|
||||
ndata_.at(pos) =
|
||||
maptolower[static_cast<unsigned char>(ndata_.at(pos))];
|
||||
++pos;
|
||||
--nlen;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Name& name)
|
||||
{
|
||||
os << name.toText();
|
||||
return (os);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,81 +17,561 @@
|
||||
#ifndef __NAME_H
|
||||
#define __NAME_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ISC {
|
||||
namespace DNS {
|
||||
class Buffer;
|
||||
class NameCompressor;
|
||||
class NameDecompressor;
|
||||
#include "exceptions.h"
|
||||
|
||||
namespace isc {
|
||||
namespace dns {
|
||||
class InputBuffer;
|
||||
class OutputBuffer;
|
||||
class MessageRenderer;
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the name parser
|
||||
/// encounters an empty label in the middle of a name.
|
||||
///
|
||||
class EmptyLabel : public Exception {
|
||||
public:
|
||||
EmptyLabel(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the name parser
|
||||
/// encounters too long a name.
|
||||
///
|
||||
class TooLongName : public Exception {
|
||||
public:
|
||||
TooLongName(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the name parser
|
||||
/// encounters too long a label.
|
||||
///
|
||||
class TooLongLabel : public Exception {
|
||||
public:
|
||||
TooLongLabel(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the name parser
|
||||
/// encounters an obsolete or incomplete label type. In effect "obsolete" only
|
||||
/// applies to bitstring labels, which would begin with "\[". Incomplete cases
|
||||
/// include an incomplete escaped sequence such as "\12".
|
||||
///
|
||||
class BadLabelType : public Exception {
|
||||
public:
|
||||
BadLabelType(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the name parser
|
||||
/// fails to decode a "\"-escaped sequence.
|
||||
///
|
||||
class BadEscape : public Exception {
|
||||
public:
|
||||
BadEscape(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the wire-format
|
||||
/// name contains an invalid compression pointer.
|
||||
///
|
||||
class BadPointer : public Exception {
|
||||
public:
|
||||
BadPointer(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A standard DNS module exception that is thrown if the name parser
|
||||
/// finds the input (string or wire-format data) is incomplete.
|
||||
///
|
||||
/// An attempt of constructing a name from an empty string will trigger this
|
||||
/// exception.
|
||||
///
|
||||
class IncompleteName : public Exception {
|
||||
public:
|
||||
IncompleteName(const char* file, size_t line, const char* what) :
|
||||
isc::dns::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
///
|
||||
/// This is a supplemental class used only as a return value of Name::compare().
|
||||
/// It encapsulate a tuple of the comparison: ordering, number of common labels,
|
||||
/// and relationship as follows:
|
||||
/// - ordering: relative ordering under the DNSSEC order relation
|
||||
/// - labels: the number of common significant labels of the two names being
|
||||
/// compared
|
||||
/// - relationship: see NameComparisonResult::NameRelation
|
||||
///
|
||||
class NameComparisonResult {
|
||||
public:
|
||||
/// The relation of two names under comparison.
|
||||
/// Its semantics for the case of
|
||||
/// <code>name1->compare(name2)</code> (where name1 and name2 are instances
|
||||
/// of the Name class) is as follows:
|
||||
/// - SUPERDOMAIN: name1 properly contains name2; name2 is a proper
|
||||
/// subdomain of name1
|
||||
/// - SUBDOMAIN: name1 is a proper subdomain of name2
|
||||
/// - EQUAL: name1 and name2 are equal
|
||||
/// - COMMONANCESTOR: name1 and name2 share a common ancestor
|
||||
///
|
||||
/// Note that in our implementation there's always a hierarchical
|
||||
/// relationship between any two names since all names are absolute and
|
||||
/// they at least share the trailing empty label.
|
||||
/// So, for example, the relationship between "com." and "net." is
|
||||
/// "commonancestor". This may be counter intuitive and inconvenient, but
|
||||
/// we'll keep this design at the moment until we decide whether and how to
|
||||
/// handle "non absolute" names (see the description of the \c Name class).
|
||||
/// If we want to (re)introduce the notion of non absolute names, we'll
|
||||
/// want to distinguish "com" and "com.", and the current definition would
|
||||
/// be more compatible for that purpose.
|
||||
/// If, on the other hand, we finally decide we really don't need that
|
||||
/// notion, we'll probably reconsider the design here, too.
|
||||
enum NameRelation {
|
||||
none = 0,
|
||||
contains = 1,
|
||||
subdomain = 2,
|
||||
equal = 3,
|
||||
commonancestor = 4
|
||||
SUPERDOMAIN = 0,
|
||||
SUBDOMAIN = 1,
|
||||
EQUAL = 2,
|
||||
COMMONANCESTOR = 3
|
||||
};
|
||||
|
||||
explicit NameComparisonResult(int order, int nlabels,
|
||||
///
|
||||
/// \name Constructors and Destructor
|
||||
///
|
||||
//@{
|
||||
/// \brief Constructor from a comparison tuple
|
||||
///
|
||||
/// This constructor simply initializes the object in the straightforward
|
||||
/// way.
|
||||
explicit NameComparisonResult(int order, unsigned int nlabels,
|
||||
NameRelation relation) :
|
||||
order_(order), nlabels_(nlabels), relation_(relation) {}
|
||||
int get_order() const { return (order_); }
|
||||
int get_common_labels() const { return (nlabels_); }
|
||||
NameRelation get_relation() const { return (relation_); }
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Getter Methods
|
||||
///
|
||||
//@{
|
||||
/// Returns the ordering of the comparison result
|
||||
int getOrder() const { return (order_); }
|
||||
/// Returns the number of common labels of the comparison result
|
||||
unsigned int getCommonLabels() const { return (nlabels_); }
|
||||
/// Returns the NameRelation of the comparison result
|
||||
NameRelation getRelation() const { return (relation_); }
|
||||
//@}
|
||||
private:
|
||||
int order_;
|
||||
int nlabels_;
|
||||
unsigned int nlabels_;
|
||||
NameRelation relation_;
|
||||
};
|
||||
|
||||
///
|
||||
/// The \c Name class encapsulates DNS names.
|
||||
///
|
||||
/// It provides interfaces to construct a name from string or wire-format data,
|
||||
/// transform a name into a string or wire-format data, compare two names, get
|
||||
/// access to various properties of a name, etc.
|
||||
///
|
||||
/// Notes to developers: Internally, a name object maintains the name data
|
||||
/// in wire format as an instance of \c std::string. Since many string
|
||||
/// implementations adopt copy-on-write data sharing, we expect this approach
|
||||
/// will make copying a name less expensive in typical cases. If this is
|
||||
/// found to be a significant performance bottleneck later, we may reconsider
|
||||
/// the internal representation or perhaps the API.
|
||||
///
|
||||
/// A name object also maintains a vector of offsets (\c offsets_ member),
|
||||
/// each of which is the offset to a label of the name: The n-th element of
|
||||
/// the vector specifies the offset to the n-th label. For example, if the
|
||||
/// object represents "www.example.com", the elements of the offsets vector
|
||||
/// are 0, 4, 12, and 16. Note that the offset to the trailing dot (16) is
|
||||
/// included. In the BIND9 DNS library from which this implementation is
|
||||
/// derived, the offsets are optional, probably due to performance
|
||||
/// considerations (in fact, offsets can always be calculated from the name
|
||||
/// data, and in that sense are redundant). In our implementation, however,
|
||||
/// we always build and maintain the offsets. We believe we need more low
|
||||
/// level, specialized data structure and interface where we really need to
|
||||
/// pursue performance, and would rather keep this generic API and
|
||||
/// implementation simpler.
|
||||
///
|
||||
/// While many other DNS APIs introduce an "absolute or relative"
|
||||
/// attribute of names as defined in RFC1035, names are always "absolute" in
|
||||
/// the initial design of this API.
|
||||
/// In fact, separating absolute and relative would confuse API users
|
||||
/// unnecessarily. For example, it's not so intuitive to consider the
|
||||
/// comparison result of an absolute name with a relative name.
|
||||
/// We've looked into how the concept of absolute names is used in BIND9,
|
||||
/// and found that in many cases names are generally absolute.
|
||||
/// The only reasonable case of separating absolute and relative is in a master
|
||||
/// file parser, where a relative name must be a complete name with an "origin"
|
||||
/// name, which must be absolute. So, in this initial design, we chose a
|
||||
/// simpler approach: the API generally handles names as absolute; when we
|
||||
/// introduce a parser of master files, we'll introduce the notion of relative
|
||||
/// names as a special case.
|
||||
///
|
||||
class Name {
|
||||
///
|
||||
/// \name Constructors and Destructor
|
||||
///
|
||||
//@{
|
||||
private:
|
||||
/// The default constructor
|
||||
///
|
||||
/// This is used internally in the class implementation, but at least at
|
||||
/// the moment defined as private because it will construct an incomplete
|
||||
/// object in that it doesn't have any labels. We may reconsider this
|
||||
/// design choice as we see more applications of the class.
|
||||
Name() : length_(0), labelcount_(0) {}
|
||||
public:
|
||||
Name() : length_(0), labels_(0) {}
|
||||
explicit Name(const std::string& namestr) : length_(0), labels_(0)
|
||||
{ from_string(namestr); }
|
||||
explicit Name(NameDecompressor& decompressor, Buffer& buffer);
|
||||
// copy constructor (default cp-ctor should work fine)
|
||||
//Name(const Name& orig);
|
||||
// destructor (default dtor should work fine)
|
||||
//~Name();
|
||||
/// Constructor from a string
|
||||
///
|
||||
/// If the given string does not represent a valid DNS name, an exception
|
||||
/// of class \c EmptyLabel, \c TooLongLabel, \c BadLabelType, \c BadEscape,
|
||||
/// \c TooLongName, or \c IncompleteName will be thrown.
|
||||
/// In addition, if resource allocation for the new name fails, a
|
||||
/// corresponding standard exception will be thrown.
|
||||
///
|
||||
/// \param namestr A string representation of the name to be constructed.
|
||||
/// \param downcase Whether to convert upper case alphabets to lower case.
|
||||
explicit Name(const std::string& namestr, bool downcase = false);
|
||||
/// Constructor from wire-format data.
|
||||
///
|
||||
/// The \c buffer parameter normally stores a complete DNS message
|
||||
/// containing the name to be constructed. The current read position of
|
||||
/// the buffer points to the head of the name.
|
||||
///
|
||||
/// The input data may or may not be compressed; if it's compressed, this
|
||||
/// method will automatically decompress it.
|
||||
///
|
||||
/// If the given data does not represent a valid DNS name, an exception
|
||||
/// of class \c TooLongName, \c BadLabelType, \c BadPointer, or
|
||||
/// \c IncompleteName will be thrown.
|
||||
/// In addition, if resource allocation for the new name fails, a
|
||||
/// corresponding standard exception will be thrown.
|
||||
///
|
||||
/// \param buffer A buffer storing the wire format data.
|
||||
/// \param downcase Whether to convert upper case alphabets to lower case.
|
||||
explicit Name(InputBuffer& buffer, bool downcase = false);
|
||||
//@}
|
||||
|
||||
std::string to_text(bool omit_final_dot = false) const;
|
||||
void to_wire(Buffer& buffer, NameCompressor& compressor) const;
|
||||
size_t get_length() const { return (length_); }
|
||||
unsigned int get_labels() const { return (labels_); }
|
||||
///
|
||||
/// \name Getter Methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Gets the length of the <code>Name</code> in its wire format.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \return the length (the number of octets in wire format) of the
|
||||
/// <code>Name</code>
|
||||
size_t getLength() const { return (length_); }
|
||||
|
||||
/// \brief Returns the number of labels contained in the <code>Name</code>.
|
||||
///
|
||||
/// Note that an empty label (corresponding to a trailing '.') is counted
|
||||
/// as a single label, so the return value of this method must be >0.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \return the number of labels
|
||||
unsigned int getLabelCount() const { return (labelcount_); }
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Converter methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Convert the Name to a string.
|
||||
///
|
||||
/// This method returns a <code>std::string</code> object representing the
|
||||
/// Name as a string. Unless <code>omit_final_dot</code> is
|
||||
/// <code>true</code>, the returned string ends with a dot '.'; the default
|
||||
/// is <code>false</code>. The default value of this parameter is
|
||||
/// <code>true</code>; converted names will have a trailing dot by default.
|
||||
///
|
||||
/// This function assumes the name is in proper uncompressed wire format.
|
||||
/// If it finds an unexpected label character including compression pointer,
|
||||
/// an exception of class \c BadLabelType will be thrown.
|
||||
/// In addition, if resource allocation for the result string fails, a
|
||||
/// corresponding standard exception will be thrown.
|
||||
//
|
||||
/// \param omit_final_dot whether to omit the trailing dot in the output.
|
||||
/// \return a string representation of the <code>Name</code>.
|
||||
std::string toText(bool omit_final_dot = false) const;
|
||||
|
||||
/// \brief Render the <code>Name</code> in the wire format with compression.
|
||||
///
|
||||
/// This method dumps the Name in wire format with help of \c renderer,
|
||||
/// which encapsulates output buffer and name compression algorithm to
|
||||
/// render the name.
|
||||
///
|
||||
/// If resource allocation in rendering process fails, a corresponding
|
||||
/// standard exception will be thrown.
|
||||
///
|
||||
/// \param renderer DNS message rendering context that encapsulates the
|
||||
/// output buffer and name compression information.
|
||||
void toWire(MessageRenderer& renderer) const;
|
||||
|
||||
/// \brief Render the <code>Name</code> in the wire format without
|
||||
/// compression.
|
||||
///
|
||||
/// If resource allocation in rendering process fails, a corresponding
|
||||
/// standard exception will be thrown. This can be avoided by preallocating
|
||||
/// a sufficient size of \c buffer. Specifically, if
|
||||
/// <code>buffer.getCapacity() - buffer.getLength() >= Name::MAX_WIRE</code>
|
||||
/// then this method should not throw an exception.
|
||||
///
|
||||
void toWire(OutputBuffer& buffer) const;
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Comparison methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Compare two <code>Name</code>s.
|
||||
///
|
||||
/// This method compares the <code>Name</code> and <code>other</code> and
|
||||
/// returns the result in the form of a <code>NameComparisonResult</code>
|
||||
/// object.
|
||||
///
|
||||
/// Note that this is case-insensitive comparison.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \param other the right-hand operand to compare against.
|
||||
/// \return a <code>NameComparisonResult</code> object representing the
|
||||
/// comparison result.
|
||||
NameComparisonResult compare(const Name& other) const;
|
||||
|
||||
/// \brief Return true iff two names are equal.
|
||||
///
|
||||
/// Semantically this could be implemented based on the result of the
|
||||
/// \c compare() method, but the actual implementation uses different code
|
||||
/// that simply performs character-by-character comparison (case
|
||||
/// insensitive for the name label parts) on the two names. This is because
|
||||
/// it would be much faster and the simple equality check would be pretty
|
||||
/// common.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \param other the <code>Name</code> object to compare against.
|
||||
/// \return true if the two names are equal; otherwise false.
|
||||
bool equals(const Name& other) const;
|
||||
|
||||
/// Same as equals()
|
||||
bool operator==(const Name& other) const { return (this->equals(other)); }
|
||||
|
||||
/// \brief Return true iff two names are not equal.
|
||||
///
|
||||
/// This method simply negates the result of \c equal() method, and in that
|
||||
/// sense it's redundant. The separate method is provided just for
|
||||
/// convenience.
|
||||
bool nequals(const Name& other) const { return !(this->equals(other)); }
|
||||
|
||||
/// Same as nequals()
|
||||
bool operator!=(const Name& other) const { return (this->nequals(other)); }
|
||||
|
||||
/// \brief Less-than or equal comparison for Name against <code>other</code>
|
||||
///
|
||||
/// The comparison is based on the result of the \c compare() method.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \param other the <code>Name</code> object to compare against.
|
||||
/// \return true if <code>compare(other).getOrder() <= 0</code>;
|
||||
/// otherwise false.
|
||||
bool leq(const Name& other) const;
|
||||
|
||||
/// Same as leq()
|
||||
bool operator<=(const Name& other) const { return (leq(other)); }
|
||||
|
||||
/// \brief Greater-than or equal comparison for Name against
|
||||
/// <code>other</code>
|
||||
///
|
||||
/// The comparison is based on the result of the \c compare() method.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \param other the <code>Name</code> object to compare against.
|
||||
/// \return true if <code>compare(other).getOrder() >= 0</code>;
|
||||
/// otherwise false.
|
||||
bool geq(const Name& other) const;
|
||||
|
||||
/// Same as geq()
|
||||
bool operator>=(const Name& other) const { return (geq(other)); }
|
||||
|
||||
/// \brief Less-than comparison for Name against <code>other</code>
|
||||
///
|
||||
/// The comparison is based on the result of the \c compare() method.
|
||||
///
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \param other the <code>Name</code> object to compare against.
|
||||
/// \return true if <code>compare(other).getOrder() < 0</code>;
|
||||
/// otherwise false.
|
||||
bool lthan(const Name& other) const;
|
||||
|
||||
/// Same as lthan()
|
||||
bool operator<(const Name& other) const { return (lthan(other)); }
|
||||
|
||||
/// \brief Greater-than comparison for Name against <code>other</code>
|
||||
///
|
||||
/// The comparison is based on the result of the \c compare() method.
|
||||
////
|
||||
/// This method never throws an exception.
|
||||
///
|
||||
/// \param other the <code>Name</code> object to compare against.
|
||||
/// \return true if <code>compare(other).getOrder() > 0</code>;
|
||||
/// otherwise false.
|
||||
bool gthan(const Name& other) const;
|
||||
|
||||
/// Same as gthan()
|
||||
bool operator>(const Name& other) const { return (gthan(other)); }
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Transformer methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Extract a specified subpart of Name.
|
||||
///
|
||||
/// <code>name.split(first, n)</code> constructs a new name starting from
|
||||
/// the <code>first</code>-th label of the \c name, and subsequent \c n
|
||||
/// labels including the \c first one. Since names in this current
|
||||
/// implementation are always "absolute", if the specified range doesn't
|
||||
/// contain the trailing dot of the original \c name, then a dot will be
|
||||
/// appended to the resulting name. As a result, the number of labels
|
||||
/// will be <code>n + 1</code>, rather than \c n. For example,
|
||||
/// when \c n is <code>Name("www.example.com")</code>,
|
||||
/// both <code>n.split(1, 2)</code> and <code>n.split(1, 3)</code>
|
||||
/// will produce a name corresponding to "example.com.", which has 3 labels.
|
||||
/// Note also that labels are counted from 0, and so <code>first = 1</code>
|
||||
/// in this example specified the label "example", not "www".
|
||||
///
|
||||
/// Parameter \c n must be larger than 0, and the range specified by
|
||||
/// \c first and \c n must not exceed the valid range of the original name;
|
||||
/// otherwise, an exception of class \c OutOfRange will be thrown.
|
||||
///
|
||||
/// Note to developers: we may want to have different versions (signatures)
|
||||
/// of this method. For example, we want to split the Name based on a given
|
||||
/// suffix name.
|
||||
///
|
||||
/// \param first The start position (in labels) of the extracted name
|
||||
/// \param n Number of labels of the extracted name
|
||||
/// \return A new Name object based on the Name containing <code>n</code>
|
||||
/// labels including and following the <code>first</code> label.
|
||||
Name split(unsigned int first, unsigned int n) const;
|
||||
|
||||
/// \brief Concatenate two names.
|
||||
///
|
||||
/// This method appends \c suffix to \c this Name. The trailing dot of
|
||||
/// \c this Name will be removed. For example, if \c this is "www."
|
||||
/// and \c suffix is "example.com.", a successful return of this method
|
||||
/// will be a name of "www.example.com."
|
||||
///
|
||||
///The resulting length of the concatenated name must not exceed
|
||||
/// \c Name::MAX_WIRE; otherwise an exception of class
|
||||
/// \c TooLongName will be thrown.
|
||||
///
|
||||
/// \param suffix a Name object to be appended to the Name.
|
||||
/// \return a new Name object concatenating \c suffix to \c this Name.
|
||||
Name concatenate(const Name& suffix) const;
|
||||
bool is_wildcard() const;
|
||||
bool operator==(const Name& other) const;
|
||||
bool equals(const Name& other) const; // alias of ==
|
||||
bool operator!=(const Name& other) const { return (!(*this == other)); }
|
||||
bool nequals(const Name& other) const; // alias of !=
|
||||
bool operator<=(const Name& other) const;
|
||||
bool leq(const Name& other) const; // alias of <=
|
||||
bool operator>=(const Name& other) const;
|
||||
bool geq(const Name& other) const; // alias of >=
|
||||
bool operator<(const Name& other) const;
|
||||
bool lthan(const Name& other) const; // alias of <
|
||||
bool operator>(const Name& other) const;
|
||||
bool gthan(const Name& other) const; // alias of >
|
||||
|
||||
/// \brief Downcase all upper case alphabet characters in the name.
|
||||
///
|
||||
/// This method modifies the calling object so that it can perform the
|
||||
/// conversion as fast as possible and can be exception free.
|
||||
///
|
||||
/// The return value of this version of \c downcase() is a reference to
|
||||
/// the calling object (i.e., \c *this) so that the caller can use the
|
||||
/// result of downcasing in a single line. For example, if variable
|
||||
/// \c n is a \c Name class object possibly containing upper case
|
||||
/// characters, and \c b is an \c OutputBuffer class object, then the
|
||||
/// following code will dump the name in wire format to \c b with
|
||||
/// downcasing upper case characters:
|
||||
///
|
||||
/// \code n.downcase().toWire(b); \endcode
|
||||
///
|
||||
/// Since this method modifies the calling object, a \c const name object
|
||||
/// cannot call it. If \c n is a \c const Name class object, it must first
|
||||
/// be copied to a different object and the latter must be used for the
|
||||
/// downcase modification.
|
||||
///
|
||||
/// \return A reference to the calling object with being downcased.
|
||||
Name& downcase();
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Testing methods
|
||||
///
|
||||
//@{
|
||||
/// \brief Test if this is a wildcard name.
|
||||
///
|
||||
/// \return \c true if the least significant label of this Name is
|
||||
/// <code>'*'</code>; otherwise \c false.
|
||||
bool isWildcard() const;
|
||||
//@}
|
||||
|
||||
///
|
||||
/// \name Protocol constants
|
||||
///
|
||||
//@{
|
||||
/// \brief Max allowable length of domain names.
|
||||
static const size_t MAX_WIRE = 255;
|
||||
|
||||
/// \brief Max allowable labels of domain names.
|
||||
///
|
||||
/// This is <code>ceil(MAX_WIRE / 2)</code>, and is equal to the number of
|
||||
/// labels of name "a.a.a.a....a." (127 "a"'s and trailing dot).
|
||||
static const size_t MAX_LABELS = 128;
|
||||
|
||||
/// \brief Max allowable length of labels of a domain name.
|
||||
static const size_t MAX_LABELLEN = 63;
|
||||
|
||||
/// \brief Max possible pointer value for name compression.
|
||||
///
|
||||
/// This is the highest number of 14-bit unsigned integer. Name compression
|
||||
/// pointers are identified as a 2-byte value starting with the upper two
|
||||
/// bit being 11.
|
||||
static const uint16_t MAX_COMPRESS_POINTER = 0x3fff;
|
||||
/// \brief A 8-bit masked value indicating a start of compression pointer.
|
||||
static const uint16_t COMPRESS_POINTER_MARK8 = 0xc0;
|
||||
/// \brief A 16-bit masked value indicating a start of compression pointer.
|
||||
static const uint16_t COMPRESS_POINTER_MARK16 = 0xc000;
|
||||
//@}
|
||||
|
||||
private:
|
||||
static const unsigned int MAXWIRE = 255;
|
||||
|
||||
std::string ndata_;
|
||||
std::vector<char> offsets_;
|
||||
std::vector<unsigned char> offsets_;
|
||||
unsigned int length_;
|
||||
unsigned int labels_;
|
||||
|
||||
void from_string(const std::string& namestr);
|
||||
unsigned int labelcount_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Name& name);
|
||||
///
|
||||
/// \brief Insert the name as a string into stream.
|
||||
///
|
||||
/// This method convert the \c name into a string and inserts it into the
|
||||
/// output stream \c os.
|
||||
///
|
||||
/// This function overloads the global operator<< to behave as described in
|
||||
/// ostream::operator<< but applied to \c Name objects.
|
||||
///
|
||||
/// \param os A \c std::ostream object on which the insertion operation is
|
||||
/// performed.
|
||||
/// \param name The \c Name object output by the operation.
|
||||
/// \return A reference to the same \c std::ostream object referenced by
|
||||
/// parameter \c os after the insertion operation.
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Name& name);
|
||||
}
|
||||
}
|
||||
#endif // __NAME_H
|
||||
|
537
src/lib/dns/cpp/name_unittest.cc
Normal file
537
src/lib/dns/cpp/name_unittest.cc
Normal file
@@ -0,0 +1,537 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "name.h"
|
||||
#include "messagerenderer.h"
|
||||
|
||||
#include "unittest_util.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using isc::UnitTestUtil;
|
||||
using isc::dns::InputBuffer;
|
||||
using isc::dns::OutputBuffer;
|
||||
using isc::dns::Name;
|
||||
using isc::dns::MessageRenderer;
|
||||
using isc::dns::NameComparisonResult;
|
||||
|
||||
//
|
||||
// XXX: these are defined as class static constants, but some compilers
|
||||
// seemingly cannot find the symbols when used in the EXPECT_xxx macros.
|
||||
//
|
||||
const size_t isc::dns::Name::MAX_WIRE;
|
||||
const size_t isc::dns::Name::MAX_LABELS;
|
||||
|
||||
namespace {
|
||||
class NameTest : public ::testing::Test {
|
||||
protected:
|
||||
NameTest() : example_name("www.example.com"),
|
||||
example_name_upper("WWW.EXAMPLE.COM"),
|
||||
small_name("aaa.example.com"),
|
||||
large_name("zzz.example.com"),
|
||||
buffer_actual(0), buffer_expected(0)
|
||||
{}
|
||||
|
||||
const Name example_name;
|
||||
Name example_name_upper; // this will be modified and cannot be const
|
||||
const Name small_name;
|
||||
const Name large_name;
|
||||
OutputBuffer buffer_actual, buffer_expected;
|
||||
|
||||
//
|
||||
// helper methods
|
||||
//
|
||||
static Name nameFactoryFromWire(const char* datafile, size_t position,
|
||||
bool downcase = false);
|
||||
// construct a name including all non-upper-case-alphabet characters.
|
||||
static Name nameFactoryLowerCase();
|
||||
void compareInWireFormat(const Name& name_actual,
|
||||
const Name& name_expected);
|
||||
};
|
||||
|
||||
Name
|
||||
NameTest::nameFactoryFromWire(const char* datafile, size_t position,
|
||||
bool downcase)
|
||||
{
|
||||
std::vector<unsigned char> data;
|
||||
UnitTestUtil::readWireData(datafile, data);
|
||||
|
||||
InputBuffer buffer(&data[0], data.size());
|
||||
buffer.setPosition(position);
|
||||
|
||||
return (Name(buffer, downcase));
|
||||
}
|
||||
|
||||
Name
|
||||
NameTest::nameFactoryLowerCase()
|
||||
{
|
||||
std::string lowercase_namestr;
|
||||
lowercase_namestr.reserve(Name::MAX_WIRE);
|
||||
|
||||
unsigned int ch = 0;
|
||||
unsigned int labelcount = 0;
|
||||
do {
|
||||
if (ch < 'A' || ch > 'Z') {
|
||||
std::ostringstream ss;
|
||||
ss.setf(std::ios_base::right, std::ios_base::adjustfield);
|
||||
ss.width(3);
|
||||
ss << std::setfill('0') << ch;
|
||||
lowercase_namestr += '\\' + ss.str();
|
||||
|
||||
if (++labelcount == Name::MAX_LABELLEN) {
|
||||
lowercase_namestr.push_back('.');
|
||||
labelcount = 0;
|
||||
}
|
||||
}
|
||||
} while (++ch <= Name::MAX_WIRE);
|
||||
|
||||
return (Name(lowercase_namestr));
|
||||
}
|
||||
|
||||
void
|
||||
NameTest::compareInWireFormat(const Name& name_actual,
|
||||
const Name& name_expected)
|
||||
{
|
||||
buffer_actual.clear();
|
||||
buffer_expected.clear();
|
||||
|
||||
name_actual.toWire(buffer_actual);
|
||||
name_expected.toWire(buffer_expected);
|
||||
|
||||
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
|
||||
buffer_actual.getData(), buffer_actual.getLength(),
|
||||
buffer_expected.getData(), buffer_expected.getLength());
|
||||
}
|
||||
|
||||
TEST_F(NameTest, fromText)
|
||||
{
|
||||
std::vector<std::string> strnames;
|
||||
strnames.push_back("www.example.com");
|
||||
strnames.push_back("www.example.com."); // with a trailing dot
|
||||
strnames.push_back("wWw.exAmpLe.com"); // mixed cases
|
||||
strnames.push_back("\\wWw.exAmpLe.com"); // escape with a backslash
|
||||
// decimal representation for "WWW"
|
||||
strnames.push_back("\\087\\087\\087.example.com");
|
||||
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for (it = strnames.begin(); it != strnames.end(); ++it) {
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name, Name(*it));
|
||||
}
|
||||
|
||||
// root names
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, Name("@"), Name("."));
|
||||
|
||||
// downcase
|
||||
EXPECT_EQ(Name("Www.eXample.coM", true).toText(), example_name.toText());
|
||||
|
||||
//
|
||||
// Tests for bogus names. These should trigger an exception.
|
||||
//
|
||||
// empty label cannot be followed by another label
|
||||
EXPECT_THROW(Name(".a"), isc::dns::EmptyLabel);
|
||||
// duplicate period
|
||||
EXPECT_THROW(Name("a.."), isc::dns::EmptyLabel);
|
||||
// label length must be < 64
|
||||
EXPECT_THROW(Name("012345678901234567890123456789"
|
||||
"012345678901234567890123456789"
|
||||
"0123"), isc::dns::TooLongLabel);
|
||||
// now-unsupported bitstring labels
|
||||
EXPECT_THROW(Name("\\[b11010000011101]"), isc::dns::BadLabelType);
|
||||
// label length must be < 64
|
||||
EXPECT_THROW(Name("012345678901234567890123456789"
|
||||
"012345678901234567890123456789"
|
||||
"012\\x"), isc::dns::TooLongLabel);
|
||||
// but okay as long as resulting len < 64 even if the original string is
|
||||
// "too long"
|
||||
EXPECT_NO_THROW(Name("012345678901234567890123456789"
|
||||
"012345678901234567890123456789"
|
||||
"01\\x"));
|
||||
// incomplete \DDD pattern (exactly 3 D's must appear)
|
||||
EXPECT_THROW(Name("\\12abc"), isc::dns::BadEscape);
|
||||
// \DDD must not exceed 255
|
||||
EXPECT_THROW(Name("\\256"), isc::dns::BadEscape);
|
||||
// Same tests for \111 as for \\x above
|
||||
EXPECT_THROW(Name("012345678901234567890123456789"
|
||||
"012345678901234567890123456789"
|
||||
"012\\111"), isc::dns::TooLongLabel);
|
||||
EXPECT_NO_THROW(Name("012345678901234567890123456789"
|
||||
"012345678901234567890123456789"
|
||||
"01\\111"));
|
||||
// A domain name must be 255 octets or less
|
||||
EXPECT_THROW(Name("123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"1234"), isc::dns::TooLongName);
|
||||
// This is a possible longest name and should be accepted
|
||||
EXPECT_NO_THROW(Name("123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123"));
|
||||
// \DDD must consist of 3 digits.
|
||||
EXPECT_THROW(Name("\\12"), isc::dns::IncompleteName);
|
||||
|
||||
// a name with the max number of labels. should be constructed without
|
||||
// an error, and its length should be the max value.
|
||||
Name maxlabels = Name("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 40
|
||||
"0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 80
|
||||
"0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 120
|
||||
"0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 160
|
||||
"0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 200
|
||||
"0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 240
|
||||
"0.1.2.3.4.5.6.");
|
||||
EXPECT_EQ(Name::MAX_LABELS, maxlabels.getLabelCount());
|
||||
}
|
||||
|
||||
TEST_F(NameTest, fromWire)
|
||||
{
|
||||
//
|
||||
// test cases derived from BIND9 tests.
|
||||
//
|
||||
// normal case with a compression pointer
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
|
||||
nameFactoryFromWire("testdata/name_fromWire1", 25),
|
||||
Name("vix.com"));
|
||||
// bogus label character (looks like a local compression pointer)
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire2", 25),
|
||||
isc::dns::BadLabelType);
|
||||
// a bad compression pointer (too big)
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire3_1", 25),
|
||||
isc::dns::BadPointer);
|
||||
// forward reference
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire3_2", 25),
|
||||
isc::dns::BadPointer);
|
||||
// invalid name length
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire4", 550),
|
||||
isc::dns::TooLongName);
|
||||
|
||||
// skip test for from Wire5. It's for disabling decompression, but our
|
||||
// implementation always allows it.
|
||||
|
||||
// bad pointer (too big)
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire6", 25),
|
||||
isc::dns::BadPointer);
|
||||
// input ends unexpectedly
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire7", 25),
|
||||
isc::dns::IncompleteName);
|
||||
// many hops of compression but valid. should succeed.
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
|
||||
nameFactoryFromWire("testdata/name_fromWire8", 383),
|
||||
Name("vix.com"));
|
||||
|
||||
//
|
||||
// Additional test cases
|
||||
//
|
||||
|
||||
// large names, a long but valid one, and invalid (too long) one.
|
||||
EXPECT_EQ(Name::MAX_WIRE,
|
||||
nameFactoryFromWire("testdata/name_fromWire9", 0).getLength());
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire10", 0).getLength(),
|
||||
isc::dns::TooLongName);
|
||||
|
||||
// A name with possible maximum number of labels; awkward but valid
|
||||
EXPECT_EQ(nameFactoryFromWire("testdata/name_fromWire11",
|
||||
0).getLabelCount(),
|
||||
Name::MAX_LABELS);
|
||||
|
||||
// Wire format including an invalid label length
|
||||
EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire12", 0),
|
||||
isc::dns::BadLabelType);
|
||||
|
||||
// converting upper-case letters to down-case
|
||||
EXPECT_EQ("vix.com.", nameFactoryFromWire("testdata/name_fromWire1",
|
||||
25, true).toText());
|
||||
EXPECT_EQ(3,
|
||||
nameFactoryFromWire("testdata/name_fromWire1",
|
||||
25).getLabelCount());
|
||||
}
|
||||
|
||||
TEST_F(NameTest, toText)
|
||||
{
|
||||
// tests derived from BIND9
|
||||
EXPECT_EQ("a.b.c.d", Name("a.b.c.d").toText(true));
|
||||
EXPECT_EQ("a.\\\\[[.c.d", Name("a.\\\\[\\[.c.d").toText(true));
|
||||
EXPECT_EQ("a.b.C.d.", Name("a.b.C.d").toText(false));
|
||||
EXPECT_EQ("a.b.", Name("a.b.").toText(false));
|
||||
|
||||
// test omit_final_dot. It's false by default.
|
||||
EXPECT_EQ("a.b.c.d", Name("a.b.c.d.").toText(true));
|
||||
EXPECT_EQ(Name("a.b.").toText(false), Name("a.b.").toText());
|
||||
|
||||
// the root name is a special case: omit_final_dot will be ignored.
|
||||
EXPECT_EQ(".", Name(".").toText(true));
|
||||
|
||||
// test all printable characters to see whether special characters are
|
||||
// escaped while the others are intact. note that the conversion is
|
||||
// implementation specific; for example, it's not invalid to escape a
|
||||
// "normal" character such as 'a' with regard to the standard.
|
||||
std::string all_printable("!\\\"#\\$%&'\\(\\)*+,-\\./0123456789:\\;<=>?\\@"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"[\\\\]^_.`abcdefghijklmnopqrstuvwxyz{|}~.");
|
||||
EXPECT_EQ(all_printable,
|
||||
nameFactoryFromWire("testdata/name_fromWire13", 0).toText());
|
||||
|
||||
std::string all_nonprintable(
|
||||
"\\000\\001\\002\\003\\004\\005\\006\\007\\008\\009"
|
||||
"\\010\\011\\012\\013\\014\\015\\016\\017\\018\\019"
|
||||
"\\020\\021\\022\\023\\024\\025\\026\\027\\028\\029"
|
||||
"\\030\\031\\032\\127\\128\\129"
|
||||
"\\130\\131\\132\\133\\134\\135\\136\\137\\138\\139"
|
||||
"\\140\\141\\142\\143\\144\\145\\146\\147\\148\\149"
|
||||
"\\150\\151\\152\\153\\154\\155\\156."
|
||||
"\\157\\158\\159"
|
||||
"\\160\\161\\162\\163\\164\\165\\166\\167\\168\\169"
|
||||
"\\170\\171\\172\\173\\174\\175\\176\\177\\178\\179"
|
||||
"\\180\\181\\182\\183\\184\\185\\186\\187\\188\\189"
|
||||
"\\190\\191\\192\\193\\194\\195\\196\\197\\198\\199"
|
||||
"\\200\\201\\202\\203\\204\\205\\206\\207\\208\\209"
|
||||
"\\210\\211\\212\\213\\214\\215\\216\\217\\218\\219."
|
||||
"\\220\\221\\222\\223\\224\\225\\226\\227\\228\\229"
|
||||
"\\230\\231\\232\\233\\234\\235\\236\\237\\238\\239"
|
||||
"\\240\\241\\242\\243\\244\\245\\246\\247\\248\\249"
|
||||
"\\250\\251\\252\\253\\254\\255.");
|
||||
EXPECT_EQ(all_nonprintable,
|
||||
nameFactoryFromWire("testdata/name_fromWire14", 0).toText());
|
||||
}
|
||||
|
||||
TEST_F(NameTest, toWireBuffer)
|
||||
{
|
||||
std::vector<unsigned char> data;
|
||||
OutputBuffer buffer(0);
|
||||
|
||||
UnitTestUtil::readWireData(std::string("01610376697803636f6d00"), data);
|
||||
Name("a.vix.com.").toWire(buffer);
|
||||
EXPECT_EQ(true, buffer.getLength() == data.size() &&
|
||||
memcmp(buffer.getData(), &data[0], data.size()) == 0);
|
||||
}
|
||||
|
||||
//
|
||||
// We test various corner cases in Renderer tests, but add this test case
|
||||
// to fill the code coverage gap.
|
||||
//
|
||||
TEST_F(NameTest, toWireRenderer)
|
||||
{
|
||||
std::vector<unsigned char> data;
|
||||
OutputBuffer buffer(0);
|
||||
MessageRenderer renderer(buffer);
|
||||
|
||||
UnitTestUtil::readWireData(std::string("01610376697803636f6d00"), data);
|
||||
Name("a.vix.com.").toWire(renderer);
|
||||
EXPECT_EQ(true, buffer.getLength() == data.size() &&
|
||||
memcmp(buffer.getData(), &data[0], data.size()) == 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Helper class to hold comparison test parameters.
|
||||
//
|
||||
struct CompareParameters {
|
||||
CompareParameters(const Name& n1, const Name& n2,
|
||||
NameComparisonResult::NameRelation r, int o,
|
||||
unsigned int l) :
|
||||
name1(n1), name2(n2), reln(r), order(o), labels(l) {}
|
||||
static int normalizeOrder(int o)
|
||||
{
|
||||
if (o > 0) {
|
||||
return (1);
|
||||
} else if (o < 0) {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
Name name1;
|
||||
Name name2;
|
||||
NameComparisonResult::NameRelation reln;
|
||||
int order;
|
||||
unsigned int labels;
|
||||
};
|
||||
|
||||
TEST_F(NameTest, compare)
|
||||
{
|
||||
std::vector<CompareParameters> params;
|
||||
params.push_back(CompareParameters(Name("c.d"), Name("a.b.c.d"),
|
||||
NameComparisonResult::SUPERDOMAIN,
|
||||
-1, 3));
|
||||
params.push_back(CompareParameters(Name("a.b.c.d"), Name("c.d"),
|
||||
NameComparisonResult::SUBDOMAIN, 1, 3));
|
||||
params.push_back(CompareParameters(Name("a.b.c.d"), Name("c.d.e.f"),
|
||||
NameComparisonResult::COMMONANCESTOR,
|
||||
-1, 1));
|
||||
params.push_back(CompareParameters(Name("a.b.c.d"), Name("f.g.c.d"),
|
||||
NameComparisonResult::COMMONANCESTOR,
|
||||
-1, 3));
|
||||
params.push_back(CompareParameters(Name("a.b.c.d"), Name("A.b.C.d."),
|
||||
NameComparisonResult::EQUAL,
|
||||
0, 5));
|
||||
|
||||
std::vector<CompareParameters>::const_iterator it;
|
||||
for (it = params.begin(); it != params.end(); ++it) {
|
||||
NameComparisonResult result = (*it).name1.compare((*it).name2);
|
||||
EXPECT_EQ((*it).reln, result.getRelation());
|
||||
EXPECT_EQ((*it).order,
|
||||
CompareParameters::normalizeOrder(result.getOrder()));
|
||||
EXPECT_EQ((*it).labels, result.getCommonLabels());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NameTest, equal)
|
||||
{
|
||||
EXPECT_TRUE(example_name == Name("WWW.EXAMPLE.COM."));
|
||||
EXPECT_TRUE(example_name.equals(Name("WWW.EXAMPLE.COM.")));
|
||||
EXPECT_TRUE(example_name != Name("www.example.org."));
|
||||
EXPECT_TRUE(example_name.nequals(Name("www.example.org.")));
|
||||
// lengths don't match
|
||||
EXPECT_TRUE(example_name != Name("www2.example.com."));
|
||||
EXPECT_TRUE(example_name.nequals(Name("www2.example.com.")));
|
||||
// lengths are equal, but # of labels don't match (first test checks the
|
||||
// prerequisite).
|
||||
EXPECT_EQ(example_name.getLength(), Name("www\\.example.com.").getLength());
|
||||
EXPECT_TRUE(example_name != Name("www\\.example.com."));
|
||||
EXPECT_TRUE(example_name.nequals(Name("www\\.example.com.")));
|
||||
}
|
||||
|
||||
TEST_F(NameTest, isWildcard)
|
||||
{
|
||||
EXPECT_EQ(false, example_name.isWildcard());
|
||||
EXPECT_EQ(true, Name("*.a.example.com").isWildcard());
|
||||
EXPECT_EQ(false, Name("a.*.example.com").isWildcard());
|
||||
}
|
||||
|
||||
TEST_F(NameTest, concatenate)
|
||||
{
|
||||
NameComparisonResult result =
|
||||
Name("aaa.www.example.com.").compare(Name("aaa").concatenate(example_name));
|
||||
EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
|
||||
|
||||
result = example_name.compare(Name(".").concatenate(example_name));
|
||||
EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
|
||||
|
||||
result = example_name.compare(example_name.concatenate(Name(".")));
|
||||
EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
|
||||
|
||||
// concatenating two valid names would result in too long a name.
|
||||
Name n1("123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789.");
|
||||
Name n2("123456789.123456789.123456789.123456789.123456789."
|
||||
"123456789.123456789.123456789.123456789.123456789."
|
||||
"1234.");
|
||||
EXPECT_THROW(n1.concatenate(n2), isc::dns::TooLongName);
|
||||
}
|
||||
|
||||
TEST_F(NameTest, split)
|
||||
{
|
||||
// normal cases with or without explicitly specifying the trailing dot.
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 2),
|
||||
Name("example.com."));
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 3),
|
||||
Name("example.com."));
|
||||
// edge cases: only the first or last label.
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(0, 1),
|
||||
Name("www."));
|
||||
EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(3, 1),
|
||||
Name("."));
|
||||
// invalid range: an exception should be thrown.
|
||||
EXPECT_THROW(example_name.split(1, 0), isc::dns::OutOfRange);
|
||||
EXPECT_THROW(example_name.split(2, 3), isc::dns::OutOfRange);
|
||||
}
|
||||
|
||||
TEST_F(NameTest, downcase)
|
||||
{
|
||||
// usual case: all-upper case name to all-lower case
|
||||
compareInWireFormat(example_name_upper.downcase(), example_name);
|
||||
// confirm that non upper-case characters are intact
|
||||
compareInWireFormat(nameFactoryLowerCase().downcase(),
|
||||
nameFactoryLowerCase());
|
||||
// confirm the calling object is actually modified
|
||||
example_name_upper.downcase();
|
||||
compareInWireFormat(example_name_upper, example_name);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// The following set of tests confirm the result of <=, <, >=, >
|
||||
// The test logic is simple, and all tests are just straightforward variations
|
||||
// of the first one.
|
||||
//
|
||||
TEST_F(NameTest, leq)
|
||||
{
|
||||
// small <= large is true
|
||||
EXPECT_TRUE(small_name.leq(large_name));
|
||||
EXPECT_TRUE(small_name <= large_name);
|
||||
|
||||
// small <= small is true
|
||||
EXPECT_TRUE(small_name.leq(small_name));
|
||||
EXPECT_TRUE(small_name <= small_name);
|
||||
|
||||
// large <= small is false
|
||||
EXPECT_FALSE(large_name.leq(small_name));
|
||||
EXPECT_FALSE(large_name <= small_name);
|
||||
}
|
||||
|
||||
TEST_F(NameTest, geq)
|
||||
{
|
||||
EXPECT_TRUE(large_name.geq(small_name));
|
||||
EXPECT_TRUE(large_name >= small_name);
|
||||
|
||||
EXPECT_TRUE(large_name.geq(large_name));
|
||||
EXPECT_TRUE(large_name >= large_name);
|
||||
|
||||
EXPECT_FALSE(small_name.geq(large_name));
|
||||
EXPECT_FALSE(small_name >= large_name);
|
||||
}
|
||||
|
||||
TEST_F(NameTest, lthan)
|
||||
{
|
||||
EXPECT_TRUE(small_name.lthan(large_name));
|
||||
EXPECT_TRUE(small_name < large_name);
|
||||
|
||||
EXPECT_FALSE(small_name.lthan(small_name));
|
||||
EXPECT_FALSE(small_name < small_name);
|
||||
|
||||
EXPECT_FALSE(large_name.lthan(small_name));
|
||||
EXPECT_FALSE(large_name < small_name);
|
||||
}
|
||||
|
||||
TEST_F(NameTest, gthan)
|
||||
{
|
||||
EXPECT_TRUE(large_name.gthan(small_name));
|
||||
EXPECT_TRUE(large_name > small_name);
|
||||
|
||||
EXPECT_FALSE(large_name.gthan(large_name));
|
||||
EXPECT_FALSE(large_name > large_name);
|
||||
|
||||
EXPECT_FALSE(small_name.gthan(large_name));
|
||||
EXPECT_FALSE(small_name > large_name);
|
||||
}
|
||||
|
||||
// test operator<<. We simply confirm it appends the result of toText().
|
||||
TEST_F(NameTest, LeftShiftOperator)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << example_name;
|
||||
EXPECT_EQ(example_name.toText(), oss.str());
|
||||
}
|
||||
}
|
14
src/lib/dns/cpp/testdata/name_fromWire1
vendored
Normal file
14
src/lib/dns/cpp/testdata/name_fromWire1
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# a global14 compression pointer
|
||||
#
|
||||
000a85800001000300000003
|
||||
# V i x c o m
|
||||
0356697803636f6d0000020001c00c00
|
||||
02000100000e10000b05697372763102
|
||||
7061c00cc00c0002000100000e100009
|
||||
066e732d657874c00cc00c0002000100
|
||||
000e10000e036e733104676e61630363
|
||||
6f6d00c0250001000100000e100004cc
|
||||
98b886c03c0001000100000e100004cc
|
||||
98b840c051000100010002a14a0004c6
|
||||
97f8f6
|
12
src/lib/dns/cpp/testdata/name_fromWire10
vendored
Normal file
12
src/lib/dns/cpp/testdata/name_fromWire10
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Too large name; should trigger an exception.
|
||||
#
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 040102030400
|
12
src/lib/dns/cpp/testdata/name_fromWire11
vendored
Normal file
12
src/lib/dns/cpp/testdata/name_fromWire11
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# A name with possible maximum number of labels; should be accepted safely.
|
||||
#
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 01000100010001000100 01000100010001000100
|
||||
01000100010001000100 0100010000
|
13
src/lib/dns/cpp/testdata/name_fromWire12
vendored
Normal file
13
src/lib/dns/cpp/testdata/name_fromWire12
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Wire format including an invalid label length
|
||||
#
|
||||
#(1) a (7) e x a m p l e
|
||||
01 61 07 65 78 61 6d 70 6c 65
|
||||
# invalid label length: 64
|
||||
40
|
||||
# a "label" of 64 characters: shouldn't be parsed
|
||||
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
|
||||
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
|
||||
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
|
||||
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
|
||||
00
|
5
src/lib/dns/cpp/testdata/name_fromWire13
vendored
Normal file
5
src/lib/dns/cpp/testdata/name_fromWire13
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#
|
||||
# A name including all "printable" characters
|
||||
#
|
||||
|
||||
3f2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f1f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e00
|
7
src/lib/dns/cpp/testdata/name_fromWire14
vendored
Normal file
7
src/lib/dns/cpp/testdata/name_fromWire14
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# A name including all "non-printable" characters
|
||||
#
|
||||
|
||||
3f000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f207f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c
|
||||
3f9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadb
|
||||
24dcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00
|
15
src/lib/dns/cpp/testdata/name_fromWire2
vendored
Normal file
15
src/lib/dns/cpp/testdata/name_fromWire2
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# bogus label character (looks like a local compression pointer)
|
||||
#
|
||||
000a85800001000300000003
|
||||
#this is the bogus label character:
|
||||
83
|
||||
76697803636f6d0000020001c00c00
|
||||
02000100000e10000b05697372763102
|
||||
7061c00cc00c0002000100000e100009
|
||||
066e732d657874c00cc00c0002000100
|
||||
000e10000e036e733104676e61630363
|
||||
6f6d00c0250001000100000e100004cc
|
||||
98b886c03c0001000100000e100004cc
|
||||
98b840c051000100010002a14a0004c6
|
||||
97f8f6
|
11
src/lib/dns/cpp/testdata/name_fromWire3_1
vendored
Normal file
11
src/lib/dns/cpp/testdata/name_fromWire3_1
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# a bad compression pointer starting with the bits 1111 (too big pointer)
|
||||
#
|
||||
000a85800001000300000003
|
||||
03766978 03636f6d 00 0002 0001
|
||||
f00c 0002 0001 0000 0e10 000b 056973727631 027061 c00c
|
||||
c00c 0002 0001 0000 0e10 0009 066e732d657874 c00c
|
||||
c00c 0002 0001 0000 0e10 000e 036e7331 04676e6163 03636f6d 00
|
||||
c025 0001 0001 0000 0e10 0004 cc98b886
|
||||
c03c 0001 0001 0000 0e10 0004 cc98b840
|
||||
c051 0001 0001 0002 a14a 0004 c697f8f6
|
13
src/lib/dns/cpp/testdata/name_fromWire3_2
vendored
Normal file
13
src/lib/dns/cpp/testdata/name_fromWire3_2
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# a bad compression pointer due to forward reference of 0x30 to
|
||||
# another compression pointer with a valid backreference
|
||||
#
|
||||
000a85800001000300000003
|
||||
03766978 03636f6d 00 0002 0001
|
||||
#'30' is the forward reference, 'c00c' at the end is the valid pointer:
|
||||
c030 0002 0001 0000 0e10 000b 056973727631 027061 c00c
|
||||
c00c 0002 0001 0000 0e10 0009 066e732d657874 c00c
|
||||
c00c 0002 0001 0000 0e10 000e 036e7331 04676e6163 03636f6d 00
|
||||
c025 0001 0001 0000 0e10 0004 cc98b886
|
||||
c03c 0001 0001 0000 0e10 0004 cc98b840
|
||||
c051 0001 0001 0002 a14a 0004 c697f8f6
|
45
src/lib/dns/cpp/testdata/name_fromWire4
vendored
Normal file
45
src/lib/dns/cpp/testdata/name_fromWire4
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# invalid name length, pointer at offset 0x0226 points to
|
||||
# long name at offset 0x25
|
||||
#
|
||||
000a 8580 0001 0003 0000 0001
|
||||
03 766978 03 636f6d 00 0002 0001
|
||||
c00c 0002 0001 00000e10
|
||||
0101
|
||||
# long name starts here
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a
|
||||
03616263 0358595a 03616263 0358595a
|
||||
03414243 0378797a 03414243 0378797a 00
|
||||
# compression pointer start here and refers back to long name
|
||||
c023 0002 0001 00000e10 0009 066e732d657874 c00c
|
||||
c00c 0002 0001 00000e10 000e 036e733104676e616303636f6d00
|
||||
c025 0001 0001 00000e10 0004 cc98b886
|
14
src/lib/dns/cpp/testdata/name_fromWire6
vendored
Normal file
14
src/lib/dns/cpp/testdata/name_fromWire6
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# a bad pointer
|
||||
#
|
||||
000a85800001000300000003
|
||||
# the bad pointer is f00c (offset = 300c) which is too large
|
||||
0376697803636f6d0000020001 f00c 00
|
||||
02000100000e10000b05697372763102
|
||||
7061c00cc00c0002000100000e100009
|
||||
066e732d657874c00cc00c0002000100
|
||||
000e10000e036e733104676e61630363
|
||||
6f6d00c0250001000100000e100004cc
|
||||
98b886c03c0001000100000e100004cc
|
||||
98b840c051000100010002a14a0004c6
|
||||
97f8f6
|
6
src/lib/dns/cpp/testdata/name_fromWire7
vendored
Normal file
6
src/lib/dns/cpp/testdata/name_fromWire7
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# input ends unexpectedly
|
||||
#
|
||||
000a85800001000300000003
|
||||
# parser will start at the ending 'c0', which is an incomplete sequence.
|
||||
0376697803636f6d0000020001 c0
|
27
src/lib/dns/cpp/testdata/name_fromWire8
vendored
Normal file
27
src/lib/dns/cpp/testdata/name_fromWire8
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# many hops of compression. absolutely many, but should be decompressed.
|
||||
#
|
||||
000a85800001000300000013
|
||||
03 766978 03 636f6d 00 0002 0001
|
||||
c00c 0002 0001 00000e10 000b 056973727631027061 c00c
|
||||
c019 0002 0001 00000e10 0009 066e732d657874 c00c
|
||||
c030 0002 0001 00000e10 000e 036e7331 04676e6163 03636f6d 00
|
||||
c045 0001 0001 00000e10 0004 cc98b886
|
||||
c05f 0001 0001 00000e10 0004 cc98b840
|
||||
c06f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c07f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c08f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c09f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c0af 0001 0001 0002a14a 0004 c697f8f6
|
||||
c0bf 0001 0001 0002a14a 0004 c697f8f6
|
||||
c0cf 0001 0001 0002a14a 0004 c697f8f6
|
||||
c0df 0001 0001 0002a14a 0004 c697f8f6
|
||||
c0ef 0001 0001 0002a14a 0004 c697f8f6
|
||||
c0ff 0001 0001 0002a14a 0004 c697f8f6
|
||||
c10f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c11f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c12f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c13f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c14f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c15f 0001 0001 0002a14a 0004 c697f8f6
|
||||
c16f 0001 0001 0002a14a 0004 c697f8f6
|
12
src/lib/dns/cpp/testdata/name_fromWire9
vendored
Normal file
12
src/lib/dns/cpp/testdata/name_fromWire9
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# A possible longest name; should be accepted safely.
|
||||
#
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 09010203040506070809 09010203040506070809
|
||||
09010203040506070809 0301020300
|
12
src/lib/dns/cpp/testdata/name_toWire1
vendored
Normal file
12
src/lib/dns/cpp/testdata/name_toWire1
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Rendering 3 names with compression. [x] means a compression pointer pointing
|
||||
# to offset 'x'.
|
||||
#
|
||||
#bytes:
|
||||
# 0 1 2 3 4 5 6 7 8 9 a b c d e
|
||||
#(1)a(7)e x a m p l e(3)c o m .
|
||||
0161076578616d706c6503636f6d00
|
||||
#(1)b [2]
|
||||
0162c002
|
||||
# a . e x a m p l e . o r g .
|
||||
0161076578616d706c65036f726700
|
14
src/lib/dns/cpp/testdata/name_toWire2
vendored
Normal file
14
src/lib/dns/cpp/testdata/name_toWire2
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Rendering names in a large buffer. [x] means a compression pointer pointing
|
||||
# to offset 'x'.
|
||||
#
|
||||
#bytes:
|
||||
#3f 40
|
||||
#ff 00
|
||||
#(1) a (7) e x a m p l e (3) c o m .
|
||||
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
|
||||
#[3fff] = a.example.com: can be compressed
|
||||
ffff
|
||||
#(1) b(7) e x a m p l e (3) c o m .; cannot compress as the pointer
|
||||
# (0x4001) would exceed 0x4000
|
||||
01 62 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
|
14
src/lib/dns/cpp/testdata/name_toWire3
vendored
Normal file
14
src/lib/dns/cpp/testdata/name_toWire3
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Rendering names including one explicitly uncompressed.
|
||||
# [x] means a compression pointer pointing to offset 'x'.
|
||||
#
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (bytes)
|
||||
#(1) a (7) e x a m p l e (3) c o m .
|
||||
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
|
||||
|
||||
#15 29 (bytes)
|
||||
#(1) b(7) e x a m p l e (3) c o m .; specified to be not compressed,
|
||||
# but can be pointed to from others
|
||||
01 62 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
|
||||
#[0f] referring to the second (uncompressed name)
|
||||
c0 0f
|
16
src/lib/dns/cpp/testdata/name_toWire4
vendored
Normal file
16
src/lib/dns/cpp/testdata/name_toWire4
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Rendering 3 names with compression, including one resulting in a chain of
|
||||
# pointers (the last one).
|
||||
# legend: [x] means a compression pointer pointing to offset 'x'.
|
||||
#bytes:
|
||||
#00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e
|
||||
#(1) a (7) e x a m p l e (3) c o m .
|
||||
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
|
||||
|
||||
#0f 10 11 12
|
||||
#(1) b [2] (b.example.com.)
|
||||
01 62 c0 02
|
||||
|
||||
#13 14
|
||||
# [0f]: (b.example.com.)
|
||||
c0 0f
|
124
src/lib/dns/cpp/unittest_util.cc
Normal file
124
src/lib/dns/cpp/unittest_util.cc
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "name.h"
|
||||
#include "unittest_util.h"
|
||||
|
||||
using isc::UnitTestUtil;
|
||||
using isc::dns::NameComparisonResult;
|
||||
|
||||
void
|
||||
UnitTestUtil::readWireData(const char* datafile,
|
||||
std::vector<unsigned char>& data)
|
||||
{
|
||||
std::ifstream ifs;
|
||||
|
||||
ifs.open(datafile, std::ios_base::in);
|
||||
if ((ifs.rdstate() & std::istream::failbit) != 0) {
|
||||
throw std::runtime_error("failed to open data file: " +
|
||||
std::string(datafile));
|
||||
}
|
||||
|
||||
data.clear();
|
||||
|
||||
std::string s;
|
||||
while (getline(ifs, s), !ifs.eof()) {
|
||||
if (ifs.bad() || ifs.fail()) {
|
||||
throw std::runtime_error("unexpected data line");
|
||||
}
|
||||
if (s.empty() || s[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
readWireData(s, data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UnitTestUtil::readWireData(const std::string& datastr,
|
||||
std::vector<unsigned char>& data)
|
||||
{
|
||||
std::istringstream iss(datastr);
|
||||
|
||||
do {
|
||||
std::string bytes;
|
||||
iss >> bytes;
|
||||
if (iss.bad() || iss.fail() || (bytes.size() % 2) != 0) {
|
||||
throw std::runtime_error("unexpected input or I/O error");
|
||||
}
|
||||
|
||||
for (int pos = 0; pos < bytes.size(); pos += 2) {
|
||||
unsigned int ch;
|
||||
std::istringstream(bytes.substr(pos, 2)) >> std::hex >> ch;
|
||||
data.push_back(static_cast<unsigned char>(ch));
|
||||
}
|
||||
} while (!iss.eof());
|
||||
}
|
||||
|
||||
::testing::AssertionResult
|
||||
UnitTestUtil::matchWireData(const char* dataexp1, const char* lenexp1,
|
||||
const char* dataexp2, const char* lenexp2,
|
||||
const void* data1, size_t len1,
|
||||
const void* data2, size_t len2)
|
||||
{
|
||||
::testing::Message msg;
|
||||
size_t cmplen = std::min(len1, len2);
|
||||
|
||||
for (int i = 0; i < cmplen; i++) {
|
||||
int ch1 = static_cast<const uint8_t*>(data1)[i];
|
||||
int ch2 = static_cast<const uint8_t*>(data2)[i];
|
||||
if (ch1 != ch2) {
|
||||
msg << "Wire data mismatch at " << i << "th byte\n"
|
||||
<< " Actual: " << ch1 << "\n"
|
||||
<< "Expected: " << ch2 << "\n";
|
||||
return (::testing::AssertionFailure(msg));
|
||||
}
|
||||
}
|
||||
if (len1 != len2) {
|
||||
msg << "Wire data mismatch in length:\n"
|
||||
<< " Actual: " << len1 << "\n"
|
||||
<< "Expected: " << len2 << "\n";
|
||||
return (::testing::AssertionFailure(msg));
|
||||
}
|
||||
return ::testing::AssertionSuccess();
|
||||
}
|
||||
|
||||
::testing::AssertionResult
|
||||
UnitTestUtil::matchName(const char* nameexp1, const char* nameexp2,
|
||||
const isc::dns::Name& name1,
|
||||
const isc::dns::Name& name2)
|
||||
{
|
||||
::testing::Message msg;
|
||||
|
||||
NameComparisonResult cmpresult = name1.compare(name2);
|
||||
if (cmpresult.getOrder() != 0 ||
|
||||
cmpresult.getRelation() != NameComparisonResult::EQUAL) {
|
||||
msg << "Two names are expected to be equal but not:\n"
|
||||
<< " One: " << name1 << "\n"
|
||||
<< "Other: " << name2 << "\n";
|
||||
return (::testing::AssertionFailure(msg));
|
||||
}
|
||||
return ::testing::AssertionSuccess();
|
||||
}
|
85
src/lib/dns/cpp/unittest_util.h
Normal file
85
src/lib/dns/cpp/unittest_util.h
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
|
||||
#ifndef __UNITTEST_UTIL_H
|
||||
#define __UNITTEST_UTIL_H 1
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "name.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace isc {
|
||||
|
||||
class UnitTestUtil {
|
||||
public:
|
||||
///
|
||||
/// read text format wire data from a file and put it to the given vector.
|
||||
///
|
||||
static void readWireData(const char*datafile,
|
||||
std::vector<unsigned char>& data);
|
||||
|
||||
///
|
||||
/// convert a sequence of hex strings into the corresponding list of
|
||||
/// 8-bit integers, and append them to the vector.
|
||||
///
|
||||
static void readWireData(const std::string& datastr,
|
||||
std::vector<unsigned char>& data);
|
||||
|
||||
///
|
||||
/// Compare len1 bytes of data1 with len2 bytes of data2 as binary data.
|
||||
///
|
||||
/// If they don't match report the point of mismatch in the google test
|
||||
/// format. This method is expected to be used from the EXPECT_PRED_FORMAT4
|
||||
/// macro of google test as follows:
|
||||
/// \code EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
|
||||
/// actual_data, actual_data_len,
|
||||
/// expected_data, expected_data_len); \endcode
|
||||
/// Parameters from dataexp1 to lenexp2 are passed via the macro but will
|
||||
/// be ignored by this method.
|
||||
/// Note: newer versions of google test supports the direct use of
|
||||
/// AssertionResult with the EXPECT_TRUE macro, which would be more
|
||||
/// intuitive, but to be as compatible as possible we use the more primitive
|
||||
/// macro, i.e., EXPECT_PRED_FORMAT4.
|
||||
///
|
||||
static ::testing::AssertionResult
|
||||
matchWireData(const char* dataexp1, const char* lenexp1,
|
||||
const char* dataexp2, const char* lenexp2,
|
||||
const void* data1, size_t len1,
|
||||
const void* data2, size_t len2);
|
||||
|
||||
///
|
||||
/// Compare two names.
|
||||
///
|
||||
/// This check method uses \c Name::compare() for comparison, which performs
|
||||
/// deeper checks including the equality of offsets, and should be better
|
||||
/// than EXPECT_EQ, which uses operater==. Like the \c matchWireData()
|
||||
/// method, the usage is a bit awkward; the caller should use
|
||||
/// \c EXPECT_PRED_FORMAT2.
|
||||
///
|
||||
static ::testing::AssertionResult
|
||||
matchName(const char* nameexp1, const char* nameexp2,
|
||||
const isc::dns::Name& name1, const isc::dns::Name& name2);
|
||||
};
|
||||
|
||||
}
|
||||
#endif // __UNITTEST_UTIL_H
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// End:
|
Reference in New Issue
Block a user