2
0
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:
JINMEI Tatuya
2010-01-04 20:48:26 +00:00
39 changed files with 3344 additions and 3108 deletions

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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());
}
}

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

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

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

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

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

View 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());
}
}

View File

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

View File

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

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

View 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

View 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

View 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

View File

@@ -0,0 +1,5 @@
#
# A name including all "printable" characters
#
3f2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f1f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e00

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

View 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

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

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

View 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();
}

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