spack/var/spack/repos/builtin/packages/mpi-bash/mpibash-4.3.patch
Adam J. Stewart 2264e30d99
Update URL parsing regexes and tests (#13411)
* Update URL parsing regexes and tests

* Get rid of no longer used README

* Merge py-udunits and py-cf-units

* netcdf -> netcdf-c

* setup_environment -> setup_*_environment

* Fix doc tests

* Few last minute fixes

* Simplify prefix removal copypasta
2019-10-28 20:27:54 -05:00

1566 lines
46 KiB
Diff

diff -Naur bash-4.3/builtins/circle.def mpibash-4.3/builtins/circle.def
--- bash-4.3/builtins/circle.def 1969-12-31 17:00:00.000000000 -0700
+++ mpibash-4.3/builtins/circle.def 2014-05-13 11:27:37.314100671 -0600
@@ -0,0 +1,620 @@
+This file is circle.def, from which is created circle.c.
+It implements all of the "circle_*" builtins in Bash.
+
+$PRODUCES circle.c
+
+#include <config.h>
+
+#include <stdio.h>
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include "../bashintl.h"
+#include "../shell.h"
+#include "common.h"
+#include "bashgetopt.h"
+#include <libcircle.h>
+
+extern int running_trap, trap_saved_exit_value;
+
+static int circle_rank; /* Rank in the Libcircle job */
+static SHELL_VAR *create_func = NULL; /* User-defined callback function for CIRCLE_cb_create. */
+static SHELL_VAR *process_func = NULL; /* User-defined callback function for CIRCLE_cb_process. */
+static SHELL_VAR *reduce_init_func = NULL; /* User-defined callback function for CIRCLE_cb_reduce_init. */
+static SHELL_VAR *reduce_fini_func = NULL; /* User-defined callback function for CIRCLE_cb_reduce_fini. */
+static SHELL_VAR *reduce_op_func = NULL; /* User-defined callback function for CIRCLE_cb_reduce_op. */
+static CIRCLE_handle *current_handle = NULL; /* Active handle within a callback or NULL if not within a callback */
+static int within_reduction = 0; /* 1=within a reduction callback; 0=not */
+
+/* Return with a usage message if no arguments remain. */
+#define YES_ARGS(LIST) \
+ if ((LIST) == 0) \
+ { \
+ builtin_usage (); \
+ return (EX_USAGE); \
+ }
+
+/* Perform the same operation as bind_variable, but with VALUE being a
+ * number, not a string. */
+static SHELL_VAR *
+bind_variable_number (name, value, flags)
+ const char *name;
+ long value;
+ int flags;
+{
+ char numstr[25]; /* String version of VALUE */
+
+ sprintf (numstr, "%ld", value);
+ return bind_variable (name, numstr, flags);
+}
+
+/* Invoke the user-defined creation-callback function (create_func). */
+static void
+internal_create_func (handle)
+ CIRCLE_handle *handle;
+{
+ WORD_LIST *funcargs;
+
+ if (create_func == NULL)
+ return;
+ current_handle = handle;
+ funcargs = make_word_list (make_word ("cb_create"), NULL);
+ execute_shell_function (create_func, funcargs);
+ dispose_words (funcargs);
+ current_handle = NULL;
+}
+
+/* Invoke the user-defined process-callback function (process_func). */
+static void
+internal_process_func (handle)
+ CIRCLE_handle *handle;
+{
+ WORD_LIST *funcargs;
+
+ if (process_func == NULL)
+ return;
+ current_handle = handle;
+ funcargs = make_word_list (make_word ("cb_process"), NULL);
+ execute_shell_function (process_func, funcargs);
+ dispose_words (funcargs);
+ current_handle = NULL;
+}
+
+/* Invoke the user-defined reduction-initiation callback function
+ * (reduce_init_func). */
+static void
+internal_reduce_init_func (void)
+{
+ WORD_LIST *funcargs;
+
+ if (reduce_init_func == NULL)
+ return;
+ within_reduction = 1;
+ funcargs = make_word_list (make_word ("cb_reduce_init"), NULL);
+ execute_shell_function (reduce_init_func, funcargs);
+ dispose_words (funcargs);
+ within_reduction = 0;
+}
+
+/* Invoke the user-defined reduction callback function
+ * (reduce_op_func). */
+static void
+internal_reduce_op_func (buf1, size1, buf2, size2)
+ const void* buf1;
+ size_t size1;
+ const void* buf2;
+ size_t size2;
+{
+ WORD_LIST *funcargs;
+
+ if (reduce_op_func == NULL)
+ return;
+ within_reduction = 1;
+ funcargs = make_word_list (make_word (buf2), NULL);
+ funcargs = make_word_list (make_word (buf1), funcargs);
+ funcargs = make_word_list (make_word ("cb_reduce_op"), funcargs);
+ execute_shell_function (reduce_op_func, funcargs);
+ dispose_words (funcargs);
+ within_reduction = 0;
+}
+
+/* Invoke the user-defined reduction-finalization callback function
+ * (reduce_fini_func). */
+static void
+internal_reduce_fini_func (buf, size)
+ const void* buf;
+ size_t size;
+{
+ WORD_LIST *funcargs;
+
+ if (reduce_fini_func == NULL)
+ return;
+ funcargs = make_word_list (make_word (buf), NULL);
+ funcargs = make_word_list (make_word ("cb_reduce_fini"), funcargs);
+ execute_shell_function (reduce_fini_func, funcargs);
+ dispose_words (funcargs);
+}
+
+/* Look up a user-provided callback function. */
+static int
+find_callback_function (list, user_func)
+ WORD_LIST *list;
+ SHELL_VAR **user_func;
+{
+ char *funcname; /* Name of the user-defined function. */
+
+ /* If no argument was provided, nullify the callback function. */
+ if (list == NULL)
+ {
+ *user_func = NULL;
+ return EXECUTION_SUCCESS;
+ }
+
+ /* Get the callback function. */
+ funcname = list->word->word;
+ list = list->next;
+ no_args (list);
+ *user_func = find_function (funcname);
+ if (*user_func == NULL)
+ {
+ builtin_error (_("function %s not found"), funcname);
+ return EXECUTION_FAILURE;
+ }
+ return EXECUTION_SUCCESS;
+}
+
+/* Initialize Libcircle. */
+void
+initialize_libcircle (argc, argv)
+ int argc;
+ char **argv;
+{
+ circle_rank = CIRCLE_init (argc, argv, CIRCLE_DEFAULT_FLAGS);
+ bind_variable_number ("circle_rank", circle_rank, 0);
+ CIRCLE_enable_logging (CIRCLE_LOG_WARN);
+ CIRCLE_cb_create (internal_create_func);
+ CIRCLE_cb_process (internal_process_func);
+ CIRCLE_cb_reduce_init (internal_reduce_init_func);
+ CIRCLE_cb_reduce_op (internal_reduce_op_func);
+ CIRCLE_cb_reduce_fini (internal_reduce_fini_func);
+}
+
+/* Finalize Libcircle. */
+void
+finalize_libcircle (void)
+{
+ CIRCLE_finalize ();
+}
+
+/* ---------------------------------------------------------------------- */
+
+$BUILTIN circle_set_options
+$FUNCTION circle_set_options_builtin
+$SHORT_DOC circle_set_options [flag]...
+Change Libcircle's run-time behavior.
+
+Arguments:
+ FLAG "split_random", "split_equal", or "create_global"
+
+Multiple flags can be provided. If no flags are provided, Libcircle
+reverts to its default options.
+
+Exit Status:
+Returns 0 unless an invalid option is given.
+$END
+/*'*/
+
+/* Here is the circle_set_options builtin. */
+int
+circle_set_options_builtin (list)
+ WORD_LIST *list;
+{
+ char *word; /* One argument */
+ int flags = 0; /* Flags to pass to CIRCLE_set_options */
+
+ if (list == NULL)
+ flags = CIRCLE_DEFAULT_FLAGS;
+ else
+ while (list != NULL)
+ {
+ word = list->word->word;
+ if (!strcmp (word, "split_random"))
+ flags |= CIRCLE_SPLIT_RANDOM;
+ else if (!strcmp (word, "split_equal"))
+ flags |= CIRCLE_SPLIT_EQUAL;
+ else if (!strcmp (word, "create_global"))
+ flags |= CIRCLE_CREATE_GLOBAL;
+ else
+ {
+ builtin_error (_("invalid flag \"%s\""), word);
+ return (EXECUTION_FAILURE);
+ }
+ list = list->next;
+ }
+ CIRCLE_set_options (flags);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_cb_create
+$FUNCTION circle_cb_create_builtin
+$SHORT_DOC circle_cb_create [func]
+Register a function that will create work when asked.
+
+Arguments:
+ FUNC User-defined callback function that will invoke
+ circle_enqueue when called
+
+If FUNC is omitted, no function will be associated with work creation.
+This can be used to nullify a previous circle_cb_create invocation.
+
+Exit Status:
+Returns 0 unless an invalid function is given or an error occurs.
+$END
+
+/* Here is the circle_cb_create builtin. */
+int
+circle_cb_create_builtin (list)
+ WORD_LIST *list;
+{
+ return find_callback_function (list, &create_func);
+}
+
+$BUILTIN circle_cb_process
+$FUNCTION circle_cb_process_builtin
+$SHORT_DOC circle_cb_process [func]
+Register a function that will process work when asked.
+
+Arguments:
+ FUNC User-defined callback function that will invoke
+ circle_enqueue when called
+
+If FUNC is omitted, no function will be associated with work processing.
+This can be used to nullify a previous circle_cb_process invocation.
+
+Exit Status:
+Returns 0 unless an invalid function is given or an error occurs.
+$END
+
+/* Here is the circle_cb_process builtin. */
+int
+circle_cb_process_builtin (list)
+ WORD_LIST *list;
+{
+ return find_callback_function (list, &process_func);
+}
+
+$BUILTIN circle_begin
+$FUNCTION circle_begin_builtin
+$SHORT_DOC circle_begin
+Begin creation and processing of the distributed work queue.
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+
+/* Here is the circle_begin builtin. */
+int
+circle_begin_builtin (list)
+ WORD_LIST *list;
+{
+ no_args (list);
+ CIRCLE_begin ();
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_enqueue
+$FUNCTION circle_enqueue_builtin
+$SHORT_DOC circle_enqueue work
+Enqueue work onto the distributed queue.
+
+Arguments:
+ WORK "Work" as represented by an arbitrary string of limited
+ size (generally around 4KB)
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+
+/* Here is the circle_enqueue builtin. */
+int
+circle_enqueue_builtin (list)
+ WORD_LIST *list;
+{
+ char *work; /* Work to perform */
+
+ /* Extract the work argument. */
+ YES_ARGS (list);
+ work = list->word->word;
+ list = list->next;
+ no_args (list);
+
+ /* Complain if we're not within a proper callback function. */
+ if (current_handle == NULL)
+ {
+ builtin_error (_("not within a Libcircle \"create\" or \"process\" callback function"));
+ return EXECUTION_FAILURE;
+ }
+
+ /* Enqueue the work. */
+ if (current_handle->enqueue (work) == -1)
+ return EXECUTION_FAILURE;
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_dequeue
+$FUNCTION circle_dequeue_builtin
+$SHORT_DOC circle_dequeue var
+Dequeue work from the distributed queue into a variable.
+
+Arguments:
+ VAR Variable in which to receive previously enqueued "work"
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+
+/* Here is the circle_dequeue builtin. */
+int
+circle_dequeue_builtin (list)
+ WORD_LIST *list;
+{
+ char *varname; /* Variable in which to store the work string */
+ char work[CIRCLE_MAX_STRING_LEN+1]; /* Work to perform */
+
+ /* Extract the variable-name argument. */
+ YES_ARGS (list);
+ varname = list->word->word;
+ list = list->next;
+ no_args (list);
+
+ /* Complain if we're not within a callback function. */
+ if (current_handle == NULL)
+ {
+ builtin_error (_("not within a Libcircle callback function"));
+ return EXECUTION_FAILURE;
+ }
+
+ /* Dequeue the work and bind it to the given variable. */
+ if (current_handle->dequeue (work) == -1)
+ return EXECUTION_FAILURE;
+ bind_variable (varname, work, 0);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_enable_logging
+$FUNCTION circle_enable_logging_builtin
+$SHORT_DOC circle_enable_logging log_level
+Change Libcircle's logging verbosity
+
+Arguments:
+ LOG_LEVEL "fatal", "error", "warning", "info", or "debug"
+
+Exit Status:
+Returns 0 unless an invalid option is given.
+$END
+/*'*/
+
+/* Here is the circle_enable_logging builtin. */
+int
+circle_enable_logging_builtin (list)
+ WORD_LIST *list;
+{
+ char *word; /* One argument */
+ CIRCLE_loglevel loglevel; /* Level to set */
+
+ /* Parse the log level. */
+ YES_ARGS (list);
+ word = list->word->word;
+ if (!strcmp (word, "fatal"))
+ loglevel = CIRCLE_LOG_FATAL;
+ else if (!strcmp (word, "error"))
+ loglevel = CIRCLE_LOG_ERR;
+ else if (!strcmp (word, "warning"))
+ loglevel = CIRCLE_LOG_WARN;
+ else if (!strcmp (word, "info"))
+ loglevel = CIRCLE_LOG_INFO;
+ else if (!strcmp (word, "debug"))
+ loglevel = CIRCLE_LOG_DBG;
+ else
+ {
+ builtin_error (_("invalid log level \"%s\""), word);
+ return (EXECUTION_FAILURE);
+ }
+
+ /* Set the log level. */
+ CIRCLE_enable_logging (loglevel);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_abort
+$FUNCTION circle_abort_builtin
+$SHORT_DOC circle_abort
+Terminate queue processing.
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+
+/* Here is the circle_abort builtin. */
+int
+circle_abort_builtin (list)
+ WORD_LIST *list;
+{
+ no_args (list);
+ CIRCLE_abort ();
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_checkpoint
+$FUNCTION circle_checkpoint_builtin
+$SHORT_DOC circle_checkpoint
+Checkpoint a work queue to disk.
+
+Write a file called circle${circle_rank}.txt containing the current
+queue state of rank ${circle_rank}. On a later run, a worker can
+invoke circle_read_restarts to repopulate its queue from such a
+checkpoint file.
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+/*'*/
+
+/* Here is the circle_checkpoint builtin. */
+int
+circle_checkpoint_builtin (list)
+ WORD_LIST *list;
+{
+ no_args (list);
+ CIRCLE_checkpoint ();
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_read_restarts
+$FUNCTION circle_read_restarts_builtin
+$SHORT_DOC circle_read_restarts
+Repopulate a work queue from a disk checkpoint.
+
+Read queue contents from a file called circle${circle_rank}.txt, which
+was previously produced by circle_checkpoint.
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+/*'*/
+
+/* Here is the circle_read_restarts builtin. */
+int
+circle_read_restarts_builtin (list)
+ WORD_LIST *list;
+{
+ no_args (list);
+ CIRCLE_read_restarts ();
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN circle_cb_reduce_init
+$FUNCTION circle_cb_reduce_init_builtin
+$SHORT_DOC circle_cb_reduce_init [func]
+Register a function that will initiate a reduction operation.
+
+Arguments:
+ FUNC User-defined callback function that will invoke
+ circle_reduce when called
+
+FUNC will be invoked on all ranks.
+
+If FUNC is omitted, no function will be associated with reduction
+initialization. This can be used to nullify a previous
+circle_cb_reduce_init invocation.
+
+Exit Status:
+Returns 0 unless an invalid function is given or an error occurs.
+$END
+
+/* Here is the circle_cb_reduce_init builtin. */
+int
+circle_cb_reduce_init_builtin (list)
+ WORD_LIST *list;
+{
+ return find_callback_function (list, &reduce_init_func);
+}
+
+$BUILTIN circle_cb_reduce_op
+$FUNCTION circle_cb_reduce_op_builtin
+$SHORT_DOC circle_cb_reduce_op [func]
+Register a function that will complete a reduction operation.
+
+Arguments:
+ FUNC User-defined callback function that will receive
+ two items to reduce and invoke circle_reduce on
+ the reduced value
+
+If FUNC is omitted, no function will be associated with reduction
+execution. This can be used to nullify a previous circle_cb_reduce_op
+invocation.
+
+Exit Status:
+Returns 0 unless an invalid function is given or an error occurs.
+$END
+
+/* Here is the circle_cb_reduce_op builtin. */
+int
+circle_cb_reduce_op_builtin (list)
+ WORD_LIST *list;
+{
+ return find_callback_function (list, &reduce_op_func);
+}
+
+$BUILTIN circle_cb_reduce_fini
+$FUNCTION circle_cb_reduce_fini_builtin
+$SHORT_DOC circle_cb_reduce_fini [func]
+Register a function that will complete a reduction operation.
+
+Arguments:
+ FUNC User-defined callback function that will receive
+ the final reduced data
+
+If FUNC is omitted, no function will be associated with reduction
+completion. This can be used to nullify a previous
+circle_cb_reduce_fini invocation.
+
+Libcircle guarantees that FUNC will be invoked only on rank 0.
+
+Exit Status:
+Returns 0 unless an invalid function is given or an error occurs.
+$END
+
+/* Here is the circle_cb_reduce_fini builtin. */
+int
+circle_cb_reduce_fini_builtin (list)
+ WORD_LIST *list;
+{
+ return find_callback_function (list, &reduce_fini_func);
+}
+
+$BUILTIN circle_reduce
+$FUNCTION circle_reduce_builtin
+$SHORT_DOC circle_reduce work
+Seed the next phase of a reduction operation
+
+Arguments:
+ WORK "Work" as represented by an arbitrary string of limited
+ size (generally around 4KB)
+
+This function should be called both by the callback function
+registered with circle_reduce_init and the callback function
+registered with circle_reduce_op.
+
+Exit Status:
+Returns 0 unless an error occurs.
+$END
+
+/* Here is the circle_reduce builtin. */
+int
+circle_reduce_builtin (list)
+ WORD_LIST *list;
+{
+ char *work; /* Work to perform */
+
+ /* Extract the work argument. */
+ YES_ARGS (list);
+ work = list->word->word;
+ list = list->next;
+ no_args (list);
+
+ /* Complain if we're not within a proper callback function. */
+ if (!within_reduction)
+ {
+ builtin_error (_("not within a Libcircle \"reduce_init\" or \"reduce_op\" callback function"));
+ return EXECUTION_FAILURE;
+ }
+
+ /* Reduce the work. */
+ CIRCLE_reduce (work, strlen (work));
+ return EXECUTION_SUCCESS;
+}
diff -Naur bash-4.3/builtins/Makefile.in mpibash-4.3/builtins/Makefile.in
--- bash-4.3/builtins/Makefile.in 2012-05-25 07:29:19.000000000 -0600
+++ mpibash-4.3/builtins/Makefile.in 2014-05-13 11:27:37.314100671 -0600
@@ -141,7 +141,9 @@
$(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
$(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
$(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \
- $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def
+ $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def \
+ $(srcdir)/mpi.def \
+@CIRCLE@ $(srcdir)/circle.def
STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
getopt.h
@@ -153,7 +155,9 @@
jobs.o kill.o let.o mapfile.o \
pushd.o read.o return.o set.o setattr.o shift.o source.o \
suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
- wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
+ wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o \
+ mpi.o \
+@CIRCLE@ circle.o
CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h tmpbuiltins.c \
tmpbuiltins.h
@@ -317,6 +321,8 @@
getopts.o: getopts.def
reserved.o: reserved.def
complete.o: complete.def
+@CIRCLE@ circle.o: circle.def
+mpi.o: mpi.def
# C files
bashgetopt.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
@@ -644,6 +650,19 @@
mapfile.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
mapfile.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/variables.h $(topdir)/conftypes.h
mapfile.o: $(topdir)/arrayfunc.h ../pathnames.h
+@CIRCLE@ circle.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+@CIRCLE@ circle.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
+@CIRCLE@ circle.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+@CIRCLE@ circle.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+@CIRCLE@ circle.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
+mpi.o: ../config.h ../config-top.h ../config-bot.h ../bashintl.h
+mpi.o: ../include/gettext.h ../shell.h ../config.h ../bashjmp.h
+mpi.o: ../include/posixjmp.h ../command.h ../syntax.h ../general.h
+mpi.o: ../bashtypes.h ../include/chartypes.h ../xmalloc.h ../bashansi.h
+mpi.o: ../error.h ../variables.h ../array.h ../assoc.h ../hashlib.h
+mpi.o: ../conftypes.h ../arrayfunc.h ../quit.h ../sig.h ../include/maxpath.h
+mpi.o: ../unwind_prot.h ../dispose_cmd.h ../make_cmd.h ../include/ocache.h
+mpi.o: ../subst.h ../pathnames.h ../externs.h common.h bashgetopt.h
#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
diff -Naur bash-4.3/builtins/mpi.def mpibash-4.3/builtins/mpi.def
--- bash-4.3/builtins/mpi.def 1969-12-31 17:00:00.000000000 -0700
+++ mpibash-4.3/builtins/mpi.def 2014-05-13 11:27:37.314100671 -0600
@@ -0,0 +1,744 @@
+This file is mpi.def, from which is created mpi.c.
+It implements all of the "mpi_*" builtins in Bash.
+
+$PRODUCES mpi.c
+
+#include <config.h>
+
+#include <stdio.h>
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include "../bashintl.h"
+#include "../shell.h"
+#include "common.h"
+#include "bashgetopt.h"
+#include <mpi.h>
+
+extern int running_trap, trap_saved_exit_value;
+
+/* Keep track of who we are within MPI_COMM_WORLD. */
+static int mpi_rank;
+static int mpi_num_ranks;
+
+/* Try an MPI operation. Return with an error message on failure. */
+#define MPI_TRY(STMT) \
+ do \
+ { \
+ int mpierr; \
+ mpierr = STMT; \
+ if (mpierr != MPI_SUCCESS) \
+ return report_mpi_error (mpierr); \
+ } \
+ while (0)
+
+/* Return with a usage message if no arguments remain. */
+#define YES_ARGS(LIST) \
+ if ((LIST) == 0) \
+ { \
+ builtin_usage (); \
+ return (EX_USAGE); \
+ }
+
+/* Return with an error message if a given variable is read-only or if
+ * we can't write to it for any other reason (e.g., it's defined as a
+ * function). */
+#define REQUIRE_WRITABLE(NAME) \
+ do \
+ { \
+ SHELL_VAR *bindvar = find_shell_variable (NAME); \
+ if (bindvar) \
+ { \
+ if (readonly_p (bindvar)) \
+ { \
+ err_readonly (NAME); \
+ return (EXECUTION_FAILURE); \
+ } \
+ if (unbind_variable (NAME) == -1) \
+ { \
+ builtin_error ("Failed to write to variable %s", NAME); \
+ return (EXECUTION_FAILURE); \
+ } \
+ } \
+ } \
+ while (0)
+
+/* Initialize MPI. */
+void
+initialize_mpi (argc, argv)
+ int argc;
+ char **argv;
+{
+ int init_done;
+
+ MPI_Initialized (&init_done);
+ if (!init_done)
+ MPI_Init (&argc, &argv);
+ MPI_Errhandler_set (MPI_COMM_WORLD, MPI_ERRORS_RETURN);
+ MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank);
+ MPI_Comm_size (MPI_COMM_WORLD, &mpi_num_ranks);
+}
+
+/* Finalize MPI. */
+void
+finalize_mpi ()
+{
+ MPI_Finalize ();
+}
+
+/* Parse an operation name into an MPI_Op. Return 1 on success, 0 on
+ * failure. */
+static int
+parse_operation (char *name, MPI_Op *op)
+{
+ /* Define a mapping from operator names to MPI_Op values. */
+ typedef struct {
+ char *name; /* Operation name (e.g., "sum") */
+ MPI_Op value; /* Operation value (e.g., MPI_SUM) */
+ } opname2value_t;
+ static opname2value_t oplist[] = {
+ {"max", MPI_MAX},
+ {"min", MPI_MIN},
+ {"sum", MPI_SUM},
+ {"prod", MPI_PROD},
+ {"land", MPI_LAND},
+ {"band", MPI_BAND},
+ {"lor", MPI_LOR},
+ {"bor", MPI_BOR},
+ {"lxor", MPI_LXOR},
+ {"bxor", MPI_BXOR},
+ {"maxloc", MPI_MAXLOC},
+ {"minloc", MPI_MINLOC}
+ };
+ size_t i;
+
+ for (i = 0; i < sizeof(oplist)/sizeof(opname2value_t); i++)
+ if (!strcmp(name, oplist[i].name))
+ {
+ *op = oplist[i].value;
+ if (i > 0)
+ {
+ /* As a performance optimization, bubble up the value we
+ * just found. */
+ opname2value_t prev = oplist[i - 1];
+ oplist[i - 1] = oplist[i];
+ oplist[i] = prev;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/* Report an error to the user and return EXECUTION_FAILURE. */
+static int
+report_mpi_error (mpierr)
+ int mpierr;
+{
+ char errstr[MPI_MAX_ERROR_STRING];
+ int errstrlen;
+
+ MPI_Error_string (mpierr, errstr, &errstrlen);
+ builtin_error ("%s", errstr);
+ return EXECUTION_FAILURE;
+}
+
+/* Perform the same operation as bind_variable, but with VALUE being a
+ * number, not a string. */
+static SHELL_VAR *
+bind_variable_number (name, value, flags)
+ const char *name;
+ long value;
+ int flags;
+{
+ char numstr[25]; /* String version of VALUE */
+
+ sprintf (numstr, "%ld", value);
+ return bind_variable (name, numstr, flags);
+}
+
+/* Perform the same operation as bind_array_variable, but with VALUE
+ * being a number, not a string. */
+static SHELL_VAR *
+bind_array_variable_number (name, ind, value, flags)
+ char *name;
+ arrayind_t ind;
+ long value;
+ int flags;
+{
+ char numstr[25]; /* String version of VALUE */
+
+ sprintf (numstr, "%ld", value);
+ return bind_array_variable (name, ind, numstr, flags);
+}
+
+/* Define a reduction-type function (allreduce, scan, exscan, etc.). */
+typedef int (*reduction_func_t)(void *, void *, int, MPI_Datatype, MPI_Op, MPI_Comm);
+
+/* Perform any reduction-type operation (allreduce, scan, exscan, etc.). */
+static int
+reduction_like (list, funcname, func)
+ WORD_LIST *list;
+ char *funcname;
+ reduction_func_t func;
+{
+ char *word; /* One argument */
+ struct {
+ long int value; /* Reduced value */
+ int rank; /* Rank associated with the above */
+ } number, result;
+ MPI_Op operation = MPI_SUM; /* Operation to perform */
+ char *varname; /* Name of the variable to bind the results to */
+ intmax_t n;
+ int i;
+
+ /* Parse "-O OPERATION" (optional), where OPERATION is a reduction
+ * operation. */
+ YES_ARGS (list);
+ word = list->word->word;
+ if (ISOPTION (word, 'O'))
+ {
+ list = list->next;
+ if (list == 0)
+ {
+ sh_needarg (funcname);
+ return (EX_USAGE);
+ }
+ word = list->word->word;
+ if (!parse_operation (word, &operation))
+ {
+ sh_invalidopt ("-O");
+ return (EX_USAGE);
+ }
+ list = list->next;
+ }
+
+ /* Parse the argument, which must be a number. */
+ YES_ARGS (list);
+ word = list->word->word;
+ if (!legal_number (word, &n))
+ {
+ sh_neednumarg (funcname);
+ return (EX_USAGE);
+ }
+ number.value = (long int) n;
+ number.rank = mpi_rank;
+ list = list->next;
+
+ /* Parse the target variable, which must not be read-only. */
+ YES_ARGS (list);
+ varname = list->word->word;
+ if (mpi_rank != 0 || func != MPI_Exscan)
+ REQUIRE_WRITABLE (varname);
+ list = list->next;
+ no_args (list);
+
+ /* Perform the reduction operation. Bind the given array variable
+ * to the result and, for minloc/maxloc, the associated rank. */
+ if (mpi_rank != 0 || func != MPI_Exscan) {
+ bind_array_variable (varname, 0, "", 0);
+ bind_array_variable (varname, 1, "", 0);
+ }
+ if (operation == MPI_MINLOC || operation == MPI_MAXLOC)
+ {
+ MPI_TRY (func (&number, &result, 1, MPI_LONG_INT, operation, MPI_COMM_WORLD));
+ if (mpi_rank != 0 || func != MPI_Exscan)
+ bind_array_variable_number (varname, 1, result.rank, 0);
+ }
+ else
+ MPI_TRY (func (&number.value, &result.value, 1, MPI_LONG, operation, MPI_COMM_WORLD));
+ if (mpi_rank != 0 || func != MPI_Exscan)
+ bind_array_variable_number (varname, 0, result.value, 0);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN mpi_comm_rank
+$FUNCTION mpi_comm_rank_builtin
+$SHORT_DOC mpi_comm_rank name
+Return the process's rank in the MPI job.
+
+Arguments:
+ NAME Scalar variable in which to receive the rank
+
+Exit Status:
+Returns 0 unless an invalid option is given.
+$END
+/*'*/
+
+/* Here is the mpi_comm_rank builtin. */
+int
+mpi_comm_rank_builtin (list)
+ WORD_LIST *list;
+{
+ char *varname; /* Name of the variable to bind the results to */
+
+ YES_ARGS (list);
+ varname = list->word->word;
+ REQUIRE_WRITABLE (varname);
+ list = list->next;
+ no_args (list);
+ bind_variable_number (varname, mpi_rank, 0);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN mpi_comm_size
+$FUNCTION mpi_comm_size_builtin
+$SHORT_DOC mpi_comm_size name
+Return the total number of ranks in the MPI job.
+
+Arguments:
+ NAME Scalar variable in which to receive the number of ranks
+
+Exit Status:
+Returns 0 unless an invalid option is given.
+$END
+
+/* Here is the mpi_comm_size builtin. */
+int
+mpi_comm_size_builtin (list)
+ WORD_LIST *list;
+{
+ char *varname; /* Name of the variable to bind the results to */
+
+ YES_ARGS (list);
+ varname = list->word->word;
+ REQUIRE_WRITABLE (varname);
+ list = list->next;
+ no_args (list);
+ bind_variable_number (varname, mpi_num_ranks, 0);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN mpi_abort
+$FUNCTION mpi_abort_builtin
+$SHORT_DOC mpi_abort [n]
+Abort all processes in the MPI job and exit the shell.
+
+Exits not only the caller's shell (with a status of N) but also all
+remote shells that are part of the same MPI job. If N is omitted, the
+exit status is that of the last command executed.
+
+This command should be used only in extreme circumstances. It is
+better for each process to exit normally on its own.
+$END
+/*'*/
+
+/* Here is the mpi_abort builtin. */
+int
+mpi_abort_builtin (list)
+ WORD_LIST *list;
+{
+ int exit_value;
+
+ exit_value = (running_trap == 1 && list == 0) ? trap_saved_exit_value : get_exitstat (list); /* Copied from exit.def */
+ MPI_TRY (MPI_Abort (MPI_COMM_WORLD, exit_value));
+ return EXECUTION_FAILURE;
+}
+
+$BUILTIN mpi_send
+$FUNCTION mpi_send_builtin
+$SHORT_DOC mpi_send [-t tag] rank message
+Send a message to a remote process in the same MPI job.
+
+Options:
+ -t TAG Send the message using tag TAG (default: 0). TAG must
+ be a nonnegative integer.
+
+Arguments:
+ RANK Whom to send the message to. RANK must be an integer in
+ the range [0, $(mpi_comm_size)-1].
+
+ MESSAGE String to send to rank RANK.
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_send builtin. */
+int
+mpi_send_builtin (list)
+ WORD_LIST *list;
+{
+ char *word; /* One argument */
+ intmax_t target_rank; /* MPI target rank */
+ char *message; /* Message to send to rank target_rank */
+ intmax_t tag = 0; /* Message tag to use */
+
+ /* Parse "-t TAG" (optional), where TAG is a number or "any". */
+ YES_ARGS (list);
+ word = list->word->word;
+ if (ISOPTION (word, 't'))
+ {
+ list = list->next;
+ if (list == 0)
+ {
+ sh_needarg ("mpi_recv");
+ return (EX_USAGE);
+ }
+ word = list->word->word;
+ if (!legal_number (word, &tag))
+ {
+ sh_neednumarg ("-t");
+ return (EX_USAGE);
+ }
+ list = list->next;
+ }
+ else if (*word == '-')
+ {
+ sh_invalidopt (word);
+ builtin_usage ();
+ return (EX_USAGE);
+ }
+
+ /* Parse the target rank, which must be a number. */
+ YES_ARGS (list);
+ word = list->word->word;
+ if (!legal_number (word, &target_rank))
+ {
+ builtin_error (_("mpi_send: numeric rank required"));
+ return (EX_USAGE);
+ }
+ list = list->next;
+
+ /* Parse the message to send. */
+ YES_ARGS (list);
+ message = list->word->word;
+ list = list->next;
+ no_args (list);
+
+ /* Send the message. */
+ MPI_TRY (MPI_Send (message, strlen(message)+1, MPI_BYTE, (int)target_rank, (int)tag, MPI_COMM_WORLD));
+ return EXECUTION_SUCCESS;
+}
+
+
+$BUILTIN mpi_recv
+$FUNCTION mpi_recv_builtin
+$SHORT_DOC mpi_recv [-t tag] rank name
+Receive a message from a remote process in the same MPI job.
+
+Options:
+ -t TAG Receive only messages sent using tag TAG (default: 0).
+ TAG must be either a nonnegative integer or the string
+ "any" to receive messages sent using any tag.
+
+Arguments:
+ RANK Receive only messages sent from sender RANK. RANK
+ must either be in the range [0, $(mpi_comm_size)-1] or
+ be the string "any" to receive messages from any sender.
+
+ NAME Array variable in which to receive the message, sender
+ rank, and tag.
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_recv builtin. */
+int
+mpi_recv_builtin (list)
+ WORD_LIST *list;
+{
+ char *word; /* One argument */
+ intmax_t source_rank; /* MPI source rank */
+ char *endptr; /* Used for parsing strings into numbers */
+ MPI_Status status; /* Status of an MPI operation */
+ int count; /* Message length in bytes */
+ intmax_t tag = 0; /* Message tag to use */
+ char *varname; /* Name of the variable to bind the results to */
+ static char *message = NULL; /* Message received from MPI */
+ static size_t alloced = 0; /* Number of bytes allocated for the above */
+ int opt; /* Parsed option */
+
+ /* Parse any options provided. */
+ reset_internal_getopt ();
+ while ((opt = internal_getopt (list, "t:")) != -1)
+ {
+ switch (opt)
+ {
+ case 't':
+ if (!strcmp (list_optarg, "any"))
+ tag = MPI_ANY_TAG;
+ else if (!legal_number (list_optarg, &tag))
+ {
+ builtin_error (_("-t: numeric argument or \"any\" required"));
+ return (EX_USAGE);
+ }
+ break;
+
+ default:
+ sh_invalidopt (word);
+ builtin_usage ();
+ return (EX_USAGE);
+ }
+ }
+ list = loptend;
+
+ /* Parse the source rank, which must be a number or "any". */
+ YES_ARGS (list);
+ word = list->word->word;
+ if (!legal_number (word, &source_rank))
+ {
+ if (!strcmp (word, "any"))
+ source_rank = MPI_ANY_SOURCE;
+ else
+ {
+ builtin_error (_("mpi_recv: numeric rank or \"any\" required"));
+ return (EX_USAGE);
+ }
+ }
+ list = list->next;
+
+ /* Parse the target variable, which must not be read-only. */
+ YES_ARGS (list);
+ varname = list->word->word;
+ REQUIRE_WRITABLE (varname);
+ list = list->next;
+ no_args (list);
+
+ /* Receive a message. Because we don't know long the message will
+ * be, we first probe to get the length. */
+ MPI_TRY (MPI_Probe ((int)source_rank, (int)tag, MPI_COMM_WORLD, &status));
+ MPI_TRY (MPI_Get_count (&status, MPI_BYTE, &count));
+ if (alloced < count)
+ {
+ message = xrealloc (message, count);
+ alloced = count;
+ }
+ MPI_TRY (MPI_Recv (message, count, MPI_BYTE, status.MPI_SOURCE, status.MPI_TAG, MPI_COMM_WORLD, &status));
+ bind_array_variable (varname, 0, message, 0);
+ bind_array_variable_number (varname, 1, status.MPI_SOURCE, 0);
+ bind_array_variable_number (varname, 2, status.MPI_TAG, 0);
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN mpi_barrier
+$FUNCTION mpi_barrier_builtin
+$SHORT_DOC mpi_barrier
+Synchronizes all of the processes in the MPI job.
+
+No process will return from mpi_barrier until all processes have
+called mpi_barrier.
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_barrier builtin. */
+int
+mpi_barrier_builtin (list)
+ WORD_LIST *list;
+{
+ no_args (list);
+ MPI_TRY (MPI_Barrier (MPI_COMM_WORLD));
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN mpi_bcast
+$FUNCTION mpi_bcast_builtin
+$SHORT_DOC mpi_bcast [message] name
+Broadcast a message to all processes in the same MPI job.
+
+Arguments:
+ MESSAGE String to broadcast from one process to all the others.
+
+ NAME Scalar variable in which to receive the broadcast message.
+
+Exactly one process in the MPI job must specify a message to
+broadcast. No process will return from mpi_bcast until all processes
+have called mpi_bcast.
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_bcast builtin. */
+int
+mpi_bcast_builtin (list)
+ WORD_LIST *list;
+{
+ char *word; /* One argument */
+ int root; /* MPI root rank */
+ char *root_message; /* Message to broadcast */
+ int msglen; /* Length in bytes of the above (including the NULL byte) */
+ char *varname; /* Name of the variable to bind the results to */
+ static int *all_lengths = NULL; /* List of every rank's msglen */
+ static char *message = NULL; /* Message received from the root */
+ static int alloced = 0; /* Bytes allocated for the above */
+ int i;
+
+ /* Parse the optional message and target variable, which must not be
+ * read-only. */
+ YES_ARGS (list);
+ if (list->next == NULL)
+ {
+ /* Non-root */
+ root_message = NULL;
+ msglen = -1;
+ }
+ else
+ {
+ /* Root */
+ root_message = list->word->word;
+ msglen = (int) strlen(root_message) + 1;
+ list = list->next;
+ }
+ varname = list->word->word;
+ REQUIRE_WRITABLE (varname);
+ list = list->next;
+ no_args (list);
+
+ /* Acquire global agreement on the root and the message size. */
+ if (all_lengths == NULL)
+ all_lengths = xmalloc (mpi_num_ranks*sizeof(int));
+ MPI_TRY (MPI_Allgather (&msglen, 1, MPI_INT, all_lengths, 1, MPI_INT, MPI_COMM_WORLD));
+ root = -1;
+ for (i = 0; i < mpi_num_ranks; i++)
+ {
+ if (all_lengths[i] == -1)
+ continue;
+ if (root != -1)
+ {
+ builtin_error (_("mpi_bcast: more than one process specified a message"));
+ return (EXECUTION_FAILURE);
+ }
+ root = i;
+ msglen = all_lengths[i];
+ }
+ if (root == -1)
+ {
+ builtin_error (_("mpi_bcast: no process specified a message"));
+ return (EXECUTION_FAILURE);
+ }
+
+ /* Broadcast the message. */
+ if (mpi_rank == root)
+ {
+ MPI_TRY (MPI_Bcast (root_message, msglen, MPI_BYTE, root, MPI_COMM_WORLD));
+ bind_variable (varname, root_message, 0);
+ }
+ else
+ {
+ if (alloced < msglen)
+ {
+ message = xrealloc (message, msglen);
+ alloced = msglen;
+ }
+ MPI_TRY (MPI_Bcast (message, msglen, MPI_BYTE, root, MPI_COMM_WORLD));
+ bind_variable (varname, message, 0);
+ }
+ return EXECUTION_SUCCESS;
+}
+
+$BUILTIN mpi_scan
+$FUNCTION mpi_scan_builtin
+$SHORT_DOC mpi_scan number name
+Perform an inclusive scan across all processes in the same MPI job.
+
+ -O OPERATION Operation to perform. Must be one of "max", "min",
+ "sum", "prod", "land", "band", "lor", "bor", "lxor",
+ "bxor", "maxloc", or "minloc" (default: "sum").
+
+Arguments:
+ NUMBER Integer to use in the scan operation.
+
+ NAME Array variable in which to receive the result and, in
+ the case of maxloc and minloc, the associated rank.
+
+In an inclusive-scan operation, each process i presents a number,
+a[i]. Once all processes in the MPI job have presented their number,
+the command returns a[0] to rank 0, a[0]+a[1] to rank 1,
+a[0]+a[1]+a[2] to rank 2, and so forth. The -O option enables "+" to
+be replaced with other operations.
+
+Inclusive scans can be useful for assigning a unique index to each
+process in the MPI job.
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_scan builtin. */
+int
+mpi_scan_builtin (list)
+ WORD_LIST *list;
+{
+ return reduction_like (list, "mpi_scan", MPI_Scan);
+}
+
+$BUILTIN mpi_exscan
+$FUNCTION mpi_exscan_builtin
+$SHORT_DOC mpi_exscan number name
+Perform an exclusive scan across all processes in the same MPI job.
+
+ -O OPERATION Operation to perform. Must be one of "max", "min",
+ "sum", "prod", "land", "band", "lor", "bor", "lxor",
+ "bxor", "maxloc", or "minloc" (default: "sum").
+
+Arguments:
+ NUMBER Integer to use in the scan operation.
+
+ NAME Array variable in which to receive the result and, in
+ the case of maxloc and minloc, the associated rank.
+
+In a exclusive-scan operation, each process i presents a number, a[i].
+Once all processes in the MPI job have presented their number, the
+command assigns a[0] to NAME on rank 1, a[0]+a[1] to NAME on rank 2,
+a[0]+a[1]+a[2] to NAME on rank 3, and so forth. No assignment is
+performed on rank 0. The -O option enables "+" to be replaced with
+other operations.
+
+Exclusive scans can be useful for assigning a unique index to each
+process in the MPI job.
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_exscan builtin. */
+int
+mpi_exscan_builtin (list)
+ WORD_LIST *list;
+{
+ return reduction_like (list, "mpi_exscan", MPI_Exscan);
+}
+
+$BUILTIN mpi_allreduce
+$FUNCTION mpi_allreduce_builtin
+$SHORT_DOC mpi_allreduce number name
+Reduce numbers from all processes in an MPI job to a single number.
+
+Options:
+
+ -O OPERATION Operation to perform. Must be one of "max", "min",
+ "sum", "prod", "land", "band", "lor", "bor", "lxor",
+ "bxor", "maxloc", or "minloc" (default: "sum").
+
+Arguments:
+ NUMBER Integer to use in the allreduce operation.
+
+ NAME Array variable in which to receive the result and, in
+ the case of maxloc and minloc, the associated rank.
+
+In an all-reduce operation, each process i presents a number, a[i].
+Once all processes in the MPI job have presented their number, the
+command returns a[0]+a[1]+...+a[n-1] to all ranks. The -O option
+enables "+" to be replaced with other operations.
+
+All-reduces can be useful for reaching global agreement (e.g., of a
+termination condition).
+
+Exit Status:
+Returns 0 unless an invalid option is given or an error occurs.
+$END
+
+/* Here is the mpi_allreduce builtin. */
+int
+mpi_allreduce_builtin (list)
+ WORD_LIST *list;
+{
+ return reduction_like (list, "mpi_allreduce", MPI_Allreduce);
+}
diff -Naur bash-4.3/config.h.in mpibash-4.3/config.h.in
--- bash-4.3/config.h.in 2013-06-29 15:35:33.000000000 -0600
+++ mpibash-4.3/config.h.in 2014-05-13 11:27:37.314100671 -0600
@@ -1147,6 +1147,12 @@
/* Define if you have the `__argz_stringify' function. */
#undef HAVE___ARGZ_STRINGIFY
+/* Define if you have both the <libcircle.h> header file and the libcircle library. */
+#undef HAVE_LIBCIRCLE
+
+/* Define if you have the `CIRCLE_cb_reduce_op' function. */
+#undef HAVE_CIRCLE_CB_REDUCE_OP
+
/* End additions for lib/intl */
#include "config-bot.h"
diff -Naur bash-4.3/configure.ac mpibash-4.3/configure.ac
--- bash-4.3/configure.ac 2014-02-11 08:37:53.000000000 -0700
+++ mpibash-4.3/configure.ac 2014-05-13 11:27:37.302100179 -0600
@@ -24,7 +24,7 @@
AC_REVISION([for Bash 4.3, version 4.063])dnl
define(bashvers, 4.3)
-define(relstatus, release)
+define(relstatus, MPI)
AC_INIT([bash], bashvers-relstatus, [bug-bash@gnu.org])
@@ -813,6 +813,21 @@
fi
])
+dnl Ensure that we can find an MPI library.
+AC_CHECK_FUNCS([MPI_Init], [], [
+ AC_MSG_ERROR([Cannot continue without MPI. Consider specifying CC=mpicc.])])
+
+dnl If we have Libcircle, use it, too.
+AC_SEARCH_LIBS([CIRCLE_cb_create], [circle], [AC_CHECK_HEADERS([libcircle.h])])
+if test "x$ac_cv_header_libcircle_h" = xyes; then
+ libcircle_make_prefix=""
+ AC_DEFINE([HAVE_LIBCIRCLE], [1], [Define if you have the Libcircle header and library.])
+ AC_CHECK_FUNCS([CIRCLE_cb_reduce_op])
+else
+ libcircle_make_prefix="#"
+fi
+AC_SUBST([CIRCLE], [$libcircle_make_prefix])
+
BASH_CHECK_DECL(strtoimax)
BASH_CHECK_DECL(strtol)
BASH_CHECK_DECL(strtoll)
diff -Naur bash-4.3/Makefile.in mpibash-4.3/Makefile.in
--- bash-4.3/Makefile.in 2014-01-25 14:27:30.000000000 -0700
+++ mpibash-4.3/Makefile.in 2014-05-13 11:27:37.314100671 -0600
@@ -104,7 +104,7 @@
VERSPROG = bashversion$(EXEEXT)
VERSOBJ = bashversion.$(OBJEXT)
-Program = bash$(EXEEXT)
+Program = mpibash$(EXEEXT)
Version = @BASHVERS@
PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
RELSTATUS = @RELSTATUS@
diff -Naur bash-4.3/shell.c mpibash-4.3/shell.c
--- bash-4.3/shell.c 2014-01-14 06:04:32.000000000 -0700
+++ mpibash-4.3/shell.c 2014-05-13 11:27:37.314100671 -0600
@@ -107,6 +107,13 @@
extern char *primary_prompt, *secondary_prompt;
extern char *this_command_name;
+extern void initialize_mpi __P((int, char **));
+extern void finalize_mpi __P((void));
+#ifdef HAVE_LIBCIRCLE
+extern void initialize_libcircle __P((int, char **));
+extern void finalize_libcircle __P((void));
+#endif
+
/* Non-zero means that this shell has already been run; i.e. you should
call shell_reinitialize () if you need to start afresh. */
int shell_initialized = 0;
@@ -324,7 +331,7 @@
static void init_interactive_script __P((void));
static void set_shell_name __P((char *));
-static void shell_initialize __P((void));
+static void shell_initialize __P((int, char **));
static void shell_reinitialize __P((void));
static void show_shell_usage __P((FILE *, int));
@@ -561,7 +568,7 @@
/* From here on in, the shell must be a normal functioning shell.
Variables from the environment are expected to be set, etc. */
- shell_initialize ();
+ shell_initialize (argc, argv);
set_default_lang ();
set_default_locale_vars ();
@@ -941,6 +948,12 @@
end_job_control ();
#endif /* JOB_CONTROL */
+#ifdef HAVE_LIBCIRCLE
+ finalize_libcircle ();
+#else
+ finalize_mpi ();
+#endif
+
/* Always return the exit status of the last command to our parent. */
sh_exit (s);
}
@@ -1691,7 +1704,9 @@
/* Do whatever is necessary to initialize the shell.
Put new initializations in here. */
static void
-shell_initialize ()
+shell_initialize (argc, argv)
+ int argc;
+ char **argv;
{
char hostname[256];
@@ -1760,6 +1775,17 @@
initialize_shell_options (privileged_mode||running_setuid);
initialize_bashopts (privileged_mode||running_setuid);
#endif
+
+ /* Initialize Libcircle and MPI. */
+#ifdef HAVE_LIBCIRCLE
+ initialize_libcircle (argc, argv);
+ initialize_mpi (argc, argv);
+ bind_variable ("libcircle", "yes", 0);
+#else
+ initialize_mpi (argc, argv);
+ bind_variable ("libcircle", "no", 0);
+#endif
+ bind_variable ("mpibash", "yes", 0);
}
/* Function called by main () when it appears that the shell has already