summaryrefslogtreecommitdiffstats
path: root/modules/core
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:01:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:01:30 +0000
commit6beeb1b708550be0d4a53b272283e17e5e35fe17 (patch)
tree1ce8673d4aaa948e5554000101f46536a1e4cc29 /modules/core
parentInitial commit. (diff)
downloadapache2-6beeb1b708550be0d4a53b272283e17e5e35fe17.tar.xz
apache2-6beeb1b708550be0d4a53b272283e17e5e35fe17.zip
Adding upstream version 2.4.57.upstream/2.4.57upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/core')
-rw-r--r--modules/core/Makefile.in3
-rw-r--r--modules/core/NWGNUmakefile257
-rw-r--r--modules/core/config.m460
-rw-r--r--modules/core/mod_macro.c950
-rw-r--r--modules/core/mod_macro.dep45
-rw-r--r--modules/core/mod_macro.dsp111
-rw-r--r--modules/core/mod_macro.mak353
-rw-r--r--modules/core/mod_so.c442
-rw-r--r--modules/core/mod_so.h38
-rw-r--r--modules/core/mod_watchdog.c718
-rw-r--r--modules/core/mod_watchdog.dep59
-rw-r--r--modules/core/mod_watchdog.dsp115
-rw-r--r--modules/core/mod_watchdog.h213
-rw-r--r--modules/core/mod_watchdog.mak353
-rw-r--r--modules/core/test/Makefile67
-rw-r--r--modules/core/test/conf/inc63_1.conf5
-rw-r--r--modules/core/test/conf/inc63_2.conf3
-rw-r--r--modules/core/test/conf/test01.conf3
-rw-r--r--modules/core/test/conf/test02.conf3
-rw-r--r--modules/core/test/conf/test03.conf5
-rw-r--r--modules/core/test/conf/test04.conf5
-rw-r--r--modules/core/test/conf/test05.conf5
-rw-r--r--modules/core/test/conf/test06.conf6
-rw-r--r--modules/core/test/conf/test07.conf3
-rw-r--r--modules/core/test/conf/test08.conf3
-rw-r--r--modules/core/test/conf/test09.conf6
-rw-r--r--modules/core/test/conf/test10.conf10
-rw-r--r--modules/core/test/conf/test11.conf15
-rw-r--r--modules/core/test/conf/test12.conf12
-rw-r--r--modules/core/test/conf/test13.conf18
-rw-r--r--modules/core/test/conf/test14.conf23
-rw-r--r--modules/core/test/conf/test15.conf9
-rw-r--r--modules/core/test/conf/test16.conf11
-rw-r--r--modules/core/test/conf/test17.conf10
-rw-r--r--modules/core/test/conf/test18.conf10
-rw-r--r--modules/core/test/conf/test19.conf26
-rw-r--r--modules/core/test/conf/test20.conf11
-rw-r--r--modules/core/test/conf/test21.conf11
-rw-r--r--modules/core/test/conf/test22.conf11
-rw-r--r--modules/core/test/conf/test23.conf15
-rw-r--r--modules/core/test/conf/test24.conf23
-rw-r--r--modules/core/test/conf/test25.conf27
-rw-r--r--modules/core/test/conf/test26.conf19
-rw-r--r--modules/core/test/conf/test27.conf22
-rw-r--r--modules/core/test/conf/test28.conf13
-rw-r--r--modules/core/test/conf/test29.conf10
-rw-r--r--modules/core/test/conf/test30.conf12
-rw-r--r--modules/core/test/conf/test31.conf16
-rw-r--r--modules/core/test/conf/test32.conf7
-rw-r--r--modules/core/test/conf/test33.conf3
-rw-r--r--modules/core/test/conf/test34.conf14
-rw-r--r--modules/core/test/conf/test35.conf10
-rw-r--r--modules/core/test/conf/test36.conf12
-rw-r--r--modules/core/test/conf/test37.conf7
-rw-r--r--modules/core/test/conf/test38.conf10
-rw-r--r--modules/core/test/conf/test39.conf23
-rw-r--r--modules/core/test/conf/test40.conf33
-rw-r--r--modules/core/test/conf/test41.conf20
-rw-r--r--modules/core/test/conf/test42.conf13
-rw-r--r--modules/core/test/conf/test43.conf29
-rw-r--r--modules/core/test/conf/test44.conf19
-rw-r--r--modules/core/test/conf/test45.conf7
-rw-r--r--modules/core/test/conf/test46.conf11
-rw-r--r--modules/core/test/conf/test47.conf15
-rw-r--r--modules/core/test/conf/test48.conf23
-rw-r--r--modules/core/test/conf/test49.conf2
-rw-r--r--modules/core/test/conf/test50.conf5
-rw-r--r--modules/core/test/conf/test51.conf9
-rw-r--r--modules/core/test/conf/test52.conf8
-rw-r--r--modules/core/test/conf/test53.conf2
-rw-r--r--modules/core/test/conf/test54.conf6
-rw-r--r--modules/core/test/conf/test55.conf11
-rw-r--r--modules/core/test/conf/test56.conf18
-rw-r--r--modules/core/test/conf/test57.conf4
-rw-r--r--modules/core/test/conf/test58.conf4
-rw-r--r--modules/core/test/conf/test59.conf4
-rw-r--r--modules/core/test/conf/test60.conf17
-rw-r--r--modules/core/test/conf/test61.conf18
-rw-r--r--modules/core/test/conf/test62.conf25
-rw-r--r--modules/core/test/conf/test63.conf9
-rw-r--r--modules/core/test/conf/test64.conf5
-rw-r--r--modules/core/test/conf/test65.conf11
-rw-r--r--modules/core/test/conf/test66.conf7
-rw-r--r--modules/core/test/conf/test67.conf1
-rw-r--r--modules/core/test/conf/test68.conf5
-rw-r--r--modules/core/test/conf/test69.conf14
-rw-r--r--modules/core/test/ref/test01.out3
-rw-r--r--modules/core/test/ref/test02.out3
-rw-r--r--modules/core/test/ref/test03.out3
-rw-r--r--modules/core/test/ref/test04.out3
-rw-r--r--modules/core/test/ref/test05.out3
-rw-r--r--modules/core/test/ref/test06.out3
-rw-r--r--modules/core/test/ref/test07.out3
-rw-r--r--modules/core/test/ref/test08.out3
-rw-r--r--modules/core/test/ref/test09.out3
-rw-r--r--modules/core/test/ref/test10.out3
-rw-r--r--modules/core/test/ref/test11.out6
-rw-r--r--modules/core/test/ref/test12.out7
-rw-r--r--modules/core/test/ref/test13.out8
-rw-r--r--modules/core/test/ref/test14.out14
-rw-r--r--modules/core/test/ref/test15.out6
-rw-r--r--modules/core/test/ref/test16.out5
-rw-r--r--modules/core/test/ref/test17.out7
-rw-r--r--modules/core/test/ref/test18.out7
-rw-r--r--modules/core/test/ref/test19.out9
-rw-r--r--modules/core/test/ref/test20.out4
-rw-r--r--modules/core/test/ref/test21.out5
-rw-r--r--modules/core/test/ref/test22.out6
-rw-r--r--modules/core/test/ref/test23.out7
-rw-r--r--modules/core/test/ref/test24.out8
-rw-r--r--modules/core/test/ref/test25.out9
-rw-r--r--modules/core/test/ref/test26.out11
-rw-r--r--modules/core/test/ref/test27.out8
-rw-r--r--modules/core/test/ref/test28.out6
-rw-r--r--modules/core/test/ref/test29.out4
-rw-r--r--modules/core/test/ref/test30.out7
-rw-r--r--modules/core/test/ref/test31.out23
-rw-r--r--modules/core/test/ref/test32.out3
-rw-r--r--modules/core/test/ref/test33.out3
-rw-r--r--modules/core/test/ref/test34.out13
-rw-r--r--modules/core/test/ref/test35.out13
-rw-r--r--modules/core/test/ref/test36.out20
-rw-r--r--modules/core/test/ref/test37.out3
-rw-r--r--modules/core/test/ref/test38.out6
-rw-r--r--modules/core/test/ref/test39.out7
-rw-r--r--modules/core/test/ref/test40.out18
-rw-r--r--modules/core/test/ref/test41.out9
-rw-r--r--modules/core/test/ref/test42.out15
-rw-r--r--modules/core/test/ref/test43.out8
-rw-r--r--modules/core/test/ref/test44.out5
-rw-r--r--modules/core/test/ref/test45.out19
-rw-r--r--modules/core/test/ref/test46.out9
-rw-r--r--modules/core/test/ref/test47.out8
-rw-r--r--modules/core/test/ref/test48.out20
-rw-r--r--modules/core/test/ref/test49.out3
-rw-r--r--modules/core/test/ref/test50.out3
-rw-r--r--modules/core/test/ref/test51.out3
-rw-r--r--modules/core/test/ref/test52.out6
-rw-r--r--modules/core/test/ref/test53.out3
-rw-r--r--modules/core/test/ref/test54.out6
-rw-r--r--modules/core/test/ref/test55.out8
-rw-r--r--modules/core/test/ref/test56.out12
-rw-r--r--modules/core/test/ref/test57.out3
-rw-r--r--modules/core/test/ref/test58.out3
-rw-r--r--modules/core/test/ref/test59.out3
-rw-r--r--modules/core/test/ref/test60.out15
-rw-r--r--modules/core/test/ref/test61.out9
-rw-r--r--modules/core/test/ref/test62.out15
-rw-r--r--modules/core/test/ref/test63.out10
-rw-r--r--modules/core/test/ref/test64.out7
-rw-r--r--modules/core/test/ref/test65.out7
-rw-r--r--modules/core/test/ref/test66.out7
-rw-r--r--modules/core/test/ref/test67.out5
-rw-r--r--modules/core/test/ref/test68.out6
-rw-r--r--modules/core/test/ref/test69.out10
155 files changed, 5126 insertions, 0 deletions
diff --git a/modules/core/Makefile.in b/modules/core/Makefile.in
new file mode 100644
index 0000000..167b343
--- /dev/null
+++ b/modules/core/Makefile.in
@@ -0,0 +1,3 @@
+
+include $(top_srcdir)/build/special.mk
+
diff --git a/modules/core/NWGNUmakefile b/modules/core/NWGNUmakefile
new file mode 100644
index 0000000..a4dd8d3
--- /dev/null
+++ b/modules/core/NWGNUmakefile
@@ -0,0 +1,257 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)/build/NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APRUTIL)/include \
+ $(SRC)/include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = macro
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache $(VERSION_STR) Macro Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Echo Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/macro.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_macro.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(PRELUDE) \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ aprlib \
+ libc \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @aprlib.imp \
+ @httpd.imp \
+ @libc.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ macro_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ $(call COPY,$(OBJDIR)/*.nlm, $(INSTALLBASE)/modules/)
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APBUILD)/NWGNUtail.inc
+
+
diff --git a/modules/core/config.m4 b/modules/core/config.m4
new file mode 100644
index 0000000..94fb4a1
--- /dev/null
+++ b/modules/core/config.m4
@@ -0,0 +1,60 @@
+dnl modules enabled in this directory by default
+
+dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
+
+APACHE_MODPATH_INIT(core)
+
+APR_CHECK_APR_DEFINE(APR_HAS_DSO)
+
+case "x$enable_so" in
+ "xyes")
+ if test $ac_cv_define_APR_HAS_DSO = "no"; then
+ AC_MSG_ERROR([mod_so has been requested but cannot be built on your system])
+ fi
+ ;;
+ "xshared")
+ AC_MSG_ERROR([mod_so can not be built as a shared DSO])
+ ;;
+ "xno")
+ ;;
+ "x")
+ enable_so=$ac_cv_define_APR_HAS_DSO
+ ;;
+esac
+
+dnl mod_so can only be built statically. Override the default here.
+if test "x$enable_so" = "xyes"; then
+ enable_so="static"
+fi
+
+if test "x$enable_so" = "xstatic"; then
+ APR_ADDTO(HTTPD_LDFLAGS, [-export-dynamic])
+ INSTALL_DSO=yes
+else
+ INSTALL_DSO=no
+fi
+APACHE_SUBST(INSTALL_DSO)
+
+if test "$sharedobjs" = "yes"; then
+ if test $ac_cv_define_APR_HAS_DSO = "no"; then
+ AC_MSG_ERROR([shared objects have been requested but cannot be built since mod_so cannot be built])
+ elif test $enable_so = "no"; then
+ AC_MSG_ERROR([shared objects have been requested but cannot be built since mod_so was disabled])
+ fi
+fi
+
+APACHE_MODULE(so, DSO capability. This module will be automatically enabled unless you build all modules statically., , , $enable_so)
+
+APACHE_MODULE(watchdog, Watchdog module, , , most, [
+ APR_CHECK_APR_DEFINE(APR_HAS_THREADS)
+ if test $ac_cv_define_APR_HAS_THREADS = "no"; then
+ AC_MSG_WARN([mod_watchdog requires apr to be built with --enable-threads])
+ enable_watchdog=no
+ fi
+])
+
+APACHE_MODULE(macro, Define and use macros in configuration files, , , most)
+
+APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])
+
+APACHE_MODPATH_FINISH
diff --git a/modules/core/mod_macro.c b/modules/core/mod_macro.c
new file mode 100644
index 0000000..04af43b
--- /dev/null
+++ b/modules/core/mod_macro.c
@@ -0,0 +1,950 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+
+/************************************************ COMPILE TIME DEBUG CONTROL */
+/*
+ debug:
+ #define MOD_MACRO_DEBUG 1
+
+ gdb:
+ run -f ./test/conf/test??.conf
+*/
+/* #define MOD_MACRO_DEBUG 1 */
+#undef MOD_MACRO_DEBUG
+
+#if defined(debug)
+#undef debug
+#endif /* debug */
+
+#if defined(MOD_MACRO_DEBUG)
+#define debug(stmt) stmt
+#else
+#define debug(stmt)
+#endif /* MOD_MACRO_DEBUG */
+
+/******************************************************** MODULE DECLARATION */
+
+module AP_MODULE_DECLARE_DATA macro_module;
+
+/********************************************************** MACRO MANAGEMENT */
+
+/*
+ this is a macro: name, arguments, contents, location.
+*/
+typedef struct
+{
+ char *name; /* lower case name of the macro */
+ apr_array_header_t *arguments; /* of char*, macro parameter names */
+ apr_array_header_t *contents; /* of char*, macro body */
+ char *location; /* of macro definition, for error messages */
+} ap_macro_t;
+
+/* configuration tokens.
+ */
+#define BEGIN_MACRO "<Macro"
+#define END_MACRO "</Macro>"
+#define USE_MACRO "Use"
+#define UNDEF_MACRO "UndefMacro"
+
+/*
+ Macros are kept globally...
+ They are not per-server or per-directory entities.
+
+ note: they are in a temp_pool, and there is a lazy initialization.
+ ap_macros is reset to NULL in pre_config hook to not depend
+ on static vs dynamic configuration.
+
+ hash type: (char *) name -> (ap_macro_t *) macro
+*/
+static apr_hash_t *ap_macros = NULL;
+
+/*************************************************************** PARSE UTILS */
+
+#define empty_string_p(p) (!(p) || *(p) == '\0')
+#define trim(line) while (*(line) == ' ' || *(line) == '\t') (line)++
+
+/*
+ return configuration-parsed arguments from line as an array.
+ the line is expected not to contain any '\n'?
+*/
+static apr_array_header_t *get_arguments(apr_pool_t * pool, const char *line)
+{
+ apr_array_header_t *args = apr_array_make(pool, 1, sizeof(char *));
+
+ trim(line);
+ while (*line) {
+ char *arg = ap_getword_conf(pool, &line);
+ char **new = apr_array_push(args);
+ *new = arg;
+ trim(line);
+ }
+
+ return args;
+}
+
+/*
+ warn if anything non blank appears, but ignore comments...
+*/
+static void warn_if_non_blank(const char * what,
+ char * ptr,
+ ap_configfile_t * cfg)
+{
+ char * p;
+ for (p=ptr; *p; p++) {
+ if (*p == '#')
+ break;
+ if (*p != ' ' && *p != '\t') {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02989)
+ "%s on line %d of %s: %s",
+ what, cfg->line_number, cfg->name, ptr);
+ break;
+ }
+ }
+}
+
+/*
+ get read lines as an array till end_token.
+ counts nesting for begin_token/end_token.
+ it assumes a line-per-line configuration (thru getline).
+ this function could be exported.
+ begin_token may be NULL.
+*/
+static char *get_lines_till_end_token(apr_pool_t * pool,
+ ap_configfile_t * config_file,
+ const char *end_token,
+ const char *begin_token,
+ const char *where,
+ apr_array_header_t ** plines)
+{
+ apr_array_header_t *lines = apr_array_make(pool, 1, sizeof(char *));
+ char line[MAX_STRING_LEN]; /* sorry, but this is expected by getline:-( */
+ int macro_nesting = 1, any_nesting = 1;
+ int line_number_start = config_file->line_number;
+
+ while (!ap_cfg_getline(line, MAX_STRING_LEN, config_file)) {
+ char *ptr = line;
+ char *first, **new;
+ /* skip comments */
+ if (*line == '#')
+ continue;
+ first = ap_getword_conf_nc(pool, &ptr);
+ if (first) {
+ /* detect nesting... */
+ if (!strncmp(first, "</", 2)) {
+ any_nesting--;
+ if (any_nesting < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING,
+ 0, NULL, APLOGNO(02793)
+ "bad (negative) nesting on line %d of %s",
+ config_file->line_number - line_number_start,
+ where);
+ }
+ }
+ else if (!strncmp(first, "<", 1)) {
+ any_nesting++;
+ }
+
+ if (!strcasecmp(first, end_token)) {
+ /* check for proper closing */
+ char * endp = (char *) ap_strrchr_c(line, '>');
+
+ /* this cannot happen if end_token contains '>' */
+ if (endp == NULL) {
+ return "end directive missing closing '>'";
+ }
+
+ warn_if_non_blank(
+ APLOGNO(02794) "non blank chars found after directive closing",
+ endp+1, config_file);
+
+ macro_nesting--;
+ if (!macro_nesting) {
+ if (any_nesting) {
+ ap_log_error(APLOG_MARK,
+ APLOG_WARNING, 0, NULL, APLOGNO(02795)
+ "bad cumulated nesting (%+d) in %s",
+ any_nesting, where);
+ }
+ *plines = lines;
+ return NULL;
+ }
+ }
+ else if (begin_token && !strcasecmp(first, begin_token)) {
+ macro_nesting++;
+ }
+ }
+ new = apr_array_push(lines);
+ *new = apr_psprintf(pool, "%s" APR_EOL_STR, line); /* put EOL back? */
+ }
+
+ return apr_psprintf(pool, "expected token not found: %s", end_token);
+}
+
+/* the @* arguments are double-quote escaped when substituted */
+#define ESCAPE_ARG '@'
+
+/* other $* and %* arguments are simply replaced without escaping */
+#define ARG_PREFIX "$%@"
+
+/*
+ characters allowed in an argument?
+ not used yet, because that would trigger some backward compatibility.
+*/
+#define ARG_CONTENT \
+ "abcdefghijklmnopqrstuvwxyz" \
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ "0123456789_" ARG_PREFIX
+
+/*
+ returns whether it looks like an argument, i.e. prefixed by ARG_PREFIX.
+*/
+static int looks_like_an_argument(const char *word)
+{
+ return ap_strchr(ARG_PREFIX, *word) != 0;
+}
+
+/*
+ generates an error on macro with two arguments of the same name.
+ generates an error if a macro argument name is empty.
+ generates a warning if arguments name prefixes conflict.
+ generates a warning if the first char of an argument is not in ARG_PREFIX
+*/
+static const char *check_macro_arguments(apr_pool_t * pool,
+ const ap_macro_t * macro)
+{
+ char **tab = (char **) macro->arguments->elts;
+ int nelts = macro->arguments->nelts;
+ int i;
+
+ for (i = 0; i < nelts; i++) {
+ size_t ltabi = strlen(tab[i]);
+ int j;
+
+ if (ltabi == 0) {
+ return apr_psprintf(pool,
+ "macro '%s' (%s): empty argument #%d name",
+ macro->name, macro->location, i + 1);
+ }
+ else if (!looks_like_an_argument(tab[i])) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02796)
+ "macro '%s' (%s) "
+ "argument name '%s' (#%d) without expected prefix, "
+ "better prefix argument names with one of '%s'.",
+ macro->name, macro->location,
+ tab[i], i + 1, ARG_PREFIX);
+ }
+
+ for (j = i + 1; j < nelts; j++) {
+ size_t ltabj = strlen(tab[j]);
+
+ /* must not use the same argument name twice */
+ if (!strcmp(tab[i], tab[j])) {
+ return apr_psprintf(pool,
+ "argument name conflict in macro '%s' (%s): "
+ "argument '%s': #%d and #%d, "
+ "change argument names!",
+ macro->name, macro->location,
+ tab[i], i + 1, j + 1);
+ }
+
+ /* warn about common prefix, but only if non empty names */
+ if (ltabi && ltabj &&
+ !strncmp(tab[i], tab[j], ltabi < ltabj ? ltabi : ltabj)) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING,
+ 0, NULL, APLOGNO(02797)
+ "macro '%s' (%s): "
+ "argument name prefix conflict (%s #%d and %s #%d), "
+ "be careful about your macro definition!",
+ macro->name, macro->location,
+ tab[i], i + 1, tab[j], j + 1);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ warn about empty strings in array. could be legitimate.
+*/
+static void check_macro_use_arguments(const char *where,
+ const apr_array_header_t * array)
+{
+ char **tab = (char **) array->elts;
+ int i;
+ for (i = 0; i < array->nelts; i++) {
+ if (empty_string_p(tab[i])) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02798)
+ "%s: empty argument #%d", where, i + 1);
+ }
+ }
+}
+
+/******************************************************** SUBSTITUTION UTILS */
+
+/* could be switched to '\'' */
+#define DELIM '"'
+#define ESCAPE '\\'
+
+/*
+ returns the number of needed escapes for the string
+*/
+static int number_of_escapes(const char delim, const char *str)
+{
+ int nesc = 0;
+ const char *s = str;
+ while (*s) {
+ if (*s == ESCAPE || *s == delim)
+ nesc++;
+ s++;
+ }
+ debug(fprintf(stderr, "escapes: %d ---%s---\n", nesc, str));
+ return nesc;
+}
+
+/*
+ replace name by replacement at the beginning of buf of bufsize.
+ returns an error message or NULL.
+ C is not really a nice language for processing strings.
+*/
+static char *substitute(char *buf,
+ const int bufsize,
+ const char *name,
+ const char *replacement, const int do_esc)
+{
+ int lbuf = strlen(buf),
+ lname = strlen(name),
+ lrepl = strlen(replacement),
+ lsubs = lrepl +
+ (do_esc ? (2 + number_of_escapes(DELIM, replacement)) : 0),
+ shift = lsubs - lname, size = lbuf + shift, i, j;
+
+ /* buf must starts with name */
+ ap_assert(!strncmp(buf, name, lname));
+
+ /* hmmm??? */
+ if (!strcmp(name, replacement))
+ return NULL;
+
+ debug(fprintf(stderr,
+ "substitute(%s,%s,%s,%d,sh=%d,lbuf=%d,lrepl=%d,lsubs=%d)\n",
+ buf, name, replacement, do_esc, shift, lbuf, lrepl, lsubs));
+
+ if (size >= bufsize) {
+ /* could/should I reallocate? */
+ return "cannot substitute, buffer size too small";
+ }
+
+ /* cannot use strcpy as strings may overlap */
+ if (shift != 0) {
+ memmove(buf + lname + shift, buf + lname, lbuf - lname + 1);
+ }
+
+ /* insert the replacement with escapes */
+ j = 0;
+ if (do_esc)
+ buf[j++] = DELIM;
+ for (i = 0; i < lrepl; i++, j++) {
+ if (do_esc && (replacement[i] == DELIM || replacement[i] == ESCAPE))
+ buf[j++] = ESCAPE;
+ buf[j] = replacement[i];
+ }
+ if (do_esc)
+ buf[j++] = DELIM;
+
+ return NULL;
+}
+
+/*
+ find first occurrence of args in buf.
+ in case of conflict, the LONGEST argument is kept. (could be the FIRST?).
+ returns the pointer and the whichone found, or NULL.
+*/
+static char *next_substitution(const char *buf,
+ const apr_array_header_t * args, int *whichone)
+{
+ char *chosen = NULL, **tab = (char **) args->elts;
+ size_t lchosen = 0;
+ int i;
+
+ for (i = 0; i < args->nelts; i++) {
+ char *found = ap_strstr((char *) buf, tab[i]);
+ size_t lfound = strlen(tab[i]);
+ if (found && (!chosen || found < chosen ||
+ (found == chosen && lchosen < lfound))) {
+ chosen = found;
+ lchosen = lfound;
+ *whichone = i;
+ }
+ }
+
+ return chosen;
+}
+
+/*
+ substitute macro arguments by replacements in buf of bufsize.
+ returns an error message or NULL.
+ if used is defined, returns the used macro arguments.
+*/
+static const char *substitute_macro_args(
+ char *buf,
+ int bufsize,
+ const ap_macro_t * macro,
+ const apr_array_header_t * replacements,
+ apr_array_header_t * used)
+{
+ char *ptr = buf,
+ **atab = (char **) macro->arguments->elts,
+ **rtab = (char **) replacements->elts;
+ int whichone = -1;
+
+ if (used) {
+ ap_assert(used->nalloc >= replacements->nelts);
+ }
+ debug(fprintf(stderr, "1# %s", buf));
+
+ while ((ptr = next_substitution(ptr, macro->arguments, &whichone))) {
+ const char *errmsg = substitute(ptr, buf - ptr + bufsize,
+ atab[whichone], rtab[whichone],
+ atab[whichone][0] == ESCAPE_ARG);
+ if (errmsg) {
+ return errmsg;
+ }
+ ptr += strlen(rtab[whichone]);
+ if (used) {
+ used->elts[whichone] = 1;
+ }
+ }
+ debug(fprintf(stderr, "2# %s", buf));
+
+ return NULL;
+}
+
+/*
+ perform substitutions in a macro contents and
+ return the result as a newly allocated array, if result is defined.
+ may also return an error message.
+ passes used down to substitute_macro_args.
+*/
+static const char *process_content(apr_pool_t * pool,
+ const ap_macro_t * macro,
+ const apr_array_header_t * replacements,
+ apr_array_header_t * used,
+ apr_array_header_t ** result)
+{
+ apr_array_header_t *contents = macro->contents;
+ char line[MAX_STRING_LEN];
+ int i;
+
+ if (result) {
+ *result = apr_array_make(pool, contents->nelts, sizeof(char *));
+ }
+
+ /* for each line of the macro body */
+ for (i = 0; i < contents->nelts; i++) {
+ const char *errmsg;
+ /* copy the line and substitute macro parameters */
+ strncpy(line, ((char **) contents->elts)[i], MAX_STRING_LEN - 1);
+ errmsg = substitute_macro_args(line, MAX_STRING_LEN,
+ macro, replacements, used);
+ if (errmsg) {
+ return apr_psprintf(pool,
+ "while processing line %d of macro '%s' (%s) %s",
+ i + 1, macro->name, macro->location, errmsg);
+ }
+ /* append substituted line to result array */
+ if (result) {
+ char **new = apr_array_push(*result);
+ *new = apr_pstrdup(pool, line);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ warn if some macro arguments are not used.
+*/
+static const char *check_macro_contents(apr_pool_t * pool,
+ const ap_macro_t * macro)
+{
+ int nelts = macro->arguments->nelts;
+ char **names = (char **) macro->arguments->elts;
+ apr_array_header_t *used;
+ int i;
+ const char *errmsg;
+
+ if (macro->contents->nelts == 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02799)
+ "macro '%s' (%s): empty contents!",
+ macro->name, macro->location);
+ return NULL; /* no need to further warnings... */
+ }
+
+ used = apr_array_make(pool, nelts, sizeof(char));
+
+ for (i = 0; i < nelts; i++) {
+ used->elts[i] = 0;
+ }
+
+ errmsg = process_content(pool, macro, macro->arguments, used, NULL);
+
+ if (errmsg) {
+ return errmsg;
+ }
+
+ for (i = 0; i < nelts; i++) {
+ if (!used->elts[i]) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02800)
+ "macro '%s' (%s): argument '%s' (#%d) never used",
+ macro->name, macro->location, names[i], i + 1);
+ }
+ }
+
+ return NULL;
+}
+
+
+/************************************************** MACRO PSEUDO CONFIG FILE */
+
+/*
+ The expanded content of the macro is to be parsed as a ap_configfile_t.
+ This is used to have some kind of old fashionned C object oriented inherited
+ data structure for configs.
+
+ The following struct stores the contents.
+
+ This structure holds pointers (next, upper) to the current "file" which was
+ being processed and is interrupted by the macro expansion. At the end
+ of processing the macro, the initial data structure will be put back
+ in place (see function next_one) and the reading will go on from there.
+
+ If macros are used within macros, there may be a cascade of such temporary
+ arrays used to insert the expanded macro contents before resuming the real
+ file processing.
+
+ There is some hopus-pocus to deal with line_number when transiting from
+ one config to the other.
+*/
+typedef struct
+{
+ int index; /* current element */
+ int char_index; /* current char in element */
+ int length; /* cached length of the current line */
+ apr_array_header_t *contents; /* array of char * */
+ ap_configfile_t *next; /* next config once this one is processed */
+ ap_configfile_t **upper; /* hack: where to update it if needed */
+} array_contents_t;
+
+/*
+ Get next config if any.
+ this may be called several times if there are continuations.
+*/
+static int next_one(array_contents_t * ml)
+{
+ if (ml->next) {
+ ap_assert(ml->upper);
+ *(ml->upper) = ml->next;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ returns next char if possible
+ this may involve switching to enclosing config.
+*/
+static apr_status_t array_getch(char *ch, void *param)
+{
+ array_contents_t *ml = (array_contents_t *) param;
+ char **tab = (char **) ml->contents->elts;
+
+ while (ml->char_index >= ml->length) {
+ if (ml->index >= ml->contents->nelts) {
+ /* maybe update */
+ if (ml->next && ml->next->getch && next_one(ml)) {
+ apr_status_t rc = ml->next->getch(ch, ml->next->param);
+ if (*ch==LF)
+ ml->next->line_number++;
+ return rc;
+ }
+ return APR_EOF;
+ }
+ ml->index++;
+ ml->char_index = 0;
+ ml->length = ml->index >= ml->contents->nelts ?
+ 0 : strlen(tab[ml->index]);
+ }
+
+ *ch = tab[ml->index][ml->char_index++];
+ return APR_SUCCESS;
+}
+
+/*
+ returns a buf a la fgets.
+ no more than a line at a time, otherwise the parsing is too much ahead...
+ NULL at EOF.
+*/
+static apr_status_t array_getstr(void *buf, size_t bufsize, void *param)
+{
+ array_contents_t *ml = (array_contents_t *) param;
+ char *buffer = (char *) buf;
+ char next = '\0';
+ size_t i = 0;
+ apr_status_t rc = APR_SUCCESS;
+
+ /* read chars from stream, stop on newline */
+ while (i < bufsize - 1 && next != LF &&
+ ((rc = array_getch(&next, param)) == APR_SUCCESS)) {
+ buffer[i++] = next;
+ }
+
+ if (rc == APR_EOF) {
+ /* maybe update to next, possibly a recursion */
+ if (next_one(ml)) {
+ ap_assert(ml->next->getstr);
+ /* keep next line count in sync! the caller will update
+ the current line_number, we need to forward to the next */
+ ml->next->line_number++;
+ return ml->next->getstr(buf, bufsize, ml->next->param);
+ }
+ /* else that is really all we can do */
+ return APR_EOF;
+ }
+
+ buffer[i] = '\0';
+
+ return APR_SUCCESS;
+}
+
+/*
+ close the array stream?
+*/
+static apr_status_t array_close(void *param)
+{
+ array_contents_t *ml = (array_contents_t *) param;
+ /* move index at end of stream... */
+ ml->index = ml->contents->nelts;
+ ml->char_index = ml->length;
+ return APR_SUCCESS;
+}
+
+/*
+ create an array config stream insertion "object".
+ could be exported.
+*/
+static ap_configfile_t *make_array_config(apr_pool_t * pool,
+ apr_array_header_t * contents,
+ const char *where,
+ ap_configfile_t * cfg,
+ ap_configfile_t ** upper)
+{
+ array_contents_t *ls =
+ (array_contents_t *) apr_palloc(pool, sizeof(array_contents_t));
+ ap_assert(ls!=NULL);
+
+ ls->index = 0;
+ ls->char_index = 0;
+ ls->contents = contents;
+ ls->length = ls->contents->nelts < 1 ?
+ 0 : strlen(((char **) ls->contents->elts)[0]);
+ ls->next = cfg;
+ ls->upper = upper;
+
+ return ap_pcfg_open_custom(pool, where, (void *) ls,
+ array_getch, array_getstr, array_close);
+}
+
+
+/********************************************************** KEYWORD HANDLING */
+
+/*
+ handles: <Macro macroname arg1 arg2 ...> any trash there is ignored...
+*/
+static const char *macro_section(cmd_parms * cmd,
+ void *dummy, const char *arg)
+{
+ apr_pool_t *pool;
+ char *endp, *name, *where;
+ const char *errmsg;
+ ap_macro_t *macro;
+
+ debug(fprintf(stderr, "macro_section: arg='%s'\n", arg));
+
+ /* lazy initialization */
+ if (ap_macros == NULL) {
+ pool = cmd->pool;
+ ap_macros = apr_hash_make(pool);
+ ap_assert(ap_macros != NULL);
+ apr_pool_cleanup_register(pool, &ap_macros,
+ ap_pool_cleanup_set_null,
+ apr_pool_cleanup_null);
+ }
+ else {
+ pool = apr_hash_pool_get(ap_macros);
+ }
+
+ endp = (char *) ap_strrchr_c(arg, '>');
+
+ if (endp == NULL) {
+ return BEGIN_MACRO "> directive missing closing '>'";
+ }
+
+ if (endp == arg) {
+ return BEGIN_MACRO " macro definition: empty name";
+ }
+
+ warn_if_non_blank(APLOGNO(02801) "non blank chars found after "
+ BEGIN_MACRO " closing '>'",
+ endp+1, cmd->config_file);
+
+ /* coldly drop '>[^>]*$' out */
+ *endp = '\0';
+
+ /* get lowercase macro name */
+ name = ap_getword_conf(pool, &arg);
+ if (empty_string_p(name)) {
+ return BEGIN_MACRO " macro definition: name not found";
+ }
+
+ ap_str_tolower(name);
+ macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING);
+
+ if (macro != NULL) {
+ /* already defined: warn about the redefinition */
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02802)
+ "macro '%s' multiply defined: "
+ "%s, redefined on line %d of \"%s\"",
+ macro->name, macro->location,
+ cmd->config_file->line_number, cmd->config_file->name);
+ }
+ else {
+ /* allocate a new macro */
+ macro = (ap_macro_t *) apr_palloc(pool, sizeof(ap_macro_t));
+ macro->name = name;
+ }
+
+ debug(fprintf(stderr, "macro_section: name=%s\n", name));
+
+ /* get macro arguments */
+ macro->location = apr_psprintf(pool,
+ "defined on line %d of \"%s\"",
+ cmd->config_file->line_number,
+ cmd->config_file->name);
+ debug(fprintf(stderr, "macro_section: location=%s\n", macro->location));
+
+ where =
+ apr_psprintf(pool, "macro '%s' (%s)", macro->name, macro->location);
+
+ if (looks_like_an_argument(name)) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02803)
+ "%s better prefix a macro name with any of '%s'",
+ where, ARG_PREFIX);
+ }
+
+ /* get macro parameters */
+ macro->arguments = get_arguments(pool, arg);
+
+ errmsg = check_macro_arguments(cmd->temp_pool, macro);
+
+ if (errmsg) {
+ return errmsg;
+ }
+
+ errmsg = get_lines_till_end_token(pool, cmd->config_file,
+ END_MACRO, BEGIN_MACRO,
+ where, &macro->contents);
+
+ if (errmsg) {
+ return apr_psprintf(cmd->temp_pool,
+ "%s" APR_EOL_STR "\tcontents error: %s",
+ where, errmsg);
+ }
+
+ errmsg = check_macro_contents(cmd->temp_pool, macro);
+
+ if (errmsg) {
+ return apr_psprintf(cmd->temp_pool,
+ "%s" APR_EOL_STR "\tcontents checking error: %s",
+ where, errmsg);
+ }
+
+ /* store the new macro */
+ apr_hash_set(ap_macros, name, APR_HASH_KEY_STRING, macro);
+
+ return NULL;
+}
+
+/*
+ handles: Use name value1 value2 ...
+*/
+static const char *use_macro(cmd_parms * cmd, void *dummy, const char *arg)
+{
+ char *name, *recursion, *where;
+ const char *errmsg;
+ ap_macro_t *macro;
+ apr_array_header_t *replacements;
+ apr_array_header_t *contents;
+
+ debug(fprintf(stderr, "use_macro -%s-\n", arg));
+
+ /* must be initialized, or no macros has been defined */
+ if (ap_macros == NULL) {
+ return "no macro defined before " USE_MACRO;
+ }
+
+ /* get lowercase macro name */
+ name = ap_getword_conf(cmd->temp_pool, &arg);
+ ap_str_tolower(name);
+
+ if (empty_string_p(name)) {
+ return "no macro name specified with " USE_MACRO;
+ }
+
+ /* get macro definition */
+ macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING);
+
+ if (!macro) {
+ return apr_psprintf(cmd->temp_pool, "macro '%s' undefined", name);
+ }
+
+ /* recursion is detected here by looking at the config file name,
+ * which may already contains "macro 'foo'". Ok, it looks like a hack,
+ * but otherwise it is uneasy to keep this data available somewhere...
+ * the name has just the needed visibility and liveness.
+ */
+ recursion =
+ apr_pstrcat(cmd->temp_pool, "macro '", macro->name, "'", NULL);
+
+ if (ap_strstr((char *) cmd->config_file->name, recursion)) {
+ return apr_psprintf(cmd->temp_pool,
+ "recursive use of macro '%s' is invalid",
+ macro->name);
+ }
+
+ /* get macro arguments */
+ replacements = get_arguments(cmd->temp_pool, arg);
+
+ if (macro->arguments->nelts != replacements->nelts) {
+ return apr_psprintf(cmd->temp_pool,
+ "macro '%s' (%s) used "
+ "with %d arguments instead of %d",
+ macro->name, macro->location,
+ replacements->nelts, macro->arguments->nelts);
+ }
+
+ where = apr_psprintf(cmd->temp_pool,
+ "macro '%s' (%s) used on line %d of \"%s\"",
+ macro->name, macro->location,
+ cmd->config_file->line_number,
+ cmd->config_file->name);
+
+ check_macro_use_arguments(where, replacements);
+
+ errmsg = process_content(cmd->temp_pool, macro, replacements,
+ NULL, &contents);
+
+ if (errmsg) {
+ return apr_psprintf(cmd->temp_pool,
+ "%s error while substituting: %s",
+ where, errmsg);
+ }
+
+ /* the current "config file" is replaced by a string array...
+ at the end of processing the array, the initial config file
+ will be returned there (see next_one) so as to go on. */
+ cmd->config_file = make_array_config(cmd->temp_pool, contents, where,
+ cmd->config_file, &cmd->config_file);
+
+ return NULL;
+}
+
+static const char *undef_macro(cmd_parms * cmd, void *dummy, const char *arg)
+{
+ char *name;
+ ap_macro_t *macro;
+
+ /* must be initialized, or no macros has been defined */
+ if (ap_macros == NULL) {
+ return "no macro defined before " UNDEF_MACRO;
+ }
+
+ if (empty_string_p(arg)) {
+ return "no macro name specified with " UNDEF_MACRO;
+ }
+
+ /* check that the macro is defined */
+ name = apr_pstrdup(cmd->temp_pool, arg);
+ ap_str_tolower(name);
+ macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING);
+ if (macro == NULL) {
+ /* could be a warning? */
+ return apr_psprintf(cmd->temp_pool,
+ "cannot remove undefined macro '%s'", name);
+ }
+
+ /* free macro: cannot do that */
+ /* remove macro from hash table */
+ apr_hash_set(ap_macros, name, APR_HASH_KEY_STRING, NULL);
+
+ return NULL;
+}
+
+/************************************************************* EXPORT MODULE */
+
+/*
+ macro module commands.
+ configuration file macro stuff
+ they are processed immediately when found, hence the EXEC_ON_READ.
+*/
+static const command_rec macro_cmds[] = {
+ AP_INIT_RAW_ARGS(BEGIN_MACRO, macro_section, NULL, EXEC_ON_READ | OR_ALL,
+ "Beginning of a macro definition section."),
+ AP_INIT_RAW_ARGS(USE_MACRO, use_macro, NULL, EXEC_ON_READ | OR_ALL,
+ "Use of a macro."),
+ AP_INIT_TAKE1(UNDEF_MACRO, undef_macro, NULL, EXEC_ON_READ | OR_ALL,
+ "Remove a macro definition."),
+
+ {NULL}
+};
+
+/*
+ Module hooks are request-oriented thus it does not suit configuration
+ file utils a lot. I haven't found any clean hook to apply something
+ before then after configuration file processing. Also what about
+ .htaccess files?
+
+ Thus I think that server/util.c or server/config.c
+ would be a better place for this stuff.
+*/
+
+AP_DECLARE_MODULE(macro) = {
+ STANDARD20_MODULE_STUFF, /* common stuff */
+ NULL, /* create per-directory config */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ macro_cmds, /* configuration commands */
+ NULL /* register hooks */
+};
diff --git a/modules/core/mod_macro.dep b/modules/core/mod_macro.dep
new file mode 100644
index 0000000..74ea1a5
--- /dev/null
+++ b/modules/core/mod_macro.dep
@@ -0,0 +1,45 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_macro.mak
+
+..\..\build\win32\httpd.rc : \
+ "..\..\include\ap_release.h"\
+
+
+.\mod_macro.c : \
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_config_layout.h"\
+ "..\..\include\ap_hooks.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\ap_regex.h"\
+ "..\..\include\ap_release.h"\
+ "..\..\include\apache_noprobes.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\os.h"\
+ "..\..\include\util_cfgtree.h"\
+ "..\..\srclib\apr-util\include\apr_buckets.h"\
+ "..\..\srclib\apr-util\include\apr_hooks.h"\
+ "..\..\srclib\apr-util\include\apr_optional_hooks.h"\
+ "..\..\srclib\apr-util\include\apr_uri.h"\
+ "..\..\srclib\apr-util\include\apu.h"\
+ "..\..\srclib\apr\include\apr.h"\
+ "..\..\srclib\apr\include\apr_allocator.h"\
+ "..\..\srclib\apr\include\apr_errno.h"\
+ "..\..\srclib\apr\include\apr_file_info.h"\
+ "..\..\srclib\apr\include\apr_file_io.h"\
+ "..\..\srclib\apr\include\apr_general.h"\
+ "..\..\srclib\apr\include\apr_hash.h"\
+ "..\..\srclib\apr\include\apr_inherit.h"\
+ "..\..\srclib\apr\include\apr_mmap.h"\
+ "..\..\srclib\apr\include\apr_network_io.h"\
+ "..\..\srclib\apr\include\apr_poll.h"\
+ "..\..\srclib\apr\include\apr_pools.h"\
+ "..\..\srclib\apr\include\apr_ring.h"\
+ "..\..\srclib\apr\include\apr_strings.h"\
+ "..\..\srclib\apr\include\apr_tables.h"\
+ "..\..\srclib\apr\include\apr_thread_mutex.h"\
+ "..\..\srclib\apr\include\apr_thread_proc.h"\
+ "..\..\srclib\apr\include\apr_time.h"\
+ "..\..\srclib\apr\include\apr_user.h"\
+ "..\..\srclib\apr\include\apr_want.h"\
+
diff --git a/modules/core/mod_macro.dsp b/modules/core/mod_macro.dsp
new file mode 100644
index 0000000..61914cc
--- /dev/null
+++ b/modules/core/mod_macro.dsp
@@ -0,0 +1,111 @@
+# Microsoft Developer Studio Project File - Name="mod_macro" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_macro - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_macro.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_macro.mak" CFG="mod_macro - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_macro - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_macro - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_macro - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_macro_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG" /i "../../include" /i "../../srclib/apr/include" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so /opt:ref
+# Begin Special Build Tool
+TargetPath=.\Release\mod_macro.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_macro_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG" /i "../../include" /i "../../srclib/apr/include" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so
+# Begin Special Build Tool
+TargetPath=.\Debug\mod_macro.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_macro - Win32 Release"
+# Name "mod_macro - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_macro.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\httpd.rc
+# End Source File
+# End Target
+# End Project
diff --git a/modules/core/mod_macro.mak b/modules/core/mod_macro.mak
new file mode 100644
index 0000000..656d96a
--- /dev/null
+++ b/modules/core/mod_macro.mak
@@ -0,0 +1,353 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_macro.dsp
+!IF "$(CFG)" == ""
+CFG=mod_macro - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_macro - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_macro - Win32 Release" && "$(CFG)" != "mod_macro - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_macro.mak" CFG="mod_macro - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_macro - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_macro - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_macro - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\httpd.res"
+ -@erase "$(INTDIR)\mod_macro.obj"
+ -@erase "$(INTDIR)\mod_macro_src.idb"
+ -@erase "$(INTDIR)\mod_macro_src.pdb"
+ -@erase "$(OUTDIR)\mod_macro.exp"
+ -@erase "$(OUTDIR)\mod_macro.lib"
+ -@erase "$(OUTDIR)\mod_macro.pdb"
+ -@erase "$(OUTDIR)\mod_macro.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_macro_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_macro.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_macro.pdb" /debug /out:"$(OUTDIR)\mod_macro.so" /implib:"$(OUTDIR)\mod_macro.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_macro.obj" \
+ "$(INTDIR)\httpd.res" \
+ "..\..\srclib\apr\Release\libapr-1.lib" \
+ "..\..\srclib\apr-util\Release\libaprutil-1.lib" \
+ "..\..\Release\libhttpd.lib"
+
+"$(OUTDIR)\mod_macro.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Release\mod_macro.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_macro.so"
+ if exist .\Release\mod_macro.so.manifest mt.exe -manifest .\Release\mod_macro.so.manifest -outputresource:.\Release\mod_macro.so;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\httpd.res"
+ -@erase "$(INTDIR)\mod_macro.obj"
+ -@erase "$(INTDIR)\mod_macro_src.idb"
+ -@erase "$(INTDIR)\mod_macro_src.pdb"
+ -@erase "$(OUTDIR)\mod_macro.exp"
+ -@erase "$(OUTDIR)\mod_macro.lib"
+ -@erase "$(OUTDIR)\mod_macro.pdb"
+ -@erase "$(OUTDIR)\mod_macro.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_macro_src" /FD /EHsc /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_macro.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_macro.pdb" /debug /out:"$(OUTDIR)\mod_macro.so" /implib:"$(OUTDIR)\mod_macro.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so
+LINK32_OBJS= \
+ "$(INTDIR)\mod_macro.obj" \
+ "$(INTDIR)\httpd.res" \
+ "..\..\srclib\apr\Debug\libapr-1.lib" \
+ "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \
+ "..\..\Debug\libhttpd.lib"
+
+"$(OUTDIR)\mod_macro.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Debug\mod_macro.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_macro.so"
+ if exist .\Debug\mod_macro.so.manifest mt.exe -manifest .\Debug\mod_macro.so.manifest -outputresource:.\Debug\mod_macro.so;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_macro.dep")
+!INCLUDE "mod_macro.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_macro.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_macro - Win32 Release" || "$(CFG)" == "mod_macro - Win32 Debug"
+
+!IF "$(CFG)" == "mod_macro - Win32 Release"
+
+"libapr - Win32 Release" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release"
+ cd "..\..\modules\core"
+
+"libapr - Win32 ReleaseCLEAN" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug"
+
+"libapr - Win32 Debug" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug"
+ cd "..\..\modules\core"
+
+"libapr - Win32 DebugCLEAN" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ENDIF
+
+!IF "$(CFG)" == "mod_macro - Win32 Release"
+
+"libaprutil - Win32 Release" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"
+ cd "..\..\modules\core"
+
+"libaprutil - Win32 ReleaseCLEAN" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug"
+
+"libaprutil - Win32 Debug" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
+ cd "..\..\modules\core"
+
+"libaprutil - Win32 DebugCLEAN" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ENDIF
+
+!IF "$(CFG)" == "mod_macro - Win32 Release"
+
+"libhttpd - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release"
+ cd ".\modules\core"
+
+"libhttpd - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN
+ cd ".\modules\core"
+
+!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug"
+
+"libhttpd - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"
+ cd ".\modules\core"
+
+"libhttpd - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\modules\core"
+
+!ENDIF
+
+SOURCE=..\..\build\win32\httpd.rc
+
+!IF "$(CFG)" == "mod_macro - Win32 Release"
+
+
+"$(INTDIR)\httpd.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug"
+
+
+"$(INTDIR)\httpd.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\mod_macro.c
+
+"$(INTDIR)\mod_macro.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/modules/core/mod_so.c b/modules/core/mod_so.c
new file mode 100644
index 0000000..f5d18c1
--- /dev/null
+++ b/modules/core/mod_so.c
@@ -0,0 +1,442 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module is used to load Apache modules at runtime. This means that the
+ * server functionality can be extended without recompiling and even without
+ * taking the server down at all. Only a HUP or AP_SIG_GRACEFUL signal
+ * needs to be sent to the server to reload the dynamically loaded modules.
+ *
+ * To use, you'll first need to build your module as a shared library, then
+ * update your configuration (httpd.conf) to get the Apache core to load the
+ * module at start-up.
+ *
+ * The easiest way to build a module as a shared library is to use the
+ * `SharedModule' command in the Configuration file, instead of `AddModule'.
+ * You should also change the file extension from `.o' to `.so'. So, for
+ * example, to build the status module as a shared library edit Configuration
+ * and change
+ * AddModule modules/standard/mod_status.o
+ * to
+ * SharedModule modules/standard/mod_status.so
+ *
+ * Run Configure and make. Now Apache's httpd binary will _not_ include
+ * mod_status. Instead a shared object called mod_status.so will be build, in
+ * the modules/standard directory. You can build most of the modules as shared
+ * libraries like this.
+ *
+ * To use the shared module, move the .so file(s) into an appropriate
+ * directory. You might like to create a directory called "modules" under you
+ * server root for this (e.g. /usr/local/httpd/modules).
+ *
+ * Then edit your conf/httpd.conf file, and add LoadModule lines. For
+ * example
+ * LoadModule status_module modules/mod_status.so
+ *
+ * The first argument is the module's structure name (look at the end of the
+ * module source to find this). The second option is the path to the module
+ * file, relative to the server root. Put these directives right at the top
+ * of your httpd.conf file.
+ *
+ * Now you can start Apache. A message will be logged at "debug" level to your
+ * error_log to confirm that the module(s) are loaded (use "LogLevel debug"
+ * directive to get these log messages).
+ *
+ * If you edit the LoadModule directives while the server is live you can get
+ * Apache to re-load the modules by sending it a HUP or AP_SIG_GRACEFUL
+ * signal as normal. You can use this to dynamically change the capability
+ * of your server without bringing it down.
+ *
+ * Because currently there is only limited builtin support in the Configure
+ * script for creating the shared library files (`.so'), please consult your
+ * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate
+ * compiler and linker flags and insert them manually into the Configuration
+ * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT.
+ *
+ * If you still have problems figuring out the flags both try the paper
+ * http://developer.netscape.com/library/documentation/enterprise
+ * /unix/svrplug.htm#1013807
+ * or install a Perl 5 interpreter on your platform and then run the command
+ *
+ * $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags
+ *
+ * This gives you what type of dynamic loading Perl 5 uses on your platform
+ * and which compiler and linker flags Perl 5 uses to create the shared object
+ * files.
+ *
+ * Another location where you can find useful hints is the `ltconfig' script
+ * of the GNU libtool 1.2 package. Search for your platform name inside the
+ * various "case" constructs.
+ *
+ */
+
+#include "apr.h"
+#include "apr_dso.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_core.h"
+
+#include "mod_so.h"
+
+module AP_MODULE_DECLARE_DATA so_module;
+
+
+/*
+ * Server configuration to keep track of actually
+ * loaded modules and the corresponding module name.
+ */
+
+typedef struct so_server_conf {
+ apr_array_header_t *loaded_modules;
+} so_server_conf;
+
+static void *so_sconf_create(apr_pool_t *p, server_rec *s)
+{
+ so_server_conf *soc;
+
+ soc = (so_server_conf *)apr_pcalloc(p, sizeof(so_server_conf));
+ soc->loaded_modules = apr_array_make(p, DYNAMIC_MODULE_LIMIT,
+ sizeof(ap_module_symbol_t));
+
+ return (void *)soc;
+}
+
+#ifndef NO_DLOPEN
+
+/*
+ * This is the cleanup for a loaded shared object. It unloads the module.
+ * This is called as a cleanup function from the core.
+ */
+
+static apr_status_t unload_module(void *data)
+{
+ ap_module_symbol_t *modi = (ap_module_symbol_t*)data;
+
+ /* only unload if module information is still existing */
+ if (modi->modp == NULL)
+ return APR_SUCCESS;
+
+ /* remove the module pointer from the core structure */
+ ap_remove_loaded_module(modi->modp);
+
+ /* destroy the module information */
+ modi->modp = NULL;
+ modi->name = NULL;
+ return APR_SUCCESS;
+}
+
+static const char *dso_load(cmd_parms *cmd, apr_dso_handle_t **modhandlep,
+ const char *filename, const char **used_filename)
+{
+ int retry = 0;
+ const char *fullname = ap_server_root_relative(cmd->temp_pool, filename);
+ char my_error[256];
+ if (filename != NULL && ap_strchr_c(filename, '/') == NULL) {
+ /* retry on error without path to use dlopen()'s search path */
+ retry = 1;
+ }
+
+ if (fullname == NULL && !retry) {
+ return apr_psprintf(cmd->temp_pool, "Invalid %s path %s",
+ cmd->cmd->name, filename);
+ }
+ *used_filename = fullname;
+ if (fullname && apr_dso_load(modhandlep, fullname, cmd->pool) == APR_SUCCESS) {
+ return NULL;
+ }
+ if (retry) {
+ *used_filename = filename;
+ if (apr_dso_load(modhandlep, filename, cmd->pool) == APR_SUCCESS)
+ return NULL;
+ }
+
+ return apr_pstrcat(cmd->temp_pool, "Cannot load ", filename,
+ " into server: ",
+ apr_dso_error(*modhandlep, my_error, sizeof(my_error)),
+ NULL);
+}
+
+/*
+ * This is called for the directive LoadModule and actually loads
+ * a shared object file into the address space of the server process.
+ */
+
+static const char *load_module(cmd_parms *cmd, void *dummy,
+ const char *modname, const char *filename)
+{
+ apr_dso_handle_t *modhandle;
+ apr_dso_handle_sym_t modsym;
+ module *modp;
+ const char *module_file;
+ so_server_conf *sconf;
+ ap_module_symbol_t *modi;
+ ap_module_symbol_t *modie;
+ int i;
+ const char *error;
+
+ /* we need to setup this value for dummy to make sure that we don't try
+ * to add a non-existent tree into the build when we return to
+ * execute_now.
+ */
+ *(ap_directive_t **)dummy = NULL;
+
+ /*
+ * check for already existing module
+ * If it already exists, we have nothing to do
+ * Check both dynamically-loaded modules and statically-linked modules.
+ */
+ sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,
+ &so_module);
+ modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
+ for (i = 0; i < sconf->loaded_modules->nelts; i++) {
+ modi = &modie[i];
+ if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
+ ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, cmd->pool, APLOGNO(01574)
+ "module %s is already loaded, skipping",
+ modname);
+ return NULL;
+ }
+ }
+
+ for (i = 0; ap_preloaded_modules[i]; i++) {
+ const char *preload_name;
+ apr_size_t preload_len;
+ apr_size_t thismod_len;
+
+ modp = ap_preloaded_modules[i];
+
+ /* make sure we're comparing apples with apples
+ * make sure name of preloaded module is mod_FOO.c
+ * make sure name of structure being loaded is FOO_module
+ */
+
+ if (memcmp(modp->name, "mod_", 4)) {
+ continue;
+ }
+
+ preload_name = modp->name + strlen("mod_");
+ preload_len = strlen(preload_name) - 2;
+
+ if (strlen(modname) <= strlen("_module")) {
+ continue;
+ }
+ thismod_len = strlen(modname) - strlen("_module");
+ if (strcmp(modname + thismod_len, "_module")) {
+ continue;
+ }
+
+ if (thismod_len != preload_len) {
+ continue;
+ }
+
+ if (!memcmp(modname, preload_name, preload_len)) {
+ return apr_pstrcat(cmd->pool, "module ", modname,
+ " is built-in and can't be loaded",
+ NULL);
+ }
+ }
+
+ modi = apr_array_push(sconf->loaded_modules);
+ modi->name = modname;
+
+ /*
+ * Load the file into the Apache address space
+ */
+ error = dso_load(cmd, &modhandle, filename, &module_file);
+ if (error)
+ return error;
+ ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool, APLOGNO(01575)
+ "loaded module %s from %s", modname, module_file);
+
+ /*
+ * Retrieve the pointer to the module structure through the module name:
+ * First with the hidden variant (prefix `AP_') and then with the plain
+ * symbol name.
+ */
+ if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) {
+ char my_error[256];
+
+ return apr_pstrcat(cmd->pool, "Can't locate API module structure `",
+ modname, "' in file ", module_file, ": ",
+ apr_dso_error(modhandle, my_error, sizeof(my_error)),
+ NULL);
+ }
+ modp = (module*) modsym;
+ modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle;
+ modi->modp = modp;
+
+ /*
+ * Make sure the found module structure is really a module structure
+ *
+ */
+ if (modp->magic != MODULE_MAGIC_COOKIE) {
+ return apr_psprintf(cmd->pool, "API module structure '%s' in file %s "
+ "is garbled - expected signature %08lx but saw "
+ "%08lx - perhaps this is not an Apache module DSO, "
+ "or was compiled for a different Apache version?",
+ modname, module_file,
+ MODULE_MAGIC_COOKIE, modp->magic);
+ }
+
+ /*
+ * Add this module to the Apache core structures
+ */
+ error = ap_add_loaded_module(modp, cmd->pool, modname);
+ if (error) {
+ return error;
+ }
+
+ /*
+ * Register a cleanup in the config apr_pool_t (normally pconf). When
+ * we do a restart (or shutdown) this cleanup will cause the
+ * shared object to be unloaded.
+ */
+ apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null);
+
+ /*
+ * Finally we need to run the configuration process for the module
+ */
+ ap_single_module_configure(cmd->pool, cmd->server, modp);
+
+ return NULL;
+}
+
+/*
+ * This implements the LoadFile directive and loads an arbitrary
+ * shared object file into the address space of the server process.
+ */
+
+static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
+{
+ apr_dso_handle_t *handle;
+ const char *used_file, *error;
+
+ error = dso_load(cmd, &handle, filename, &used_file);
+ if (error)
+ return error;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01576)
+ "loaded file %s", used_file);
+
+ return NULL;
+}
+
+static module *ap_find_loaded_module_symbol(server_rec *s, const char *modname)
+{
+ so_server_conf *sconf;
+ ap_module_symbol_t *modi;
+ ap_module_symbol_t *modie;
+ int i;
+
+ sconf = (so_server_conf *)ap_get_module_config(s->module_config,
+ &so_module);
+ modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
+
+ for (i = 0; i < sconf->loaded_modules->nelts; i++) {
+ modi = &modie[i];
+ if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
+ return modi->modp;
+ }
+ }
+ return NULL;
+}
+
+static void dump_loaded_modules(apr_pool_t *p, server_rec *s)
+{
+ ap_module_symbol_t *modie;
+ ap_module_symbol_t *modi;
+ so_server_conf *sconf;
+ int i;
+ apr_file_t *out = NULL;
+
+ if (!ap_exists_config_define("DUMP_MODULES")) {
+ return;
+ }
+
+ apr_file_open_stdout(&out, p);
+
+ apr_file_printf(out, "Loaded Modules:\n");
+
+ sconf = (so_server_conf *)ap_get_module_config(s->module_config,
+ &so_module);
+ for (i = 0; ; i++) {
+ modi = &ap_prelinked_module_symbols[i];
+ if (modi->name != NULL) {
+ apr_file_printf(out, " %s (static)\n", modi->name);
+ }
+ else {
+ break;
+ }
+ }
+
+ modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
+ for (i = 0; i < sconf->loaded_modules->nelts; i++) {
+ modi = &modie[i];
+ if (modi->name != NULL) {
+ apr_file_printf(out, " %s (shared)\n", modi->name);
+ }
+ }
+}
+
+#else /* not NO_DLOPEN */
+
+static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
+{
+ ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, cmd->pool, APLOGNO(01577)
+ "WARNING: LoadFile not supported on this platform");
+ return NULL;
+}
+
+static const char *load_module(cmd_parms *cmd, void *dummy,
+ const char *modname, const char *filename)
+{
+ ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, cmd->pool, APLOGNO(01578)
+ "WARNING: LoadModule not supported on this platform");
+ return NULL;
+}
+
+#endif /* NO_DLOPEN */
+
+static void register_hooks(apr_pool_t *p)
+{
+#ifndef NO_DLOPEN
+ APR_REGISTER_OPTIONAL_FN(ap_find_loaded_module_symbol);
+ ap_hook_test_config(dump_loaded_modules, NULL, NULL, APR_HOOK_MIDDLE);
+#endif
+}
+
+static const command_rec so_cmds[] = {
+ AP_INIT_TAKE2("LoadModule", load_module, NULL, RSRC_CONF | EXEC_ON_READ,
+ "a module name and the name of a shared object file to load it from"),
+ AP_INIT_ITERATE("LoadFile", load_file, NULL, RSRC_CONF | EXEC_ON_READ,
+ "shared object file or library to load into the server at runtime"),
+ { NULL }
+};
+
+AP_DECLARE_MODULE(so) = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ so_sconf_create, /* server config */
+ NULL, /* merge server config */
+ so_cmds, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
diff --git a/modules/core/mod_so.h b/modules/core/mod_so.h
new file mode 100644
index 0000000..2b26999
--- /dev/null
+++ b/modules/core/mod_so.h
@@ -0,0 +1,38 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file mod_so.h
+ * @brief Shared Object Loader Extension Module for Apache
+ *
+ * @defgroup MOD_SO mod_so
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#ifndef MOD_SO_H
+#define MOD_SO_H 1
+
+#include "apr_optional.h"
+#include "httpd.h"
+
+/* optional function declaration */
+APR_DECLARE_OPTIONAL_FN(module *, ap_find_loaded_module_symbol,
+ (server_rec *s, const char *modname));
+
+#endif /* MOD_SO_H */
+/** @} */
+
diff --git a/modules/core/mod_watchdog.c b/modules/core/mod_watchdog.c
new file mode 100644
index 0000000..99ec7cf
--- /dev/null
+++ b/modules/core/mod_watchdog.c
@@ -0,0 +1,718 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Watchdog module.
+ */
+
+#include "apr.h"
+#include "mod_watchdog.h"
+#include "ap_provider.h"
+#include "ap_mpm.h"
+#include "http_core.h"
+#include "util_mutex.h"
+
+#include "apr_atomic.h"
+
+#define AP_WATCHDOG_PGROUP "watchdog"
+#define AP_WATCHDOG_PVERSION "parent"
+#define AP_WATCHDOG_CVERSION "child"
+
+typedef struct watchdog_list_t watchdog_list_t;
+
+struct watchdog_list_t
+{
+ struct watchdog_list_t *next;
+ ap_watchdog_t *wd;
+ apr_status_t status;
+ apr_interval_time_t interval;
+ apr_interval_time_t step;
+ const void *data;
+ ap_watchdog_callback_fn_t *callback_fn;
+};
+
+struct ap_watchdog_t
+{
+ apr_uint32_t thread_started; /* set to 1 once thread running */
+ apr_proc_mutex_t *mutex;
+ const char *name;
+ watchdog_list_t *callbacks;
+ int is_running;
+ int singleton;
+ int active;
+ apr_interval_time_t step;
+ apr_thread_t *thread;
+ apr_pool_t *pool;
+};
+
+typedef struct wd_server_conf_t wd_server_conf_t;
+struct wd_server_conf_t
+{
+ int child_workers;
+ int parent_workers;
+ apr_pool_t *pool;
+ server_rec *s;
+};
+
+static wd_server_conf_t *wd_server_conf = NULL;
+static apr_interval_time_t wd_interval = AP_WD_TM_INTERVAL;
+static int mpm_is_forked = AP_MPMQ_NOT_SUPPORTED;
+static const char *wd_proc_mutex_type = "watchdog-callback";
+
+static apr_status_t wd_worker_cleanup(void *data)
+{
+ apr_status_t rv;
+ ap_watchdog_t *w = (ap_watchdog_t *)data;
+
+ /* Do nothing if the thread wasn't started. */
+ if (apr_atomic_read32(&w->thread_started) != 1)
+ return APR_SUCCESS;
+
+ if (w->is_running) {
+ watchdog_list_t *wl = w->callbacks;
+ while (wl) {
+ if (wl->status == APR_SUCCESS) {
+ /* Execute watchdog callback with STOPPING state */
+ (*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING,
+ (void *)wl->data, w->pool);
+ wl->status = APR_EOF;
+ }
+ wl = wl->next;
+ }
+ }
+ w->is_running = 0;
+ apr_thread_join(&rv, w->thread);
+ return rv;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Main watchdog worker thread. */
+/* For singleton workers child thread that first obtains the process */
+/* mutex is running. Threads in other child's are locked on mutex. */
+/* */
+/*--------------------------------------------------------------------------*/
+static void* APR_THREAD_FUNC wd_worker(apr_thread_t *thread, void *data)
+{
+ ap_watchdog_t *w = (ap_watchdog_t *)data;
+ apr_status_t rv;
+ int locked = 0;
+ int probed = 0;
+ int inited = 0;
+ int mpmq_s = 0;
+ apr_pool_t *temp_pool = NULL;
+
+ w->pool = apr_thread_pool_get(thread);
+ w->is_running = 1;
+
+ apr_atomic_set32(&w->thread_started, 1); /* thread started */
+
+ if (w->mutex) {
+ while (w->is_running) {
+ if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
+ w->is_running = 0;
+ break;
+ }
+ if (mpmq_s == AP_MPMQ_STOPPING) {
+ w->is_running = 0;
+ break;
+ }
+ rv = apr_proc_mutex_trylock(w->mutex);
+ if (rv == APR_SUCCESS) {
+ if (probed) {
+ /* Sleep after we were locked
+ * up to 1 second. Httpd can be
+ * in the middle of shutdown, and
+ * our child didn't yet received
+ * the shutdown signal.
+ */
+ probed = 10;
+ while (w->is_running && probed > 0) {
+ apr_sleep(AP_WD_TM_INTERVAL);
+ probed--;
+ if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
+ w->is_running = 0;
+ break;
+ }
+ if (mpmq_s == AP_MPMQ_STOPPING) {
+ w->is_running = 0;
+ break;
+ }
+ }
+ }
+ locked = 1;
+ break;
+ }
+ probed = 1;
+ apr_sleep(AP_WD_TM_SLICE);
+ }
+ }
+
+ apr_pool_create(&temp_pool, w->pool);
+ apr_pool_tag(temp_pool, "wd_running");
+
+ if (w->is_running) {
+ watchdog_list_t *wl = w->callbacks;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s,
+ APLOGNO(02972) "%sWatchdog (%s) running",
+ w->singleton ? "Singleton " : "", w->name);
+ apr_time_clock_hires(w->pool);
+ if (wl) {
+ while (wl && w->is_running) {
+ /* Execute watchdog callback */
+ wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_STARTING,
+ (void *)wl->data, temp_pool);
+ wl = wl->next;
+ }
+ apr_pool_clear(temp_pool);
+ }
+ else {
+ ap_run_watchdog_init(wd_server_conf->s, w->name, w->pool);
+ inited = 1;
+ }
+ }
+
+ /* Main execution loop */
+ while (w->is_running) {
+ apr_time_t curr;
+ watchdog_list_t *wl = w->callbacks;
+
+ apr_sleep(AP_WD_TM_SLICE);
+ if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
+ w->is_running = 0;
+ }
+ if (mpmq_s == AP_MPMQ_STOPPING) {
+ w->is_running = 0;
+ }
+ if (!w->is_running) {
+ break;
+ }
+ curr = apr_time_now() - AP_WD_TM_SLICE;
+ while (wl && w->is_running) {
+ if (wl->status == APR_SUCCESS) {
+ wl->step += (apr_time_now() - curr);
+ if (wl->step >= wl->interval) {
+ wl->step = 0;
+ /* Execute watchdog callback */
+ wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_RUNNING,
+ (void *)wl->data, temp_pool);
+ if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
+ w->is_running = 0;
+ }
+ if (mpmq_s == AP_MPMQ_STOPPING) {
+ w->is_running = 0;
+ }
+ }
+ }
+ wl = wl->next;
+ }
+ if (w->is_running && w->callbacks == NULL) {
+ /* This is hook mode watchdog
+ * running on WatchogInterval
+ */
+ w->step += (apr_time_now() - curr);
+ if (w->step >= wd_interval) {
+ w->step = 0;
+ /* Run watchdog step hook */
+ ap_run_watchdog_step(wd_server_conf->s, w->name, temp_pool);
+ }
+ }
+
+ apr_pool_clear(temp_pool);
+ }
+
+ apr_pool_destroy(temp_pool);
+
+ if (inited) {
+ /* Run the watchdog exit hooks.
+ * If this was singleton watchdog the init hook
+ * might never been called, so skip the exit hook
+ * in that case as well.
+ */
+ ap_run_watchdog_exit(wd_server_conf->s, w->name, w->pool);
+ }
+ else {
+ watchdog_list_t *wl = w->callbacks;
+ while (wl) {
+ if (wl->status == APR_SUCCESS) {
+ /* Execute watchdog callback with STOPPING state */
+ (*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING,
+ (void *)wl->data, w->pool);
+ }
+ wl = wl->next;
+ }
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s,
+ APLOGNO(02973) "%sWatchdog (%s) stopping",
+ w->singleton ? "Singleton " : "", w->name);
+
+ if (locked)
+ apr_proc_mutex_unlock(w->mutex);
+ apr_thread_exit(w->thread, APR_SUCCESS);
+
+ return NULL;
+}
+
+static apr_status_t wd_startup(ap_watchdog_t *w, apr_pool_t *p)
+{
+ apr_status_t rc;
+
+ apr_atomic_set32(&w->thread_started, 0);
+
+ if (w->singleton) {
+ /* Initialize singleton mutex in child */
+ rc = apr_proc_mutex_child_init(&w->mutex,
+ apr_proc_mutex_lockfile(w->mutex), p);
+ if (rc != APR_SUCCESS)
+ return rc;
+ }
+
+ /* Start the newly created watchdog */
+ rc = ap_thread_create(&w->thread, NULL, wd_worker, w, p);
+ if (rc == APR_SUCCESS) {
+ apr_pool_pre_cleanup_register(p, w, wd_worker_cleanup);
+ }
+
+ return rc;
+}
+
+static apr_status_t ap_watchdog_get_instance(ap_watchdog_t **watchdog,
+ const char *name,
+ int parent,
+ int singleton,
+ apr_pool_t *p)
+{
+ ap_watchdog_t *w;
+ const char *pver = parent ? AP_WATCHDOG_PVERSION : AP_WATCHDOG_CVERSION;
+
+ if (parent && mpm_is_forked != AP_MPMQ_NOT_SUPPORTED) {
+ /* Parent threads are not supported for
+ * forked mpm's
+ */
+ *watchdog = NULL;
+ return APR_ENOTIMPL;
+ }
+ w = ap_lookup_provider(AP_WATCHDOG_PGROUP, name, pver);
+ if (w) {
+ *watchdog = w;
+ return APR_SUCCESS;
+ }
+ w = apr_pcalloc(p, sizeof(ap_watchdog_t));
+ w->name = name;
+ w->pool = p;
+ w->singleton = parent ? 0 : singleton;
+ *watchdog = w;
+ return ap_register_provider(p, AP_WATCHDOG_PGROUP, name,
+ pver, *watchdog);
+}
+
+static apr_status_t ap_watchdog_set_callback_interval(ap_watchdog_t *w,
+ apr_interval_time_t interval,
+ const void *data,
+ ap_watchdog_callback_fn_t *callback)
+{
+ watchdog_list_t *c = w->callbacks;
+ apr_status_t rv = APR_EOF;
+
+ while (c) {
+ if (c->data == data && c->callback_fn == callback) {
+ /* We have existing callback.
+ * Update the interval and reset status, so the
+ * callback and continue execution if stopped earlier.
+ */
+ c->interval = interval;
+ c->step = 0;
+ c->status = APR_SUCCESS;
+ rv = APR_SUCCESS;
+ break;
+ }
+ c = c->next;
+ }
+ return rv;
+}
+
+static apr_status_t ap_watchdog_register_callback(ap_watchdog_t *w,
+ apr_interval_time_t interval,
+ const void *data,
+ ap_watchdog_callback_fn_t *callback)
+{
+ watchdog_list_t *c = w->callbacks;
+
+ while (c) {
+ if (c->data == data && c->callback_fn == callback) {
+ /* We have already registered callback.
+ * Do not allow callbacks that have the same
+ * function and data pointers.
+ */
+ return APR_EEXIST;
+ }
+ c = c->next;
+ }
+ c = apr_palloc(w->pool, sizeof(watchdog_list_t));
+ c->data = data;
+ c->callback_fn = callback;
+ c->interval = interval;
+ c->step = 0;
+ c->status = APR_EINIT;
+
+ c->wd = w;
+ c->next = w->callbacks;
+ w->callbacks = c;
+ w->active++;
+
+ return APR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Pre config hook. */
+/* Create default watchdogs for parent and child */
+/* Parent watchdog executes inside parent process so it doesn't need the */
+/* singleton mutex */
+/* */
+/*--------------------------------------------------------------------------*/
+static int wd_pre_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
+ apr_pool_t *ptemp)
+{
+ apr_status_t rv;
+ ap_watchdog_t *w;
+
+ ap_mpm_query(AP_MPMQ_IS_FORKED, &mpm_is_forked);
+ if ((rv = ap_watchdog_get_instance(&w,
+ AP_WATCHDOG_SINGLETON, 0, 1, pconf)) != APR_SUCCESS) {
+ return rv;
+ }
+ if ((rv = ap_watchdog_get_instance(&w,
+ AP_WATCHDOG_DEFAULT, 0, 0, pconf)) != APR_SUCCESS) {
+ return rv;
+ }
+ if (mpm_is_forked == AP_MPMQ_NOT_SUPPORTED) {
+ /* Create parent process watchdog for
+ * non forked mpm's only.
+ */
+ if ((rv = ap_watchdog_get_instance(&w,
+ AP_WATCHDOG_DEFAULT, 1, 0, pconf)) != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ if ((rv = ap_mutex_register(pconf, wd_proc_mutex_type, NULL,
+ APR_LOCK_DEFAULT, 0)) != APR_SUCCESS) {
+ return rv;
+ }
+
+ return OK;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Post config hook. */
+/* Create watchdog thread in parent and initializes Watchdog module */
+/* */
+/*--------------------------------------------------------------------------*/
+static int wd_post_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
+ apr_pool_t *ptemp, server_rec *s)
+{
+ apr_status_t rv;
+ const char *pk = "watchdog_init_module_tag";
+ apr_pool_t *ppconf = pconf;
+ const apr_array_header_t *wl;
+
+ if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
+ /* First time config phase -- skip. */
+ return OK;
+
+ apr_pool_userdata_get((void *)&wd_server_conf, pk, ppconf);
+ if (!wd_server_conf) {
+ if (!(wd_server_conf = apr_pcalloc(ppconf, sizeof(wd_server_conf_t))))
+ return APR_ENOMEM;
+ apr_pool_create(&wd_server_conf->pool, ppconf);
+ apr_pool_tag(wd_server_conf->pool, "wd_server_conf");
+ apr_pool_userdata_set(wd_server_conf, pk, apr_pool_cleanup_null, ppconf);
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(010033)
+ "Watchdog: Running with WatchdogInterval %"
+ APR_TIME_T_FMT "ms", apr_time_as_msec(wd_interval));
+ wd_server_conf->s = s;
+ if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP,
+ AP_WATCHDOG_PVERSION))) {
+ const ap_list_provider_names_t *wn;
+ int i;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02974)
+ "Watchdog: found parent providers.");
+
+ wn = (ap_list_provider_names_t *)wl->elts;
+ for (i = 0; i < wl->nelts; i++) {
+ ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
+ wn[i].provider_name,
+ AP_WATCHDOG_PVERSION);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02975)
+ "Watchdog: Looking for parent (%s).", wn[i].provider_name);
+ if (w) {
+ if (!w->active) {
+ int status = ap_run_watchdog_need(s, w->name, 1,
+ w->singleton);
+ if (status == OK) {
+ /* One of the modules returned OK to this watchdog.
+ * Mark it as active
+ */
+ w->active = 1;
+ }
+ }
+ if (w->active) {
+ /* We have active watchdog.
+ * Create the watchdog thread
+ */
+ if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01571)
+ "Watchdog: Failed to create parent worker thread.");
+ return rv;
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02976)
+ "Watchdog: Created parent worker thread (%s).", w->name);
+ wd_server_conf->parent_workers++;
+ }
+ }
+ }
+ }
+ if (wd_server_conf->parent_workers) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01572)
+ "Spawned %d parent worker threads.",
+ wd_server_conf->parent_workers);
+ }
+ if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP,
+ AP_WATCHDOG_CVERSION))) {
+ const ap_list_provider_names_t *wn;
+ int i;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02977)
+ "Watchdog: found child providers.");
+
+ wn = (ap_list_provider_names_t *)wl->elts;
+ for (i = 0; i < wl->nelts; i++) {
+ ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
+ wn[i].provider_name,
+ AP_WATCHDOG_CVERSION);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02978)
+ "Watchdog: Looking for child (%s).", wn[i].provider_name);
+ if (w) {
+ if (!w->active) {
+ int status = ap_run_watchdog_need(s, w->name, 0,
+ w->singleton);
+ if (status == OK) {
+ /* One of the modules returned OK to this watchdog.
+ * Mark it as active
+ */
+ w->active = 1;
+ }
+ }
+ if (w->active) {
+ /* We have some callbacks registered.
+ * Create mutexes for singleton watchdogs
+ */
+ if (w->singleton) {
+ rv = ap_proc_mutex_create(&w->mutex, NULL, wd_proc_mutex_type,
+ w->name, s,
+ wd_server_conf->pool, 0);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(10095)
+ "Watchdog: Failed to create singleton mutex.");
+ return rv;
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979)
+ "Watchdog: Created singleton mutex (%s).", w->name);
+ }
+ wd_server_conf->child_workers++;
+ }
+ }
+ }
+ }
+ return OK;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Child init hook. */
+/* Create watchdog threads and initializes Mutexes in child */
+/* */
+/*--------------------------------------------------------------------------*/
+static void wd_child_init_hook(apr_pool_t *p, server_rec *s)
+{
+ apr_status_t rv = OK;
+ const apr_array_header_t *wl;
+
+ if (!wd_server_conf->child_workers) {
+ /* We don't have anything configured, bail out.
+ */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02980)
+ "Watchdog: nothing configured?");
+ return;
+ }
+ if ((wl = ap_list_provider_names(p, AP_WATCHDOG_PGROUP,
+ AP_WATCHDOG_CVERSION))) {
+ const ap_list_provider_names_t *wn;
+ int i;
+ wn = (ap_list_provider_names_t *)wl->elts;
+ for (i = 0; i < wl->nelts; i++) {
+ ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
+ wn[i].provider_name,
+ AP_WATCHDOG_CVERSION);
+ if (w && w->active) {
+ /* We have some callbacks registered.
+ * Kick of the watchdog
+ */
+ if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01573)
+ "Watchdog: Failed to create child worker thread.");
+ /* No point to continue */
+ return;
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02981)
+ "Watchdog: Created child worker thread (%s).", wn[i].provider_name);
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* WatchdogInterval directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *wd_cmd_watchdog_int(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ apr_status_t rv;
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+ rv = ap_timeout_parameter_parse(arg, &wd_interval, "s");
+
+ if (rv != APR_SUCCESS)
+ return "Unparse-able WatchdogInterval setting";
+ if (wd_interval < AP_WD_TM_SLICE) {
+ return apr_psprintf(cmd->pool, "Invalid WatchdogInterval: minimal value %"
+ APR_TIME_T_FMT "ms", apr_time_as_msec(AP_WD_TM_SLICE));
+ }
+
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* List of directives specific to our module. */
+/* */
+/*--------------------------------------------------------------------------*/
+static const command_rec wd_directives[] =
+{
+ AP_INIT_TAKE1(
+ "WatchdogInterval", /* directive name */
+ wd_cmd_watchdog_int, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Watchdog interval in seconds"
+ ),
+ {NULL}
+};
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Which functions are responsible for which hooks in the server. */
+/* */
+/*--------------------------------------------------------------------------*/
+static void wd_register_hooks(apr_pool_t *p)
+{
+
+ /* Only the mpm_winnt has child init hook handler.
+ * Make sure that we are called after the mpm child init handler
+ * initializes.
+ */
+ static const char *const after_mpm[] = { "mpm_winnt.c", NULL};
+
+ /* Pre config handling
+ */
+ ap_hook_pre_config(wd_pre_config_hook,
+ NULL,
+ NULL,
+ APR_HOOK_FIRST);
+
+ /* Post config handling
+ */
+ ap_hook_post_config(wd_post_config_hook,
+ NULL,
+ NULL,
+ APR_HOOK_LAST);
+
+ /* Child init hook
+ */
+ ap_hook_child_init(wd_child_init_hook,
+ after_mpm,
+ NULL,
+ APR_HOOK_MIDDLE);
+
+ APR_REGISTER_OPTIONAL_FN(ap_watchdog_get_instance);
+ APR_REGISTER_OPTIONAL_FN(ap_watchdog_register_callback);
+ APR_REGISTER_OPTIONAL_FN(ap_watchdog_set_callback_interval);
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* The list of callback routines and data structures that provide */
+/* the static hooks into our module from the other parts of the server. */
+/* */
+/*--------------------------------------------------------------------------*/
+AP_DECLARE_MODULE(watchdog) = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ wd_directives, /* command apr_table_t */
+ wd_register_hooks /* register hooks */
+};
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* The list of optional hooks that we provide */
+/* */
+/*--------------------------------------------------------------------------*/
+APR_HOOK_STRUCT(
+ APR_HOOK_LINK(watchdog_need)
+ APR_HOOK_LINK(watchdog_init)
+ APR_HOOK_LINK(watchdog_exit)
+ APR_HOOK_LINK(watchdog_step)
+)
+
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ap, AP_WD, int, watchdog_need,
+ (server_rec *s, const char *name,
+ int parent, int singleton),
+ (s, name, parent, singleton),
+ DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_init,
+ (server_rec *s, const char *name,
+ apr_pool_t *pool),
+ (s, name, pool),
+ OK, DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_exit,
+ (server_rec *s, const char *name,
+ apr_pool_t *pool),
+ (s, name, pool),
+ OK, DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_step,
+ (server_rec *s, const char *name,
+ apr_pool_t *pool),
+ (s, name, pool),
+ OK, DECLINED)
diff --git a/modules/core/mod_watchdog.dep b/modules/core/mod_watchdog.dep
new file mode 100644
index 0000000..147475b
--- /dev/null
+++ b/modules/core/mod_watchdog.dep
@@ -0,0 +1,59 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_watchdog.mak
+
+..\..\build\win32\httpd.rc : \
+ "..\..\include\ap_release.h"\
+
+
+.\mod_watchdog.c : \
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_config_layout.h"\
+ "..\..\include\ap_expr.h"\
+ "..\..\include\ap_hooks.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\ap_mpm.h"\
+ "..\..\include\ap_provider.h"\
+ "..\..\include\ap_regex.h"\
+ "..\..\include\ap_release.h"\
+ "..\..\include\apache_noprobes.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\os.h"\
+ "..\..\include\scoreboard.h"\
+ "..\..\include\util_cfgtree.h"\
+ "..\..\include\util_filter.h"\
+ "..\..\include\util_mutex.h"\
+ "..\..\srclib\apr-util\include\apr_buckets.h"\
+ "..\..\srclib\apr-util\include\apr_hooks.h"\
+ "..\..\srclib\apr-util\include\apr_optional.h"\
+ "..\..\srclib\apr-util\include\apr_optional_hooks.h"\
+ "..\..\srclib\apr-util\include\apr_uri.h"\
+ "..\..\srclib\apr-util\include\apu.h"\
+ "..\..\srclib\apr\include\apr.h"\
+ "..\..\srclib\apr\include\apr_allocator.h"\
+ "..\..\srclib\apr\include\apr_dso.h"\
+ "..\..\srclib\apr\include\apr_errno.h"\
+ "..\..\srclib\apr\include\apr_file_info.h"\
+ "..\..\srclib\apr\include\apr_file_io.h"\
+ "..\..\srclib\apr\include\apr_general.h"\
+ "..\..\srclib\apr\include\apr_global_mutex.h"\
+ "..\..\srclib\apr\include\apr_hash.h"\
+ "..\..\srclib\apr\include\apr_inherit.h"\
+ "..\..\srclib\apr\include\apr_mmap.h"\
+ "..\..\srclib\apr\include\apr_network_io.h"\
+ "..\..\srclib\apr\include\apr_poll.h"\
+ "..\..\srclib\apr\include\apr_pools.h"\
+ "..\..\srclib\apr\include\apr_portable.h"\
+ "..\..\srclib\apr\include\apr_proc_mutex.h"\
+ "..\..\srclib\apr\include\apr_ring.h"\
+ "..\..\srclib\apr\include\apr_shm.h"\
+ "..\..\srclib\apr\include\apr_strings.h"\
+ "..\..\srclib\apr\include\apr_tables.h"\
+ "..\..\srclib\apr\include\apr_thread_mutex.h"\
+ "..\..\srclib\apr\include\apr_thread_proc.h"\
+ "..\..\srclib\apr\include\apr_time.h"\
+ "..\..\srclib\apr\include\apr_user.h"\
+ "..\..\srclib\apr\include\apr_want.h"\
+ ".\mod_watchdog.h"\
+
diff --git a/modules/core/mod_watchdog.dsp b/modules/core/mod_watchdog.dsp
new file mode 100644
index 0000000..fcb1f28
--- /dev/null
+++ b/modules/core/mod_watchdog.dsp
@@ -0,0 +1,115 @@
+# Microsoft Developer Studio Project File - Name="mod_watchdog" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_watchdog - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_watchdog.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_watchdog.mak" CFG="mod_watchdog - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_watchdog - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_watchdog - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_watchdog_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so /opt:ref
+# Begin Special Build Tool
+TargetPath=.\Release\mod_watchdog.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_watchdog_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so
+# Begin Special Build Tool
+TargetPath=.\Debug\mod_watchdog.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_watchdog - Win32 Release"
+# Name "mod_watchdog - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_watchdog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_watchdog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\httpd.rc
+# End Source File
+# End Target
+# End Project
diff --git a/modules/core/mod_watchdog.h b/modules/core/mod_watchdog.h
new file mode 100644
index 0000000..8e7112c
--- /dev/null
+++ b/modules/core/mod_watchdog.h
@@ -0,0 +1,213 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MOD_WATCHDOG_H
+#define MOD_WATCHDOG_H
+
+/**
+ * @file mod_watchdog.h
+ * @brief Watchdog module for Apache
+ *
+ * @defgroup MOD_WATCHDOG mod_watchdog
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "ap_provider.h"
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_shm.h"
+#include "apr_hash.h"
+#include "apr_hooks.h"
+#include "apr_optional.h"
+#include "apr_file_io.h"
+#include "apr_time.h"
+#include "apr_thread_proc.h"
+#include "apr_global_mutex.h"
+#include "apr_thread_mutex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Default singleton watchdog instance name.
+ * Singleton watchdog is protected by mutex and
+ * guaranteed to be run inside a single child process
+ * at any time.
+ */
+#define AP_WATCHDOG_SINGLETON "_singleton_"
+
+/**
+ * Default watchdog instance name
+ */
+#define AP_WATCHDOG_DEFAULT "_default_"
+
+/**
+ * Default Watchdog interval
+ */
+#define AP_WD_TM_INTERVAL APR_TIME_C(1000000) /* 1 second */
+
+/**
+ * Watchdog thread timer resolution
+ */
+#define AP_WD_TM_SLICE APR_TIME_C(100000) /* 100 ms */
+
+/* State values for callback */
+#define AP_WATCHDOG_STATE_STARTING 1
+#define AP_WATCHDOG_STATE_RUNNING 2
+#define AP_WATCHDOG_STATE_STOPPING 3
+
+typedef struct ap_watchdog_t ap_watchdog_t;
+
+/* Create a set of AP_WD_DECLARE(type), AP_WD_DECLARE_NONSTD(type) and
+ * AP_WD_DECLARE_DATA with appropriate export and import tags for the platform
+ */
+#if !defined(AP_WD_DECLARE)
+#if !defined(WIN32)
+#define AP_WD_DECLARE(type) type
+#define AP_WD_DECLARE_NONSTD(type) type
+#define AP_WD_DECLARE_DATA
+#elif defined(AP_WD_DECLARE_STATIC)
+#define AP_WD_DECLARE(type) type __stdcall
+#define AP_WD_DECLARE_NONSTD(type) type
+#define AP_WD_DECLARE_DATA
+#elif defined(AP_WD_DECLARE_EXPORT)
+#define AP_WD_DECLARE(type) __declspec(dllexport) type __stdcall
+#define AP_WD_DECLARE_NONSTD(type) __declspec(dllexport) type
+#define AP_WD_DECLARE_DATA __declspec(dllexport)
+#else
+#define AP_WD_DECLARE(type) __declspec(dllimport) type __stdcall
+#define AP_WD_DECLARE_NONSTD(type) __declspec(dllimport) type
+#define AP_WD_DECLARE_DATA __declspec(dllimport)
+#endif
+#endif
+
+/**
+ * Callback function used for watchdog.
+ * @param state Watchdog state function. See @p AP_WATCHDOG_STATE_ .
+ * @param data is what was passed to @p ap_watchdog_register_callback function.
+ * @param pool Temporary callback pool destroyed after the call.
+ * @return APR_SUCCESS to continue calling this callback.
+ */
+typedef apr_status_t ap_watchdog_callback_fn_t(int state, void *data,
+ apr_pool_t *pool);
+
+/**
+ * Get watchdog instance.
+ * @param watchdog Storage for watchdog instance.
+ * @param name Watchdog name.
+ * @param parent Non-zero to get the parent process watchdog instance.
+ * @param singleton Non-zero to get the singleton watchdog instance.
+ * @param p The pool to use.
+ * @return APR_SUCCESS if all went well
+ * @remark Use @p AP_WATCHDOG_DEFAULT to get default watchdog instance.
+ * If separate watchdog thread is needed provide unique name
+ * and function will create a new watchdog instance.
+ * Note that default client process watchdog works in singleton mode.
+ */
+APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_watchdog_get_instance,
+ (ap_watchdog_t **watchdog, const char *name, int parent,
+ int singleton, apr_pool_t *p));
+
+/**
+ * Register watchdog callback.
+ * @param watchdog Watchdog to use
+ * @param interval Interval on which the callback function will execute.
+ * @param callback The function to call on watchdog event.
+ * @param data The data to pass to the callback function.
+ * @return APR_SUCCESS if all went well. APR_EEXIST if already registered.
+ */
+APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_watchdog_register_callback,
+ (ap_watchdog_t *watchdog, apr_interval_time_t interval,
+ const void *data, ap_watchdog_callback_fn_t *callback));
+
+/**
+ * Update registered watchdog callback interval.
+ * @param w Watchdog to use
+ * @param interval New interval on which the callback function will execute.
+ * @param callback The function to call on watchdog event.
+ * @param data The data to pass to the callback function.
+ * @return APR_SUCCESS if all went well. APR_EOF if callback was not found.
+ */
+APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_watchdog_set_callback_interval,
+ (ap_watchdog_t *w, apr_interval_time_t interval,
+ const void *data, ap_watchdog_callback_fn_t *callback));
+
+/**
+ * Watchdog require hook.
+ * @param s The server record
+ * @param name Watchdog name.
+ * @param parent Non-zero to indicate the parent process watchdog mode.
+ * @param singleton Non-zero to indicate the singleton watchdog mode.
+ * @return OK to enable notifications from this watchdog, DECLINED otherwise.
+ * @remark This is called in post config phase for all watchdog instances
+ * that have no callbacks registered. Modules using this hook
+ * should ensure that their post_config hook is called after watchdog
+ * post_config.
+ */
+APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_need, (server_rec *s,
+ const char *name,
+ int parent, int singleton))
+
+
+/**
+ * Watchdog initialize hook.
+ * It is called after the watchdog thread is initialized.
+ * @param s The server record
+ * @param name Watchdog name.
+ * @param pool The pool used to create the watchdog.
+ */
+APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_init, (
+ server_rec *s,
+ const char *name,
+ apr_pool_t *pool))
+
+/**
+ * Watchdog terminate hook.
+ * It is called when the watchdog thread is terminated.
+ * @param s The server record
+ * @param name Watchdog name.
+ * @param pool The pool used to create the watchdog.
+ */
+APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_exit, (
+ server_rec *s,
+ const char *name,
+ apr_pool_t *pool))
+
+/**
+ * Fixed interval watchdog hook.
+ * It is called regularly on @p AP_WD_TM_INTERVAL interval.
+ * @param s The server record
+ * @param name Watchdog name.
+ * @param pool Temporary pool destroyed after the call.
+ */
+APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_step, (
+ server_rec *s,
+ const char *name,
+ apr_pool_t *pool))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MOD_WATCHDOG_H */
+/** @} */
diff --git a/modules/core/mod_watchdog.mak b/modules/core/mod_watchdog.mak
new file mode 100644
index 0000000..6b58c6d
--- /dev/null
+++ b/modules/core/mod_watchdog.mak
@@ -0,0 +1,353 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_watchdog.dsp
+!IF "$(CFG)" == ""
+CFG=mod_watchdog - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_watchdog - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_watchdog - Win32 Release" && "$(CFG)" != "mod_watchdog - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_watchdog.mak" CFG="mod_watchdog - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_watchdog - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_watchdog - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_watchdog.obj"
+ -@erase "$(INTDIR)\mod_watchdog.res"
+ -@erase "$(INTDIR)\mod_watchdog_src.idb"
+ -@erase "$(INTDIR)\mod_watchdog_src.pdb"
+ -@erase "$(OUTDIR)\mod_watchdog.exp"
+ -@erase "$(OUTDIR)\mod_watchdog.lib"
+ -@erase "$(OUTDIR)\mod_watchdog.pdb"
+ -@erase "$(OUTDIR)\mod_watchdog.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_watchdog_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_watchdog.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_watchdog.pdb" /debug /out:"$(OUTDIR)\mod_watchdog.so" /implib:"$(OUTDIR)\mod_watchdog.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_watchdog.obj" \
+ "$(INTDIR)\mod_watchdog.res" \
+ "..\..\srclib\apr\Release\libapr-1.lib" \
+ "..\..\srclib\apr-util\Release\libaprutil-1.lib" \
+ "..\..\Release\libhttpd.lib"
+
+"$(OUTDIR)\mod_watchdog.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Release\mod_watchdog.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_watchdog.so"
+ if exist .\Release\mod_watchdog.so.manifest mt.exe -manifest .\Release\mod_watchdog.so.manifest -outputresource:.\Release\mod_watchdog.so;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_watchdog.obj"
+ -@erase "$(INTDIR)\mod_watchdog.res"
+ -@erase "$(INTDIR)\mod_watchdog_src.idb"
+ -@erase "$(INTDIR)\mod_watchdog_src.pdb"
+ -@erase "$(OUTDIR)\mod_watchdog.exp"
+ -@erase "$(OUTDIR)\mod_watchdog.lib"
+ -@erase "$(OUTDIR)\mod_watchdog.pdb"
+ -@erase "$(OUTDIR)\mod_watchdog.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_watchdog_src" /FD /EHsc /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_watchdog.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_watchdog.pdb" /debug /out:"$(OUTDIR)\mod_watchdog.so" /implib:"$(OUTDIR)\mod_watchdog.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so
+LINK32_OBJS= \
+ "$(INTDIR)\mod_watchdog.obj" \
+ "$(INTDIR)\mod_watchdog.res" \
+ "..\..\srclib\apr\Debug\libapr-1.lib" \
+ "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \
+ "..\..\Debug\libhttpd.lib"
+
+"$(OUTDIR)\mod_watchdog.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Debug\mod_watchdog.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_watchdog.so"
+ if exist .\Debug\mod_watchdog.so.manifest mt.exe -manifest .\Debug\mod_watchdog.so.manifest -outputresource:.\Debug\mod_watchdog.so;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_watchdog.dep")
+!INCLUDE "mod_watchdog.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_watchdog.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release" || "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release"
+
+"libapr - Win32 Release" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release"
+ cd "..\..\modules\core"
+
+"libapr - Win32 ReleaseCLEAN" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+"libapr - Win32 Debug" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug"
+ cd "..\..\modules\core"
+
+"libapr - Win32 DebugCLEAN" :
+ cd ".\..\..\srclib\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ENDIF
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release"
+
+"libaprutil - Win32 Release" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"
+ cd "..\..\modules\core"
+
+"libaprutil - Win32 ReleaseCLEAN" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+"libaprutil - Win32 Debug" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
+ cd "..\..\modules\core"
+
+"libaprutil - Win32 DebugCLEAN" :
+ cd ".\..\..\srclib\apr-util"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\modules\core"
+
+!ENDIF
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release"
+
+"libhttpd - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release"
+ cd ".\modules\core"
+
+"libhttpd - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN
+ cd ".\modules\core"
+
+!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+"libhttpd - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"
+ cd ".\modules\core"
+
+"libhttpd - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\modules\core"
+
+!ENDIF
+
+SOURCE=..\..\build\win32\httpd.rc
+
+!IF "$(CFG)" == "mod_watchdog - Win32 Release"
+
+
+"$(INTDIR)\mod_watchdog.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug"
+
+
+"$(INTDIR)\mod_watchdog.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\mod_watchdog.c
+
+"$(INTDIR)\mod_watchdog.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/modules/core/test/Makefile b/modules/core/test/Makefile
new file mode 100644
index 0000000..bd2a6cb
--- /dev/null
+++ b/modules/core/test/Makefile
@@ -0,0 +1,67 @@
+#
+# mod_macro non regression tests
+
+# where is apache
+APA.dir = /tmp/apache
+
+# apache executable with mod macro loaded
+HTTPD = \
+ $(APA.dir)/bin/httpd \
+ -C 'LoadModule macro_module modules/mod_macro.so' \
+ -C "Define PWD $$PWD/conf"
+
+# default target
+.PHONY: default
+default: clean
+
+# run all non regression tests
+.PHONY: check
+check: check-out
+
+# result directory
+OUT = out
+out:
+ mkdir $@
+
+# test cases & results
+F.conf = $(wildcard conf/test*.conf)
+F.out = $(F.conf:conf/%.conf=$(OUT)/%.out)
+
+# run all tests
+.PHONY: run-test
+run-test: $(F.out)
+
+# generate & compare in a separate directory
+.PHONY: check-out
+check-out: out
+ $(RM) out/*.out
+ $(MAKE) OUT=out run-test
+ diff -r out/ ref/
+
+# generate & compare in the same directory
+.PHONY: check-ref
+check-ref:
+ $(RM) ref/*.out
+ $(MAKE) OUT=ref run-test
+ svn diff ref/
+
+# run one test case
+# filter output so that it is portable
+# use '|' sed separator because $PWD will contain plenty '/'
+$(OUT)/%.out: conf/%.conf
+ { \
+ echo "# testing with $<" ; \
+ $(HTTPD) -f $$PWD/$< 2>&1 ; \
+ echo "# exit: $$?" ; \
+ } > $@.tmp ; \
+ sed -e "s|$$PWD|.|g" \
+ -e "s|^\[[\.a-zA-Z0-9 :]*\] ||" \
+ -e "s|\[pid [0-9]*:tid [0-9]*] ||" \
+ $@.tmp > $@ ; \
+ $(RM) $@.tmp
+
+# cleanup
+.PHONY: clean
+clean:
+ $(RM) *~
+ $(RM) -r out
diff --git a/modules/core/test/conf/inc63_1.conf b/modules/core/test/conf/inc63_1.conf
new file mode 100644
index 0000000..6a436f9
--- /dev/null
+++ b/modules/core/test/conf/inc63_1.conf
@@ -0,0 +1,5 @@
+# macro for include
+<Macro Foo $where>
+ Warning "Foo macro at $where"
+</Macro>
+Use Foo "inc63_.conf:5"
diff --git a/modules/core/test/conf/inc63_2.conf b/modules/core/test/conf/inc63_2.conf
new file mode 100644
index 0000000..3a0da9e
--- /dev/null
+++ b/modules/core/test/conf/inc63_2.conf
@@ -0,0 +1,3 @@
+# use macro defined elsewhere
+Use Foo "inc63_2.conf:2"
+Use Bla "inc63_2.conf:3"
diff --git a/modules/core/test/conf/test01.conf b/modules/core/test/conf/test01.conf
new file mode 100644
index 0000000..9a3d9ab
--- /dev/null
+++ b/modules/core/test/conf/test01.conf
@@ -0,0 +1,3 @@
+# no macro name
+<Macro>
+</Macro>
diff --git a/modules/core/test/conf/test02.conf b/modules/core/test/conf/test02.conf
new file mode 100644
index 0000000..1fe4b41
--- /dev/null
+++ b/modules/core/test/conf/test02.conf
@@ -0,0 +1,3 @@
+# no macro name and spaces
+<Macro >
+</Macro>
diff --git a/modules/core/test/conf/test03.conf b/modules/core/test/conf/test03.conf
new file mode 100644
index 0000000..fdcf4c8
--- /dev/null
+++ b/modules/core/test/conf/test03.conf
@@ -0,0 +1,5 @@
+# use undefined macro
+<Macro foo>
+ Warning "macro foo"
+</Macro>
+Use bla
diff --git a/modules/core/test/conf/test04.conf b/modules/core/test/conf/test04.conf
new file mode 100644
index 0000000..8228775
--- /dev/null
+++ b/modules/core/test/conf/test04.conf
@@ -0,0 +1,5 @@
+# wrong args
+<Macro foo>
+ Warning "macro foo"
+</Macro>
+Use foo hello
diff --git a/modules/core/test/conf/test05.conf b/modules/core/test/conf/test05.conf
new file mode 100644
index 0000000..2166aca
--- /dev/null
+++ b/modules/core/test/conf/test05.conf
@@ -0,0 +1,5 @@
+# wrong args
+<Macro foo $premier>
+ Warning "macro foo $premier"
+</Macro>
+Use foo
diff --git a/modules/core/test/conf/test06.conf b/modules/core/test/conf/test06.conf
new file mode 100644
index 0000000..35e6b68
--- /dev/null
+++ b/modules/core/test/conf/test06.conf
@@ -0,0 +1,6 @@
+# wrong args
+<Macro foo $premier>
+ Warning "macro foo $premier"
+</Macro>
+Use foo one two
+
diff --git a/modules/core/test/conf/test07.conf b/modules/core/test/conf/test07.conf
new file mode 100644
index 0000000..06f050e
--- /dev/null
+++ b/modules/core/test/conf/test07.conf
@@ -0,0 +1,3 @@
+# missing end macro
+<Macro foo $premier>
+hello
diff --git a/modules/core/test/conf/test08.conf b/modules/core/test/conf/test08.conf
new file mode 100644
index 0000000..333dbd9
--- /dev/null
+++ b/modules/core/test/conf/test08.conf
@@ -0,0 +1,3 @@
+# missing begin macro
+ServerName hello
+</Macro>
diff --git a/modules/core/test/conf/test09.conf b/modules/core/test/conf/test09.conf
new file mode 100644
index 0000000..2513b6e
--- /dev/null
+++ b/modules/core/test/conf/test09.conf
@@ -0,0 +1,6 @@
+# recursion is bad
+<Macro foo>
+Use foo
+</Macro>
+
+Use foo
diff --git a/modules/core/test/conf/test10.conf b/modules/core/test/conf/test10.conf
new file mode 100644
index 0000000..157129d
--- /dev/null
+++ b/modules/core/test/conf/test10.conf
@@ -0,0 +1,10 @@
+# indirect recursion is bad
+<Macro foo>
+Use bla
+</Macro>
+
+<Macro bla>
+Use foo
+</Macro>
+
+Use foo
diff --git a/modules/core/test/conf/test11.conf b/modules/core/test/conf/test11.conf
new file mode 100644
index 0000000..f397ec6
--- /dev/null
+++ b/modules/core/test/conf/test11.conf
@@ -0,0 +1,15 @@
+# inner macros...
+<Macro foo $arg>
+<Macro $arg.in>
+Warning "macro $arg.in line 1"
+</Macro>
+</Macro>
+
+# generate a one.in macro
+Use foo one
+
+# use it!
+Use one.in
+
+# end processing
+Error "done line 15."
diff --git a/modules/core/test/conf/test12.conf b/modules/core/test/conf/test12.conf
new file mode 100644
index 0000000..84403c6
--- /dev/null
+++ b/modules/core/test/conf/test12.conf
@@ -0,0 +1,12 @@
+# multiply defined generates a warning
+<Macro foo>
+ Warning "macro foo 1, line 1"
+</Macro>
+
+<Macro foo>
+ Warning "macro foo 2, line 1"
+</Macro>
+
+Use foo
+
+Error "done line 12."
diff --git a/modules/core/test/conf/test13.conf b/modules/core/test/conf/test13.conf
new file mode 100644
index 0000000..244470d
--- /dev/null
+++ b/modules/core/test/conf/test13.conf
@@ -0,0 +1,18 @@
+# case insensitive
+<Macro FOO>
+ Warning "macro FOO line 1"
+</MACRO>
+
+<MACRO bla>
+ Warning "macro bla line 1"
+</macro>
+
+use foo
+
+<macro foo>
+ Warning "redefined macro foo line 1"
+</macro>
+
+use FOO
+
+Error "done line 18."
diff --git a/modules/core/test/conf/test14.conf b/modules/core/test/conf/test14.conf
new file mode 100644
index 0000000..48d8888
--- /dev/null
+++ b/modules/core/test/conf/test14.conf
@@ -0,0 +1,23 @@
+# VirtualHost example
+
+<Macro MyVirtualHost $host $port $dir>
+ Listen $port
+ <VirtualHost $host:$port>
+ DocumentRoot $dir
+ <Directory $dir>
+ Warning "directory $dir"
+ </Directory>
+ # limit access to intranet subdir.
+ <Directory $dir/intranet>
+ Warning "directory $dir/intranet"
+ </Directory>
+ </VirtualHost>
+</Macro>
+
+Use MyVirtualHost www.apache.org 80 /projects/apache/web
+
+Use MyVirtualHost www.perl.com 8080 /projects/perl/web
+
+Use MyVirtualHost www.ensmp.fr 1234 /projects/mines/web
+
+Error "done line 23."
diff --git a/modules/core/test/conf/test15.conf b/modules/core/test/conf/test15.conf
new file mode 100644
index 0000000..7990e15
--- /dev/null
+++ b/modules/core/test/conf/test15.conf
@@ -0,0 +1,9 @@
+# non nested...
+<macro test>
+<directory /tmp>
+</macro>
+
+use test
+</directory>
+
+Error should not reach this point.
diff --git a/modules/core/test/conf/test16.conf b/modules/core/test/conf/test16.conf
new file mode 100644
index 0000000..471f66e
--- /dev/null
+++ b/modules/core/test/conf/test16.conf
@@ -0,0 +1,11 @@
+# bad nesting
+
+<Macro foo>
+</Limit>
+</Macro>
+
+<Limit GET>
+Use foo
+</Limit>
+
+stop
diff --git a/modules/core/test/conf/test17.conf b/modules/core/test/conf/test17.conf
new file mode 100644
index 0000000..f6294bb
--- /dev/null
+++ b/modules/core/test/conf/test17.conf
@@ -0,0 +1,10 @@
+# bad but good nesting
+
+<Macro foo>
+</Directory>
+</Macro>
+
+<Directory /tmp>
+Use foo
+
+Error "done on line 10."
diff --git a/modules/core/test/conf/test18.conf b/modules/core/test/conf/test18.conf
new file mode 100644
index 0000000..118617d
--- /dev/null
+++ b/modules/core/test/conf/test18.conf
@@ -0,0 +1,10 @@
+# bad but good nesting
+
+<Macro foo>
+</Location>
+</Macro>
+
+<Location /intranet>
+Use foo
+
+Error "done on line 10."
diff --git a/modules/core/test/conf/test19.conf b/modules/core/test/conf/test19.conf
new file mode 100644
index 0000000..6568e96
--- /dev/null
+++ b/modules/core/test/conf/test19.conf
@@ -0,0 +1,26 @@
+# okay till done
+
+<Macro foo $where>
+ # something
+ Warning "macro foo line 2 in $where"
+</Macro>
+
+<Directory /tmp>
+ Use foo Directory
+</Directory>
+
+<Location /intra>
+ Use foo Location
+</Location>
+
+<VirtualHost www.apache.org>
+ Use foo VirtualHost
+</VirtualHost>
+
+<VirtualHost www.perl.com>
+ <Directory /tmp>
+ Use foo "VirtualHost & Directory"
+ </Directory>
+</VirtualHost>
+
+Error "done line 26."
diff --git a/modules/core/test/conf/test20.conf b/modules/core/test/conf/test20.conf
new file mode 100644
index 0000000..ccbae0d
--- /dev/null
+++ b/modules/core/test/conf/test20.conf
@@ -0,0 +1,11 @@
+# directory in directory through a macro
+
+<Macro foo $dir>
+ <Directory $dir>
+ Warning "macro foo $dir"
+ </Directory>
+</Macro>
+
+<Directory /tmp>
+ Use foo /tmp
+</Directory>
diff --git a/modules/core/test/conf/test21.conf b/modules/core/test/conf/test21.conf
new file mode 100644
index 0000000..7a8c4c9
--- /dev/null
+++ b/modules/core/test/conf/test21.conf
@@ -0,0 +1,11 @@
+# raise an error
+
+<Macro foo>
+ <Directory /tmp>
+ Error "macro foo dir /tmp"
+ </Directory>
+</Macro>
+
+<VirtualHost *>
+ Use foo
+</VirtualHost>
diff --git a/modules/core/test/conf/test22.conf b/modules/core/test/conf/test22.conf
new file mode 100644
index 0000000..5a89f83
--- /dev/null
+++ b/modules/core/test/conf/test22.conf
@@ -0,0 +1,11 @@
+# simple nesting
+
+<Macro foo>
+ <Directory /tmp>
+ Warning "macro foo"
+ </Directory>
+</Macro>
+
+Use foo
+
+Error "done on line 11."
diff --git a/modules/core/test/conf/test23.conf b/modules/core/test/conf/test23.conf
new file mode 100644
index 0000000..e21e2ee
--- /dev/null
+++ b/modules/core/test/conf/test23.conf
@@ -0,0 +1,15 @@
+# macro defined in a directory
+
+<Directory /tmp>
+ <Macro foo>
+ Warning "macro foo in /tmp"
+ </Macro>
+</Directory>
+
+Use foo
+
+<Directory /tmp>
+ Use foo
+</Directory>
+
+Error "done!"
diff --git a/modules/core/test/conf/test24.conf b/modules/core/test/conf/test24.conf
new file mode 100644
index 0000000..d35070e
--- /dev/null
+++ b/modules/core/test/conf/test24.conf
@@ -0,0 +1,23 @@
+# nesting...
+
+<Macro bla>
+ <Location /intra>
+ Warning "macro bla intra"
+ </Location>
+ <Location /private>
+ Warning "macro bla private"
+ </Location>
+</Macro>
+
+# ok location in config
+Use bla
+
+# ok, location in VH
+<VirtualHost foo.com>
+ Use bla
+</VirtualHost>
+
+<Directory /tmp>
+ # fails: Location within an Directory
+ Use bla
+</Directory>
diff --git a/modules/core/test/conf/test25.conf b/modules/core/test/conf/test25.conf
new file mode 100644
index 0000000..724cf94
--- /dev/null
+++ b/modules/core/test/conf/test25.conf
@@ -0,0 +1,27 @@
+# ok till stop.
+
+<Macro RestrictedAccessPolicy $ips>
+ Warning "restricted access policy $ips"
+</Macro>
+
+<Directory /unexpected/1>
+ Use RestrictedAccessPolicy 10.0.0.0/8
+</Directory>
+
+<Macro LocalAccessOnly>
+ Use RestrictedAccessPolicy 10.0.0.0/8
+</Macro>
+
+<Directory /unexpected/2>
+ Use RestrictedAccessPolicy "192.54.172.0/24 192.54.148.0/24 10.0.0.0/8"
+</Directory>
+
+<Location /intra>
+ Use LocalAccessOnly
+</Location>
+
+<Location /admin>
+ Use LocalAccessOnly
+</Location>
+
+Error "done line 27."
diff --git a/modules/core/test/conf/test26.conf b/modules/core/test/conf/test26.conf
new file mode 100644
index 0000000..bb4b5ad
--- /dev/null
+++ b/modules/core/test/conf/test26.conf
@@ -0,0 +1,19 @@
+# ok till stop.
+# test quotes...
+
+<Macro funny "first arg" 'second ... arg'>
+ <Directory first arg>
+ Warning "funny directory"
+ </Directory>
+ <Location second ... arg>
+ Warning "funny location"
+ </Location>
+</Macro>
+
+Use funny /unexpected/1 /intra
+
+<VirtualHost www.apache.org>
+ Use funny /unexpected/2 /intranet
+</VirtualHost>
+
+Error "done!"
diff --git a/modules/core/test/conf/test27.conf b/modules/core/test/conf/test27.conf
new file mode 100644
index 0000000..2f3e83c
--- /dev/null
+++ b/modules/core/test/conf/test27.conf
@@ -0,0 +1,22 @@
+# define a macro in a macro.
+
+<Macro foo $dir $name>
+ <Macro foo.$name>
+ <Directory $dir>
+ Warning "foo.$name $dir"
+ </Directory>
+ </Macro>
+</Macro>
+
+Use foo /unexpected/1 one
+Use foo /unexpected/2 two
+
+Use foo.one
+Use foo.two
+Use foo.one
+
+UndefMacro foo.one
+UndefMacro foo.two
+UndefMacro foo
+
+Error "done!"
diff --git a/modules/core/test/conf/test28.conf b/modules/core/test/conf/test28.conf
new file mode 100644
index 0000000..69c1c9b
--- /dev/null
+++ b/modules/core/test/conf/test28.conf
@@ -0,0 +1,13 @@
+# interaction with IfModule
+
+<IfModule mod_macro.c>
+ <Macro foo>
+ Warning "macro foo"
+ </Macro>
+
+ Use foo
+
+ Error "done!"
+</IfModule>
+
+Error "should not get there"
diff --git a/modules/core/test/conf/test29.conf b/modules/core/test/conf/test29.conf
new file mode 100644
index 0000000..7d1f380
--- /dev/null
+++ b/modules/core/test/conf/test29.conf
@@ -0,0 +1,10 @@
+# trigger line overflow during expansion
+
+<Macro toobigaline a>
+ Warning aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+</Macro>
+
+Use toobigaline "cette ligne va etre vraiment trop longue ya pas de doute"
+
+Error "should not get there!"
diff --git a/modules/core/test/conf/test30.conf b/modules/core/test/conf/test30.conf
new file mode 100644
index 0000000..72b2bb2
--- /dev/null
+++ b/modules/core/test/conf/test30.conf
@@ -0,0 +1,12 @@
+# name conficts: the longest is chosen
+# also test a parametric section
+
+<Macro foo $dir $directive>
+ <$directive $dir>
+ Warning "section $directive $dir"
+ </$directive>
+</Macro>
+
+Use foo /unexpected/1 Directory
+
+Error "done!"
diff --git a/modules/core/test/conf/test31.conf b/modules/core/test/conf/test31.conf
new file mode 100644
index 0000000..14964ba
--- /dev/null
+++ b/modules/core/test/conf/test31.conf
@@ -0,0 +1,16 @@
+# parameter name conflicts
+
+<Macro bla $dir $di $dd $d>
+ Warning "argument name conflicts"
+ $d $di $dir $dd
+</Macro>
+
+Use bla '' '' 8080 Listen
+
+<Macro foo $d $di $dir $dd>
+ Warning "conflicts, but arguments are not used"
+</Macro>
+
+Use foo '' '' 8080 Listen
+
+Error "done on line 16."
diff --git a/modules/core/test/conf/test32.conf b/modules/core/test/conf/test32.conf
new file mode 100644
index 0000000..0b116ec
--- /dev/null
+++ b/modules/core/test/conf/test32.conf
@@ -0,0 +1,7 @@
+# error if same argument name.
+
+<Macro foo $arg1 $arg2 $arg3 $arg2>
+# bad
+</Macro>
+
+
diff --git a/modules/core/test/conf/test33.conf b/modules/core/test/conf/test33.conf
new file mode 100644
index 0000000..2a8a6db
--- /dev/null
+++ b/modules/core/test/conf/test33.conf
@@ -0,0 +1,3 @@
+# empty name.
+
+Use ''
diff --git a/modules/core/test/conf/test34.conf b/modules/core/test/conf/test34.conf
new file mode 100644
index 0000000..1f4671f
--- /dev/null
+++ b/modules/core/test/conf/test34.conf
@@ -0,0 +1,14 @@
+# macro parameter prefix conflicts in two orders
+
+<Macro foo $d $dd>
+ Warning "macro foo conflict one"
+</Macro>
+
+<Macro bla $dd $d>
+ Warning "macro bla conflict two"
+</Macro>
+
+Use foo 1 2
+Use bla 1 2
+
+Error "done on line 14."
diff --git a/modules/core/test/conf/test35.conf b/modules/core/test/conf/test35.conf
new file mode 100644
index 0000000..37a623e
--- /dev/null
+++ b/modules/core/test/conf/test35.conf
@@ -0,0 +1,10 @@
+# unused arguments
+
+<Macro warnings u1 u2 n1 n2 u3>
+ Warning "macro cannot be used just within a comment u1 u2 u3"
+ # n1 n2
+</Macro>
+
+Use warnings 1 2 3 4 5
+
+Error "done on line 10."
diff --git a/modules/core/test/conf/test36.conf b/modules/core/test/conf/test36.conf
new file mode 100644
index 0000000..a68667e
--- /dev/null
+++ b/modules/core/test/conf/test36.conf
@@ -0,0 +1,12 @@
+<Macro warnings $u $n $u1 $n1 $u2 $n2>
+ Warning "many warnings! $u $u1 $u2"
+ # $n $n1 $n2
+</Macro>
+
+# warn about unused arguments
+Use warnings 1 2 3 4 5 6
+
+# may warn about empty arguments?
+Use warnings '' '' '' '' '' ''
+
+Error "done!"
diff --git a/modules/core/test/conf/test37.conf b/modules/core/test/conf/test37.conf
new file mode 100644
index 0000000..296dde7
--- /dev/null
+++ b/modules/core/test/conf/test37.conf
@@ -0,0 +1,7 @@
+# empty argument name
+
+<Macro stupid ''>
+ Warn "macro stupid"
+</Macro>
+
+Use stupid hello
diff --git a/modules/core/test/conf/test38.conf b/modules/core/test/conf/test38.conf
new file mode 100644
index 0000000..184763f
--- /dev/null
+++ b/modules/core/test/conf/test38.conf
@@ -0,0 +1,10 @@
+# ifmodule
+
+<IfModule mod_macro.c>
+Warning it is really a good idea to have mod_macro.c installed.
+</IfModule>
+
+<IfModule !mod_perl.c>
+Error it seems you do not have mod perl installed.
+</IfModule>
+
diff --git a/modules/core/test/conf/test39.conf b/modules/core/test/conf/test39.conf
new file mode 100644
index 0000000..792232f
--- /dev/null
+++ b/modules/core/test/conf/test39.conf
@@ -0,0 +1,23 @@
+# okay till stop.
+
+<IfModule mod_macro.c>
+ <Macro ModMacro>
+ Warning Thanks for using mod_macro!
+ </Macro>
+</IfModule>
+
+<IfModule !mod_macro.c>
+ <Macro ModMacro>
+ Error Sorry, mod_macro must be installed to run this configuration file.
+ </Macro>
+</IfModule>
+
+Use ModMacro
+
+<Macro foo>
+ Warning "macro foo"
+</Macro>
+
+Use foo
+
+Error "done!"
diff --git a/modules/core/test/conf/test40.conf b/modules/core/test/conf/test40.conf
new file mode 100644
index 0000000..e6b81f7
--- /dev/null
+++ b/modules/core/test/conf/test40.conf
@@ -0,0 +1,33 @@
+# configuration example with mod_macro
+#
+
+<VirtualHost www.foo.com>
+ DocumentRoot /foo/document/root/directory
+
+ <Macro SubDirAccessControl $subdir>
+ # access control to subdirs...
+ <Location /$subdir>
+ Warning "location /$subdir"
+ </Location>
+ </Macro>
+
+ # repeat uses
+ Use SubDirAccessControl A
+ Use SubDirAccessControl B
+ Use SubDirAccessControl C
+ Use SubDirAccessControl D
+ Use SubDirAccessControl E
+ Use SubDirAccessControl G
+ Use SubDirAccessControl H
+ Use SubDirAccessControl J
+ Use SubDirAccessControl K
+ Use SubDirAccessControl L
+ Use SubDirAccessControl M
+ Use SubDirAccessControl N
+
+ # cleanup
+ UndefMacro SubDirAccessControl
+
+</VirtualHost>
+
+Error Stop configuration file processing.
diff --git a/modules/core/test/conf/test41.conf b/modules/core/test/conf/test41.conf
new file mode 100644
index 0000000..c4e6bdb
--- /dev/null
+++ b/modules/core/test/conf/test41.conf
@@ -0,0 +1,20 @@
+# another configuration example without mod_macro
+
+<VirtualHost www.foo.com>
+ DocumentRoot /foo/document/root/directory
+
+ <Location /A>
+ Warning "location /A"
+ </Location>
+
+ <Location /B>
+ Warning "location /B"
+ </Location>
+
+ <Location /C>
+ Warning "location /C"
+ </Location>
+
+</VirtualHost>
+
+Error Stop configuration file processing.
diff --git a/modules/core/test/conf/test42.conf b/modules/core/test/conf/test42.conf
new file mode 100644
index 0000000..a142604
--- /dev/null
+++ b/modules/core/test/conf/test42.conf
@@ -0,0 +1,13 @@
+# multiple macro uses
+
+<Macro foo $p>
+ Warning "macro foo $p"
+</Macro>
+
+Use foo ''
+Use foo ''
+Use foo ''
+Use foo ''
+Use foo ''
+
+Error "done on line 13."
diff --git a/modules/core/test/conf/test43.conf b/modules/core/test/conf/test43.conf
new file mode 100644
index 0000000..264b916
--- /dev/null
+++ b/modules/core/test/conf/test43.conf
@@ -0,0 +1,29 @@
+# non necessarily nested.
+
+<Macro begindir $dir>
+<Directory $dir>
+# hello
+</Macro>
+
+<Macro enddir>
+</Directory>
+</Macro>
+
+Use begindir /unexpected/1
+Use enddir
+
+
+Use begindir /unexpected/2
+Use enddir
+
+Use begindir /unexpected/3
+<Limit GET>
+</Limit>
+Use enddir
+
+<VirtualHost foo.com>
+Use begindir /unexpected/4
+Use enddir
+</VirtualHost>
+
+Error ok!
diff --git a/modules/core/test/conf/test44.conf b/modules/core/test/conf/test44.conf
new file mode 100644
index 0000000..ef4883e
--- /dev/null
+++ b/modules/core/test/conf/test44.conf
@@ -0,0 +1,19 @@
+# working recursion...
+
+<Macro foo>
+use bla
+</Macro>
+
+<Macro bla>
+<IfDefine NoFoo>
+use foo
+</IfDefine>
+</Macro>
+
+
+<IfDefine !NoFoo>
+# foo gonna call bla, bla wont call foo back...
+use foo
+</IfDefine>
+
+Error okay.
diff --git a/modules/core/test/conf/test45.conf b/modules/core/test/conf/test45.conf
new file mode 100644
index 0000000..0394935
--- /dev/null
+++ b/modules/core/test/conf/test45.conf
@@ -0,0 +1,7 @@
+# strange chars
+
+<Macro warnings $1 %2 &3 @4 #5 ~6 *7 .8 ,9 !a -b +c =d :e ;f ?g>
+# hello $1 %2 &3 @4 #5 ~6 *7 .8 ,9 !a -b +c =d :e ;f ?g
+</Macro>
+
+Error "done on line 7."
diff --git a/modules/core/test/conf/test46.conf b/modules/core/test/conf/test46.conf
new file mode 100644
index 0000000..50520ed
--- /dev/null
+++ b/modules/core/test/conf/test46.conf
@@ -0,0 +1,11 @@
+# various working prefixes
+
+<Macro $i %j @k>
+# hello %j @k
+</Macro>
+
+<Macro warnings $i second>
+# not used.
+</Macro>
+
+Error okay.
diff --git a/modules/core/test/conf/test47.conf b/modules/core/test/conf/test47.conf
new file mode 100644
index 0000000..6e73664
--- /dev/null
+++ b/modules/core/test/conf/test47.conf
@@ -0,0 +1,15 @@
+# empty macro contents...
+
+<Macro foo>
+</Macro>
+
+Use foo
+
+<Macro bla $i>
+</Macro>
+
+<Macro bof $i>
+# some contents...
+</Macro>
+
+Error okay.
diff --git a/modules/core/test/conf/test48.conf b/modules/core/test/conf/test48.conf
new file mode 100644
index 0000000..96bf461
--- /dev/null
+++ b/modules/core/test/conf/test48.conf
@@ -0,0 +1,23 @@
+# test substitution...
+
+<Macro M %premier>
+Warning %premier
+</Macro>
+
+Use M 1
+Use M 12
+Use M 123
+Use M 1234
+Use M 12345
+Use M 123456
+Use M 1234567
+Use M 12345678
+Use M 123456789
+Use M 1234567890
+Use M 1234567890a
+Use M 1234567890ab
+Use M 1234567890abc
+Use M 1234567890abcd
+Use M 1234567890abcde
+
+Error "done line 23."
diff --git a/modules/core/test/conf/test49.conf b/modules/core/test/conf/test49.conf
new file mode 100644
index 0000000..7a21c82
--- /dev/null
+++ b/modules/core/test/conf/test49.conf
@@ -0,0 +1,2 @@
+# undef macro before anything
+UndefMacro foo
diff --git a/modules/core/test/conf/test50.conf b/modules/core/test/conf/test50.conf
new file mode 100644
index 0000000..33dd359
--- /dev/null
+++ b/modules/core/test/conf/test50.conf
@@ -0,0 +1,5 @@
+# undef non existing macro
+<Macro foo>
+ Warning "foo macro"
+</Macro>
+UndefMacro bla
diff --git a/modules/core/test/conf/test51.conf b/modules/core/test/conf/test51.conf
new file mode 100644
index 0000000..50214fa
--- /dev/null
+++ b/modules/core/test/conf/test51.conf
@@ -0,0 +1,9 @@
+# undef existing macro, and try to use it
+<Macro foo>
+ Warning "foo macro contents"
+</Macro>
+# expanded, but will not be processed because of error
+Use foo
+UndefMacro foo
+# error, does not exist anymore
+Use foo
diff --git a/modules/core/test/conf/test52.conf b/modules/core/test/conf/test52.conf
new file mode 100644
index 0000000..bb77c73
--- /dev/null
+++ b/modules/core/test/conf/test52.conf
@@ -0,0 +1,8 @@
+# undef existing macro, and try to use it
+<Macro foo>
+ Warning "foo macro contents line 1"
+</Macro>
+Use foo
+UndefMacro foo
+
+Error "done line 8."
diff --git a/modules/core/test/conf/test53.conf b/modules/core/test/conf/test53.conf
new file mode 100644
index 0000000..08e8c98
--- /dev/null
+++ b/modules/core/test/conf/test53.conf
@@ -0,0 +1,2 @@
+# use undefined macro without prior definition
+Use bla
diff --git a/modules/core/test/conf/test54.conf b/modules/core/test/conf/test54.conf
new file mode 100644
index 0000000..7dd30ac
--- /dev/null
+++ b/modules/core/test/conf/test54.conf
@@ -0,0 +1,6 @@
+# empty macro
+<Macro foo>
+</Macro>
+Use foo
+
+Error "done line 6."
diff --git a/modules/core/test/conf/test55.conf b/modules/core/test/conf/test55.conf
new file mode 100644
index 0000000..bd978e9
--- /dev/null
+++ b/modules/core/test/conf/test55.conf
@@ -0,0 +1,11 @@
+# line numbers...
+<Macro foo $where>
+ Warning "macro foo(:2) line 1 ($where)"
+</Macro>
+<Macro bla $where>
+ Warning "macro bla(:5) line 1 ($where)"
+ Use foo "bla line 2"
+</Macro>
+Use foo "file line 9"
+Use bla "file line 10"
+Error "done line 11."
diff --git a/modules/core/test/conf/test56.conf b/modules/core/test/conf/test56.conf
new file mode 100644
index 0000000..b7366a2
--- /dev/null
+++ b/modules/core/test/conf/test56.conf
@@ -0,0 +1,18 @@
+# nesting warnings
+<Macro Open $dir>
+ <Directory $dir>
+ Warning "Open:2 $dir"
+</Macro>
+<Macro Close>
+ Warning "Close:1"
+ </Directory>
+</Macro>
+
+# some uses
+Use Open /tmp
+Use Close
+
+Use Open /etc
+Use Close
+
+Error "done line 18."
diff --git a/modules/core/test/conf/test57.conf b/modules/core/test/conf/test57.conf
new file mode 100644
index 0000000..7c36868
--- /dev/null
+++ b/modules/core/test/conf/test57.conf
@@ -0,0 +1,4 @@
+# empty argument name
+<Macro foo $x ''>
+ Warning "macro foo line 1"
+</Macro>
diff --git a/modules/core/test/conf/test58.conf b/modules/core/test/conf/test58.conf
new file mode 100644
index 0000000..6c8a2eb
--- /dev/null
+++ b/modules/core/test/conf/test58.conf
@@ -0,0 +1,4 @@
+# bad directive closing
+<Macro foo
+ Warning "macro foo line 1"
+</Macro>
diff --git a/modules/core/test/conf/test59.conf b/modules/core/test/conf/test59.conf
new file mode 100644
index 0000000..9f43d7d
--- /dev/null
+++ b/modules/core/test/conf/test59.conf
@@ -0,0 +1,4 @@
+# empty name
+<Macro ''>
+ Warning "empty quoted name macro"
+</Macro>
diff --git a/modules/core/test/conf/test60.conf b/modules/core/test/conf/test60.conf
new file mode 100644
index 0000000..969a4eb
--- /dev/null
+++ b/modules/core/test/conf/test60.conf
@@ -0,0 +1,17 @@
+# @ escaping
+<Macro Foo $one $two>
+ Warning "macro Foo arg 1: $one"
+ Warning "macro Foo arg 2: $two"
+</Macro>
+<Macro Bla @first @second>
+ Warning Macro Bla arg 1: @first
+ Warning Macro Bla arg 2: @second
+ Use Foo @first 'second'
+ Use Foo 'first' @second
+ Use Foo @first @second
+</Macro>
+
+Use Foo hello world
+Use Bla "hello world" "thank you"
+
+Error "done on line 17."
diff --git a/modules/core/test/conf/test61.conf b/modules/core/test/conf/test61.conf
new file mode 100644
index 0000000..cd28597
--- /dev/null
+++ b/modules/core/test/conf/test61.conf
@@ -0,0 +1,18 @@
+# deep expansion
+<Macro F1 $x>
+ Warning "F1:1 x=$x"
+</Macro>
+<Macro F2 $x>
+ Warning "F2:1 x=$x"
+ Use F1 $x
+</Macro>
+<Macro F3 $x>
+ Warning "F3:1 x=$x"
+ Use F2 $x
+</Macro>
+<Macro F4 $x>
+ Warning "F4:1 x=$x"
+ Use F3 $x
+</Macro>
+Use F4 "line=17"
+Error "done line 18."
diff --git a/modules/core/test/conf/test62.conf b/modules/core/test/conf/test62.conf
new file mode 100644
index 0000000..9d611de
--- /dev/null
+++ b/modules/core/test/conf/test62.conf
@@ -0,0 +1,25 @@
+# test continuations
+<Macro Line \
+ $start \
+ $stop>
+ Warning \
+ "Line:1-2 start at $start"
+ Warning \
+ "Line:3-4 stop at $stop"
+</Macro>
+
+Use Line 11 11
+Use Line \
+ 12 13
+Use Line \
+ 14 \
+ 16
+Use Line 17 \
+ 18
+Use Line \
+ \
+ 19 \
+ \
+ 23
+
+Error "done line 25."
diff --git a/modules/core/test/conf/test63.conf b/modules/core/test/conf/test63.conf
new file mode 100644
index 0000000..7988ae4
--- /dev/null
+++ b/modules/core/test/conf/test63.conf
@@ -0,0 +1,9 @@
+# include
+include ${PWD}/inc63_1.conf
+Use Foo "test63.conf:3"
+<Macro Bla $where>
+ Warning "Bla at $where"
+</Macro>
+include ${PWD}/inc63_2.conf
+Use Bla "test63.conf:8"
+Error "done at line 9."
diff --git a/modules/core/test/conf/test64.conf b/modules/core/test/conf/test64.conf
new file mode 100644
index 0000000..6c12328
--- /dev/null
+++ b/modules/core/test/conf/test64.conf
@@ -0,0 +1,5 @@
+# just continuations
+Warning "on line 2"
+Warning \
+ "from line 3 to line 4"
+Error "done on line 5."
diff --git a/modules/core/test/conf/test65.conf b/modules/core/test/conf/test65.conf
new file mode 100644
index 0000000..df9adc3
--- /dev/null
+++ b/modules/core/test/conf/test65.conf
@@ -0,0 +1,11 @@
+# simple use continuation
+<Macro Line $line>
+ # first macro line is a comment
+ Warning "Line: $line"
+</Macro>
+Use Line \
+ "on line 6-7"
+Use \
+ Line \
+ "on line 8-10"
+Error "done on line 11."
diff --git a/modules/core/test/conf/test66.conf b/modules/core/test/conf/test66.conf
new file mode 100644
index 0000000..a14e587
--- /dev/null
+++ b/modules/core/test/conf/test66.conf
@@ -0,0 +1,7 @@
+# no double substitution
+<Macro Foo $x $y>
+ Warning "Foo: x=$x y=$y"
+</Macro>
+Use Foo X Y
+Use Foo "$y" "$x"
+Error "done on line 7."
diff --git a/modules/core/test/conf/test67.conf b/modules/core/test/conf/test67.conf
new file mode 100644
index 0000000..04a5d3d
--- /dev/null
+++ b/modules/core/test/conf/test67.conf
@@ -0,0 +1 @@
+Error "done at line 1 without LF." \ No newline at end of file
diff --git a/modules/core/test/conf/test68.conf b/modules/core/test/conf/test68.conf
new file mode 100644
index 0000000..2a7b85b
--- /dev/null
+++ b/modules/core/test/conf/test68.conf
@@ -0,0 +1,5 @@
+# two directives with continuations & no eol at eof
+Warning \
+ "line 2-3"
+Error \
+ "done on line 4-5." \ No newline at end of file
diff --git a/modules/core/test/conf/test69.conf b/modules/core/test/conf/test69.conf
new file mode 100644
index 0000000..11a0830
--- /dev/null
+++ b/modules/core/test/conf/test69.conf
@@ -0,0 +1,14 @@
+# warn if ignored non-blank stuff after closing '>'
+<Macro Foo> this stuff is ignored...
+ Warning "Foo"
+</Macro> this stuff is ignored as well...
+Use Foo
+<Macro Bla>
+ Warning "Bla"
+</Macro>
+Use Bla
+<Macro Comments> # comments are fine
+ Warning "Comments"
+</Macro> # comments are fine
+Use Comments
+Error "done on line 14."
diff --git a/modules/core/test/ref/test01.out b/modules/core/test/ref/test01.out
new file mode 100644
index 0000000..9ea6665
--- /dev/null
+++ b/modules/core/test/ref/test01.out
@@ -0,0 +1,3 @@
+# testing with conf/test01.conf
+httpd: Syntax error on line 2 of ./conf/test01.conf: <Macro macro definition: empty name
+# exit: 1
diff --git a/modules/core/test/ref/test02.out b/modules/core/test/ref/test02.out
new file mode 100644
index 0000000..6b49191
--- /dev/null
+++ b/modules/core/test/ref/test02.out
@@ -0,0 +1,3 @@
+# testing with conf/test02.conf
+httpd: Syntax error on line 2 of ./conf/test02.conf: <Macro macro definition: empty name
+# exit: 1
diff --git a/modules/core/test/ref/test03.out b/modules/core/test/ref/test03.out
new file mode 100644
index 0000000..f857901
--- /dev/null
+++ b/modules/core/test/ref/test03.out
@@ -0,0 +1,3 @@
+# testing with conf/test03.conf
+httpd: Syntax error on line 5 of ./conf/test03.conf: macro 'bla' undefined
+# exit: 1
diff --git a/modules/core/test/ref/test04.out b/modules/core/test/ref/test04.out
new file mode 100644
index 0000000..aaa2e6b
--- /dev/null
+++ b/modules/core/test/ref/test04.out
@@ -0,0 +1,3 @@
+# testing with conf/test04.conf
+httpd: Syntax error on line 5 of ./conf/test04.conf: macro 'foo' (defined on line 2 of "./conf/test04.conf") used with 1 arguments instead of 0
+# exit: 1
diff --git a/modules/core/test/ref/test05.out b/modules/core/test/ref/test05.out
new file mode 100644
index 0000000..184c40c
--- /dev/null
+++ b/modules/core/test/ref/test05.out
@@ -0,0 +1,3 @@
+# testing with conf/test05.conf
+httpd: Syntax error on line 5 of ./conf/test05.conf: macro 'foo' (defined on line 2 of "./conf/test05.conf") used with 0 arguments instead of 1
+# exit: 1
diff --git a/modules/core/test/ref/test06.out b/modules/core/test/ref/test06.out
new file mode 100644
index 0000000..221dd05
--- /dev/null
+++ b/modules/core/test/ref/test06.out
@@ -0,0 +1,3 @@
+# testing with conf/test06.conf
+httpd: Syntax error on line 5 of ./conf/test06.conf: macro 'foo' (defined on line 2 of "./conf/test06.conf") used with 2 arguments instead of 1
+# exit: 1
diff --git a/modules/core/test/ref/test07.out b/modules/core/test/ref/test07.out
new file mode 100644
index 0000000..60003ec
--- /dev/null
+++ b/modules/core/test/ref/test07.out
@@ -0,0 +1,3 @@
+# testing with conf/test07.conf
+httpd: Syntax error on line 2 of ./conf/test07.conf: macro 'foo' (defined on line 2 of "./conf/test07.conf")\n\tcontents error: expected token not found: </Macro>
+# exit: 1
diff --git a/modules/core/test/ref/test08.out b/modules/core/test/ref/test08.out
new file mode 100644
index 0000000..124c7a0
--- /dev/null
+++ b/modules/core/test/ref/test08.out
@@ -0,0 +1,3 @@
+# testing with conf/test08.conf
+httpd: Syntax error on line 3 of ./conf/test08.conf: </Macro> without matching <Macro> section
+# exit: 1
diff --git a/modules/core/test/ref/test09.out b/modules/core/test/ref/test09.out
new file mode 100644
index 0000000..9af1225
--- /dev/null
+++ b/modules/core/test/ref/test09.out
@@ -0,0 +1,3 @@
+# testing with conf/test09.conf
+httpd: Syntax error on line 1 of macro 'foo' (defined on line 2 of "./conf/test09.conf") used on line 6 of "./conf/test09.conf": recursive use of macro 'foo' is invalid
+# exit: 1
diff --git a/modules/core/test/ref/test10.out b/modules/core/test/ref/test10.out
new file mode 100644
index 0000000..4d81abc
--- /dev/null
+++ b/modules/core/test/ref/test10.out
@@ -0,0 +1,3 @@
+# testing with conf/test10.conf
+httpd: Syntax error on line 1 of macro 'bla' (defined on line 6 of "./conf/test10.conf") used on line 1 of "macro 'foo' (defined on line 2 of "./conf/test10.conf") used on line 10 of "./conf/test10.conf"": recursive use of macro 'foo' is invalid
+# exit: 1
diff --git a/modules/core/test/ref/test11.out b/modules/core/test/ref/test11.out
new file mode 100644
index 0000000..d18c95e
--- /dev/null
+++ b/modules/core/test/ref/test11.out
@@ -0,0 +1,6 @@
+# testing with conf/test11.conf
+[core:warn] macro one.in line 1 on line 1 of macro 'one.in' (defined on line 1 of "macro 'foo' (defined on line 2 of "./conf/test11.conf") used on line 9 of "./conf/test11.conf"") used on line 12 of "./conf/test11.conf"
+[core:error] done line 15. on line 15 of ./conf/test11.conf
+AH00526: Syntax error on line 15 of ./conf/test11.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test12.out b/modules/core/test/ref/test12.out
new file mode 100644
index 0000000..b1ab234
--- /dev/null
+++ b/modules/core/test/ref/test12.out
@@ -0,0 +1,7 @@
+# testing with conf/test12.conf
+[macro:warn] macro 'foo' multiply defined: defined on line 2 of "./conf/test12.conf", redefined on line 6 of "./conf/test12.conf"
+[core:warn] macro foo 2, line 1 on line 1 of macro 'foo' (defined on line 6 of "./conf/test12.conf") used on line 10 of "./conf/test12.conf"
+[core:error] done line 12. on line 12 of ./conf/test12.conf
+AH00526: Syntax error on line 12 of ./conf/test12.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test13.out b/modules/core/test/ref/test13.out
new file mode 100644
index 0000000..13d501e
--- /dev/null
+++ b/modules/core/test/ref/test13.out
@@ -0,0 +1,8 @@
+# testing with conf/test13.conf
+[macro:warn] macro 'foo' multiply defined: defined on line 2 of "./conf/test13.conf", redefined on line 12 of "./conf/test13.conf"
+[core:warn] macro FOO line 1 on line 1 of macro 'foo' (defined on line 2 of "./conf/test13.conf") used on line 10 of "./conf/test13.conf"
+[core:warn] redefined macro foo line 1 on line 1 of macro 'foo' (defined on line 12 of "./conf/test13.conf") used on line 16 of "./conf/test13.conf"
+[core:error] done line 18. on line 18 of ./conf/test13.conf
+AH00526: Syntax error on line 18 of ./conf/test13.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test14.out b/modules/core/test/ref/test14.out
new file mode 100644
index 0000000..1650715
--- /dev/null
+++ b/modules/core/test/ref/test14.out
@@ -0,0 +1,14 @@
+# testing with conf/test14.conf
+AH00112: Warning: DocumentRoot [/projects/apache/web] does not exist
+[core:warn] directory /projects/apache/web on line 5 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 17 of "./conf/test14.conf"
+[core:warn] directory /projects/apache/web/intranet on line 8 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 17 of "./conf/test14.conf"
+AH00112: Warning: DocumentRoot [/projects/perl/web] does not exist
+[core:warn] directory /projects/perl/web on line 5 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 19 of "./conf/test14.conf"
+[core:warn] directory /projects/perl/web/intranet on line 8 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 19 of "./conf/test14.conf"
+AH00112: Warning: DocumentRoot [/projects/mines/web] does not exist
+[core:warn] directory /projects/mines/web on line 5 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 21 of "./conf/test14.conf"
+[core:warn] directory /projects/mines/web/intranet on line 8 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 21 of "./conf/test14.conf"
+[core:error] done line 23. on line 23 of ./conf/test14.conf
+AH00526: Syntax error on line 23 of ./conf/test14.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test15.out b/modules/core/test/ref/test15.out
new file mode 100644
index 0000000..b0b82b7
--- /dev/null
+++ b/modules/core/test/ref/test15.out
@@ -0,0 +1,6 @@
+# testing with conf/test15.conf
+[macro:warn] bad cumulated nesting (+1) in macro 'test' (defined on line 2 of "./conf/test15.conf")
+[core:error] should not reach this point. on line 9 of ./conf/test15.conf
+AH00526: Syntax error on line 9 of ./conf/test15.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test16.out b/modules/core/test/ref/test16.out
new file mode 100644
index 0000000..6e0f9ca
--- /dev/null
+++ b/modules/core/test/ref/test16.out
@@ -0,0 +1,5 @@
+# testing with conf/test16.conf
+[macro:warn] bad (negative) nesting on line 2 of macro 'foo' (defined on line 3 of "./conf/test16.conf")
+[macro:warn] bad cumulated nesting (-1) in macro 'foo' (defined on line 3 of "./conf/test16.conf")
+httpd: Syntax error on line 9 of ./conf/test16.conf: </Limit> without matching <Limit> section
+# exit: 1
diff --git a/modules/core/test/ref/test17.out b/modules/core/test/ref/test17.out
new file mode 100644
index 0000000..c6ca16d
--- /dev/null
+++ b/modules/core/test/ref/test17.out
@@ -0,0 +1,7 @@
+# testing with conf/test17.conf
+[macro:warn] bad (negative) nesting on line 2 of macro 'foo' (defined on line 3 of "./conf/test17.conf")
+[macro:warn] bad cumulated nesting (-1) in macro 'foo' (defined on line 3 of "./conf/test17.conf")
+[core:error] done on line 10. on line 10 of ./conf/test17.conf
+AH00526: Syntax error on line 10 of ./conf/test17.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test18.out b/modules/core/test/ref/test18.out
new file mode 100644
index 0000000..c5cee81
--- /dev/null
+++ b/modules/core/test/ref/test18.out
@@ -0,0 +1,7 @@
+# testing with conf/test18.conf
+[macro:warn] bad (negative) nesting on line 2 of macro 'foo' (defined on line 3 of "./conf/test18.conf")
+[macro:warn] bad cumulated nesting (-1) in macro 'foo' (defined on line 3 of "./conf/test18.conf")
+[core:error] done on line 10. on line 10 of ./conf/test18.conf
+AH00526: Syntax error on line 10 of ./conf/test18.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test19.out b/modules/core/test/ref/test19.out
new file mode 100644
index 0000000..411e569
--- /dev/null
+++ b/modules/core/test/ref/test19.out
@@ -0,0 +1,9 @@
+# testing with conf/test19.conf
+[core:warn] macro foo line 2 in Directory on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 9 of "./conf/test19.conf"
+[core:warn] macro foo line 2 in Location on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 13 of "./conf/test19.conf"
+[core:warn] macro foo line 2 in VirtualHost on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 17 of "./conf/test19.conf"
+[core:warn] macro foo line 2 in VirtualHost & Directory on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 22 of "./conf/test19.conf"
+[core:error] done line 26. on line 26 of ./conf/test19.conf
+AH00526: Syntax error on line 26 of ./conf/test19.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test20.out b/modules/core/test/ref/test20.out
new file mode 100644
index 0000000..3ce2b60
--- /dev/null
+++ b/modules/core/test/ref/test20.out
@@ -0,0 +1,4 @@
+# testing with conf/test20.conf
+AH00526: Syntax error on line 1 of macro 'foo' (defined on line 3 of "./conf/test20.conf") used on line 10 of "./conf/test20.conf":
+<Directory not allowed here
+# exit: 1
diff --git a/modules/core/test/ref/test21.out b/modules/core/test/ref/test21.out
new file mode 100644
index 0000000..ac8d843
--- /dev/null
+++ b/modules/core/test/ref/test21.out
@@ -0,0 +1,5 @@
+# testing with conf/test21.conf
+[core:error] macro foo dir /tmp on line 2 of macro 'foo' (defined on line 3 of "./conf/test21.conf") used on line 10 of "./conf/test21.conf"
+AH00526: Syntax error on line 2 of macro 'foo' (defined on line 3 of "./conf/test21.conf") used on line 10 of "./conf/test21.conf":
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test22.out b/modules/core/test/ref/test22.out
new file mode 100644
index 0000000..def17dd
--- /dev/null
+++ b/modules/core/test/ref/test22.out
@@ -0,0 +1,6 @@
+# testing with conf/test22.conf
+[core:warn] macro foo on line 2 of macro 'foo' (defined on line 3 of "./conf/test22.conf") used on line 9 of "./conf/test22.conf"
+[core:error] done on line 11. on line 11 of ./conf/test22.conf
+AH00526: Syntax error on line 11 of ./conf/test22.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test23.out b/modules/core/test/ref/test23.out
new file mode 100644
index 0000000..827c861
--- /dev/null
+++ b/modules/core/test/ref/test23.out
@@ -0,0 +1,7 @@
+# testing with conf/test23.conf
+[core:warn] macro foo in /tmp on line 1 of macro 'foo' (defined on line 4 of "./conf/test23.conf") used on line 9 of "./conf/test23.conf"
+[core:warn] macro foo in /tmp on line 1 of macro 'foo' (defined on line 4 of "./conf/test23.conf") used on line 12 of "./conf/test23.conf"
+[core:error] done! on line 15 of ./conf/test23.conf
+AH00526: Syntax error on line 15 of ./conf/test23.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test24.out b/modules/core/test/ref/test24.out
new file mode 100644
index 0000000..e5d370d
--- /dev/null
+++ b/modules/core/test/ref/test24.out
@@ -0,0 +1,8 @@
+# testing with conf/test24.conf
+[core:warn] macro bla intra on line 2 of macro 'bla' (defined on line 3 of "./conf/test24.conf") used on line 13 of "./conf/test24.conf"
+[core:warn] macro bla private on line 5 of macro 'bla' (defined on line 3 of "./conf/test24.conf") used on line 13 of "./conf/test24.conf"
+[core:warn] macro bla intra on line 2 of macro 'bla' (defined on line 3 of "./conf/test24.conf") used on line 17 of "./conf/test24.conf"
+[core:warn] macro bla private on line 5 of macro 'bla' (defined on line 3 of "./conf/test24.conf") used on line 17 of "./conf/test24.conf"
+AH00526: Syntax error on line 1 of macro 'bla' (defined on line 3 of "./conf/test24.conf") used on line 22 of "./conf/test24.conf":
+<Location not allowed here
+# exit: 1
diff --git a/modules/core/test/ref/test25.out b/modules/core/test/ref/test25.out
new file mode 100644
index 0000000..56bb0bd
--- /dev/null
+++ b/modules/core/test/ref/test25.out
@@ -0,0 +1,9 @@
+# testing with conf/test25.conf
+[core:warn] restricted access policy 10.0.0.0/8 on line 1 of macro 'restrictedaccesspolicy' (defined on line 3 of "./conf/test25.conf") used on line 8 of "./conf/test25.conf"
+[core:warn] restricted access policy 192.54.172.0/24 192.54.148.0/24 10.0.0.0/8 on line 1 of macro 'restrictedaccesspolicy' (defined on line 3 of "./conf/test25.conf") used on line 16 of "./conf/test25.conf"
+[core:warn] restricted access policy 10.0.0.0/8 on line 1 of macro 'restrictedaccesspolicy' (defined on line 3 of "./conf/test25.conf") used on line 1 of "macro 'localaccessonly' (defined on line 11 of "./conf/test25.conf") used on line 20 of "./conf/test25.conf""
+[core:warn] restricted access policy 10.0.0.0/8 on line 1 of macro 'restrictedaccesspolicy' (defined on line 3 of "./conf/test25.conf") used on line 1 of "macro 'localaccessonly' (defined on line 11 of "./conf/test25.conf") used on line 24 of "./conf/test25.conf""
+[core:error] done line 27. on line 27 of ./conf/test25.conf
+AH00526: Syntax error on line 27 of ./conf/test25.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test26.out b/modules/core/test/ref/test26.out
new file mode 100644
index 0000000..28cba28
--- /dev/null
+++ b/modules/core/test/ref/test26.out
@@ -0,0 +1,11 @@
+# testing with conf/test26.conf
+[macro:warn] macro 'funny' (defined on line 4 of "./conf/test26.conf") argument name 'first arg' (#1) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'funny' (defined on line 4 of "./conf/test26.conf") argument name 'second ... arg' (#2) without expected prefix, better prefix argument names with one of '$%@'.
+[core:warn] funny directory on line 2 of macro 'funny' (defined on line 4 of "./conf/test26.conf") used on line 13 of "./conf/test26.conf"
+[core:warn] funny location on line 5 of macro 'funny' (defined on line 4 of "./conf/test26.conf") used on line 13 of "./conf/test26.conf"
+[core:warn] funny directory on line 2 of macro 'funny' (defined on line 4 of "./conf/test26.conf") used on line 16 of "./conf/test26.conf"
+[core:warn] funny location on line 5 of macro 'funny' (defined on line 4 of "./conf/test26.conf") used on line 16 of "./conf/test26.conf"
+[core:error] done! on line 19 of ./conf/test26.conf
+AH00526: Syntax error on line 19 of ./conf/test26.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test27.out b/modules/core/test/ref/test27.out
new file mode 100644
index 0000000..46aa8ea
--- /dev/null
+++ b/modules/core/test/ref/test27.out
@@ -0,0 +1,8 @@
+# testing with conf/test27.conf
+[core:warn] foo.one /unexpected/1 on line 2 of macro 'foo.one' (defined on line 1 of "macro 'foo' (defined on line 3 of "./conf/test27.conf") used on line 11 of "./conf/test27.conf"") used on line 14 of "./conf/test27.conf"
+[core:warn] foo.two /unexpected/2 on line 2 of macro 'foo.two' (defined on line 1 of "macro 'foo' (defined on line 3 of "./conf/test27.conf") used on line 12 of "./conf/test27.conf"") used on line 15 of "./conf/test27.conf"
+[core:warn] foo.one /unexpected/1 on line 2 of macro 'foo.one' (defined on line 1 of "macro 'foo' (defined on line 3 of "./conf/test27.conf") used on line 11 of "./conf/test27.conf"") used on line 16 of "./conf/test27.conf"
+[core:error] done! on line 22 of ./conf/test27.conf
+AH00526: Syntax error on line 22 of ./conf/test27.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test28.out b/modules/core/test/ref/test28.out
new file mode 100644
index 0000000..eb0a23f
--- /dev/null
+++ b/modules/core/test/ref/test28.out
@@ -0,0 +1,6 @@
+# testing with conf/test28.conf
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 4 of "./conf/test28.conf") used on line 8 of "./conf/test28.conf"
+[core:error] done! on line 10 of ./conf/test28.conf
+AH00526: Syntax error on line 10 of ./conf/test28.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test29.out b/modules/core/test/ref/test29.out
new file mode 100644
index 0000000..48488f9
--- /dev/null
+++ b/modules/core/test/ref/test29.out
@@ -0,0 +1,4 @@
+# testing with conf/test29.conf
+[macro:warn] macro 'toobigaline' (defined on line 3 of "./conf/test29.conf") argument name 'a' (#1) without expected prefix, better prefix argument names with one of '$%@'.
+httpd: Syntax error on line 8 of ./conf/test29.conf: macro 'toobigaline' (defined on line 3 of "./conf/test29.conf") used on line 8 of "./conf/test29.conf" error while substituting: while processing line 1 of macro 'toobigaline' (defined on line 3 of "./conf/test29.conf") cannot substitute, buffer size too small
+# exit: 1
diff --git a/modules/core/test/ref/test30.out b/modules/core/test/ref/test30.out
new file mode 100644
index 0000000..a84c69f
--- /dev/null
+++ b/modules/core/test/ref/test30.out
@@ -0,0 +1,7 @@
+# testing with conf/test30.conf
+[macro:warn] macro 'foo' (defined on line 4 of "./conf/test30.conf"): argument name prefix conflict ($dir #1 and $directive #2), be careful about your macro definition!
+[core:warn] section Directory /unexpected/1 on line 2 of macro 'foo' (defined on line 4 of "./conf/test30.conf") used on line 10 of "./conf/test30.conf"
+[core:error] done! on line 12 of ./conf/test30.conf
+AH00526: Syntax error on line 12 of ./conf/test30.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test31.out b/modules/core/test/ref/test31.out
new file mode 100644
index 0000000..831a784
--- /dev/null
+++ b/modules/core/test/ref/test31.out
@@ -0,0 +1,23 @@
+# testing with conf/test31.conf
+[macro:warn] macro 'bla' (defined on line 3 of "./conf/test31.conf"): argument name prefix conflict ($dir #1 and $di #2), be careful about your macro definition!
+[macro:warn] macro 'bla' (defined on line 3 of "./conf/test31.conf"): argument name prefix conflict ($dir #1 and $d #4), be careful about your macro definition!
+[macro:warn] macro 'bla' (defined on line 3 of "./conf/test31.conf"): argument name prefix conflict ($di #2 and $d #4), be careful about your macro definition!
+[macro:warn] macro 'bla' (defined on line 3 of "./conf/test31.conf"): argument name prefix conflict ($dd #3 and $d #4), be careful about your macro definition!
+[macro:warn] macro 'bla' (defined on line 3 of "./conf/test31.conf") used on line 8 of "./conf/test31.conf": empty argument #1
+[macro:warn] macro 'bla' (defined on line 3 of "./conf/test31.conf") used on line 8 of "./conf/test31.conf": empty argument #2
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument name prefix conflict ($d #1 and $di #2), be careful about your macro definition!
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument name prefix conflict ($d #1 and $dir #3), be careful about your macro definition!
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument name prefix conflict ($d #1 and $dd #4), be careful about your macro definition!
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument name prefix conflict ($di #2 and $dir #3), be careful about your macro definition!
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument '$d' (#1) never used
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument '$di' (#2) never used
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument '$dir' (#3) never used
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf"): argument '$dd' (#4) never used
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf") used on line 14 of "./conf/test31.conf": empty argument #1
+[macro:warn] macro 'foo' (defined on line 10 of "./conf/test31.conf") used on line 14 of "./conf/test31.conf": empty argument #2
+[core:warn] argument name conflicts on line 1 of macro 'bla' (defined on line 3 of "./conf/test31.conf") used on line 8 of "./conf/test31.conf"
+[core:warn] conflicts, but arguments are not used on line 1 of macro 'foo' (defined on line 10 of "./conf/test31.conf") used on line 14 of "./conf/test31.conf"
+[core:error] done on line 16. on line 16 of ./conf/test31.conf
+AH00526: Syntax error on line 16 of ./conf/test31.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test32.out b/modules/core/test/ref/test32.out
new file mode 100644
index 0000000..b1620af
--- /dev/null
+++ b/modules/core/test/ref/test32.out
@@ -0,0 +1,3 @@
+# testing with conf/test32.conf
+httpd: Syntax error on line 3 of ./conf/test32.conf: argument name conflict in macro 'foo' (defined on line 3 of "./conf/test32.conf"): argument '$arg2': #2 and #4, change argument names!
+# exit: 1
diff --git a/modules/core/test/ref/test33.out b/modules/core/test/ref/test33.out
new file mode 100644
index 0000000..cc5b3d0
--- /dev/null
+++ b/modules/core/test/ref/test33.out
@@ -0,0 +1,3 @@
+# testing with conf/test33.conf
+httpd: Syntax error on line 3 of ./conf/test33.conf: no macro defined before Use
+# exit: 1
diff --git a/modules/core/test/ref/test34.out b/modules/core/test/ref/test34.out
new file mode 100644
index 0000000..1264a54
--- /dev/null
+++ b/modules/core/test/ref/test34.out
@@ -0,0 +1,13 @@
+# testing with conf/test34.conf
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test34.conf"): argument name prefix conflict ($d #1 and $dd #2), be careful about your macro definition!
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test34.conf"): argument '$d' (#1) never used
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test34.conf"): argument '$dd' (#2) never used
+[macro:warn] macro 'bla' (defined on line 7 of "./conf/test34.conf"): argument name prefix conflict ($dd #1 and $d #2), be careful about your macro definition!
+[macro:warn] macro 'bla' (defined on line 7 of "./conf/test34.conf"): argument '$dd' (#1) never used
+[macro:warn] macro 'bla' (defined on line 7 of "./conf/test34.conf"): argument '$d' (#2) never used
+[core:warn] macro foo conflict one on line 1 of macro 'foo' (defined on line 3 of "./conf/test34.conf") used on line 11 of "./conf/test34.conf"
+[core:warn] macro bla conflict two on line 1 of macro 'bla' (defined on line 7 of "./conf/test34.conf") used on line 12 of "./conf/test34.conf"
+[core:error] done on line 14. on line 14 of ./conf/test34.conf
+AH00526: Syntax error on line 14 of ./conf/test34.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test35.out b/modules/core/test/ref/test35.out
new file mode 100644
index 0000000..fb56238
--- /dev/null
+++ b/modules/core/test/ref/test35.out
@@ -0,0 +1,13 @@
+# testing with conf/test35.conf
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf") argument name 'u1' (#1) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf") argument name 'u2' (#2) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf") argument name 'n1' (#3) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf") argument name 'n2' (#4) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf") argument name 'u3' (#5) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf"): argument 'n1' (#3) never used
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test35.conf"): argument 'n2' (#4) never used
+[core:warn] macro cannot be used just within a comment 1 2 5 on line 1 of macro 'warnings' (defined on line 3 of "./conf/test35.conf") used on line 8 of "./conf/test35.conf"
+[core:error] done on line 10. on line 10 of ./conf/test35.conf
+AH00526: Syntax error on line 10 of ./conf/test35.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test36.out b/modules/core/test/ref/test36.out
new file mode 100644
index 0000000..4c627d7
--- /dev/null
+++ b/modules/core/test/ref/test36.out
@@ -0,0 +1,20 @@
+# testing with conf/test36.conf
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument name prefix conflict ($u #1 and $u1 #3), be careful about your macro definition!
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument name prefix conflict ($u #1 and $u2 #5), be careful about your macro definition!
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument name prefix conflict ($n #2 and $n1 #4), be careful about your macro definition!
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument name prefix conflict ($n #2 and $n2 #6), be careful about your macro definition!
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument '$n' (#2) never used
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument '$n1' (#4) never used
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf"): argument '$n2' (#6) never used
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf": empty argument #1
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf": empty argument #2
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf": empty argument #3
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf": empty argument #4
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf": empty argument #5
+[macro:warn] macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf": empty argument #6
+[core:warn] many warnings! 1 3 5 on line 1 of macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 7 of "./conf/test36.conf"
+[core:warn] many warnings! on line 1 of macro 'warnings' (defined on line 1 of "./conf/test36.conf") used on line 10 of "./conf/test36.conf"
+[core:error] done! on line 12 of ./conf/test36.conf
+AH00526: Syntax error on line 12 of ./conf/test36.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test37.out b/modules/core/test/ref/test37.out
new file mode 100644
index 0000000..fc119c8
--- /dev/null
+++ b/modules/core/test/ref/test37.out
@@ -0,0 +1,3 @@
+# testing with conf/test37.conf
+httpd: Syntax error on line 3 of ./conf/test37.conf: macro 'stupid' (defined on line 3 of "./conf/test37.conf"): empty argument #1 name
+# exit: 1
diff --git a/modules/core/test/ref/test38.out b/modules/core/test/ref/test38.out
new file mode 100644
index 0000000..ed3f1bb
--- /dev/null
+++ b/modules/core/test/ref/test38.out
@@ -0,0 +1,6 @@
+# testing with conf/test38.conf
+[core:warn] it is really a good idea to have mod_macro.c installed. on line 4 of ./conf/test38.conf
+[core:error] it seems you do not have mod perl installed. on line 8 of ./conf/test38.conf
+AH00526: Syntax error on line 8 of ./conf/test38.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test39.out b/modules/core/test/ref/test39.out
new file mode 100644
index 0000000..ea2cede
--- /dev/null
+++ b/modules/core/test/ref/test39.out
@@ -0,0 +1,7 @@
+# testing with conf/test39.conf
+[core:warn] Thanks for using mod_macro! on line 1 of macro 'modmacro' (defined on line 4 of "./conf/test39.conf") used on line 15 of "./conf/test39.conf"
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 17 of "./conf/test39.conf") used on line 21 of "./conf/test39.conf"
+[core:error] done! on line 23 of ./conf/test39.conf
+AH00526: Syntax error on line 23 of ./conf/test39.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test40.out b/modules/core/test/ref/test40.out
new file mode 100644
index 0000000..e3c5971
--- /dev/null
+++ b/modules/core/test/ref/test40.out
@@ -0,0 +1,18 @@
+# testing with conf/test40.conf
+AH00112: Warning: DocumentRoot [/foo/document/root/directory] does not exist
+[core:warn] location /A on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 15 of "./conf/test40.conf"
+[core:warn] location /B on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 16 of "./conf/test40.conf"
+[core:warn] location /C on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 17 of "./conf/test40.conf"
+[core:warn] location /D on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 18 of "./conf/test40.conf"
+[core:warn] location /E on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 19 of "./conf/test40.conf"
+[core:warn] location /G on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 20 of "./conf/test40.conf"
+[core:warn] location /H on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 21 of "./conf/test40.conf"
+[core:warn] location /J on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 22 of "./conf/test40.conf"
+[core:warn] location /K on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 23 of "./conf/test40.conf"
+[core:warn] location /L on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 24 of "./conf/test40.conf"
+[core:warn] location /M on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 25 of "./conf/test40.conf"
+[core:warn] location /N on line 2 of macro 'subdiraccesscontrol' (defined on line 7 of "./conf/test40.conf") used on line 26 of "./conf/test40.conf"
+[core:error] Stop configuration file processing. on line 33 of ./conf/test40.conf
+AH00526: Syntax error on line 33 of ./conf/test40.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test41.out b/modules/core/test/ref/test41.out
new file mode 100644
index 0000000..3bef285
--- /dev/null
+++ b/modules/core/test/ref/test41.out
@@ -0,0 +1,9 @@
+# testing with conf/test41.conf
+AH00112: Warning: DocumentRoot [/foo/document/root/directory] does not exist
+[core:warn] location /A on line 7 of ./conf/test41.conf
+[core:warn] location /B on line 11 of ./conf/test41.conf
+[core:warn] location /C on line 15 of ./conf/test41.conf
+[core:error] Stop configuration file processing. on line 20 of ./conf/test41.conf
+AH00526: Syntax error on line 20 of ./conf/test41.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test42.out b/modules/core/test/ref/test42.out
new file mode 100644
index 0000000..bab1510
--- /dev/null
+++ b/modules/core/test/ref/test42.out
@@ -0,0 +1,15 @@
+# testing with conf/test42.conf
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 7 of "./conf/test42.conf": empty argument #1
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 8 of "./conf/test42.conf": empty argument #1
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 9 of "./conf/test42.conf": empty argument #1
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 10 of "./conf/test42.conf": empty argument #1
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 11 of "./conf/test42.conf": empty argument #1
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 7 of "./conf/test42.conf"
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 8 of "./conf/test42.conf"
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 9 of "./conf/test42.conf"
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 10 of "./conf/test42.conf"
+[core:warn] macro foo on line 1 of macro 'foo' (defined on line 3 of "./conf/test42.conf") used on line 11 of "./conf/test42.conf"
+[core:error] done on line 13. on line 13 of ./conf/test42.conf
+AH00526: Syntax error on line 13 of ./conf/test42.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test43.out b/modules/core/test/ref/test43.out
new file mode 100644
index 0000000..04a72d8
--- /dev/null
+++ b/modules/core/test/ref/test43.out
@@ -0,0 +1,8 @@
+# testing with conf/test43.conf
+[macro:warn] bad cumulated nesting (+1) in macro 'begindir' (defined on line 3 of "./conf/test43.conf")
+[macro:warn] bad (negative) nesting on line 2 of macro 'enddir' (defined on line 8 of "./conf/test43.conf")
+[macro:warn] bad cumulated nesting (-1) in macro 'enddir' (defined on line 8 of "./conf/test43.conf")
+[core:error] ok! on line 29 of ./conf/test43.conf
+AH00526: Syntax error on line 29 of ./conf/test43.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test44.out b/modules/core/test/ref/test44.out
new file mode 100644
index 0000000..e744cda
--- /dev/null
+++ b/modules/core/test/ref/test44.out
@@ -0,0 +1,5 @@
+# testing with conf/test44.conf
+[core:error] okay. on line 19 of ./conf/test44.conf
+AH00526: Syntax error on line 19 of ./conf/test44.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test45.out b/modules/core/test/ref/test45.out
new file mode 100644
index 0000000..daadaac
--- /dev/null
+++ b/modules/core/test/ref/test45.out
@@ -0,0 +1,19 @@
+# testing with conf/test45.conf
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '&3' (#3) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '#5' (#5) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '~6' (#6) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '*7' (#7) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '.8' (#8) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name ',9' (#9) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '!a' (#10) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '-b' (#11) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '+c' (#12) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '=d' (#13) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name ':e' (#14) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name ';f' (#15) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf") argument name '?g' (#16) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 3 of "./conf/test45.conf"): empty contents!
+[core:error] done on line 7. on line 7 of ./conf/test45.conf
+AH00526: Syntax error on line 7 of ./conf/test45.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test46.out b/modules/core/test/ref/test46.out
new file mode 100644
index 0000000..8059744
--- /dev/null
+++ b/modules/core/test/ref/test46.out
@@ -0,0 +1,9 @@
+# testing with conf/test46.conf
+[macro:warn] macro '$i' (defined on line 3 of "./conf/test46.conf") better prefix a macro name with any of '$%@'
+[macro:warn] macro '$i' (defined on line 3 of "./conf/test46.conf"): empty contents!
+[macro:warn] macro 'warnings' (defined on line 7 of "./conf/test46.conf") argument name 'second' (#2) without expected prefix, better prefix argument names with one of '$%@'.
+[macro:warn] macro 'warnings' (defined on line 7 of "./conf/test46.conf"): empty contents!
+[core:error] okay. on line 11 of ./conf/test46.conf
+AH00526: Syntax error on line 11 of ./conf/test46.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test47.out b/modules/core/test/ref/test47.out
new file mode 100644
index 0000000..58fb3cc
--- /dev/null
+++ b/modules/core/test/ref/test47.out
@@ -0,0 +1,8 @@
+# testing with conf/test47.conf
+[macro:warn] macro 'foo' (defined on line 3 of "./conf/test47.conf"): empty contents!
+[macro:warn] macro 'bla' (defined on line 8 of "./conf/test47.conf"): empty contents!
+[macro:warn] macro 'bof' (defined on line 11 of "./conf/test47.conf"): empty contents!
+[core:error] okay. on line 15 of ./conf/test47.conf
+AH00526: Syntax error on line 15 of ./conf/test47.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test48.out b/modules/core/test/ref/test48.out
new file mode 100644
index 0000000..6ac5e99
--- /dev/null
+++ b/modules/core/test/ref/test48.out
@@ -0,0 +1,20 @@
+# testing with conf/test48.conf
+[core:warn] 1 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 7 of "./conf/test48.conf"
+[core:warn] 12 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 8 of "./conf/test48.conf"
+[core:warn] 123 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 9 of "./conf/test48.conf"
+[core:warn] 1234 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 10 of "./conf/test48.conf"
+[core:warn] 12345 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 11 of "./conf/test48.conf"
+[core:warn] 123456 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 12 of "./conf/test48.conf"
+[core:warn] 1234567 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 13 of "./conf/test48.conf"
+[core:warn] 12345678 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 14 of "./conf/test48.conf"
+[core:warn] 123456789 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 15 of "./conf/test48.conf"
+[core:warn] 1234567890 on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 16 of "./conf/test48.conf"
+[core:warn] 1234567890a on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 17 of "./conf/test48.conf"
+[core:warn] 1234567890ab on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 18 of "./conf/test48.conf"
+[core:warn] 1234567890abc on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 19 of "./conf/test48.conf"
+[core:warn] 1234567890abcd on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 20 of "./conf/test48.conf"
+[core:warn] 1234567890abcde on line 1 of macro 'm' (defined on line 3 of "./conf/test48.conf") used on line 21 of "./conf/test48.conf"
+[core:error] done line 23. on line 23 of ./conf/test48.conf
+AH00526: Syntax error on line 23 of ./conf/test48.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test49.out b/modules/core/test/ref/test49.out
new file mode 100644
index 0000000..5e83e02
--- /dev/null
+++ b/modules/core/test/ref/test49.out
@@ -0,0 +1,3 @@
+# testing with conf/test49.conf
+httpd: Syntax error on line 2 of ./conf/test49.conf: no macro defined before UndefMacro
+# exit: 1
diff --git a/modules/core/test/ref/test50.out b/modules/core/test/ref/test50.out
new file mode 100644
index 0000000..477e854
--- /dev/null
+++ b/modules/core/test/ref/test50.out
@@ -0,0 +1,3 @@
+# testing with conf/test50.conf
+httpd: Syntax error on line 5 of ./conf/test50.conf: cannot remove undefined macro 'bla'
+# exit: 1
diff --git a/modules/core/test/ref/test51.out b/modules/core/test/ref/test51.out
new file mode 100644
index 0000000..be9cc17
--- /dev/null
+++ b/modules/core/test/ref/test51.out
@@ -0,0 +1,3 @@
+# testing with conf/test51.conf
+httpd: Syntax error on line 9 of ./conf/test51.conf: macro 'foo' undefined
+# exit: 1
diff --git a/modules/core/test/ref/test52.out b/modules/core/test/ref/test52.out
new file mode 100644
index 0000000..f41b7d6
--- /dev/null
+++ b/modules/core/test/ref/test52.out
@@ -0,0 +1,6 @@
+# testing with conf/test52.conf
+[core:warn] foo macro contents line 1 on line 1 of macro 'foo' (defined on line 2 of "./conf/test52.conf") used on line 5 of "./conf/test52.conf"
+[core:error] done line 8. on line 8 of ./conf/test52.conf
+AH00526: Syntax error on line 8 of ./conf/test52.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test53.out b/modules/core/test/ref/test53.out
new file mode 100644
index 0000000..2fb3852
--- /dev/null
+++ b/modules/core/test/ref/test53.out
@@ -0,0 +1,3 @@
+# testing with conf/test53.conf
+httpd: Syntax error on line 2 of ./conf/test53.conf: no macro defined before Use
+# exit: 1
diff --git a/modules/core/test/ref/test54.out b/modules/core/test/ref/test54.out
new file mode 100644
index 0000000..814b491
--- /dev/null
+++ b/modules/core/test/ref/test54.out
@@ -0,0 +1,6 @@
+# testing with conf/test54.conf
+[macro:warn] macro 'foo' (defined on line 2 of "./conf/test54.conf"): empty contents!
+[core:error] done line 6. on line 6 of ./conf/test54.conf
+AH00526: Syntax error on line 6 of ./conf/test54.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test55.out b/modules/core/test/ref/test55.out
new file mode 100644
index 0000000..c3590f9
--- /dev/null
+++ b/modules/core/test/ref/test55.out
@@ -0,0 +1,8 @@
+# testing with conf/test55.conf
+[core:warn] macro foo(:2) line 1 (file line 9) on line 1 of macro 'foo' (defined on line 2 of "./conf/test55.conf") used on line 9 of "./conf/test55.conf"
+[core:warn] macro bla(:5) line 1 (file line 10) on line 1 of macro 'bla' (defined on line 5 of "./conf/test55.conf") used on line 10 of "./conf/test55.conf"
+[core:warn] macro foo(:2) line 1 (bla line 2) on line 1 of macro 'foo' (defined on line 2 of "./conf/test55.conf") used on line 2 of "macro 'bla' (defined on line 5 of "./conf/test55.conf") used on line 10 of "./conf/test55.conf""
+[core:error] done line 11. on line 11 of ./conf/test55.conf
+AH00526: Syntax error on line 11 of ./conf/test55.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test56.out b/modules/core/test/ref/test56.out
new file mode 100644
index 0000000..f2a0b6e
--- /dev/null
+++ b/modules/core/test/ref/test56.out
@@ -0,0 +1,12 @@
+# testing with conf/test56.conf
+[macro:warn] bad cumulated nesting (+1) in macro 'open' (defined on line 2 of "./conf/test56.conf")
+[macro:warn] bad (negative) nesting on line 3 of macro 'close' (defined on line 6 of "./conf/test56.conf")
+[macro:warn] bad cumulated nesting (-1) in macro 'close' (defined on line 6 of "./conf/test56.conf")
+[core:warn] Open:2 /tmp on line 2 of macro 'open' (defined on line 2 of "./conf/test56.conf") used on line 12 of "./conf/test56.conf"
+[core:warn] Close:1 on line 1 of macro 'close' (defined on line 6 of "./conf/test56.conf") used on line 13 of "./conf/test56.conf"
+[core:warn] Open:2 /etc on line 2 of macro 'open' (defined on line 2 of "./conf/test56.conf") used on line 15 of "./conf/test56.conf"
+[core:warn] Close:1 on line 1 of macro 'close' (defined on line 6 of "./conf/test56.conf") used on line 16 of "./conf/test56.conf"
+[core:error] done line 18. on line 18 of ./conf/test56.conf
+AH00526: Syntax error on line 18 of ./conf/test56.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test57.out b/modules/core/test/ref/test57.out
new file mode 100644
index 0000000..77a1901
--- /dev/null
+++ b/modules/core/test/ref/test57.out
@@ -0,0 +1,3 @@
+# testing with conf/test57.conf
+httpd: Syntax error on line 2 of ./conf/test57.conf: macro 'foo' (defined on line 2 of "./conf/test57.conf"): empty argument #2 name
+# exit: 1
diff --git a/modules/core/test/ref/test58.out b/modules/core/test/ref/test58.out
new file mode 100644
index 0000000..0ece028
--- /dev/null
+++ b/modules/core/test/ref/test58.out
@@ -0,0 +1,3 @@
+# testing with conf/test58.conf
+httpd: Syntax error on line 2 of ./conf/test58.conf: <Macro> directive missing closing '>'
+# exit: 1
diff --git a/modules/core/test/ref/test59.out b/modules/core/test/ref/test59.out
new file mode 100644
index 0000000..7895917
--- /dev/null
+++ b/modules/core/test/ref/test59.out
@@ -0,0 +1,3 @@
+# testing with conf/test59.conf
+httpd: Syntax error on line 2 of ./conf/test59.conf: <Macro macro definition: name not found
+# exit: 1
diff --git a/modules/core/test/ref/test60.out b/modules/core/test/ref/test60.out
new file mode 100644
index 0000000..cac7002
--- /dev/null
+++ b/modules/core/test/ref/test60.out
@@ -0,0 +1,15 @@
+# testing with conf/test60.conf
+[core:warn] macro Foo arg 1: hello on line 1 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 14 of "./conf/test60.conf"
+[core:warn] macro Foo arg 2: world on line 2 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 14 of "./conf/test60.conf"
+[core:warn] Macro Bla arg 1: "hello world" on line 1 of macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf"
+[core:warn] Macro Bla arg 2: "thank you" on line 2 of macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf"
+[core:warn] macro Foo arg 1: hello world on line 1 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 3 of "macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf""
+[core:warn] macro Foo arg 2: second on line 2 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 3 of "macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf""
+[core:warn] macro Foo arg 1: first on line 1 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 4 of "macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf""
+[core:warn] macro Foo arg 2: thank you on line 2 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 4 of "macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf""
+[core:warn] macro Foo arg 1: hello world on line 1 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 5 of "macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf""
+[core:warn] macro Foo arg 2: thank you on line 2 of macro 'foo' (defined on line 2 of "./conf/test60.conf") used on line 5 of "macro 'bla' (defined on line 6 of "./conf/test60.conf") used on line 15 of "./conf/test60.conf""
+[core:error] done on line 17. on line 17 of ./conf/test60.conf
+AH00526: Syntax error on line 17 of ./conf/test60.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test61.out b/modules/core/test/ref/test61.out
new file mode 100644
index 0000000..59639c9
--- /dev/null
+++ b/modules/core/test/ref/test61.out
@@ -0,0 +1,9 @@
+# testing with conf/test61.conf
+[core:warn] F4:1 x=line=17 on line 1 of macro 'f4' (defined on line 13 of "./conf/test61.conf") used on line 17 of "./conf/test61.conf"
+[core:warn] F3:1 x=line=17 on line 1 of macro 'f3' (defined on line 9 of "./conf/test61.conf") used on line 2 of "macro 'f4' (defined on line 13 of "./conf/test61.conf") used on line 17 of "./conf/test61.conf""
+[core:warn] F2:1 x=line=17 on line 1 of macro 'f2' (defined on line 5 of "./conf/test61.conf") used on line 2 of "macro 'f3' (defined on line 9 of "./conf/test61.conf") used on line 2 of "macro 'f4' (defined on line 13 of "./conf/test61.conf") used on line 17 of "./conf/test61.conf"""
+[core:warn] F1:1 x=line=17 on line 1 of macro 'f1' (defined on line 2 of "./conf/test61.conf") used on line 2 of "macro 'f2' (defined on line 5 of "./conf/test61.conf") used on line 2 of "macro 'f3' (defined on line 9 of "./conf/test61.conf") used on line 2 of "macro 'f4' (defined on line 13 of "./conf/test61.conf") used on line 17 of "./conf/test61.conf""""
+[core:error] done line 18. on line 18 of ./conf/test61.conf
+AH00526: Syntax error on line 18 of ./conf/test61.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test62.out b/modules/core/test/ref/test62.out
new file mode 100644
index 0000000..a956e7e
--- /dev/null
+++ b/modules/core/test/ref/test62.out
@@ -0,0 +1,15 @@
+# testing with conf/test62.conf
+[core:warn] Line:1-2 start at 11 on line 1 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 11 of "./conf/test62.conf"
+[core:warn] Line:3-4 stop at 11 on line 2 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 11 of "./conf/test62.conf"
+[core:warn] Line:1-2 start at 12 on line 1 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 13 of "./conf/test62.conf"
+[core:warn] Line:3-4 stop at 13 on line 2 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 13 of "./conf/test62.conf"
+[core:warn] Line:1-2 start at 14 on line 1 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 16 of "./conf/test62.conf"
+[core:warn] Line:3-4 stop at 16 on line 2 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 16 of "./conf/test62.conf"
+[core:warn] Line:1-2 start at 17 on line 1 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 18 of "./conf/test62.conf"
+[core:warn] Line:3-4 stop at 18 on line 2 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 18 of "./conf/test62.conf"
+[core:warn] Line:1-2 start at 19 on line 1 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 23 of "./conf/test62.conf"
+[core:warn] Line:3-4 stop at 23 on line 2 of macro 'line' (defined on line 4 of "./conf/test62.conf") used on line 23 of "./conf/test62.conf"
+[core:error] done line 25. on line 25 of ./conf/test62.conf
+AH00526: Syntax error on line 25 of ./conf/test62.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test63.out b/modules/core/test/ref/test63.out
new file mode 100644
index 0000000..985710d
--- /dev/null
+++ b/modules/core/test/ref/test63.out
@@ -0,0 +1,10 @@
+# testing with conf/test63.conf
+[core:warn] Foo macro at inc63_.conf:5 on line 1 of macro 'foo' (defined on line 2 of "./conf/inc63_1.conf") used on line 5 of "./conf/inc63_1.conf"
+[core:warn] Foo macro at test63.conf:3 on line 1 of macro 'foo' (defined on line 2 of "./conf/inc63_1.conf") used on line 3 of "./conf/test63.conf"
+[core:warn] Foo macro at inc63_2.conf:2 on line 1 of macro 'foo' (defined on line 2 of "./conf/inc63_1.conf") used on line 2 of "./conf/inc63_2.conf"
+[core:warn] Bla at inc63_2.conf:3 on line 1 of macro 'bla' (defined on line 4 of "./conf/test63.conf") used on line 3 of "./conf/inc63_2.conf"
+[core:warn] Bla at test63.conf:8 on line 1 of macro 'bla' (defined on line 4 of "./conf/test63.conf") used on line 8 of "./conf/test63.conf"
+[core:error] done at line 9. on line 9 of ./conf/test63.conf
+AH00526: Syntax error on line 9 of ./conf/test63.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test64.out b/modules/core/test/ref/test64.out
new file mode 100644
index 0000000..99fec92
--- /dev/null
+++ b/modules/core/test/ref/test64.out
@@ -0,0 +1,7 @@
+# testing with conf/test64.conf
+[core:warn] on line 2 on line 2 of ./conf/test64.conf
+[core:warn] from line 3 to line 4 on line 4 of ./conf/test64.conf
+[core:error] done on line 5. on line 5 of ./conf/test64.conf
+AH00526: Syntax error on line 5 of ./conf/test64.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test65.out b/modules/core/test/ref/test65.out
new file mode 100644
index 0000000..62882e2
--- /dev/null
+++ b/modules/core/test/ref/test65.out
@@ -0,0 +1,7 @@
+# testing with conf/test65.conf
+[core:warn] Line: on line 6-7 on line 1 of macro 'line' (defined on line 2 of "./conf/test65.conf") used on line 7 of "./conf/test65.conf"
+[core:warn] Line: on line 8-10 on line 1 of macro 'line' (defined on line 2 of "./conf/test65.conf") used on line 10 of "./conf/test65.conf"
+[core:error] done on line 11. on line 11 of ./conf/test65.conf
+AH00526: Syntax error on line 11 of ./conf/test65.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test66.out b/modules/core/test/ref/test66.out
new file mode 100644
index 0000000..db8616a
--- /dev/null
+++ b/modules/core/test/ref/test66.out
@@ -0,0 +1,7 @@
+# testing with conf/test66.conf
+[core:warn] Foo: x=X y=Y on line 1 of macro 'foo' (defined on line 2 of "./conf/test66.conf") used on line 5 of "./conf/test66.conf"
+[core:warn] Foo: x=$y y=$x on line 1 of macro 'foo' (defined on line 2 of "./conf/test66.conf") used on line 6 of "./conf/test66.conf"
+[core:error] done on line 7. on line 7 of ./conf/test66.conf
+AH00526: Syntax error on line 7 of ./conf/test66.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test67.out b/modules/core/test/ref/test67.out
new file mode 100644
index 0000000..b83f074
--- /dev/null
+++ b/modules/core/test/ref/test67.out
@@ -0,0 +1,5 @@
+# testing with conf/test67.conf
+[core:error] done at line 1 without LF. on line 1 of ./conf/test67.conf
+AH00526: Syntax error on line 1 of ./conf/test67.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test68.out b/modules/core/test/ref/test68.out
new file mode 100644
index 0000000..0289127
--- /dev/null
+++ b/modules/core/test/ref/test68.out
@@ -0,0 +1,6 @@
+# testing with conf/test68.conf
+[core:warn] line 2-3 on line 3 of ./conf/test68.conf
+[core:error] done on line 4-5. on line 5 of ./conf/test68.conf
+AH00526: Syntax error on line 5 of ./conf/test68.conf:
+Configuration processing stopped by Error directive
+# exit: 1
diff --git a/modules/core/test/ref/test69.out b/modules/core/test/ref/test69.out
new file mode 100644
index 0000000..ac0c1db
--- /dev/null
+++ b/modules/core/test/ref/test69.out
@@ -0,0 +1,10 @@
+# testing with conf/test69.conf
+[macro:warn] non blank chars found after <Macro closing '>' on line 2 of ./conf/test69.conf: this stuff is ignored...
+[macro:warn] non blank chars found after directive closing on line 4 of ./conf/test69.conf: this stuff is ignored as well...
+[core:warn] Foo on line 1 of macro 'foo' (defined on line 2 of "./conf/test69.conf") used on line 5 of "./conf/test69.conf"
+[core:warn] Bla on line 1 of macro 'bla' (defined on line 6 of "./conf/test69.conf") used on line 9 of "./conf/test69.conf"
+[core:warn] Comments on line 1 of macro 'comments' (defined on line 10 of "./conf/test69.conf") used on line 13 of "./conf/test69.conf"
+[core:error] done on line 14. on line 14 of ./conf/test69.conf
+AH00526: Syntax error on line 14 of ./conf/test69.conf:
+Configuration processing stopped by Error directive
+# exit: 1