--- /dev/null
+Makefile
+Makefile.in
+aclocal.m4
+config.cache
+config.log
+config.status
+configure
+libtool
+autom4te.cache
--- /dev/null
+# Doxyfile 1.3.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = YAZ
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = dox
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of source
+# files, where putting all generated files in the same directory would otherwise
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src include
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED = "YAZ_BEGIN_CDECL= " "YAZ_END_CDECL=" "YAZ_EXPORT="
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED = YAZ_BEGIN_CDECL YAZ_END_CDECL YAZ_EXPORT
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
--- /dev/null
+AUTOMAKE_OPTIONS = foreign
+
+SUBDIRS = src include etc doc
+
+EXTRA_DIST= README LICENSE yazpp.m4 yaz.m4 usemarcon.m4 buildconf.sh
+
+dist-hook:
+ mkdir $(distdir)/win
+ cp $(srcdir)/win/makefile $(distdir)/win/
+ mkdir $(distdir)/debian
+ cp $(srcdir)/debian/control $(distdir)/debian
+ cp $(srcdir)/debian/changelog $(distdir)/debian
+ cp $(srcdir)/debian/rules $(distdir)/debian
+ cp $(srcdir)/debian/postinst $(distdir)/debian
+ cp $(srcdir)/debian/compat $(distdir)/debian
+ cp $(srcdir)/debian/*.install $(distdir)/debian
--- /dev/null
+#!/bin/sh
+# $Id: buildconf.sh,v 1.1 2005-10-06 09:37:25 marc Exp $
+set -x
+aclocal -I .
+libtoolize --automake --force
+automake --add-missing
+autoconf
+set -
+if [ -f config.cache ]; then
+ rm config.cache
+fi
+
+enable_configure=false
+enable_help=true
+sh_flags=""
+conf_flags=""
+case $1 in
+ -d)
+ sh_flags="-g -Wall"
+ enable_configure=true
+ enable_help=false
+ shift
+ ;;
+ -c)
+ sh_flags=""
+ enable_configure=true
+ enable_help=false
+ shift
+ ;;
+esac
+
+if $enable_configure; then
+ if test -n "$sh_flags"; then
+ CXXFLAGS="$sh_flags" ./configure $*
+ else
+ ./configure $*
+ fi
+fi
+if $enable_help; then
+ cat <<EOF
+
+Build the Makefiles with the configure command.
+ ./configure [--someoption=somevalue ...]
+
+For help on options or configuring run
+ ./configure --help
+
+Build and install binaries with the usual
+ make
+ make check
+ make install
+
+Build distribution tarball with
+ make dist
+
+Verify distribution tarball with
+ make distcheck
+
+Or just build the Debian packages without configuring
+ dpkg-buildpackage -rfakeroot
+
+When building from a CVS checkout, you need these Debian tools:
+ docbook-utils, docbook, docbook-xml, docbook-dsssl, jade, jadetex,
+ libxslt1-dev, libyaz++-dev
+EOF
+fi
--- /dev/null
+AC_INIT(configure.in)
+AM_INIT_AUTOMAKE(yazproxy,1.1.0)
+
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_CXX
+AC_HEADER_STDC
+AM_PROG_LIBTOOL
+
+YAZPP_INIT(threads,1.0)
+if test -z "$YAZPPLIB"; then
+ AC_MSG_ERROR([YAZ++ development libraries missing])
+fi
+YAZ_DOC
+USEMARCON_INIT
+
+AC_CHECK_FUNCS(setrlimit getrlimit gettimeofday)
+AC_CHECK_HEADERS(pwd.h sys/resource.h sys/stat.h sys/time.h sys/types.h sys/wait.h unistd.h)
+AC_CHECK_LIB(dl,dlopen)
+dnl
+dnl ----- libXSLT
+AC_SUBST(XSLT_LIBS)
+AC_SUBST(XSLT_CFLAGS)
+xsltdir=default
+AC_ARG_WITH(xslt,[[ --with-xslt[=PREFIX] use libxslt in PREFIX]],xsltdir=$withval)
+if test "$xsltdir" = "yes" -o "$xsltdir" = "default"; then
+ for d in /usr /usr/local; do
+ if test -x $d/bin/xslt-config; then
+ xsltdir=$d
+ fi
+ done
+fi
+if test "$xsltdir" != "no"; then
+ AC_MSG_CHECKING(for libXSLT)
+ if test -x $xsltdir/bin/xslt-config; then
+ XSLT_LIBS=`$xsltdir/bin/xslt-config --libs`
+ XSLT_CFLAGS=`$xsltdir/bin/xslt-config --cflags`
+ XSLT_VER=`$xsltdir/bin/xslt-config --version`
+ AC_MSG_RESULT($XSLT_VER)
+ AC_DEFINE(HAVE_XSLT)
+ else
+ AC_MSG_RESULT(Not found)
+ if test "$xsltdir" = "default"; then
+ AC_MSG_WARN([Libxslt development libraries not found.])
+ else
+ AC_MSG_ERROR([libxslt development libraries not found.]) fi
+ fi
+fi
+
+AC_SUBST(YAZPROXY_SRC_ROOT)
+AC_SUBST(YAZPROXY_BUILD_ROOT)
+YAZPROXY_SRC_ROOT=`cd ${srcdir}; pwd`
+YAZPROXY_BUILD_ROOT=`pwd`
+AC_OUTPUT([
+ Makefile
+ src/Makefile
+ include/Makefile
+ include/yazproxy/Makefile
+ doc/Makefile
+ doc/yazproxy.xml
+ doc/yazprint.dsl doc/yazphp.dsl doc/yazhtml.dsl
+ doc/tkl.xsl
+ etc/Makefile
+])
--- /dev/null
+## $Id: Makefile.am,v 1.1 2005-10-06 09:37:25 marc Exp $
+
+AM_CXXFLAGS = $(YAZPPINC) -I$(srcdir)/../include $(XSLT_CFLAGS) $(USEMARCONINC)
+
+lib_LTLIBRARIES = libyazproxy.la
+libyazproxy_la_LDFLAGS=-version-info 1:0:0
+
+libyazproxy_la_SOURCES= yaz-proxy.cpp yaz-proxy-config.cpp yaz-bw.cpp \
+ proxyp.h yaz-usemarcon.cpp charset-converter.cpp msg-thread.cpp msg-thread.h \
+ modules.cpp
+
+bin_PROGRAMS = yazproxy
+check_PROGRAMS = cdetails
+noinst_PROGRAMS = tstthreads t-server p2
+
+TESTS=$(check_PROGRAMS)
+
+yazproxy_SOURCES=yaz-proxy-main.cpp
+cdetails_SOURCES=cdetails.cpp
+tstthreads_SOURCES=tstthreads.cpp
+t_server_SOURCES=t-server.cpp
+p2_SOURCES=p2_frontend.cpp p2_msg.cpp p2.cpp p2_frontend.h \
+ p2_config.cpp p2_config.h \
+ p2_backend.h p2_backend_dummy.cpp \
+ p2_modules.cpp p2_modules.h \
+ p2_xmlerror.cpp p2_xmlerror.h
+
+LDADD=libyazproxy.la $(YAZPPLALIB) $(XSLT_LIBS) $(USEMARCONLALIB)
+libyazproxy_la_LIBADD = $(XSLT_LIBS)
+
+# Modules
+mod_proxy_sample_la_SOURCES = mod_sample.cpp
+mod_proxy_sample_la_LDFLAGS = -rpath $(pkglibdir) -module -avoid-version
+
+pkglib_LTLIBRARIES = mod_proxy_sample.la
--- /dev/null
+/* $Id: msg-thread.cpp,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include <yaz++/socket-observer.h>
+#include <yaz/log.h>
+
+#include "msg-thread.h"
+
+using namespace yazpp_1;
+
+IMsg_Thread::~IMsg_Thread()
+{
+
+}
+
+Msg_Thread_Queue::Msg_Thread_Queue()
+{
+ m_list = 0;
+}
+
+int Msg_Thread_Queue::size()
+{
+ int no = 0;
+ Msg_Thread_Queue_List *l;
+ for (l = m_list; l; l = l->m_next)
+ no++;
+ return no;
+}
+
+void Msg_Thread_Queue::enqueue(IMsg_Thread *m)
+{
+ Msg_Thread_Queue_List *l = new Msg_Thread_Queue_List;
+ l->m_next = m_list;
+ l->m_item = m;
+ m_list = l;
+}
+
+IMsg_Thread *Msg_Thread_Queue::dequeue()
+{
+ Msg_Thread_Queue_List **l = &m_list;
+ if (!*l)
+ return 0;
+ while ((*l)->m_next)
+ l = &(*l)->m_next;
+ IMsg_Thread *m = (*l)->m_item;
+ delete *l;
+ *l = 0;
+ return m;
+}
+
+static void *tfunc(void *p)
+{
+ Msg_Thread *pt = (Msg_Thread *) p;
+ pt->run(0);
+ return 0;
+}
+
+
+Msg_Thread::Msg_Thread(ISocketObservable *obs, int no_threads)
+ : m_SocketObservable(obs)
+{
+ pipe(m_fd);
+ obs->addObserver(m_fd[0], this);
+ obs->maskObserver(this, SOCKET_OBSERVE_READ);
+
+ m_stop_flag = false;
+ pthread_mutex_init(&m_mutex_input_data, 0);
+ pthread_cond_init(&m_cond_input_data, 0);
+ pthread_mutex_init(&m_mutex_output_data, 0);
+
+ m_no_threads = no_threads;
+ m_thread_id = new pthread_t[no_threads];
+ int i;
+ for (i = 0; i<m_no_threads; i++)
+ pthread_create(&m_thread_id[i], 0, tfunc, this);
+}
+
+Msg_Thread::~Msg_Thread()
+{
+ pthread_mutex_lock(&m_mutex_input_data);
+ m_stop_flag = true;
+ pthread_cond_broadcast(&m_cond_input_data);
+ pthread_mutex_unlock(&m_mutex_input_data);
+
+ int i;
+ for (i = 0; i<m_no_threads; i++)
+ pthread_join(m_thread_id[i], 0);
+ delete [] m_thread_id;
+
+ m_SocketObservable->deleteObserver(this);
+
+ pthread_cond_destroy(&m_cond_input_data);
+ pthread_mutex_destroy(&m_mutex_input_data);
+ pthread_mutex_destroy(&m_mutex_output_data);
+ close(m_fd[0]);
+ close(m_fd[1]);
+}
+
+void Msg_Thread::socketNotify(int event)
+{
+ if (event & SOCKET_OBSERVE_READ)
+ {
+ char buf[2];
+ read(m_fd[0], buf, 1);
+ pthread_mutex_lock(&m_mutex_output_data);
+ IMsg_Thread *out = m_output.dequeue();
+ pthread_mutex_unlock(&m_mutex_output_data);
+ if (out)
+ out->result();
+ }
+}
+
+void Msg_Thread::run(void *p)
+{
+ while(1)
+ {
+ pthread_mutex_lock(&m_mutex_input_data);
+ while (!m_stop_flag && m_input.size() == 0)
+ pthread_cond_wait(&m_cond_input_data, &m_mutex_input_data);
+ if (m_stop_flag)
+ {
+ pthread_mutex_unlock(&m_mutex_input_data);
+ break;
+ }
+ IMsg_Thread *in = m_input.dequeue();
+ pthread_mutex_unlock(&m_mutex_input_data);
+
+ IMsg_Thread *out = in->handle();
+ pthread_mutex_lock(&m_mutex_output_data);
+ m_output.enqueue(out);
+
+ write(m_fd[1], "", 1);
+ pthread_mutex_unlock(&m_mutex_output_data);
+ }
+}
+
+void Msg_Thread::put(IMsg_Thread *m)
+{
+ pthread_mutex_lock(&m_mutex_input_data);
+ m_input.enqueue(m);
+ pthread_cond_signal(&m_cond_input_data);
+ pthread_mutex_unlock(&m_mutex_input_data);
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* $Id: msg-thread.h,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <yaz++/socket-observer.h>
+#include <yaz/yconfig.h>
+
+class IMsg_Thread {
+public:
+ virtual IMsg_Thread *handle() = 0;
+ virtual void result() = 0;
+ virtual ~IMsg_Thread();
+};
+
+class Msg_Thread_Queue_List {
+ friend class Msg_Thread_Queue;
+ private:
+ IMsg_Thread *m_item;
+ Msg_Thread_Queue_List *m_next;
+};
+
+class Msg_Thread_Queue {
+ public:
+ Msg_Thread_Queue();
+ void enqueue(IMsg_Thread *in);
+ IMsg_Thread *dequeue();
+ int size();
+ private:
+ Msg_Thread_Queue_List *m_list;
+};
+
+class Msg_Thread : public yazpp_1::ISocketObserver {
+ public:
+ Msg_Thread(yazpp_1::ISocketObservable *obs, int no_threads);
+ virtual ~Msg_Thread();
+ void socketNotify(int event);
+ void put(IMsg_Thread *m);
+ IMsg_Thread *get();
+ void run(void *p);
+ int m_fd[2];
+private:
+ yazpp_1::ISocketObservable *m_SocketObservable;
+ int m_no_threads;
+ pthread_t *m_thread_id;
+ Msg_Thread_Queue m_input;
+ Msg_Thread_Queue m_output;
+ pthread_mutex_t m_mutex_input_data;
+ pthread_cond_t m_cond_input_data;
+ pthread_mutex_t m_mutex_output_data;
+ bool m_stop_flag;
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* $Id: p2.cpp,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+#include <yaz/options.h>
+
+#include <yaz++/socket-manager.h>
+#include "p2_config.h"
+#include "p2_frontend.h"
+#include "p2_xmlerror.h"
+#include "p2_modules.h"
+
+using namespace yazpp_1;
+
+extern P2_ModuleEntry *p2_backend_dummy;
+
+/*
+ frontend result set map
+ resultset -> db,query
+
+ backend result set map
+ db,query -> resultset, target
+ resultset, target
+*/
+class P2_Frontend;
+
+P2_Config *P2_Server::lockConfig()
+{
+ pthread_mutex_lock(&m_mutex_config);
+ return m_config;
+}
+
+void P2_Server::unlockConfig()
+{
+ pthread_mutex_unlock(&m_mutex_config);
+}
+
+P2_Server::P2_Server(IPDU_Observable *the_PDU_Observable,
+ Msg_Thread *my_thread,
+ P2_Config *config,
+ P2_ModuleFactory *modules)
+ : Z_Assoc(the_PDU_Observable)
+{
+ m_my_thread = my_thread;
+ m_modules = modules;
+ m_config = config;
+
+ pthread_mutex_init(&m_mutex_config, 0);
+
+ yaz_log(YLOG_LOG, "Construct P2_Server=%p", this);
+}
+
+IPDU_Observer *P2_Server::sessionNotify(IPDU_Observable
+ *the_PDU_Observable, int fd)
+{
+ P2_Frontend *my = new P2_Frontend(the_PDU_Observable, m_my_thread, this);
+ yaz_log(YLOG_LOG, "New session %s", the_PDU_Observable->getpeername());
+ return my;
+}
+
+P2_Server::~P2_Server()
+{
+ yaz_log(YLOG_LOG, "Destroy P2_server=%p", this);
+ pthread_mutex_destroy(&m_mutex_config);
+}
+
+void P2_Server::recv_GDU(Z_GDU *apdu, int len)
+{
+}
+
+void P2_Server::failNotify()
+{
+}
+
+void P2_Server::timeoutNotify()
+{
+}
+
+void P2_Server::connectNotify()
+{
+}
+
+int main(int argc, char **argv)
+{
+ p2_xmlerror_setup();
+
+ P2_Config config;
+
+ if (!config.parse_options(argc, argv))
+ {
+ yaz_log(YLOG_FATAL, "Configuration incorrect. Exiting");
+ exit(1);
+ }
+
+ SocketManager mySocketManager;
+
+ PDU_Assoc *my_PDU_Assoc = 0;
+
+ Msg_Thread my_thread(&mySocketManager, config.m_no_threads);
+
+ my_PDU_Assoc = new PDU_Assoc(&mySocketManager);
+
+ P2_ModuleFactory modules;
+
+ modules.add(p2_backend_dummy);
+
+ std::list<P2_ConfigModule *>::const_iterator it;
+ for (it = config.m_modules.begin(); it != config.m_modules.end(); it++)
+ modules.add((*it)->m_fname.c_str());
+
+ P2_Server z(my_PDU_Assoc, &my_thread, &config, &modules);
+ z.server(config.m_listen_address.c_str());
+
+ while (mySocketManager.processEvent() > 0)
+ ;
+ return 0;
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+
+#ifndef P2_BACKEND_H
+#define P2_BACKEND_H
+
+#include <yaz++/z-query.h>
+
+class IP2_BackendSet {
+public:
+ virtual ~IP2_BackendSet();
+ virtual int get(int start, int number) = 0;
+};
+
+class IP2_Backend {
+ public:
+ virtual ~IP2_Backend();
+ virtual int search(yazpp_1::Yaz_Z_Query *q, IP2_BackendSet **rset, int *hits) = 0;
+};
+
+struct P2_ModuleInterface0 {
+ IP2_Backend *(*create)(const char *address);
+};
+
+struct P2_ModuleEntry {
+ int version;
+ const char *name;
+ const char *description;
+ void *interface_ptr;
+};
+
+
+#endif
--- /dev/null
+
+#include <yaz/log.h>
+#include "p2_backend.h"
+
+class P2_BackendSetDummy : public IP2_BackendSet {
+public:
+ P2_BackendSetDummy();
+ ~P2_BackendSetDummy();
+ int get(int start, int number);
+};
+
+class P2_BackendDummy : public IP2_Backend {
+public:
+ P2_BackendDummy(const char *address);
+ ~P2_BackendDummy();
+ int search(yazpp_1::Yaz_Z_Query *q, IP2_BackendSet **rset, int *hits);
+};
+
+P2_BackendDummy::P2_BackendDummy(const char *address)
+{
+ yaz_log(YLOG_LOG, "P2_backendDummy %p create", this);
+}
+
+P2_BackendDummy::~P2_BackendDummy()
+{
+ yaz_log(YLOG_LOG, "P2_backendDummy %p destroy", this);
+}
+
+int P2_BackendDummy::search(yazpp_1::Yaz_Z_Query *q, IP2_BackendSet **rset,
+ int *hits)
+{
+ yaz_log(YLOG_LOG, "P2_backendDummy %p search", this);
+
+ P2_BackendSetDummy *s = new P2_BackendSetDummy();
+
+ *rset = s;
+ *hits = 42;
+ return 0;
+}
+
+int P2_BackendSetDummy::get(int start, int number)
+{
+ yaz_log(YLOG_LOG, "P2_backendSetDummy %p get", this);
+ return 0;
+}
+
+P2_BackendSetDummy::P2_BackendSetDummy()
+{
+ yaz_log(YLOG_LOG, "P2_backendSetDummy %p create", this);
+
+}
+
+P2_BackendSetDummy::~P2_BackendSetDummy()
+{
+ yaz_log(YLOG_LOG, "P2_backendSetDummy %p destroy", this);
+}
+
+static IP2_Backend *dummy_create(const char *address)
+{
+ return new P2_BackendDummy(address);
+}
+
+P2_ModuleInterface0 int0 = {
+ dummy_create
+};
+
+P2_ModuleEntry p2_module_entry = {
+ 0,
+ "dummy",
+ "Dummy Backend",
+ (void *) &int0
+};
+
+P2_ModuleEntry *p2_backend_dummy = &p2_module_entry;
--- /dev/null
+/* $Id: p2_config.cpp,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <yaz/log.h>
+#include <yaz/options.h>
+#include <yaz/diagbib1.h>
+#include "p2_config.h"
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xinclude.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+#endif
+
+#include <iostream>
+
+using namespace std;
+
+class P2_Config::Rep {
+
+public:
+ Rep();
+ ~Rep();
+public:
+#if HAVE_XSLT
+ xmlDocPtr m_docPtr;
+ xmlNodePtr m_proxyPtr;
+#endif
+};
+
+P2_Config::Rep::Rep()
+{
+#if HAVE_XSLT
+ m_docPtr = 0;
+ m_proxyPtr = 0;
+#endif
+}
+
+P2_Config::Rep::~Rep()
+{
+#if HAVE_XSLT
+ if (m_docPtr)
+ xmlFreeDoc(m_docPtr);
+#endif
+}
+
+P2_Config::P2_Config()
+{
+ m_max_clients = 500;
+ m_client_idletime = 600;
+ m_debug_mode = 0;
+ m_no_limit_files = 0;
+ m_no_threads = 20;
+ m_target_idletime = 600;
+
+ m_rep = new Rep();
+}
+
+bool P2_Config::parse_options(int argc, char **argv)
+{
+ char *arg;
+ int ret;
+ bool show_config = false;
+ while ((ret = options("o:a:t:v:c:u:i:m:l:T:p:n:h:XS",
+ argv, argc, &arg)) != -2)
+ {
+ switch (ret)
+ {
+ case 0:
+ if (m_listen_address.length())
+ {
+ yaz_log(YLOG_FATAL, "Multiple listener address given");
+ return false;
+ }
+ m_listen_address = arg;
+ break;
+ case 'a':
+ m_apdu_log = arg;
+ break;
+ case 'c':
+ if (m_xml_fname.length())
+ {
+ yaz_log(YLOG_FATAL, "Multiple -c options given");
+ return false;
+ }
+ if (!read_xml_config(arg))
+ {
+ return false;
+ }
+ m_xml_fname = arg;
+ break;
+ case 'i':
+ m_client_idletime = atoi(arg);
+ break;
+ case 'l':
+ m_log_file = arg;
+ break;
+ case 'm':
+ m_max_clients = atoi(arg);
+ break;
+ case 'n':
+ m_no_limit_files = atoi(arg);
+ break;
+ case 'h':
+ m_no_threads = atoi(arg);
+ break;
+ case 'o':
+ m_optimize_flags = arg;
+ break;
+ case 'p':
+ if (m_pid_fname.length())
+ {
+ yaz_log(YLOG_LOG, "Multiple -p options given");
+ return false;
+ }
+ m_pid_fname = arg;
+ break;
+ case 't':
+ if (m_default_target.length())
+ {
+ yaz_log(YLOG_LOG, "Multiple -t options given");
+ return false;
+ }
+ m_default_target = arg;
+ break;
+ case 'T':
+ m_target_idletime = atoi(arg);
+ break;
+ case 'u':
+ if (m_uid.length())
+ {
+ yaz_log(YLOG_FATAL, "-u specified more than once");
+ return false;
+ }
+ m_uid = arg;
+ break;
+ case 'v':
+ yaz_log_init_level(yaz_log_mask_str(arg));
+ break;
+ case 'X':
+ m_debug_mode = 1;
+ break;
+ case 'S':
+ show_config = true;
+ break;
+ default:
+ yaz_log(YLOG_FATAL, "Bad option %s", arg);
+ return false;
+ }
+ }
+ if (m_log_file.length())
+ yaz_log_init_file(m_log_file.c_str());
+ if (show_config)
+ print();
+ return true;
+}
+
+bool P2_Config::parse_xml_text(void *xml_ptr, bool &val)
+{
+ string v;
+ if (!parse_xml_text(xml_ptr, v))
+ return false;
+ if (v.length() == 1 && v[0] == '1')
+ val = true;
+ else
+ val = false;
+ return true;
+}
+
+bool P2_Config::parse_xml_text(void *xml_ptr, string &val)
+{
+ xmlNodePtr ptr = (xmlNodePtr) xml_ptr;
+ bool found = false;
+ string v;
+ for(ptr = ptr->children; ptr; ptr = ptr->next)
+ if (ptr->type == XML_TEXT_NODE)
+ {
+ xmlChar *t = ptr->content;
+ if (t)
+ {
+ v += (const char *) t;
+ found = true;
+ }
+ }
+ if (found)
+ val = v;
+ return found;
+}
+
+void P2_Config::parse_xml_element_target(void *xml_ptr,
+ P2_ConfigTarget *t)
+{
+ xmlNodePtr ptr = (xmlNodePtr) xml_ptr;
+
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type != XML_ELEMENT_NODE)
+ continue;
+ if (!strcmp((const char *) ptr->name, "url"))
+ {
+ parse_xml_text(ptr, t->m_target_address);
+ }
+ else if (!strcmp((const char *) ptr->name, "database"))
+ {
+ parse_xml_text(ptr, t->m_target_database);
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "Unknown element '%s' inside target",
+ (const char *) ptr->name);
+ m_errors++;
+ }
+ }
+}
+
+void P2_Config::parse_xml_element_proxy(void *xml_ptr)
+{
+ xmlNodePtr ptr = (xmlNodePtr) xml_ptr;
+
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type != XML_ELEMENT_NODE)
+ continue;
+ if (!strcmp((const char *) ptr->name, "target"))
+ {
+ P2_ConfigTarget *t = new P2_ConfigTarget();
+
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ if (!strcmp((const char *) attr->name, "name")
+ || !strcmp((const char *) attr->name, "host"))
+ {
+ parse_xml_text(attr, t->m_virt_address);
+ }
+ else if (!strcmp((const char *) attr->name, "database"))
+ {
+ parse_xml_text(attr, t->m_virt_database);
+ }
+ else if (!strcmp((const char *) attr->name, "default"))
+ {
+ parse_xml_text(attr, t->m_default);
+ }
+ else if (!strcmp((const char *) attr->name, "type"))
+ {
+ parse_xml_text(attr, t->m_type);
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "Unknown attribute '%s' for "
+ "element proxy",
+ (const char *) attr->name);
+ m_errors++;
+ }
+ parse_xml_element_target(ptr, t);
+ m_target_list.push_back(t);
+ }
+ else if (!strcmp((const char *) ptr->name, "max-clients"))
+ {
+ string v;
+ if (parse_xml_text(ptr, v))
+ m_max_clients = atoi(v.c_str());
+ }
+ else if (!strcmp((const char *) ptr->name, "module"))
+ {
+ P2_ConfigModule *t = new P2_ConfigModule();
+
+ string v;
+ if (parse_xml_text(ptr, v))
+ {
+ t->m_fname = v;
+ m_modules.push_back(t);
+ }
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "Unknown element '%s' inside proxy", ptr->name);
+ m_errors++;
+ }
+ }
+}
+
+void P2_Config::print()
+{
+ cout << "max_clients=" << m_max_clients << endl;
+ list<P2_ConfigTarget *>::const_iterator it;
+
+ for (it = m_target_list.begin(); it != m_target_list.end(); it++)
+ {
+ cout << "type=" << (*it)->m_type << " ";
+ cout << "v-address=" << (*it)->m_virt_address << " ";
+ cout << "v-db=" << (*it)->m_virt_database << " ";
+ cout << "t-address=" << (*it)->m_target_address << " ";
+ cout << "t-db=" << (*it)->m_target_database << " ";
+ cout << "default=" << (*it)->m_default << endl;
+ }
+}
+
+bool P2_Config::read_xml_config(const char *fname)
+{
+ xmlDocPtr ndoc = xmlParseFile(fname);
+
+ if (!ndoc)
+ {
+ yaz_log(YLOG_WARN, "Config file %s not found or parse error", fname);
+ return false;
+ }
+ int noSubstitutions = xmlXIncludeProcess(ndoc);
+ if (noSubstitutions == -1)
+ yaz_log(YLOG_WARN, "XInclude processing failed on config %s", fname);
+
+ xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
+ if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
+ strcmp((const char *) proxyPtr->name, "proxy"))
+ {
+ yaz_log(YLOG_WARN, "No proxy element in %s", fname);
+ xmlFreeDoc(ndoc);
+ return false;
+ }
+ m_rep->m_proxyPtr = proxyPtr;
+
+ // OK: release previous and make it the current one.
+ if (m_rep->m_docPtr)
+ xmlFreeDoc(m_rep->m_docPtr);
+ m_rep->m_docPtr = ndoc;
+
+ m_errors = 0;
+ parse_xml_element_proxy(proxyPtr);
+ if (m_errors && !m_debug_mode)
+ return false;
+ return true;
+}
+
+P2_Config::~P2_Config()
+{
+ delete m_rep;
+}
+
+P2_ConfigTarget::P2_ConfigTarget()
+{
+ m_default = false;
+}
+
+P2_ConfigTarget *P2_Config::find_target(string db)
+{
+ list<P2_ConfigTarget *>::const_iterator it;
+ for (it = m_target_list.begin(); it != m_target_list.end(); it++)
+ {
+ if ((*it)->m_virt_database == db)
+ return (*it);
+ }
+ return 0;
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+/* $Id: p2_config.h,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef P2_CONFIG_INCLUDED
+#define P2_CONFIG_INCLUDED
+
+#include <string>
+#include <list>
+
+class P2_ConfigTarget {
+ public:
+ P2_ConfigTarget();
+ std::string m_virt_address;
+ std::string m_virt_database;
+ std::string m_target_address;
+ std::string m_target_database;
+ std::string m_type;
+ bool m_default;
+};
+
+class P2_ConfigModule {
+ public:
+ std::string m_fname;
+};
+
+class P2_Config {
+ class Rep;
+ public:
+ P2_Config::P2_Config();
+ P2_Config::~P2_Config();
+ bool P2_Config::parse_options(int argc, char **argv);
+ P2_ConfigTarget *find_target(std::string db);
+ void print();
+ private:
+ bool read_xml_config(const char *fname);
+ void parse_xml_element_proxy(void *xml_ptr);
+ void parse_xml_element_target(void *xml_ptr,
+ P2_ConfigTarget *t);
+ bool parse_xml_text(void *xml_ptr, std::string &val);
+ bool parse_xml_text(void *xml_ptr, bool &val);
+ public:
+ std::string m_apdu_log;
+ std::string m_default_target;
+ std::string m_listen_address;
+ std::string m_log_file;
+ std::string m_optimize_flags;
+ std::string m_pid_fname;
+ std::string m_uid;
+ std::string m_xml_fname;
+
+ int m_max_clients;
+ int m_client_idletime;
+ int m_debug_mode;
+ int m_no_limit_files;
+ int m_no_threads;
+ int m_target_idletime;
+
+ std::list<P2_ConfigTarget *> m_target_list;
+ std::list<P2_ConfigModule *> m_modules;
+ private:
+ Rep *m_rep;
+ int m_errors;
+};
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+/* $Id: p2_frontend.cpp,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+#include "p2_frontend.h"
+
+using namespace yazpp_1;
+using namespace std;
+
+P2_Frontend::P2_Frontend(IPDU_Observable *the_PDU_Observable,
+ Msg_Thread *my_thread, P2_Server *server)
+ : Z_Assoc(the_PDU_Observable)
+{
+ m_my_thread = my_thread;
+ m_server = server;
+ m_no_requests = 0;
+ m_delete_flag = 0;
+ yaz_log(YLOG_LOG, "Construct P2_Frontend=%p", this);
+}
+
+
+IPDU_Observer *P2_Frontend::sessionNotify(IPDU_Observable
+ *the_PDU_Observable, int fd)
+{
+ return 0;
+}
+
+P2_Frontend::~P2_Frontend()
+{
+ yaz_log(YLOG_LOG, "Destroy P2_Frontend=%p", this);
+
+ list<P2_FrontResultSet *>::iterator it;
+
+ for (it = m_resultSets.begin(); it != m_resultSets.end(); it++)
+ {
+ delete *it;
+ *it = 0;
+ }
+}
+
+void P2_Frontend::recv_GDU(Z_GDU *z_pdu, int len)
+{
+ GDU *gdu = new GDU(z_pdu);
+
+ P2_Msg *m = new P2_Msg(gdu, this, m_server);
+ m_no_requests++;
+ m_my_thread->put(m);
+}
+
+void P2_Frontend::failNotify()
+{
+ m_delete_flag = 1;
+ if (m_no_requests == 0)
+ delete this;
+
+}
+
+void P2_Frontend::timeoutNotify()
+{
+ m_delete_flag = 1;
+ if (m_no_requests == 0)
+ delete this;
+}
+
+void P2_Frontend::connectNotify()
+{
+
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+/* $Id: p2_frontend.h,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef P2_FRONTEND_H
+#define P2_FRONTEND_H
+
+#include <list>
+#include <vector>
+#include <string>
+
+#include "msg-thread.h"
+#include <yaz++/z-assoc.h>
+#include <yaz++/pdu-assoc.h>
+#include <yaz++/gdu.h>
+#include <yaz++/z-query.h>
+
+class P2_Frontend;
+class P2_Server;
+class P2_Config;
+class P2_ConfigTarget;
+class P2_ModuleFactory;
+
+class IP2_BackendSet;
+
+class P2_BackendResultSet {
+ public:
+ P2_BackendResultSet();
+ ~P2_BackendResultSet();
+ yazpp_1::Yaz_Z_Query m_query;
+ std::list<std::string> m_db_list;
+ int m_hit_count;
+ IP2_BackendSet *m_int;
+ // record cache here
+};
+
+class IP2_Backend;
+
+class P2_Backend {
+ public:
+ P2_Backend(P2_ConfigTarget *cfg, IP2_Backend *backend_interface);
+ ~P2_Backend();
+ public:
+ std::list<P2_BackendResultSet *>m_resultSets;
+ P2_ConfigTarget *m_configTarget;
+ bool m_busy;
+ IP2_Backend *m_int;
+};
+
+class P2_Server : public yazpp_1::Z_Assoc {
+public:
+ ~P2_Server();
+ P2_Server(yazpp_1::IPDU_Observable *the_PDU_Observable,
+ Msg_Thread *m_my_thread,
+ P2_Config *config,
+ P2_ModuleFactory *modules);
+ P2_Config *lockConfig();
+ void unlockConfig();
+ std::list<P2_Backend *>m_backend_list;
+ P2_ModuleFactory *m_modules;
+private:
+ yazpp_1::IPDU_Observer* sessionNotify(
+ yazpp_1::IPDU_Observable *the_PDU_Observable,
+ int fd);
+ void recv_GDU(Z_GDU *apdu, int len);
+
+ void failNotify();
+ void timeoutNotify();
+ void connectNotify();
+private:
+ P2_Config *m_config;
+ Msg_Thread *m_my_thread;
+ pthread_mutex_t m_mutex_config;
+};
+
+class P2_FrontResultSet {
+public:
+ P2_FrontResultSet(const char *id);
+ ~P2_FrontResultSet();
+ void setQuery(Z_Query *z_query);
+ void setDatabases(char **db, int num);
+ std::string m_resultSetId;
+ std::vector<std::string> m_db_list;
+ yazpp_1::Yaz_Z_Query m_query;
+};
+
+class P2_Msg : public IMsg_Thread {
+public:
+ int m_close_flag;
+ yazpp_1::GDU *m_gdu;
+ yazpp_1::GDU *m_output;
+ P2_Frontend *m_front;
+ P2_Server *m_server;
+ IMsg_Thread *handle();
+ void result();
+ P2_Msg(yazpp_1::GDU *gdu, P2_Frontend *front, P2_Server *server);
+ virtual ~P2_Msg();
+ private:
+
+ Z_APDU *frontend_search_resultset(Z_APDU *z_gdu, ODR odr,
+ P2_FrontResultSet **rset);
+ Z_APDU *frontend_present_resultset(Z_APDU *z_gdu, ODR odr,
+ P2_FrontResultSet **rset);
+ Z_APDU *frontend_search_apdu(Z_APDU *z_gdu, ODR odr);
+ Z_APDU *frontend_present_apdu(Z_APDU *z_gdu, ODR odr);
+ P2_Backend *select_backend(std::string db,
+ yazpp_1::Yaz_Z_Query *query,
+ P2_BackendResultSet **bset);
+ P2_Backend *create_backend(std::string db);
+};
+
+class P2_Frontend : public yazpp_1::Z_Assoc {
+ public:
+ ~P2_Frontend();
+ P2_Frontend(yazpp_1::IPDU_Observable *the_PDU_Observable,
+ Msg_Thread *m_my_thread, P2_Server *server);
+ IPDU_Observer* sessionNotify(yazpp_1::IPDU_Observable *the_PDU_Observable,
+ int fd);
+
+ void recv_GDU(Z_GDU *apdu, int len);
+
+ void failNotify();
+ void timeoutNotify();
+ void connectNotify();
+
+ int m_no_requests;
+ int m_delete_flag;
+ std::list<P2_FrontResultSet *> m_resultSets;
+
+ private:
+ yazpp_1::GDUQueue m_in_queue;
+ Msg_Thread *m_my_thread;
+ P2_Server *m_server;
+ private:
+ bool P2_Frontend::search(Z_GDU *z_gdu);
+ bool P2_Frontend::handle_init(Z_GDU *z_gdu);
+};
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+
+#include <dlfcn.h>
+
+#include "p2_modules.h"
+
+class P2_ModuleDLEntry {
+public:
+ void *m_dl_handle;
+ P2_ModuleEntry *m_entry;
+ P2_ModuleDLEntry();
+ ~P2_ModuleDLEntry();
+};
+
+P2_ModuleDLEntry::P2_ModuleDLEntry()
+{
+ m_dl_handle = 0;
+ m_entry = 0;
+}
+
+P2_ModuleDLEntry::~P2_ModuleDLEntry()
+{
+ if (m_dl_handle)
+ dlclose(m_dl_handle);
+}
+
+P2_ModuleFactory::P2_ModuleFactory()
+{
+}
+
+P2_ModuleFactory::~P2_ModuleFactory()
+{
+}
+
+bool P2_ModuleFactory::add(P2_ModuleEntry *entry)
+{
+ P2_ModuleDLEntry *m = new P2_ModuleDLEntry();
+ m->m_entry = entry;
+ m_modules.push_back(m);
+ return true;
+}
+
+bool P2_ModuleFactory::add(const char *fname)
+{
+ void *dl_handle = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
+ if (!dl_handle)
+ return false;
+
+ P2_ModuleEntry *entry =
+ reinterpret_cast<P2_ModuleEntry *>
+ (dlsym(dl_handle, "p2_module_entry"));
+ if (!entry)
+ {
+ dlclose(dl_handle);
+ return false;
+ }
+ P2_ModuleDLEntry *m = new P2_ModuleDLEntry();
+ m->m_dl_handle = dl_handle;
+ m->m_entry = entry;
+ m_modules.push_back(m);
+ return true;
+}
+
+void *P2_ModuleFactory::get_interface(const char *name, int version)
+{
+ std::list<P2_ModuleDLEntry *>::const_iterator it;
+ for (it = m_modules.begin(); it != m_modules.end(); it++)
+ {
+ P2_ModuleDLEntry *ent = *it;
+ if (!strcmp(ent->m_entry->name, name) &&
+ ent->m_entry->version == version)
+ {
+ return ent->m_entry->interface_ptr;
+ }
+ }
+ return 0;
+}
+
--- /dev/null
+
+#ifndef P2_MODULES_H
+#define P2_MODULES_H
+
+#include "p2_backend.h"
+
+#include <list>
+
+class P2_ModuleDLEntry ;
+class P2_ModuleFactory {
+ public:
+ P2_ModuleFactory();
+ ~P2_ModuleFactory();
+ bool add(const char *fname);
+ bool add(P2_ModuleEntry *entry);
+ void *get_interface(const char *name, int version);
+ private:
+ std::list <P2_ModuleDLEntry *>m_modules;
+};
+
+#endif
--- /dev/null
+/* $Id: p2_msg.cpp,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+#include "p2_backend.h"
+#include "p2_frontend.h"
+#include "p2_config.h"
+#include "p2_modules.h"
+
+using namespace yazpp_1;
+using namespace std;
+
+IP2_BackendSet::~IP2_BackendSet()
+{
+}
+
+IP2_Backend::~IP2_Backend()
+{
+
+}
+
+P2_Backend::P2_Backend(P2_ConfigTarget *cfg, IP2_Backend *backend_int)
+{
+ m_configTarget = new P2_ConfigTarget;
+ *m_configTarget = *cfg;
+ m_busy = false;
+ m_int = backend_int;
+}
+
+P2_Backend::~P2_Backend()
+{
+ delete m_configTarget;
+}
+
+P2_BackendResultSet::P2_BackendResultSet()
+{
+ m_int = 0;
+}
+
+P2_BackendResultSet::~P2_BackendResultSet()
+{
+ delete m_int;
+}
+
+P2_Backend *P2_Msg::select_backend(string db,
+ Yaz_Z_Query *query,
+ P2_BackendResultSet **bset)
+{
+ P2_Config *cfg = m_server->lockConfig();
+
+ // see if some target has done this query before
+
+ *bset = 0;
+ P2_Backend *backend = 0;
+
+ list<P2_Backend *>::const_iterator it;
+ for (it = m_server->m_backend_list.begin();
+ it != m_server->m_backend_list.end(); it++)
+ {
+ if ((*it)->m_busy)
+ continue;
+
+ if (db != (*it)->m_configTarget->m_virt_database)
+ continue;
+ backend = *it;
+
+ if (query)
+ {
+ list<P2_BackendResultSet *>::const_iterator is;
+ for (is = (*it)->m_resultSets.begin();
+ is != (*it)->m_resultSets.end(); is++)
+ {
+ if (query->match(&(*is)->m_query))
+ {
+ *bset = *is;
+ break;
+ }
+ }
+ }
+ if (bset)
+ break;
+ }
+ if (!backend)
+ {
+ P2_ConfigTarget *target_cfg = cfg->find_target(db);
+
+ if (!target_cfg)
+ {
+ yaz_log(YLOG_WARN, "No backend for database %s",
+ db.c_str());
+ }
+ else
+ {
+ P2_ModuleInterface0 *int0 =
+ reinterpret_cast<P2_ModuleInterface0 *>
+ (m_server->m_modules->get_interface(target_cfg->m_type.c_str(),
+ 0));
+ IP2_Backend *bint = 0;
+
+ if (int0)
+ bint = int0->create(target_cfg->m_target_address.c_str());
+
+ if (bint)
+ backend = new P2_Backend(target_cfg, bint);
+
+ if (backend)
+ m_server->m_backend_list.push_back(backend);
+ }
+ }
+ if (backend)
+ backend->m_busy = true;
+ m_server->unlockConfig();
+ return backend;
+}
+
+void P2_FrontResultSet::setQuery(Z_Query *z_query)
+{
+ m_query.set_Z_Query(z_query);
+}
+
+void P2_FrontResultSet::setDatabases(char **db, int num)
+{
+ m_db_list.clear();
+
+ int i;
+ for (i = 0; i<num; i++)
+ m_db_list.push_back(db[i]);
+}
+
+P2_FrontResultSet::P2_FrontResultSet(const char *id)
+{
+ m_resultSetId = id;
+}
+
+
+P2_FrontResultSet::~P2_FrontResultSet()
+{
+}
+
+P2_Msg::P2_Msg(GDU *gdu, P2_Frontend *front, P2_Server *server)
+{
+ m_front = front;
+ m_server = server;
+ m_output = 0;
+ m_gdu = gdu;
+ m_close_flag = 0;
+}
+
+P2_Msg::~P2_Msg()
+{
+ delete m_output;
+ delete m_gdu;
+}
+
+Z_APDU *P2_Msg::frontend_search_resultset(Z_APDU *z_gdu, ODR odr,
+ P2_FrontResultSet **rset)
+{
+ Z_SearchRequest *req = z_gdu->u.searchRequest;
+ list<P2_FrontResultSet *>::iterator it;
+ P2_FrontResultSet *s = 0;
+
+ string id = req->resultSetName;
+ for (it = m_front->m_resultSets.begin(); it != m_front->m_resultSets.end(); it++)
+ {
+ if ((*it)->m_resultSetId == id)
+ {
+ s = *it;
+ break;
+ }
+ }
+ if (s)
+ {
+ // result set already exists
+ *rset = s;
+ if (req->replaceIndicator && *req->replaceIndicator)
+ { // replace indicator true
+ s->setQuery(req->query);
+ s->setDatabases(req->databaseNames, req->num_databaseNames);
+ return 0;
+ }
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF,
+ req->resultSetName);
+
+ return apdu;
+ }
+ // does not exist
+ s = new P2_FrontResultSet(req->resultSetName);
+ s->setQuery(req->query);
+ s->setDatabases(req->databaseNames, req->num_databaseNames);
+ m_front->m_resultSets.push_back(s);
+ *rset = s;
+ return 0;
+}
+
+Z_APDU *P2_Msg::frontend_search_apdu(Z_APDU *request_apdu, ODR odr)
+{
+ P2_FrontResultSet *rset;
+ Z_APDU *response_apdu = frontend_search_resultset(request_apdu, odr,
+ &rset);
+ if (response_apdu)
+ return response_apdu;
+
+ // no immediate error (yet)
+ size_t i;
+ for (i = 0; i<rset->m_db_list.size(); i++)
+ {
+ string db = rset->m_db_list[i];
+ P2_BackendResultSet *bset;
+ P2_Backend *b = select_backend(db, &rset->m_query, &bset);
+ if (!b)
+ {
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_DATABASE_UNAVAILABLE, db.c_str());
+ return apdu;
+ }
+ if (!bset)
+ { // new set
+ bset = new P2_BackendResultSet();
+
+ bset->m_query.set_Z_Query(request_apdu->u.searchRequest->query);
+ bset->m_db_list.push_back(db);
+
+ b->m_int->search(&bset->m_query, &bset->m_int, &bset->m_hit_count);
+ b->m_resultSets.push_back(bset);
+ }
+ else
+ {
+ bset->m_int->get(1, 1);
+ }
+ response_apdu = zget_APDU(odr, Z_APDU_searchResponse);
+ *response_apdu->u.searchResponse->resultCount = bset->m_hit_count;
+ b->m_busy = false;
+ }
+ if (!response_apdu)
+ {
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(odr, YAZ_BIB1_UNSUPP_SEARCH, 0);
+ return apdu;
+ }
+ return response_apdu;
+}
+
+Z_APDU *P2_Msg::frontend_present_resultset(Z_APDU *z_gdu, ODR odr,
+ P2_FrontResultSet **rset)
+{
+ Z_PresentRequest *req = z_gdu->u.presentRequest;
+ list<P2_FrontResultSet *>::iterator it;
+ P2_FrontResultSet *s = 0;
+
+ string id = req->resultSetId;
+ for (it = m_front->m_resultSets.begin(); it != m_front->m_resultSets.end(); it++)
+ {
+ if ((*it)->m_resultSetId == id)
+ {
+ s = *it;
+ break;
+ }
+ }
+ *rset = s;
+ if (s)
+ return 0; // fine result set exists
+
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_presentResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.presentResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr,
+ YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
+ req->resultSetId);
+ return apdu;
+}
+
+Z_APDU *P2_Msg::frontend_present_apdu(Z_APDU *request_apdu, ODR odr)
+{
+ P2_FrontResultSet *rset;
+ Z_APDU *response_apdu = frontend_present_resultset(request_apdu, odr,
+ &rset);
+ if (response_apdu)
+ return response_apdu;
+ return zget_APDU(odr, Z_APDU_presentResponse);
+}
+
+IMsg_Thread *P2_Msg::handle()
+{
+ ODR odr = odr_createmem(ODR_ENCODE);
+ yaz_log(YLOG_LOG, "P2_Msg:handle begin");
+ Z_GDU *request_gdu = m_gdu->get();
+
+ if (request_gdu->which == Z_GDU_Z3950)
+ {
+ Z_APDU *request_apdu = request_gdu->u.z3950;
+ Z_APDU *response_apdu = 0;
+ switch(request_apdu->which)
+ {
+ case Z_APDU_initRequest:
+ response_apdu = zget_APDU(odr, Z_APDU_initResponse);
+ ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_triggerResourceCtrl);
+ ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_search);
+ ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_present);
+ ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_namedResultSets);
+ break;
+ case Z_APDU_searchRequest:
+ response_apdu = frontend_search_apdu(request_apdu, odr);
+ break;
+ case Z_APDU_presentRequest:
+ response_apdu = frontend_present_apdu(request_apdu, odr);
+ break;
+ case Z_APDU_triggerResourceControlRequest:
+ break;
+ default:
+ response_apdu = zget_APDU(odr, Z_APDU_close);
+ m_close_flag = 1;
+ break;
+ }
+ if (response_apdu)
+ m_output = new GDU(response_apdu);
+ }
+ yaz_log(YLOG_LOG, "P2_Msg:handle end");
+ odr_destroy(odr);
+ return this;
+}
+
+void P2_Msg::result()
+{
+ m_front->m_no_requests--;
+ if (!m_front->m_delete_flag)
+ {
+ if (m_output)
+ {
+ int len;
+ m_front->send_GDU(m_output->get(), &len);
+ }
+ if (m_close_flag)
+ {
+ m_front->close();
+ m_front->m_delete_flag = 1;
+ }
+ }
+ if (m_front->m_delete_flag && m_front->m_no_requests == 0)
+ delete m_front;
+ delete this;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+/* $Id: p2_xmlerror.cpp,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <yaz/log.h>
+
+#include "p2_xmlerror.h"
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxslt/xsltutils.h>
+#endif
+
+#if HAVE_XSLT
+static void p2_xml_error_handler(void *ctx, const char *fmt, ...)
+{
+ char buf[1024];
+ size_t sz;
+
+ va_list ap;
+ va_start(ap, fmt);
+
+#ifdef WIN32
+ vsprintf(buf, fmt, ap);
+#else
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+#endif
+ sz = strlen(buf);
+ if (sz > 0 && buf[sz-1] == '\n')
+ buf[sz-1] = '\0';
+
+ yaz_log(YLOG_WARN, "%s: %s", (char*) ctx, buf);
+
+ va_end (ap);
+}
+#endif
+
+void p2_xmlerror_setup()
+{
+#if HAVE_XSLT
+ xmlSetGenericErrorFunc((void *) "XML", p2_xml_error_handler);
+ xsltSetGenericErrorFunc((void *) "XSLT", p2_xml_error_handler);
+#endif
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+/* $Id: p2_xmlerror.h,v 1.1 2005-10-06 09:37:25 marc Exp $
+ Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef P2_XMLERROR_H
+#define P2_XMLERROR_H
+
+void p2_xmlerror_setup();
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+
+#ifndef P3_FILTER_H
+#define P3_FILTER_H
+
+#include <stdexcept>
+
+
+namespace p3 {
+
+ class Package;
+
+
+
+ class Filter {
+ public:
+ virtual ~Filter(){};
+ virtual Package & process(Package & package) const {
+ return package;
+ };
+ virtual void configure(){};
+
+ // set/get the C++ way .. just as showoff
+
+ // get function - returns copy and keeps object const,
+ // thus is right val in assignment
+ unsigned int max_front_workers() const {
+ return m_max_front;
+ }
+ // set function - returns reference and changes object,
+ // thus is left val in assignment
+ unsigned int & max_front_workers() {
+ return m_max_front;
+ }
+ // more traditional set function, taking const reference
+ // or copy (here const ref for demo), returning ref to object
+ // can be chained with other similar functions!
+ Filter & max_front_workers(const unsigned int & max_front){
+ m_max_front = max_front;
+ return *this;
+ }
+
+ private:
+ unsigned int m_max_front;
+ };
+
+
+ class Filter_Exception : public std::runtime_error {
+ public:
+ Filter_Exception(const std::string message)
+ : std::runtime_error("Filter_Exception: " + message){
+ };
+ };
+
+
+ class Router {
+ public:
+ virtual ~Router(){};
+ virtual const Filter &
+ route(const Filter & filter, Package & package) const {
+ //if (!m_sillyrule)
+ //throw Router_Exception("no routing rules known");
+ return m_sillyrule;
+ };
+ virtual void configure(){};
+ Router & rule(Filter filter){
+ m_sillyrule = filter;
+ return *this;
+ }
+ private:
+ Filter m_sillyrule;
+ };
+
+
+ class Router_Exception : public std::runtime_error {
+ public:
+ Router_Exception(const std::string message)
+ : std::runtime_error("Router_Exception: " + message){};
+ };
+
+
+ class Package {
+ public:
+
+ // send package to it's next filter defined in chain
+ void move() {
+ Filter oldfilter;
+ Filter nextfilter = m_router.route(oldfilter, *this);
+ nextfilter.process(*this);
+ }
+
+
+ // get function - returns copy and keeps object const,
+ // thus is right val in assignment
+ unsigned int data() const {
+ return m_data;
+ }
+ // set function - returns reference and changes object,
+ // thus is left val in assignment
+ unsigned int & data() {
+ return m_data;
+ }
+
+ // more traditional set function, taking const reference
+ // or copy (here const ref for demo), returning ref to object
+ // can be chained with other similar functions!
+ Package & data(const unsigned int & data){
+ m_data = data;
+ return *this;
+ }
+
+ // get function - returns copy and keeps object const,
+ // thus is right val in assignment
+ Router router() const {
+ return m_router;
+ }
+ // set function - returns reference and changes object,
+ // thus is left val in assignment
+ Router & router() {
+ return m_router;
+ }
+ // more traditional set function, taking const reference
+ // or copy (here const ref for demo), returning ref to object
+ // can be chained with other similar functions!
+ Package & router(const Router & router){
+ m_router = router;
+ return *this;
+ }
+
+ private:
+ unsigned int m_data;
+ Router m_router;
+ };
+
+
+ class Package_Exception : public std::runtime_error {
+ public:
+ Package_Exception(const std::string message)
+ : std::runtime_error("Package_Exception: " + message){
+ };
+ };
+
+
+
+
+}
+
+#endif
--- /dev/null
+
+#include <iostream>
+#include "p3_filter.h"
+
+
+
+int main(int argc, char **argv) {
+
+ // test filter set/get/exception
+ try {
+ std::cout << "\nTRY" << "\n";
+ p3::Filter filter;
+ unsigned int tmp;
+
+ filter.max_front_workers(1).max_front_workers(2);
+ tmp = filter.max_front_workers();
+ std::cout << "workers: " << tmp << "\n";
+
+ filter.max_front_workers() = 3;
+ tmp = filter.max_front_workers();
+ std::cout << "workers: " << tmp << "\n";
+
+ throw p3::Filter_Exception("finished");
+ }
+ catch (std::exception &e) {
+ std::cout << e.what() << "\n";
+ }
+
+
+ try {
+ std::cout << "\nTRY" << "\n";
+
+ p3::Filter filter1;
+ p3::Filter filter2;
+
+ std::cout << "filter1 filter2" << "\n";
+
+ p3::Router router1;
+ router1.rule(filter1);
+ std::cout << "router1.rule(filter1)" << "\n";
+
+ p3::Router router2;
+ router2.rule(filter2);
+ std::cout << "router2.rule(filter2)" << "\n";
+
+ p3::Package pack_in;
+ pack_in.data(7).router(router1);
+ std::cout << "pack_in.data(7).router(router1)" << "\n";
+
+ pack_in.move();
+ std::cout << "pack_in.move()" << "\n";
+
+ pack_in.router(router2);
+ std::cout << "pack_in.router(router2)" << "\n";
+
+ pack_in.move();
+ std::cout << "pack_in.move()" << "\n";
+
+ throw p3::Router_Exception("finished");
+
+ }
+ catch (std::exception &e) {
+ std::cout << e.what() << "\n";
+ }
+
+
+
+}
+
--- /dev/null
+## $Id: usemarcon.m4,v 1.1 2005-10-06 09:37:25 marc Exp $
+AC_DEFUN([USEMARCON_INIT],
+[
+ AC_SUBST(USEMARCONLALIB)
+ AC_SUBST(USEMARCONINC)
+ usemarconconfig=NONE
+ usemarconpath=NONE
+ AC_ARG_WITH(usemarcon, [ --with-usemarcon=DIR usemarcon-config in DIR (example /home/usemarcon145)], [usemarconpath=$withval])
+
+ if test "x$usemarconpath" != "xNONE"; then
+ usemarconconfig=$usemarconpath/usemarcon-config
+ else
+ if test "x$srcdir" = "x"; then
+ usemarconsrcdir=.
+ else
+ usemarconsrcdir=$srcdir
+ fi
+ for i in ${usemarconsrcdir}/../usemarcon*; do
+ if test -d $i; then
+ if test -r $i/usemarcon-config; then
+ usemarconconfig=$i/usemarcon-config
+ fi
+ fi
+ done
+ if test "x$usemarconconfig" = "xNONE"; then
+ AC_PATH_PROG(usemarconconfig, usemarcon-config, NONE)
+ fi
+ fi
+
+ AC_MSG_CHECKING(for USEMARCON)
+ if $usemarconconfig --version >/dev/null 2>&1; then
+ USEMARCONLALIB=`$usemarconconfig --lalibs $1`
+ USEMARCONINC=`$usemarconconfig --cflags $1`
+ USEMARCONVERSION=`$usemarconconfig --version`
+ AC_MSG_RESULT($usemarconconfig)
+ AC_DEFINE(HAVE_USEMARCON)
+ else
+ AC_MSG_RESULT(Not found)
+ USEMARCONVERSION=NONE
+ fi
+])
+
--- /dev/null
+# Use this m4 function for autoconf if you use YAZ in your own
+# configure script.
+
+dnl ----- Setup Docbook documentation for YAZ
+AC_DEFUN([YAZ_DOC],
+[
+AC_SUBST(DTD_DIR)
+AC_ARG_WITH(docbook-dtd,[[ --with-docbook-dtd=DIR use docbookx.dtd in DIR]],
+[
+ if test -f "$withval/docbookx.dtd"; then
+ DTD_DIR=$withval
+ fi
+],[
+ AC_MSG_CHECKING(for docbookx.dtd)
+ DTD_DIR=""
+ for d in /usr/lib/sgml/dtd/docbook-xml \
+ /usr/share/sgml/docbook/dtd/4.2 \
+ /usr/share/sgml/docbook/dtd/xml/4.* \
+ /usr/share/sgml/docbook/xml-dtd-4.*
+ do
+ if test -f $d/docbookx.dtd; then
+ DTD_DIR=$d
+ fi
+ done
+ if test -z "$DTD_DIR"; then
+ AC_MSG_RESULT(Not found)
+ else
+ AC_MSG_RESULT($d)
+ fi
+])
+AC_SUBST(DSSSL_DIR)
+AC_ARG_WITH(docbook-dsssl,[[ --with-docbook-dsssl=DIR use Docbook DSSSL in DIR/{html,print}/docbook.dsl]],
+[
+ if test -f "$withval/html/docbook.dsl"; then
+ DSSSL_DIR=$withval
+ fi
+],[
+ AC_MSG_CHECKING(for docbook.dsl)
+ DSSSL_DIR=""
+ for d in /usr/share/sgml/docbook/stylesheet/dsssl/modular \
+ /usr/share/sgml/docbook/dsssl-stylesheets-1.* \
+ /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh
+ do
+ if test -f $d/html/docbook.dsl; then
+ AC_MSG_RESULT($d)
+ DSSSL_DIR=$d
+ break
+ fi
+ done
+ if test -z "$DSSSL_DIR"; then
+ AC_MSG_RESULT(Not found)
+ fi
+])
+AC_SUBST(XSL_DIR)
+AC_ARG_WITH(docbook-xsl,[[ --with-docbook-xsl=DIR use Docbook XSL in DIR/{htmlhelp,xhtml}]],
+[
+ if test -f "$withval/htmlhelp/htmlhelp.xsl"; then
+ XSL_DIR=$withval
+ fi
+],[
+ AC_MSG_CHECKING(for htmlhelp.xsl)
+ for d in /usr/share/sgml/docbook/stylesheet/xsl/nwalsh \
+ /usr/share/sgml/docbook/xsl-stylesheets-1.*
+ do
+ if test -f $d/htmlhelp/htmlhelp.xsl; then
+ AC_MSG_RESULT($d)
+ XSL_DIR=$d
+ break
+ fi
+ done
+ if test -z "$XSL_DIR"; then
+ AC_MSG_RESULT(Not found)
+ fi
+])
+])
+
+AC_DEFUN([YAZ_INIT],
+[
+ AC_SUBST(YAZLIB)
+ AC_SUBST(YAZLALIB)
+ AC_SUBST(YAZINC)
+ AC_SUBST(YAZVERSION)
+ yazconfig=NONE
+ yazpath=NONE
+ AC_ARG_WITH(yaz, [ --with-yaz=DIR use yaz-config in DIR (example /home/yaz-1.7)], [yazpath=$withval])
+ if test "x$yazpath" != "xNONE"; then
+ yazconfig=$yazpath/yaz-config
+ else
+ if test "x$srcdir" = "x"; then
+ yazsrcdir=.
+ else
+ yazsrcdir=$srcdir
+ fi
+ for i in ${yazsrcdir}/../../yaz ${yazsrcdir}/../yaz* ${yazsrcdir}/../yaz; do
+ if test -d $i; then
+ if test -r $i/yaz-config; then
+ yazconfig=$i/yaz-config
+ fi
+ fi
+ done
+ if test "x$yazconfig" = "xNONE"; then
+ AC_PATH_PROG(yazconfig, yaz-config, NONE)
+ fi
+ fi
+ AC_MSG_CHECKING(for YAZ)
+ if $yazconfig --version >/dev/null 2>&1; then
+ YAZLIB=`$yazconfig --libs $1`
+ # if this is empty, it's a simple version YAZ 1.6 script
+ # so we have to source it instead...
+ if test "X$YAZLIB" = "X"; then
+ . $yazconfig
+ else
+ YAZLALIB=`$yazconfig --lalibs $1`
+ YAZINC=`$yazconfig --cflags $1`
+ YAZVERSION=`$yazconfig --version`
+ fi
+ AC_MSG_RESULT([$yazconfig])
+ else
+ AC_MSG_RESULT(Not found)
+ YAZVERSION=NONE
+ fi
+ if test "X$YAZVERSION" != "XNONE"; then
+ AC_MSG_CHECKING([for YAZ version])
+ AC_MSG_RESULT([$YAZVERSION])
+ if test "$2"; then
+ have_yaz_version=`echo "$YAZVERSION" | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`
+ req_yaz_version=`echo "$2" | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`
+ if test "$have_yaz_version" -lt "$req_yaz_version"; then
+ AC_MSG_ERROR([$YAZVERSION. Requires $2 or later])
+ fi
+ if test "$req_yaz_version" -gt "2000028"; then
+ YAZINC="$YAZINC -DYAZ_USE_NEW_LOG=1"
+ fi
+ fi
+ fi
+])
+
--- /dev/null
+AC_DEFUN([YAZPP_INIT],
+[
+ AC_SUBST(YAZPPLIB)
+ AC_SUBST(YAZPPLALIB)
+ AC_SUBST(YAZPPINC)
+ AC_SUBST(YAZPPVERSION)
+ yazppconfig=NONE
+ yazpppath=NONE
+ AC_ARG_WITH(yazpp, [ --with-yazpp=DIR yaz++-config in DIR (example /home/yaz++-0.8)], [yazpppath=$withval])
+ if test "x$yazpppath" != "xNONE"; then
+ yazppconfig=$yazpppath/yaz++-config
+ else
+ if test "x$srcdir" = "x"; then
+ yazppsrcdir=.
+ else
+ yazppsrcdir=$srcdir
+ fi
+ for i in ${yazppsrcdir}/../../yaz++ ${yazppsrcdir}/../yaz++-* ${yazppsrcdir}/../yaz++; do
+ if test -d $i; then
+ if test -r $i/yaz++-config; then
+ yazppconfig=$i/yaz++-config
+ fi
+ fi
+ done
+ if test "x$yazppconfig" = "xNONE"; then
+ AC_PATH_PROG(yazppconfig, yaz++-config, NONE)
+ fi
+ fi
+ AC_MSG_CHECKING(for YAZ++)
+ if $yazppconfig --version >/dev/null 2>&1; then
+ YAZPPLIB=`$yazppconfig --libs $1`
+ YAZPPLALIB=`$yazppconfig --lalibs $1`
+ YAZPPINC=`$yazppconfig --cflags $1`
+ YAZPPVERSION=`$yazppconfig --version`
+ AC_MSG_RESULT($yazppconfig)
+ else
+ AC_MSG_RESULT(Not found)
+ YAZVERSION=NONE
+ fi
+ if test "X$YAZPPVERSION" != "XNONE"; then
+ AC_MSG_CHECKING([for YAZ++ version])
+ AC_MSG_RESULT([$YAZPPVERSION])
+ if test "$2"; then
+ have_yaz_version=`echo "$YAZPPVERSION" | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`
+ req_yaz_version=`echo "$2" | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`
+ if test "$have_yaz_version" -lt "$req_yaz_version"; then
+ AC_MSG_ERROR([$YAZPPVERSION. Requires $2 or later])
+ fi
+ fi
+ fi
+])
+