diff -r df083ef32b2f Makefile.am
--- a/Makefile.am	Tue Apr 03 10:32:03 2012 +0100
+++ b/Makefile.am	Thu Apr 05 10:41:06 2012 +0100
@@ -48,10 +48,14 @@
   make_SOURCES += guile.c
 endif
 
+if HAVE_PLUGINS
+  make_SOURCES += manage-plugins.c
+endif
+
 EXTRA_make_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
 
 noinst_HEADERS = commands.h dep.h filedef.h job.h make.h rule.h variable.h \
-		debug.h getopt.h gettext.h hash.h
+		debug.h getopt.h gettext.h hash.h plugin.h manage-plugins.h
 
 make_LDADD =	@LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ \
 		$(GUILE_LIBS)
diff -r df083ef32b2f configure.in
--- a/configure.in	Tue Apr 03 10:32:03 2012 +0100
+++ b/configure.in	Thu Apr 05 10:41:06 2012 +0100
@@ -18,7 +18,7 @@
 
 AC_INIT([GNU make],[3.82.90],[bug-make@gnu.org])
 
-AC_PREREQ([2.59])
+AC_PREREQ([2.68])
 AC_REVISION([$Id: configure.in,v 1.164 2012/03/05 14:10:42 psmith Exp $])
 
 # Autoconf setup
@@ -40,9 +40,9 @@
 
 # Specialized system macros
 AC_CANONICAL_HOST
-AC_AIX
-AC_ISC_POSIX
-AC_MINIX
+AC_USE_SYSTEM_EXTENSIONS
+AC_SEARCH_LIBS([strerror],[cposix])
+AC_USE_SYSTEM_EXTENSIONS
 
 # Enable gettext, in "external" mode.
 
@@ -77,7 +77,18 @@
 
 AM_PROG_CC_C_O
 AC_C_CONST
-AC_TYPE_SIGNAL
+AC_DIAGNOSE([obsolete],[your code may safely assume C89 semantics that RETSIGTYPE is void.
+Remove this warning and the `AC_CACHE_CHECK' when you adjust the code.])dnl
+AC_CACHE_CHECK([return type of signal handlers],[ac_cv_type_signal],[AC_COMPILE_IFELSE(
+[AC_LANG_PROGRAM([#include <sys/types.h>
+#include <signal.h>
+],
+		 [return *(signal (0, 0)) (0) == 1;])],
+		   [ac_cv_type_signal=int],
+		   [ac_cv_type_signal=void])])
+AC_DEFINE_UNQUOTED([RETSIGTYPE],[$ac_cv_type_signal],[Define as the return type of signal handlers
+		    (`int' or `void').])
+
 AC_TYPE_UID_T
 AC_TYPE_PID_T
 
@@ -175,13 +186,13 @@
 # For some strange reason, at least on Ubuntu, each version of Guile
 # comes with it's own PC file so we have to specify them as individual
 # packages.  Ugh.
-AS_IF([test "x$with_guile" != xno],
+AS_IF([test "x$with_guile" == xyes],
 [ PKG_CHECK_MODULES([GUILE], [guile-2.0], [have_guile=yes],
   [PKG_CHECK_MODULES([GUILE], [guile-1.8], [have_guile=yes],
     [have_guile=no])])
 ])
 
-AS_IF([test "$have_guile" = yes],
+AS_IF([test "$have_guile" == yes],
       [AC_DEFINE([HAVE_GUILE], [1], [Embed GNU Guile support])])
 
 AM_CONDITIONAL([HAVE_GUILE], [test "$have_guile" = yes])
@@ -204,6 +215,30 @@
   ])
 ])
 
+# see if the user wants to enable GNU make to load plugins containing make functions
+AC_ARG_WITH([plugins], [AS_HELP_STRING([--with-plugins],
+            [Support plugins which can add functions to GNU make])])
+
+
+AS_IF([test "x$with_plugins" == xyes], [
+DL_LIB=
+AC_CHECK_FUNCS(dlopen,,[
+  AC_CHECK_LIB(dl, dlopen, [DL_LIB="-ldl";
+     AC_DEFINE([HAVE_DLOPEN], [1], [DLOPEN permits GNUmake to suppor plugins on some architectures])
+     AC_DEFINE([HAVE_PLUGINS], [1], [build support for plugins])
+     LDFLAGS="$LDFLAGS -rdynamic"
+     have_plugins=yes
+     ]
+     , [
+     AC_CHECK_FUNCS(dlopen, DL_LIB="", DL_LIB="")
+  ])
+])
+LIBS="$LIBS $DL_LIB"
+])
+
+
+AM_CONDITIONAL([HAVE_PLUGINS], [test "$have_plugins" = yes])
+
 AC_CHECK_DECLS([sys_siglist, _sys_siglist, __sys_siglist], , ,
   [AC_INCLUDES_DEFAULT
 #include <signal.h>
@@ -257,8 +292,7 @@
 AC_SUBST([REMOTE]) REMOTE=stub
 use_customs=false
 AC_ARG_WITH([customs],
-[ AC_HELP_STRING([--with-customs=DIR],
-		 [enable remote jobs via Customs--see README.customs])],
+[ AS_HELP_STRING([--with-customs=DIR],[enable remote jobs via Customs--see README.customs])],
 [ AS_CASE([$withval], [n|no], [:],
     [make_cppflags="$CPPFLAGS"
      AS_CASE([$withval],
@@ -282,15 +316,13 @@
 
 AH_TEMPLATE([HAVE_CASE_INSENSITIVE_FS], [Use case insensitive file names])
 AC_ARG_ENABLE([case-insensitive-file-system],
-  AC_HELP_STRING([--enable-case-insensitive-file-system],
-		 [assume file systems are case insensitive]),
+  AS_HELP_STRING([--enable-case-insensitive-file-system],[assume file systems are case insensitive]),
   [AS_IF([test "$enableval" = yes], [AC_DEFINE([HAVE_CASE_INSENSITIVE_FS])])])
 
 # See if we can handle the job server feature, and if the user wants it.
 
 AC_ARG_ENABLE([job-server],
-  AC_HELP_STRING([--disable-job-server],
-                 [disallow recursive make communication during -jN]),
+  AS_HELP_STRING([--disable-job-server],[disallow recursive make communication during -jN]),
   [make_cv_job_server="$enableval" user_job_server="$enableval"],
   [make_cv_job_server="yes"])
 
diff -r df083ef32b2f main.c
--- a/main.c	Tue Apr 03 10:32:03 2012 +0100
+++ b/main.c	Thu Apr 05 10:41:06 2012 +0100
@@ -23,6 +23,7 @@
 #include "rule.h"
 #include "debug.h"
 #include "getopt.h"
+#include "manage-plugins.h"
 
 #include <assert.h>
 #ifdef _AMIGA
@@ -263,6 +264,11 @@
 
 static struct stringlist *new_files = 0;
 
+#ifdef HAVE_PLUGINS
+/* List of plugins to be loaded  */
+static struct stringlist *plugin_filenames = 0;
+#endif
+
 /* List of strings to be eval'd.  */
 static struct stringlist *eval_strings = 0;
 
@@ -342,6 +348,11 @@
     N_("\
   -o FILE, --old-file=FILE, --assume-old=FILE\n\
                               Consider FILE to be very old and don't remake it.\n"),
+
+#ifdef HAVE_PLUGINS
+    N_("\
+  --plugin=FILE               Load functions from a plugin (a shared library)\n"),
+#endif
     N_("\
   -p, --print-data-base       Print make's internal database.\n"),
     N_("\
@@ -425,6 +436,9 @@
     { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
       "warn-undefined-variables" },
     { CHAR_MAX+6, string, &eval_strings, 1, 0, 0, 0, 0, "eval" },
+#ifdef HAVE_PLUGINS
+    { CHAR_MAX+7, string, &plugin_filenames, 1, 1, 0, 0, 0, "plugin" },
+#endif
     { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
   };
 
@@ -1159,6 +1173,7 @@
   setup_guile ();
 #endif
 
+
   /* Read in variables from the environment.  It is important that this be
      done before $(MAKE) is figured out so its definitions will not be
      from the environment.  */
@@ -1659,6 +1674,19 @@
       define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0);
     }
 
+#ifdef HAVE_PLUGINS
+  /* Load plugins and register the functions they contain */
+  if (plugin_filenames != 0)
+    {
+      unsigned int i;
+      for (i = 0; plugin_filenames->list[i] != 0; ++i)
+        {
+          load_plugin(plugin_filenames->list[i]);
+        }
+    }
+#endif
+
+
   /* Read all the makefiles.  */
 
   read_makefiles
diff -r df083ef32b2f manage-plugins.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/manage-plugins.c	Thu Apr 05 10:41:06 2012 +0100
@@ -0,0 +1,115 @@
+/* Load plugins at runtime to allow GNU Make to be extended with new functions.
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ * This file is part of GNU Make.
+ *
+ * GNU Make is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.  
+*/
+
+#include "make.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "dep.h"
+#include "variable.h"
+#include "debug.h"
+
+#include <stdarg.h>
+
+#include "manage-plugins.h"
+#include "plugin.h"
+
+
+#define GNUMAKE_PLUGIN_API_MAJOR_VERSION 1
+
+
+#ifdef HAVE_DLOPEN
+#include <dlfcn.h>
+
+
+int load_plugin(const char *filename)
+{
+	void *dl_handle = NULL;
+	int *gnumake_plugin_api_version_ptr;
+	int *gnumake_plugin_major_version_ptr;
+	char *gnumake_plugin_name;
+	plugin_function *functable_ptr;
+	plugin_function *pf;
+
+	dl_handle  = dlopen(filename, RTLD_LOCAL | RTLD_NOW);
+	
+	if (!dl_handle)
+	{
+		
+		error (NILF, _("plugin failed to load: %s - %s"), filename, dlerror());
+		return -1;
+	}
+	
+	gnumake_plugin_api_version_ptr = (int *)dlsym(dl_handle, "gnumake_plugin_api_version");
+	if (!gnumake_plugin_api_version_ptr)
+	{
+		error (NILF, _("plugin failed to load: plugin doesn't indicate what api it requires - %s"), filename);
+		return -1;
+	}
+
+	if (*gnumake_plugin_api_version_ptr != GNUMAKE_PLUGIN_API_MAJOR_VERSION)	
+	{
+		error (NILF, _("plugin failed to load: unsupported version %d - the supported plugin api is %d - %s"), *gnumake_plugin_api_version_ptr, GNUMAKE_PLUGIN_API_MAJOR_VERSION , filename);
+		return -1;
+	}
+	
+	gnumake_plugin_major_version_ptr = (int *)dlsym(dl_handle, "gnumake_plugin_major_version");
+	if (!gnumake_plugin_major_version_ptr)
+	{
+		error (NILF, _("plugin failed to load: not a plugin (no version information) - %s"), filename);
+		return -1;
+	}
+
+	gnumake_plugin_name = (char *)dlsym(dl_handle, "gnumake_plugin_name");
+	if (!gnumake_plugin_name)
+	{
+		error (NILF, _("plugin invalid: missing gnumake_plugin_name symbol) - %s"), filename);
+		return -1;
+	}
+	
+	functable_ptr = (plugin_function *)dlsym(dl_handle, "gnumake_plugin_function_table");
+	if (!functable_ptr)
+	{
+		error (NILF, _("plugin invalid: missing gnumake_plugin_function_table symbol) - %s"), filename);
+		return -1;
+	}
+
+       	do_variable_definition (NILF, ".FEATURES", gnumake_plugin_name, o_default, f_append, 0);
+	message(1, _("plugin loaded: %s version %d"), gnumake_plugin_name, *gnumake_plugin_major_version_ptr);
+	for (pf = functable_ptr; pf->func != (void *)0; pf++)
+	{
+		message(1, _(" new function: %s"), pf->name);
+
+        	/* register function */
+        	define_new_function (NILF, pf->name, pf->min_arguments, pf->max_arguments, pf->expand_arguments, pf->func);
+        	
+	}
+
+	/* not dlclose()-ing since we want to keep it forever */
+
+	return 0;	/* no problems */
+}
+
+
+#elif defined(WINDOWS32)
+
+#else
+
+#error make does not support plugins on this architecture
+
+#endif
+
diff -r df083ef32b2f plugin.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin.h	Thu Apr 05 10:41:06 2012 +0100
@@ -0,0 +1,38 @@
+/* Plugin-structures
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ * This file is part of GNU Make.
+ *
+ * GNU Make is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.  
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#define PLUGIN_PADDING 256
+
+typedef struct 
+{
+	const char *name;
+    	unsigned char min_arguments;
+    	unsigned char max_arguments;
+    	char expand_arguments;
+	char *(*func)(char *output, char **argv, const char *fname);
+} plugin_function;
+
+typedef union 
+{
+	plugin_function pf;
+	char padding[PLUGIN_PADDING]; /* expansion room without forcing incompatibility */
+} padded_plugin_entry;
+
+#endif 
diff -r df083ef32b2f tests/plugins/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/plugins/Makefile	Thu Apr 05 10:41:06 2012 +0100
@@ -0,0 +1,13 @@
+.PHONY: all
+
+all: test-plugin.so
+
+test-plugin.so: test-plugin.o 
+	gcc -o $@ -shared test-plugin.o
+
+test-plugin.o: test-plugin.c
+	gcc -c -o $@ -fPIC -I ../../ test-plugin.c
+
+clean:
+	rm test-plugin.so test-plugin.o 
+
diff -r df083ef32b2f tests/plugins/plugintest1.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/plugins/plugintest1.mk	Thu Apr 05 10:41:06 2012 +0100
@@ -0,0 +1,8 @@
+
+# running make twice should result in 
+# 1) an error about running rm with no parameters and
+# 2) a report that everything is uptodate
+
+this:
+	touch $(equal this,this)
+	rm $(equal this,that)
diff -r df083ef32b2f tests/plugins/test-plugin.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/plugins/test-plugin.c	Thu Apr 05 10:41:06 2012 +0100
@@ -0,0 +1,50 @@
+/* A test plugin for GNU Make.
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ * This file is part of GNU Make.
+ *
+ * GNU Make is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.  
+*/
+
+#include "plugin.h"
+#include <string.h>
+
+/* A cheat here to save from having to include all the make headers - don't like it and
+  will have to think of something better: */
+extern char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
+
+int gnumake_plugin_api_version = 1; /* what api the plugin expects make to provide - just a way for make to know if it's loading a plugin that should work  */
+
+int gnumake_plugin_major_version = 1; /* The version of this plugin - might be useful for problem reports */
+char gnumake_plugin_name[] = "test_plugin";  /* also the name of the feature added to .FEATURES */
+
+/* $(equal astring1,astring2) returns blank, $(equal astring1,astring1) returns "astring1"
+ * The purpose of this function is to allow equality tests in $(if) functions e.g. $(if $(equal $(X),$(Y)),<something>,<else>)
+ * */
+static char *function_equal(char *o, char **argv, const char *funcname)
+{
+  if (argv[0] && argv[1] && strcmp(argv[0],argv[1]) == 0)
+    {
+          o = variable_buffer_output (o, argv[0], strlen (argv[0]));
+    }
+  else 
+    {
+          o = variable_buffer_output (o, "", 0);
+    }
+
+return o;
+}
+
+padded_plugin_entry gnumake_plugin_function_table[] = {
+	{"equal", 2, 2, 1, function_equal}, /* 2 args, expand them first */
+	{"", 0, 0, 0, (void *)0}
+};
