summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore67
-rw-r--r--AUTHORS3
-rw-r--r--COPYING3
-rw-r--r--ChangeLog4
-rw-r--r--HACKING39
-rw-r--r--Makefile.am94
-rw-r--r--NEWS14
l---------README1
-rw-r--r--README.org4
-rw-r--r--TODO.org42
-rwxr-xr-xbuild-aux/gitlog-to-changelog432
-rw-r--r--build-aux/test-driver.scm180
-rw-r--r--configure.ac36
-rw-r--r--doc/drmaa.texi87
-rw-r--r--drmaa/v1/ffi.ffi20
-rw-r--r--drmaa/v1/low.scm655
-rw-r--r--guix.scm37
-rw-r--r--include/drmaa.h567
-rw-r--r--pre-inst-env.in14
19 files changed, 2299 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d347fdd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,67 @@
+*.eps
+*.go
+*.log
+*.pdf
+*.png
+*.tar.xz
+*.tar.gz
+*.tmp
+*~
+.#*
+\#*\#
+,*
+/ABOUT-NLS
+/INSTALL
+/aclocal.m4
+/autom4te.cache
+/build-aux/ar-lib
+/build-aux/compile
+/build-aux/config.guess
+/build-aux/config.rpath
+/build-aux/config.sub
+/build-aux/depcomp
+/build-aux/install-sh
+/build-aux/mdate-sh
+/build-aux/missing
+/build-aux/test-driver
+/build-aux/texinfo.tex
+/config.status
+/configure
+/doc/*.1
+/doc/.dirstamp
+/doc/contributing.*.texi
+/doc/*.aux
+/doc/*.cp
+/doc/*.cps
+/doc/*.fn
+/doc/*.fns
+/doc/*.html
+/doc/*.info
+/doc/*.info-[0-9]
+/doc/*.ky
+/doc/*.pg
+/doc/*.toc
+/doc/*.t2p
+/doc/*.tp
+/doc/*.vr
+/doc/*.vrs
+/doc/stamp-vti
+/doc/version.texi
+/doc/version-*.texi
+/m4/*
+/pre-inst-env
+/test-env
+/test-tmp
+/tests/*.trs
+GPATH
+GRTAGS
+GTAGS
+Makefile
+Makefile.in
+config.cache
+stamp-h[0-9]
+tmp
+/.version
+/doc/stamp-[0-9]
+
+/drmaa/v1/ffi.scm \ No newline at end of file
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..9f63302
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Contributers to Guile DRMAA 0.1:
+
+ Ricardo Wurmus <rekado@elephly.net>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..f658e91
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,3 @@
+This project's license is GPL 3+.
+
+You can read the full license at https://www.gnu.org/licenses/gpl.html.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..fdb7b5f
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+Normally a ChangeLog is generated at "make dist" time and available in
+source tarballs.
+
+If not, see the Git commit log at <https://git.elephly.net/software/guile-drmaa.git/>.
diff --git a/HACKING b/HACKING
new file mode 100644
index 0000000..109bafe
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,39 @@
+-*- mode: org; coding: utf-8; -*-
+
+#+TITLE: Hacking drmaa
+
+* Contributing
+
+By far the easiest way to hack on Guile DRMAA is to develop using Guix:
+
+#+BEGIN_SRC bash
+# Obtain the source code
+cd /path/to/source-code
+guix environment -l guix.scm
+# In the new shell, run:
+autoreconf -vif && ./configure && make check
+#+END_SRC
+
+You can now hack this project's files to your heart's content, whilst
+testing them from your =guix environment= shell.
+
+To try out any scripts in the project you can now use
+
+#+BEGIN_SRC bash
+./pre-inst-env scripts/${script-name}
+#+END_SRC
+
+** Manual Installation
+
+If you do not yet use Guix, you will have to install this project's
+dependencies manually:
+ - autoconf
+ - automake
+ - pkg-config
+ - texinfo
+
+Once those dependencies are installed you can run:
+
+#+BEGIN_SRC bash
+autoreconf -vif && ./configure && make check
+#+END_SRC
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..caa3c8c
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,94 @@
+# Handle substitution of fully-expanded Autoconf variables.
+do_subst = $(SED) \
+ -e 's,[@]GUILE[@],$(GUILE),g' \
+ -e 's,[@]guilemoduledir[@],$(guilemoduledir),g' \
+ -e 's,[@]guileobjectdir[@],$(guileobjectdir),g' \
+ -e 's,[@]localedir[@],$(localedir),g'
+
+nodist_noinst_SCRIPTS = pre-inst-env
+
+GOBJECTS = $(SOURCES:%.scm=%.go)
+
+moddir=$(prefix)/share/guile/site/$(GUILE_EFFECTIVE_VERSION)
+godir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache
+ccachedir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache
+
+nobase_mod_DATA = $(SOURCES) $(NOCOMP_SOURCES)
+nobase_go_DATA = $(GOBJECTS)
+
+# Make sure source files are installed first, so that the mtime of
+# installed compiled files is greater than that of installed source
+# files. See
+# <http://lists.gnu.org/archive/html/guile-devel/2010-07/msg00125.html>
+# for details.
+guile_install_go_files = install-nobase_goDATA
+$(guile_install_go_files): install-nobase_modDATA
+
+EXTRA_DIST = $(SOURCES) $(NOCOMP_SOURCES) drmaa/v1/ffi.ffi
+GUILE_WARNINGS = -Wunbound-variable -Warity-mismatch -Wformat
+SUFFIXES = .scm .go .ffi
+.scm.go:
+ $(AM_V_GEN)$(top_builddir)/pre-inst-env $(GUILE_TOOLS) compile $(GUILE_WARNINGS) -o "$@" "$<"
+
+drmaa/v1/ffi.scm: drmaa/v1/ffi.ffi
+ $(AM_V_GEN)$(top_builddir)/pre-inst-env $(GUILE_TOOLS) compile-ffi -I $(top_srcdir)/include -X -o "$@" "$<" && \
+ $(SED) -e 's,(define drmaa-v1-ffi-llibs (list)),(define drmaa-v1-ffi-llibs (delay (list (dynamic-link (getenv "GUILE_DRMAA_LIBRARY"))))),' \
+ -e 's,drmaa-v1-ffi-llibs),(force drmaa-v1-ffi-llibs)),' -i $@
+
+SOURCES = drmaa.scm \
+ drmaa/v1/ffi.scm \
+ drmaa/v1/low.scm
+
+TESTS =
+
+TEST_EXTENSIONS = .scm
+SCM_LOG_DRIVER = \
+ $(top_builddir)/pre-inst-env \
+ $(GUILE) --no-auto-compile -e main \
+ $(top_srcdir)/build-aux/test-driver.scm
+
+# Tell 'build-aux/test-driver.scm' to display only source file names,
+# not indivdual test names.
+AM_SCM_LOG_DRIVER_FLAGS = --brief=yes
+
+AM_SCM_LOG_FLAGS = --no-auto-compile -L "$(top_srcdir)"
+
+AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)"
+
+info_TEXINFOS = doc/drmaa.texi
+dvi: # Don't build dvi docs
+
+EXTRA_DIST += README.org \
+ README \
+ HACKING \
+ COPYING \
+ NEWS \
+ AUTHORS \
+ ChangeLog \
+ guix.scm \
+ build-aux/test-driver.scm \
+ configure.ac \
+ Makefile.am \
+ pre-inst-env.in \
+ build-aux/test-driver.scm \
+ $(TESTS)
+
+ACLOCAL_AMFLAGS = -I m4
+
+dist-hook: $(distdir)/ChangeLog
+gen-ChangeLog $(distdir)/ChangeLog:
+ $(AM_V_GEN)if test -d .git; then \
+ $(top_srcdir)/build-aux/gitlog-to-changelog \
+ > $(distdir)/cl-t; \
+ rm -f $(distdir)/ChangeLog; \
+ mv $(distdir)/cl-t $(distdir)/ChangeLog; \
+ fi
+
+clean-go:
+ -$(RM) $(GOBJECTS)
+.PHONY: clean-go gen-ChangeLog
+
+CLEANFILES = \
+ drmaa/v1/ffi.scm \
+ $(GOBJECTS) \
+ $(TESTS:tests/%.scm=%.log)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..bb8b5b2
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,14 @@
+-*- mode: org; coding: utf-8; -*-
+
+#+TITLE: Guile DRMAA NEWS – history of user-visible changes
+#+STARTUP: content hidestars
+
+Copyright © 2020, 2021 Ricardo Wurmus <rekado@elephly.net>
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved.
+
+Please send Guile DRMAA bug reports to <rekado@elephly.net>.
+
+* Publication at 0.1
diff --git a/README b/README
new file mode 120000
index 0000000..314e17d
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+README.org \ No newline at end of file
diff --git a/README.org b/README.org
new file mode 100644
index 0000000..7d2e607
--- /dev/null
+++ b/README.org
@@ -0,0 +1,4 @@
+-*- mode: org; coding: utf-8; -*-
+
+#+TITLE: README for Guile Drmaa
+
diff --git a/TODO.org b/TODO.org
new file mode 100644
index 0000000..00cada7
--- /dev/null
+++ b/TODO.org
@@ -0,0 +1,42 @@
+#+TYP_TODO: MAYBE TODO DONE
+* TODO error message becomes a scheduling command
+
+Consider this code:
+
+#+begin_src scheme
+(use-modules (drmaa v1 low))
+(define (test)
+ (let ((t (allocate-job-template!)))
+ (set-attribute! t (DRMAA 'REMOTE_COMMAND) "/bin/ls")
+ (set-attribute! t (DRMAA 'JS_STATE)
+ (DRMAA 'SUBMISSION_STATE_ACTIVE))
+ (set-attribute! t (DRMAA 'WD)
+ "/home/rwurmus/")
+
+ ;; This is wrong and leads to an error
+ (set-attribute! t (DRMAA 'NATIVE_SPECIFICATION)
+ "-b n -V -q all.q -w n -A rwurmus")
+ (run-bulk-jobs t 1)))
+
+(init-session!)
+(test)
+(exit-session!)
+#+end_src
+
+Since there is no =rwurmus= accounting group, the template fails with an error message. Part of this error message is interpreted as a command:
+
+#+begin_example
+scheme@(guile-user)> (test)
+WARNING - Accounting to 'rwurmus' was denied, thus your job was assigned into your default department 'akalin
+WARNING - Accounting to 'rwurmus' was denied, thus your job was assigned into your default department 'akalin
+ice-9/boot-9.scm:1669:16: In procedure raise-exception:
+ERROR:
+ 1. &message: "master got unknown command from JSV: \"'.\" (17)"
+
+Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
+scheme@(guile-user) [1]> ,bt
+In ice-9/boot-9.scm:
+ 1669:16 0 (raise-exception _ #:continuable? _)
+#+end_example
+
+That’s the trailing “'.” of the error message that somehow slips by and is interpreted as a command. Is some buffer too small?
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
new file mode 100755
index 0000000..e02d34c
--- /dev/null
+++ b/build-aux/gitlog-to-changelog
@@ -0,0 +1,432 @@
+eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
+ & eval 'exec perl -wS "$0" $argv:q'
+ if 0;
+# Convert git log output to ChangeLog format.
+
+my $VERSION = '2012-07-29 06:11'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job. Otherwise, update this string manually.
+
+# Copyright (C) 2008-2013 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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/>.
+
+# Written by Jim Meyering
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw(strftime);
+
+(my $ME = $0) =~ s|.*/||;
+
+# use File::Coda; # http://meyering.net/code/Coda/
+END {
+ defined fileno STDOUT or return;
+ close STDOUT and return;
+ warn "$ME: failed to close standard output: $!\n";
+ $? ||= 1;
+}
+
+sub usage ($)
+{
+ my ($exit_code) = @_;
+ my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
+ if ($exit_code != 0)
+ {
+ print $STREAM "Try '$ME --help' for more information.\n";
+ }
+ else
+ {
+ print $STREAM <<EOF;
+Usage: $ME [OPTIONS] [ARGS]
+
+Convert git log output to ChangeLog format. If present, any ARGS
+are passed to "git log". To avoid ARGS being parsed as options to
+$ME, they may be preceded by '--'.
+
+OPTIONS:
+
+ --amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
+ makes a change to SHA1's commit log text or metadata.
+ --append-dot append a dot to the first line of each commit message if
+ there is no other punctuation or blank at the end.
+ --no-cluster never cluster commit messages under the same date/author
+ header; the default is to cluster adjacent commit messages
+ if their headers are the same and neither commit message
+ contains multiple paragraphs.
+ --srcdir=DIR the root of the source tree, from which the .git/
+ directory can be derived.
+ --since=DATE convert only the logs since DATE;
+ the default is to convert all log entries.
+ --format=FMT set format string for commit subject and body;
+ see 'man git-log' for the list of format metacharacters;
+ the default is '%s%n%b%n'
+ --strip-tab remove one additional leading TAB from commit message lines.
+ --strip-cherry-pick remove data inserted by "git cherry-pick";
+ this includes the "cherry picked from commit ..." line,
+ and the possible final "Conflicts:" paragraph.
+ --help display this help and exit
+ --version output version information and exit
+
+EXAMPLE:
+
+ $ME --since=2008-01-01 > ChangeLog
+ $ME -- -n 5 foo > last-5-commits-to-branch-foo
+
+SPECIAL SYNTAX:
+
+The following types of strings are interpreted specially when they appear
+at the beginning of a log message line. They are not copied to the output.
+
+ Copyright-paperwork-exempt: Yes
+ Append the "(tiny change)" notation to the usual "date name email"
+ ChangeLog header to mark a change that does not require a copyright
+ assignment.
+ Co-authored-by: Joe User <user\@example.com>
+ List the specified name and email address on a second
+ ChangeLog header, denoting a co-author.
+ Signed-off-by: Joe User <user\@example.com>
+ These lines are simply elided.
+
+In a FILE specified via --amend, comment lines (starting with "#") are ignored.
+FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
+a line) referring to a commit in the current project, and CODE refers to one
+or more consecutive lines of Perl code. Pairs must be separated by one or
+more blank line.
+
+Here is sample input for use with --amend=FILE, from coreutils:
+
+3a169f4c5d9159283548178668d2fae6fced3030
+# fix typo in title:
+s/all tile types/all file types/
+
+1379ed974f1fa39b12e2ffab18b3f7a607082202
+# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
+# Change the author to be Paul. Note the escaped "@":
+s,Jim .*>,Paul Eggert <eggert\\\@cs.ucla.edu>,
+
+EOF
+ }
+ exit $exit_code;
+}
+
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return the new string.
+sub shell_quote($)
+{
+ my ($s) = @_;
+ if ($s =~ m![^\w+/.,-]!)
+ {
+ # Convert each single quote to '\''
+ $s =~ s/\'/\'\\\'\'/g;
+ # Then single quote the string.
+ $s = "'$s'";
+ }
+ return $s;
+}
+
+sub quoted_cmd(@)
+{
+ return join (' ', map {shell_quote $_} @_);
+}
+
+# Parse file F.
+# Comment lines (starting with "#") are ignored.
+# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
+# (alone on a line) referring to a commit in the current project, and
+# CODE refers to one or more consecutive lines of Perl code.
+# Pairs must be separated by one or more blank line.
+sub parse_amend_file($)
+{
+ my ($f) = @_;
+
+ open F, '<', $f
+ or die "$ME: $f: failed to open for reading: $!\n";
+
+ my $fail;
+ my $h = {};
+ my $in_code = 0;
+ my $sha;
+ while (defined (my $line = <F>))
+ {
+ $line =~ /^\#/
+ and next;
+ chomp $line;
+ $line eq ''
+ and $in_code = 0, next;
+
+ if (!$in_code)
+ {
+ $line =~ /^([0-9a-fA-F]{40})$/
+ or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
+ $fail = 1, next;
+ $sha = lc $1;
+ $in_code = 1;
+ exists $h->{$sha}
+ and (warn "$ME: $f:$.: duplicate SHA1\n"),
+ $fail = 1, next;
+ }
+ else
+ {
+ $h->{$sha} ||= '';
+ $h->{$sha} .= "$line\n";
+ }
+ }
+ close F;
+
+ $fail
+ and exit 1;
+
+ return $h;
+}
+
+# git_dir_option $SRCDIR
+#
+# From $SRCDIR, the --git-dir option to pass to git (none if $SRCDIR
+# is undef). Return as a list (0 or 1 element).
+sub git_dir_option($)
+{
+ my ($srcdir) = @_;
+ my @res = ();
+ if (defined $srcdir)
+ {
+ my $qdir = shell_quote $srcdir;
+ my $cmd = "cd $qdir && git rev-parse --show-toplevel";
+ my $qcmd = shell_quote $cmd;
+ my $git_dir = qx($cmd);
+ defined $git_dir
+ or die "$ME: cannot run $qcmd: $!\n";
+ $? == 0
+ or die "$ME: $qcmd had unexpected exit code or signal ($?)\n";
+ chomp $git_dir;
+ push @res, "--git-dir=$git_dir/.git";
+ }
+ @res;
+}
+
+{
+ my $since_date;
+ my $format_string = '%s%n%b%n';
+ my $amend_file;
+ my $append_dot = 0;
+ my $cluster = 1;
+ my $strip_tab = 0;
+ my $strip_cherry_pick = 0;
+ my $srcdir;
+ GetOptions
+ (
+ help => sub { usage 0 },
+ version => sub { print "$ME version $VERSION\n"; exit },
+ 'since=s' => \$since_date,
+ 'format=s' => \$format_string,
+ 'amend=s' => \$amend_file,
+ 'append-dot' => \$append_dot,
+ 'cluster!' => \$cluster,
+ 'strip-tab' => \$strip_tab,
+ 'strip-cherry-pick' => \$strip_cherry_pick,
+ 'srcdir=s' => \$srcdir,
+ ) or usage 1;
+
+ defined $since_date
+ and unshift @ARGV, "--since=$since_date";
+
+ # This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
+ # that makes a correction in the log or attribution of that commit.
+ my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
+
+ my @cmd = ('git',
+ git_dir_option $srcdir,
+ qw(log --log-size),
+ '--pretty=format:%H:%ct %an <%ae>%n%n'.$format_string, @ARGV);
+ open PIPE, '-|', @cmd
+ or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
+ . "(Is your Git too old? Version 1.5.1 or later is required.)\n");
+
+ my $prev_multi_paragraph;
+ my $prev_date_line = '';
+ my @prev_coauthors = ();
+ while (1)
+ {
+ defined (my $in = <PIPE>)
+ or last;
+ $in =~ /^log size (\d+)$/
+ or die "$ME:$.: Invalid line (expected log size):\n$in";
+ my $log_nbytes = $1;
+
+ my $log;
+ my $n_read = read PIPE, $log, $log_nbytes;
+ $n_read == $log_nbytes
+ or die "$ME:$.: unexpected EOF\n";
+
+ # Extract leading hash.
+ my ($sha, $rest) = split ':', $log, 2;
+ defined $sha
+ or die "$ME:$.: malformed log entry\n";
+ $sha =~ /^[0-9a-fA-F]{40}$/
+ or die "$ME:$.: invalid SHA1: $sha\n";
+
+ # If this commit's log requires any transformation, do it now.
+ my $code = $amend_code->{$sha};
+ if (defined $code)
+ {
+ eval 'use Safe';
+ my $s = new Safe;
+ # Put the unpreprocessed entry into "$_".
+ $_ = $rest;
+
+ # Let $code operate on it, safely.
+ my $r = $s->reval("$code")
+ or die "$ME:$.:$sha: failed to eval \"$code\":\n$@\n";
+
+ # Note that we've used this entry.
+ delete $amend_code->{$sha};
+
+ # Update $rest upon success.
+ $rest = $_;
+ }
+
+ # Remove lines inserted by "git cherry-pick".
+ if ($strip_cherry_pick)
+ {
+ $rest =~ s/^\s*Conflicts:\n.*//sm;
+ $rest =~ s/^\s*\(cherry picked from commit [\da-f]+\)\n//m;
+ }
+
+ my @line = split "\n", $rest;
+ my $author_line = shift @line;
+ defined $author_line
+ or die "$ME:$.: unexpected EOF\n";
+ $author_line =~ /^(\d+) (.*>)$/
+ or die "$ME:$.: Invalid line "
+ . "(expected date/author/email):\n$author_line\n";
+
+ # Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
+ # `(tiny change)' annotation.
+ my $tiny = (grep (/^Copyright-paperwork-exempt:\s+[Yy]es$/, @line)
+ ? ' (tiny change)' : '');
+
+ my $date_line = sprintf "%s %s$tiny\n",
+ strftime ("%F", localtime ($1)), $2;
+
+ my @coauthors = grep /^Co-authored-by:.*$/, @line;
+ # Omit meta-data lines we've already interpreted.
+ @line = grep !/^(?:Signed-off-by:[ ].*>$
+ |Co-authored-by:[ ]
+ |Copyright-paperwork-exempt:[ ]
+ )/x, @line;
+
+ # Remove leading and trailing blank lines.
+ if (@line)
+ {
+ while ($line[0] =~ /^\s*$/) { shift @line; }
+ while ($line[$#line] =~ /^\s*$/) { pop @line; }
+ }
+
+ # Record whether there are two or more paragraphs.
+ my $multi_paragraph = grep /^\s*$/, @line;
+
+ # Format 'Co-authored-by: A U Thor <email@example.com>' lines in
+ # standard multi-author ChangeLog format.
+ for (@coauthors)
+ {
+ s/^Co-authored-by:\s*/\t /;
+ s/\s*</ </;
+
+ /<.*?@.*\..*>/
+ or warn "$ME: warning: missing email address for "
+ . substr ($_, 5) . "\n";
+ }
+
+ # If clustering of commit messages has been disabled, if this header
+ # would be different from the previous date/name/email/coauthors header,
+ # or if this or the previous entry consists of two or more paragraphs,
+ # then print the header.
+ if ( ! $cluster
+ || $date_line ne $prev_date_line
+ || "@coauthors" ne "@prev_coauthors"
+ || $multi_paragraph
+ || $prev_multi_paragraph)
+ {
+ $prev_date_line eq ''
+ or print "\n";
+ print $date_line;
+ @coauthors
+ and print join ("\n", @coauthors), "\n";
+ }
+ $prev_date_line = $date_line;
+ @prev_coauthors = @coauthors;
+ $prev_multi_paragraph = $multi_paragraph;
+
+ # If there were any lines
+ if (@line == 0)
+ {
+ warn "$ME: warning: empty commit message:\n $date_line\n";
+ }
+ else
+ {
+ if ($append_dot)
+ {
+ # If the first line of the message has enough room, then
+ if (length $line[0] < 72)
+ {
+ # append a dot if there is no other punctuation or blank
+ # at the end.
+ $line[0] =~ /[[:punct:]\s]$/
+ or $line[0] .= '.';
+ }
+ }
+
+ # Remove one additional leading TAB from each line.
+ $strip_tab
+ and map { s/^\t// } @line;
+
+ # Prefix each non-empty line with a TAB.
+ @line = map { length $_ ? "\t$_" : '' } @line;
+
+ print "\n", join ("\n", @line), "\n";
+ }
+
+ defined ($in = <PIPE>)
+ or last;
+ $in ne "\n"
+ and die "$ME:$.: unexpected line:\n$in";
+ }
+
+ close PIPE
+ or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
+ # FIXME-someday: include $PROCESS_STATUS in the diagnostic
+
+ # Complain about any unused entry in the --amend=F specified file.
+ my $fail = 0;
+ foreach my $sha (keys %$amend_code)
+ {
+ warn "$ME:$amend_file: unused entry: $sha\n";
+ $fail = 1;
+ }
+
+ exit $fail;
+}
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "my $VERSION = '"
+# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "'; # UTC"
+# End:
diff --git a/build-aux/test-driver.scm b/build-aux/test-driver.scm
new file mode 100644
index 0000000..a818968
--- /dev/null
+++ b/build-aux/test-driver.scm
@@ -0,0 +1,180 @@
+
+;;;; test-driver.scm - Guile test driver for Automake testsuite harness
+
+(define script-version "2019-01-15.13") ;UTC
+
+;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
+;;; Copyright © 2019 Alex Sassmannshausen <alex@pompo.co>
+;;;
+;;; This program 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.
+;;;
+;;; This program 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/>.
+
+;;;; Commentary:
+;;;
+;;; This script provides a Guile test driver using the SRFI-64 Scheme API for
+;;; test suites. SRFI-64 is distributed with Guile since version 2.0.9.
+;;;
+;;; This script is a lightly modified version of the orignal written by
+;;; Matthieu Lirzin. The changes make it suitable for use as part of the
+;;; guile-hall infrastructure.
+;;;
+;;;; Code:
+
+(use-modules (ice-9 getopt-long)
+ (ice-9 pretty-print)
+ (srfi srfi-26)
+ (srfi srfi-64))
+
+(define (show-help)
+ (display "Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--brief={yes|no}}] [--]
+ TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+"))
+
+(define %options
+ '((test-name (value #t))
+ (log-file (value #t))
+ (trs-file (value #t))
+ (color-tests (value #t))
+ (expect-failure (value #t)) ;XXX: not implemented yet
+ (enable-hard-errors (value #t)) ;not implemented in SRFI-64
+ (brief (value #t))
+ (help (single-char #\h) (value #f))
+ (version (single-char #\V) (value #f))))
+
+(define (option->boolean options key)
+ "Return #t if the value associated with KEY in OPTIONS is 'yes'."
+ (and=> (option-ref options key #f) (cut string=? <> "yes")))
+
+(define* (test-display field value #:optional (port (current-output-port))
+ #:key pretty?)
+ "Display 'FIELD: VALUE\n' on PORT."
+ (if pretty?
+ (begin
+ (format port "~A:~%" field)
+ (pretty-print value port #:per-line-prefix "+ "))
+ (format port "~A: ~S~%" field value)))
+
+(define* (result->string symbol #:key colorize?)
+ "Return SYMBOL as an upper case string. Use colors when COLORIZE is #t."
+ (let ((result (string-upcase (symbol->string symbol))))
+ (if colorize?
+ (string-append (case symbol
+ ((pass) "") ;green
+ ((xfail) "") ;light green
+ ((skip) "") ;blue
+ ((fail xpass) "") ;red
+ ((error) "")) ;magenta
+ result
+ "") ;no color
+ result)))
+
+(define* (test-runner-gnu test-name #:key color? brief? out-port trs-port)
+ "Return an custom SRFI-64 test runner. TEST-NAME is a string specifying the
+file name of the current the test. COLOR? specifies whether to use colors,
+and BRIEF?, well, you know. OUT-PORT and TRS-PORT must be output ports. The
+current output port is supposed to be redirected to a '.log' file."
+
+ (define (test-on-test-begin-gnu runner)
+ ;; Procedure called at the start of an individual test case, before the
+ ;; test expression (and expected value) are evaluated.
+ (let ((result (cute assq-ref (test-result-alist runner) <>)))
+ (format #t "test-name: ~A~%" (result 'test-name))
+ (format #t "location: ~A~%"
+ (string-append (result 'source-file) ":"
+ (number->string (result 'source-line))))
+ (test-display "source" (result 'source-form) #:pretty? #t)))
+
+ (define (test-on-test-end-gnu runner)
+ ;; Procedure called at the end of an individual test case, when the result
+ ;; of the test is available.
+ (let* ((results (test-result-alist runner))
+ (result? (cut assq <> results))
+ (result (cut assq-ref results <>)))
+ (unless brief?
+ ;; Display the result of each test case on the console.
+ (format out-port "~A: ~A - ~A~%"
+ (result->string (test-result-kind runner) #:colorize? color?)
+ test-name (test-runner-test-name runner)))
+ (when (result? 'expected-value)
+ (test-display "expected-value" (result 'expected-value)))
+ (when (result? 'expected-error)
+ (test-display "expected-error" (result 'expected-error) #:pretty? #t))
+ (when (result? 'actual-value)
+ (test-display "actual-value" (result 'actual-value)))
+ (when (result? 'actual-error)
+ (test-display "actual-error" (result 'actual-error) #:pretty? #t))
+ (format #t "result: ~a~%" (result->string (result 'result-kind)))
+ (newline)
+ (format trs-port ":test-result: ~A ~A~%"
+ (result->string (test-result-kind runner))
+ (test-runner-test-name runner))))
+
+ (define (test-on-group-end-gnu runner)
+ ;; Procedure called by a 'test-end', including at the end of a test-group.
+ (let ((fail (or (positive? (test-runner-fail-count runner))
+ (positive? (test-runner-xpass-count runner))))
+ (skip (or (positive? (test-runner-skip-count runner))
+ (positive? (test-runner-xfail-count runner)))))
+ ;; XXX: The global results need some refinements for XPASS.
+ (format trs-port ":global-test-result: ~A~%"
+ (if fail "FAIL" (if skip "SKIP" "PASS")))
+ (format trs-port ":recheck: ~A~%"
+ (if fail "yes" "no"))
+ (format trs-port ":copy-in-global-log: ~A~%"
+ (if (or fail skip) "yes" "no"))
+ (when brief?
+ ;; Display the global test group result on the console.
+ (format out-port "~A: ~A~%"
+ (result->string (if fail 'fail (if skip 'skip 'pass))
+ #:colorize? color?)
+ test-name))
+ #f))
+
+ (let ((runner (test-runner-null)))
+ (test-runner-on-test-begin! runner test-on-test-begin-gnu)
+ (test-runner-on-test-end! runner test-on-test-end-gnu)
+ (test-runner-on-group-end! runner test-on-group-end-gnu)
+ (test-runner-on-bad-end-name! runner test-on-bad-end-name-simple)
+ runner))
+
+;;;
+;;; Entry point.
+;;;
+
+(define (main . args)
+ (let* ((opts (getopt-long (command-line) %options))
+ (option (cut option-ref opts <> <>)))
+ (cond
+ ((option 'help #f) (show-help))
+ ((option 'version #f) (format #t "test-driver.scm ~A" script-version))
+ (else
+ (let ((log (open-file (option 'log-file "") "w0"))
+ (trs (open-file (option 'trs-file "") "wl"))
+ (out (duplicate-port (current-output-port) "wl")))
+ (redirect-port log (current-output-port))
+ (redirect-port log (current-warning-port))
+ (redirect-port log (current-error-port))
+ (test-with-runner
+ (test-runner-gnu (option 'test-name #f)
+ #:color? (option->boolean opts 'color-tests)
+ #:brief? (option->boolean opts 'brief)
+ #:out-port out #:trs-port trs)
+ (load-from-path (option 'test-name #f)))
+ (close-port log)
+ (close-port trs)
+ (close-port out))))
+ (exit 0)))
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..7b53d7e
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,36 @@
+
+dnl -*- Autoconf -*-
+
+AC_INIT([guile-drmaa], [0.1])
+AC_SUBST(AUTHOR, "\"Ricardo Wurmus\"")
+AC_SUBST(COPYRIGHT, "'(2020 2021)")
+AC_SUBST(LICENSE, gpl3+)
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([1.12 silent-rules subdir-objects color-tests parallel-tests -Woverride -Wno-portability])
+AM_SILENT_RULES([yes])
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([pre-inst-env], [chmod +x pre-inst-env])
+
+dnl Search for 'guile' and 'guild'. This macro defines
+dnl 'GUILE_EFFECTIVE_VERSION'.
+GUILE_PKG([3.0 2.2 2.0])
+GUILE_PROGS
+GUILE_SITE_DIR
+if test "x$GUILD" = "x"; then
+ AC_MSG_ERROR(['guild' binary not found; please check your Guile installation.])
+fi
+
+dnl Installation directories for .scm and .go files.
+guilemoduledir="${datarootdir}/guile/site/$GUILE_EFFECTIVE_VERSION"
+guileobjectdir="${libdir}/guile/$GUILE_EFFECTIVE_VERSION/site-ccache"
+AC_SUBST([guilemoduledir])
+AC_SUBST([guileobjectdir])
+
+AC_PATH_PROG([SED], [sed])
+if test "x$SED" = "x"; then
+ AC_MSG_ERROR(['sed' could not be found; it is needed during the build.])
+fi
+
+
+AC_OUTPUT
diff --git a/doc/drmaa.texi b/doc/drmaa.texi
new file mode 100644
index 0000000..494adc1
--- /dev/null
+++ b/doc/drmaa.texi
@@ -0,0 +1,87 @@
+
+\input texinfo
+@c -*-texinfo-*-
+
+@c %**start of header
+@setfilename guile-drmaa.info
+@documentencoding UTF-8
+@settitle Guile DRMAA Reference Manual
+@c %**end of header
+
+@include version.texi
+
+@copying
+Copyright @copyright{} 2020 Ricardo Wurmus
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
+copy of the license is included in the section entitled ``GNU Free
+Documentation License''.
+@end copying
+
+@dircategory The Algorithmic Language Scheme
+@direntry
+* Guile DRMAA: (guile-drmaa).
+@end direntry
+
+@titlepage
+@title The Guile DRMAA Manual
+@author Ricardo Wurmus
+
+@page
+@vskip 0pt plus 1filll
+Edition @value{EDITION} @*
+@value{UPDATED} @*
+
+@insertcopying
+@end titlepage
+
+@contents
+
+@c *********************************************************************
+@node Top
+@top Guile DRMAA
+
+This document describes Guile DRMAA version @value{VERSION}.
+
+@menu
+* Introduction:: Why Guile DRMAA?
+* Installation:: How do I install it?
+@end menu
+
+@c *********************************************************************
+@node Introduction
+@chapter Introduction
+
+DRMAA stands for @dfn{Distributed Resource Management Application
+API}; it's a common specification implemented in different HPC cluster
+schedulers to allow for programmatic submission and management of
+compute jobs.
+
+There are two versions of the DRMAA specifications: most cluster
+scheduler systems support the old version 1.0; the more recent version
+2.0 has only few implementations.
+
+Guile DRMAA currently only provides bindings for version 1.0, allowing
+you to manage jobs on most cluster schedulers with Guile Scheme.
+
+@c *********************************************************************
+@node Installation
+@chapter Installation
+
+Guile DRMAA uses the GNU build system. To install Guile DRMAA from
+a release tarball just unpack it and run the usual commands:
+
+@example
+./configure
+make
+make install
+@end example
+
+If you want to build the sources from the source repository you need to
+bootstrap the build system first. Run the @code{bootstrap.sh} script
+first and then perform the above steps.
+
+@bye
diff --git a/drmaa/v1/ffi.ffi b/drmaa/v1/ffi.ffi
new file mode 100644
index 0000000..4327926
--- /dev/null
+++ b/drmaa/v1/ffi.ffi
@@ -0,0 +1,20 @@
+;;; Guile DRMAA --- Guile bindings for DRMAA
+;;; Copyright © 2020, 2021 Ricardo Wurmus <rekado@elephly.net>
+;;;
+;;; This file is part of Guile DRMAA.
+;;;
+;;; Guile DRMAA 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.
+;;;
+;;; Guile DRMAA 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 Guile DRMAA. If not, see <http://www.gnu.org/licenses/>.
+
+(define-ffi-module (drmaa v1 ffi)
+ #:include '("include/drmaa.h"))
diff --git a/drmaa/v1/low.scm b/drmaa/v1/low.scm
new file mode 100644
index 0000000..76f0e73
--- /dev/null
+++ b/drmaa/v1/low.scm
@@ -0,0 +1,655 @@
+;;; Guile DRMAA --- Guile bindings for DRMAA
+;;; Copyright © 2020, 2021 Ricardo Wurmus <rekado@elephly.net>
+;;;
+;;; This file is part of Guile DRMAA.
+;;;
+;;; Guile DRMAA 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.
+;;;
+;;; Guile DRMAA 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 Guile DRMAA. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (drmaa v1 low)
+ #:use-module (drmaa v1 ffi)
+ #:use-module (bytestructures guile)
+ #:use-module (system foreign)
+ #:use-module (system ffi-help-rt)
+ #:use-module (ice-9 match)
+ #:use-module (rnrs bytevectors)
+ #:use-module (rnrs enums)
+ #:use-module (srfi srfi-34)
+ #:use-module (srfi srfi-35)
+ #:export (DRMAA
+
+ get-next-attr-name!
+ get-next-attr-value!
+ get-next-job-id!
+ get-num-attr-names
+ get-num-attr-values
+ get-num-job-ids
+ release-attr-names!
+ release-attr-values!
+ release-job-ids!
+
+ init-session!
+ exit-session!
+
+ allocate-job-template!
+ delete-job-template!
+ set-attribute!
+ get-attribute
+ set-vector-attribute!
+ get-vector-attribute
+ get-attribute-names
+ get-vector-attribute-names
+
+ run-job
+ run-bulk-jobs
+
+ control
+ job-ps
+ synchronize
+ wait
+
+ w-if-exited?
+ w-exit-status
+ w-if-signaled?
+ w-termsig
+ w-coredump?
+ w-if-aborted?
+
+ get-contact
+ drmaa-version
+ get-drm-system
+ get-drmaa-implementation))
+
+;; XXX: patch (drmaa v1 ffi) because it uses an undefined
+;; procedure. The generated code for drmaa_set_vector_attribute uses
+;; unwrap~array, which is not implemented in ffi-help-rt.
+;; (This may not be necessary for nyacc 1.03.1+.)
+(module-define! (resolve-module '(drmaa v1 ffi))
+ 'unwrap~array
+ (@@ (drmaa v1 ffi) unwrap~pointer))
+
+(define (make-cstr-array string-list)
+ "Return a bytevector containing pointers to each of the strings in
+STRING-LIST."
+ (let* ((n (length string-list))
+ (pointers (map string->pointer string-list))
+ (addresses (map pointer-address pointers))
+ (bv (make-bytevector (* (1+ n) (sizeof '*))))
+ (bv-set! (case (sizeof '*)
+ ((4) bytevector-u32-native-set!)
+ ((8) bytevector-u64-native-set!))))
+ (for-each (lambda (address index)
+ (bv-set! bv (* (sizeof '*) index) address))
+ addresses (iota n))
+ ;; The vector must be NULL-terminated
+ (bv-set! bv (1+ n) 0)
+ bv))
+
+(define-syntax-rule (return ret success error-message)
+ (cond
+ ((eq? ret (DRMAA 'ERRNO_SUCCESS)) success)
+ (else
+ (raise (condition
+ (&message
+ (message
+ (format #false "~a (~a)"
+ (char*->string error-message)
+ ret))))))))
+
+(define (DRMAA sym)
+ (or (drmaa-v1-ffi-symbol-val (symbol-append 'DRMAA_ sym))
+ (raise (condition
+ (&message
+ (message
+ (format #false "Unknown DRMAA symbol: ~a" sym)))))))
+
+
+;;; String vector helpers
+
+(define (get-next-attr-name! names)
+ (let* ((name
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ATTR_BUFFER)))))
+ (ret (drmaa_get_next_attr_name
+ names name
+ (DRMAA 'ATTR_BUFFER))))
+ (and (eq? ret (DRMAA 'ERRNO_SUCCESS))
+ (char*->string name))))
+
+(define (get-next-attr-value! values)
+ (let* ((value
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ATTR_BUFFER)))))
+ (ret (drmaa_get_next_attr_value
+ values value
+ (DRMAA 'ATTR_BUFFER))))
+ (and (eq? ret (DRMAA 'ERRNO_SUCCESS))
+ (char*->string value))))
+
+(define (get-next-job-id! values)
+ (let* ((value
+ (make-char* (bytevector->pointer
+ ;; TODO: Perhaps not correct to use JOBNAME_BUFFER here
+ (make-bytevector (DRMAA 'JOBNAME_BUFFER)))))
+ (ret (drmaa_get_next_job_id
+ values value
+ ;; TODO: Perhaps not correct to use JOBNAME_BUFFER here
+ (DRMAA 'JOBNAME_BUFFER))))
+ (and (eq? ret (DRMAA 'ERRNO_SUCCESS))
+ (char*->string value))))
+
+(define (get-num-attr-names values)
+ (let* ((size (make-size_t))
+ (ret (drmaa_get_num_attr_names
+ values (pointer-to size))))
+ (and (eq? ret (DRMAA 'ERRNO_SUCCESS))
+ (fh-object-ref size))))
+
+(define (get-num-attr-values values)
+ (let* ((size (make-size_t))
+ (ret (drmaa_get_num_attr_values
+ values (pointer-to size))))
+ (and (eq? ret (DRMAA 'ERRNO_SUCCESS))
+ (fh-object-ref size))))
+
+(define (get-num-job-ids values)
+ (let* ((size (make-size_t))
+ (ret (drmaa_get_num_job_ids
+ values (pointer-to size))))
+ (and (eq? ret (DRMAA 'ERRNO_SUCCESS))
+ (fh-object-ref size))))
+
+(define (release-attr-names! values)
+ (drmaa_release_attr_names values)
+ #true)
+
+(define (release-attr-values! values)
+ (drmaa_release_attr_values values)
+ #true)
+
+(define (release-job-ids! values)
+ (drmaa_release_job_ids values)
+ #true)
+
+(define (extract type)
+ (define next
+ (match type
+ ('job-id get-next-job-id!)
+ ('name get-next-attr-name!)
+ ('value get-next-attr-value!)))
+ (define release
+ (match type
+ ('job-id release-job-ids!)
+ ('name release-attr-names!)
+ ('value release-attr-values!)))
+ (lambda (values)
+ (let loop ((res '()))
+ (let ((item (next values)))
+ (if item
+ (loop (cons item res))
+ (begin
+ (release values)
+ (reverse res)))))))
+
+(define extract-job-ids
+ (extract 'job-id))
+(define extract-names
+ (extract 'name))
+(define extract-values
+ (extract 'value))
+
+
+;;; Session management
+
+(define* (init-session! #:optional contact)
+ "Initialize the DRMAA library and create a new DRMAA session. If
+the binary module provides only one DRMAA implementation, the string
+CONTACT need not be provided; in that case the default implementation
+will be used."
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_init (or contact %null-pointer)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true
+ error-message)))
+
+(define (exit-session!)
+ "Terminate an existing DRMAA session. Queued and running jobs will
+not be affected by this."
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_exit error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true
+ error-message)))
+
+
+;;; Job templates
+
+(define (allocate-job-template!)
+ (let ((template (make-drmaa_job_template_t*))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_allocate_job_template (pointer-to template)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ template
+ error-message)))
+
+(define (delete-job-template! template)
+ ;; TODO: Call this in a finalizer.
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_delete_job_template template
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true
+ error-message)))
+
+(define (set-attribute! template name value)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_set_attribute template
+ (string->pointer name) value
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true
+ error-message)))
+
+(define (get-attribute template name)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (value
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ATTR_BUFFER))))))
+ (return (drmaa_get_attribute template
+ (string->pointer name)
+ value
+ (DRMAA 'ATTR_BUFFER)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (char*->string value)
+ error-message)))
+
+(define (set-vector-attribute! template name . values)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (array (make-cstr-array values)))
+ (return (drmaa_set_vector_attribute template
+ name
+ (bytevector->pointer array)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true
+ error-message)))
+
+(define (get-vector-attribute template name)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (values (make-drmaa_attr_values_t*)))
+ (return (drmaa_get_vector_attribute template
+ name
+ (pointer-to values)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (extract-values values)
+ error-message)))
+
+(define (get-attribute-names)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (names (make-drmaa_attr_names_t*)))
+ (return (drmaa_get_attribute_names (pointer-to names)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (extract-names names)
+ error-message)))
+
+(define (get-vector-attribute-names)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (names (make-drmaa_attr_names_t*)))
+ (return (drmaa_get_vector_attribute_names (pointer-to names)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (extract-names names)
+ error-message)))
+
+
+;;; Job submission
+
+(define (run-job template)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (job-id
+ (make-char* (bytevector->pointer
+ ;; TODO: Perhaps not correct to use JOBNAME_BUFFER here
+ (make-bytevector (DRMAA 'JOBNAME_BUFFER))))))
+ (return (drmaa_run_job job-id
+ ;; TODO: Perhaps not correct to use JOBNAME_BUFFER here
+ (DRMAA 'JOBNAME_BUFFER)
+ template
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (char*->string job-id)
+ error-message)))
+
+(define* (run-bulk-jobs template end
+ #:key
+ (start 1) (increment 1))
+ "Submit a set of parametric jobs, which can be run concurrently.
+The attributes defined in TEMPLATE are used for every job in the set.
+Each job is identical except for its index. The first job has an
+index equal to START; the next has an index equal to the sum of START
+and INCREMENT. END is the maximum value of the index, but the value
+of the last job's index may not be equal to END if the difference
+between START and END is not evenly divisible by INCREMENT.
+
+Return a list of job identifiers."
+ (unless (positive? start)
+ (raise (condition
+ (&message
+ (message "`start' must be greater than or equal to 1")))))
+ (unless (<= start end)
+ (raise (condition
+ (&message
+ (message "`start' must be less than or equal to `end'")))))
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (job-ids (make-drmaa_job_ids_t*)))
+ (return (drmaa_run_bulk_jobs
+ (pointer-to job-ids)
+ template
+ start end increment
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (extract-job-ids job-ids)
+ error-message)))
+
+
+;;; Job status and control
+
+(define (control job-id action)
+ "Enact the ACTION on the job identified by JOB-ID. The following
+symbols are considered valid actions: suspend, resume, hold, release,
+and terminate. If JOB-ID is the symbol *, all jobs submitted during
+the current session will be affected."
+ (unless (member action '(suspend resume hold release terminate))
+ (raise (condition
+ (&message
+ (message
+ (format #false "Invalid action: ~a" action))))))
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (action
+ (DRMAA (symbol-append 'CONTROL_
+ (string->symbol
+ (string-upcase
+ (symbol->string action)))))))
+ (return (drmaa_control (match job-id
+ ('* (DRMAA 'JOB_IDS_SESSION_ALL))
+ (_ job-id))
+ action
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true
+ error-message)))
+
+(define (job-status->symbol status-code)
+ (cond
+ ((eq? status-code (DRMAA 'PS_FAILED))
+ 'failed)
+ ((eq? status-code (DRMAA 'PS_DONE))
+ 'done)
+ ((eq? status-code (DRMAA 'PS_USER_SYSTEM_SUSPENDED))
+ 'user-system-suspended)
+ ((eq? status-code (DRMAA 'PS_USER_SUSPENDED))
+ 'user-suspended)
+ ((eq? status-code (DRMAA 'PS_RUNNING))
+ 'running)
+ ((eq? status-code (DRMAA 'PS_USER_SYSTEM_ON_HOLD))
+ 'user-system-on-hold)
+ ((eq? status-code (DRMAA 'PS_USER_ON_HOLD))
+ 'user-on-hold)
+ ((eq? status-code (DRMAA 'PS_SYSTEM_ON_HOLD))
+ 'system-on-hold)
+ ((eq? status-code (DRMAA 'PS_QUEUED_ACTIVE))
+ 'queued-active)
+ ((eq? status-code (DRMAA 'PS_UNDETERMINED))
+ 'undetermined)
+ (else
+ (raise (condition
+ (&message
+ (message
+ (format #false "Unexpected status: ~a" status-code))))))))
+
+(define (job-ps job-id)
+ (let ((error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER)))))
+ (status-code (make-uint8)))
+ (return (drmaa_job_ps job-id
+ (pointer-to status-code)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (job-status->symbol status-code)
+ error-message)))
+
+(define (synchronize job-ids timeout dispose?)
+ (let ((timeout
+ (or timeout (DRMAA 'TIMEOUT_WAIT_FOREVER)))
+ (job-ids (make-cstr-array job-ids))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_synchronize (bytevector->pointer job-ids)
+ timeout
+ (if dispose? 1 0)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ #true error-message)))
+
+(define (wait job-id timeout)
+ (let ((timeout
+ (or timeout (DRMAA 'TIMEOUT_WAIT_FOREVER)))
+ (job-id-out
+ (make-char* (bytevector->pointer
+ ;; TODO: Perhaps not correct to use JOBNAME_BUFFER here
+ (make-bytevector (DRMAA 'JOBNAME_BUFFER)))))
+ (status-code (make-uint8))
+ (rusage (make-drmaa_attr_values_t*))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wait (match job-id
+ ('* (DRMAA 'JOB_IDS_SESSION_ANY))
+ (_ job-id))
+ job-id-out
+ ;; TODO: Perhaps not correct to use JOBNAME_BUFFER here
+ (DRMAA 'JOBNAME_BUFFER)
+ (pointer-to status-code)
+ timeout
+ (pointer-to rusage)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (values job-id-out status-code (extract-values rusage))
+ error-message)))
+
+(define (w-if-exited? status-code)
+ (let ((exited (make-uint8))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wifexited (pointer-to exited)
+ status-code
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (positive? exited)
+ error-message)))
+
+(define (w-exit-status status-code)
+ (let ((exit-status (make-uint8))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wexitstatus (pointer-to exit-status)
+ status-code
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ exit-status
+ error-message)))
+
+(define (w-if-signaled? status-code)
+ "Return #TRUE if the job was terminated because it received a signal."
+ (let ((signaled (make-uint8))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wifsignaled (pointer-to signaled)
+ status-code
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (positive? signaled)
+ error-message)))
+
+(define (w-termsig status-code)
+ "Return the name of the signal that terminated the job."
+ (let ((signal
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'SIGNAL_BUFFER)))))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wtermsig signal
+ (DRMAA 'SIGNAL_BUFFER)
+ status-code
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (char*->string signal)
+ error-message)))
+
+(define (w-coredump? status-code)
+ "Return #TRUE if the STATUS-CODE indicates that a core image of the
+terminated job was created."
+ (let ((core-dumped (make-uint8))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wcoredump (pointer-to core-dumped)
+ status-code
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (positive? core-dumped)
+ error-message)))
+
+(define (w-if-aborted? status-code)
+ "Return #TRUE if the STATUS-CODE indicates that the job ended before
+entering the running state."
+ (let ((aborted (make-uint8))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_wifaborted (pointer-to aborted)
+ status-code
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (positive? aborted)
+ error-message)))
+
+
+;;; Auxilliary functions
+
+(define (get-contact)
+ "When called before INIT-SESSION! return a string containing a
+comma-delimited list of default DRMAA implementation contact strings,
+one per DRM implementation provided. If called after INIT-SESSION!
+return the contact string for the DRM system for which the library has
+been initialized."
+ (let ((contact
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'CONTACT_BUFFER)))))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_get_DRM_system contact
+ (DRMAA 'CONTACT_BUFFER)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (char*->string contact)
+ error-message)))
+
+(define (drmaa-version)
+ "Return as a pair the major and minor version of the DRMAA C binding
+specification implemented by the selected DRMAA implementation."
+ (let ((major (make-uint8))
+ (minor (make-uint8))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_version (pointer-to major)
+ (pointer-to minor)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (cons (fh-object-ref major)
+ (fh-object-ref minor))
+ error-message)))
+
+(define (get-drm-system)
+ "When called before INIT-SESSION! return a string containing a
+comma-delimited list of DRM system identifiers, one per DRM system
+implementation provided. If called after INIT-SESSION! return the
+selected DRM system."
+ (let ((drm-system
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'DRM_SYSTEM_BUFFER)))))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_get_DRM_system drm-system
+ (DRMAA 'DRM_SYSTEM_BUFFER)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (char*->string drm-system)
+ error-message)))
+
+(define (get-drmaa-implementation)
+ "When called before INIT-SESSION! return a string containing a
+comma-delimited list of DRMAA implementations, one per DRMAA
+implementation provided. If called after INIT-SESSION! return the
+selected DRMAA implementation."
+ (let ((drmaa-implementation
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'DRMAA_IMPL_BUFFER)))))
+ (error-message
+ (make-char* (bytevector->pointer
+ (make-bytevector (DRMAA 'ERROR_STRING_BUFFER))))))
+ (return (drmaa_get_DRMAA_implementation drmaa-implementation
+ (DRMAA 'DRMAA_IMPL_BUFFER)
+ error-message
+ (DRMAA 'ERROR_STRING_BUFFER))
+ (char*->string drmaa-implementation)
+ error-message)))
diff --git a/guix.scm b/guix.scm
new file mode 100644
index 0000000..c616028
--- /dev/null
+++ b/guix.scm
@@ -0,0 +1,37 @@
+(use-modules
+ (guix packages)
+ ((guix licenses) #:prefix license:)
+ (guix download)
+ (guix build-system gnu)
+ (gnu packages)
+ (gnu packages autotools)
+ (gnu packages base)
+ (gnu packages mes)
+ (gnu packages guile)
+ (gnu packages guile-xyz)
+ (gnu packages pkg-config)
+ (gnu packages texinfo)
+ (gnu packages parallel))
+
+(package
+ (name "guile-drmaa")
+ (version "0.1")
+ (source "./guile-drmaa-0.1.tar.gz")
+ (build-system gnu-build-system)
+ (arguments `())
+ (native-inputs
+ `(("autoconf" ,autoconf)
+ ("automake" ,automake)
+ ("pkg-config" ,pkg-config)
+ ("texinfo" ,texinfo)
+ ("sed" ,sed)))
+ (inputs
+ `(("guile" ,guile-3.0)))
+ (propagated-inputs
+ `(("guile-bytestructures" ,guile-bytestructures)
+ ("nyacc" ,nyacc)))
+ (synopsis "")
+ (description "")
+ (home-page "")
+ (license license:gpl3+))
+
diff --git a/include/drmaa.h b/include/drmaa.h
new file mode 100644
index 0000000..f7329ce
--- /dev/null
+++ b/include/drmaa.h
@@ -0,0 +1,567 @@
+/*
+ * FedStage DRMAA utilities library
+ * Copyright (C) 2006-2008 FedStage Systems
+ *
+ * This program 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.
+ *
+ * This program 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/>.
+ */
+/*
+ * Documentation taken from:
+ *
+ * Distributed Resource Management Application API C Bindings v1.0
+ *
+ * Copyright (C) Global Grid Forum (2003). All Rights Reserved.
+ *
+ * This document and translations of it may be copied and furnished to
+ * others, and derivative works that comment on or otherwise explain it
+ * or assist in its implementation may be prepared, copied, published
+ * and distributed, in whole or in part, without restriction of any kind,
+ * provided that the above copyright notice and this paragraph are included
+ * on all such copies and derivative works. However, this document itself
+ * may not be modified in any way, such as by removing the copyright notice
+ * or references to the GGF or other organizations, except as needed for the
+ * purpose of developing Grid Recommendations in which case the procedures
+ * for copyrights defined in the GGF Document process must be followed,
+ * or as required to translate it into languages other than English.
+ *
+ * The limited permissions granted above are perpetual and will not be
+ * revoked by the GGF or its successors or assigns.
+ * This document and the information contained herein is provided on an
+ * "AS IS" basis and THE GLOBAL GRID FORUM DISCLAIMS ALL WARRANTIES, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ * INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES
+ * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/**
+ * @file drmaa.h
+ * DRMAA interface functions.
+ * @author Łukasz Cieśnik <lukasz.ciesnik@fedstage.com>
+ */
+
+#ifndef __DRMAA_H
+#define __DRMAA_H
+
+#include <stddef.h>
+#include <stdio.h>
+
+/** @defgroup drmaa_jobt Job template operations. */
+
+/** @defgroup drmaa DRMAA interface. */
+/* @{ */
+
+typedef struct drmaa_job_template_s drmaa_job_template_t;
+typedef struct drmaa_attr_names_s drmaa_attr_names_t;
+typedef struct drmaa_attr_values_s drmaa_attr_values_t;
+typedef struct drmaa_job_ids_s drmaa_job_ids_t;
+
+#define DRMAA_ATTR_BUFFER 1024
+#define DRMAA_CONTACT_BUFFER 1024
+#define DRMAA_DRM_SYSTEM_BUFFER 1024
+#define DRMAA_DRMAA_IMPL_BUFFER 1024
+#define DRMAA_ERROR_STRING_BUFFER 4096
+#define DRMAA_JOBNAME_BUFFER 128
+#define DRMAA_SIGNAL_BUFFER 32
+
+#define DRMAA_TIMEOUT_NO_WAIT 0
+#define DRMAA_TIMEOUT_WAIT_FOREVER -1
+#define DRMAA_PS_UNDETERMINED 0x00
+#define DRMAA_PS_QUEUED_ACTIVE 0x10
+#define DRMAA_PS_SYSTEM_ON_HOLD 0x11
+#define DRMAA_PS_USER_ON_HOLD 0x12
+#define DRMAA_PS_USER_SYSTEM_ON_HOLD 0x13
+#define DRMAA_PS_RUNNING 0x20
+#define DRMAA_PS_SYSTEM_SUSPENDED 0x21
+#define DRMAA_PS_USER_SUSPENDED 0x22
+#define DRMAA_PS_USER_SYSTEM_SUSPENDED 0x23
+#define DRMAA_PS_DONE 0x30
+#define DRMAA_PS_FAILED 0x40
+#define DRMAA_CONTROL_SUSPEND 0
+#define DRMAA_CONTROL_RESUME 1
+#define DRMAA_CONTROL_HOLD 2
+#define DRMAA_CONTROL_RELEASE 3
+#define DRMAA_CONTROL_TERMINATE 4
+#define DRMAA_JOB_IDS_SESSION_ALL "DRMAA_JOB_IDS_SESSION_ALL"
+#define DRMAA_JOB_IDS_SESSION_ANY "DRMAA_JOB_IDS_SESSION_ANY"
+
+#define DRMAA_BLOCK_EMAIL "drmaa_block_email"
+#define DRMAA_DEADLINE_TIME "drmaa_deadline_time"
+#define DRMAA_DURATION_HLIMIT "drmaa_duration_hlimit"
+#define DRMAA_DURATION_SLIMIT "drmaa_duration_slimit"
+#define DRMAA_ERROR_PATH "drmaa_error_path"
+#define DRMAA_INPUT_PATH "drmaa_input_path"
+#define DRMAA_JOB_CATEGORY "drmaa_job_category"
+#define DRMAA_JOB_NAME "drmaa_job_name"
+#define DRMAA_JOIN_FILES "drmaa_join_files"
+#define DRMAA_JS_STATE "drmaa_js_state"
+#define DRMAA_NATIVE_SPECIFICATION "drmaa_native_specification"
+#define DRMAA_OUTPUT_PATH "drmaa_output_path"
+#define DRMAA_REMOTE_COMMAND "drmaa_remote_command"
+#define DRMAA_START_TIME "drmaa_start_time"
+#define DRMAA_TRANSFER_FILES "drmaa_transfer_files"
+#define DRMAA_V_ARGV "drmaa_v_argv"
+#define DRMAA_V_EMAIL "drmaa_v_email"
+#define DRMAA_V_ENV "drmaa_v_env"
+#define DRMAA_WCT_HLIMIT "drmaa_wct_hlimit"
+#define DRMAA_WCT_SLIMIT "drmaa_wct_slimit"
+#define DRMAA_WD "drmaa_wd"
+
+#define DRMAA_SUBMISSION_STATE_ACTIVE "drmaa_active"
+#define DRMAA_SUBMISSION_STATE_HOLD "drmaa_hold"
+#define DRMAA_PLACEHOLDER_HD "$drmaa_hd_ph$"
+#define DRMAA_PLACEHOLDER_WD "$drmaa_wd_ph$"
+#define DRMAA_PLACEHOLDER_INCR "$drmaa_incr_ph$"
+
+#define DRMAA_ERRNO_SUCCESS 0
+#define DRMAA_ERRNO_INTERNAL_ERROR 1
+#define DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE 2
+#define DRMAA_ERRNO_AUTH_FAILURE 3
+#define DRMAA_ERRNO_INVALID_ARGUMENT 4
+#define DRMAA_ERRNO_NO_ACTIVE_SESSION 5
+#define DRMAA_ERRNO_NO_MEMORY 6
+#define DRMAA_ERRNO_INVALID_CONTACT_STRING 7
+#define DRMAA_ERRNO_DEFAULT_CONTACT_STRING_ERROR 8
+#define DRMAA_ERRNO_NO_DEFAULT_CONTACT_STRING_SELECTED 9
+#define DRMAA_ERRNO_DRMS_INIT_FAILED 10
+#define DRMAA_ERRNO_ALREADY_ACTIVE_SESSION 11
+#define DRMAA_ERRNO_DRMS_EXIT_ERROR 12
+#define DRMAA_ERRNO_INVALID_ATTRIBUTE_FORMAT 13
+#define DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE 14
+#define DRMAA_ERRNO_CONFLICTING_ATTRIBUTE_VALUES 15
+#define DRMAA_ERRNO_TRY_LATER 16
+#define DRMAA_ERRNO_DENIED_BY_DRM 17
+#define DRMAA_ERRNO_INVALID_JOB 18
+#define DRMAA_ERRNO_RESUME_INCONSISTENT_STATE 19
+#define DRMAA_ERRNO_SUSPEND_INCONSISTENT_STATE 20
+#define DRMAA_ERRNO_HOLD_INCONSISTENT_STATE 21
+#define DRMAA_ERRNO_RELEASE_INCONSISTENT_STATE 22
+#define DRMAA_ERRNO_EXIT_TIMEOUT 23
+#define DRMAA_ERRNO_NO_RUSAGE 24
+#define DRMAA_ERRNO_NO_MORE_ELEMENTS 25
+#define DRMAA_NO_ERRNO 26 /* Try to be compatible with SGE drmaa.h which defines DRMAA error codes as enum */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/**
+ * The drmaa_init() function SHALL initialize DRMAA library and create
+ * a new DRMAA session, using the contact parameter, if provided, to
+ * determine to which DRMS to connect. This function MUST be called
+ * before any other DRMAA function, except for drmaa_get_DRM_system(),
+ * drmaa_get_DRMAA_implementation(), drmaa_get_contact(), and
+ * drmaa_strerror(). If @a contact is @c NULL, the default DRM system
+ * SHALL be used, provided there is only one DRMAA implementation
+ * in the provided binary module. When there is more than one DRMAA
+ * implementation in the binary module, drmaa_init() SHALL return
+ * the DRMAA_ERRNO_NO_DEFAULT_CONTACT_STRING_SELECTED error code.
+ * The drmaa_init() function SHOULD be called by only one of the threads.
+ * The main thread is RECOMMENDED. A call by another thread SHALL return
+ * the DRMAA_ERRNO_ALREADY_ACTIVE_SESSION error code.
+ */
+int drmaa_init(
+ const char *contact,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The drmaa_exit() function SHALL disengage from DRMAA library and
+ * allow the DRMAA library to perform any necessary internal cleanup.
+ * This routine SHALL end the current DRMAA session but SHALL NOT
+ * affect any jobs (e.g, queued and running jobs SHALL remain queued and
+ * running). drmaa_exit() SHOULD be called by only one of the threads.
+ * The first call to call drmaa_exit() by a thread will operate normally.
+ * All other calls from the same and other threads SHALL fail, returning
+ * a DRMAA_ERRNO_NO_ACTIVE_SESSION error code.
+ */
+int drmaa_exit( char *error_diagnosis, size_t error_diag_len );
+
+
+
+/**
+ * The function drmaa_allocate_job_template() SHALL allocate a new job
+ * template, returned in @a jt. This template is used to describe the
+ * job to be submitted. This description is accomplished by setting the
+ * desired scalar and vector attributes to their appropriate values. This
+ * template is then used in the job submission process.
+ * @addtogroup drmaa_jobt
+ */
+int drmaa_allocate_job_template(
+ drmaa_job_template_t **jt,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The function drmaa_delete_job_template() SHALL free the job template
+ * pointed to by @a jt.
+ * @addtogroup drmaa_jobt
+ */
+int drmaa_delete_job_template(
+ drmaa_job_template_t *jt,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The function drmaa_set_attribute() SHALL set the value of the scalar
+ * attribute, @a name, in the job template, @a jt, to the value, @a value.
+ * @addtogroup drmaa_jobt
+ */
+int drmaa_set_attribute(
+ drmaa_job_template_t *jt,
+ const char *name, const char *value,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The function drmaa_get_attribute() SHALL fill the @a value buffer with
+ * up to @a value_len characters of the scalar attribute, @a name's, value
+ * in the given job template.
+ * @addtogroup drmaa_jobt
+ */
+int drmaa_get_attribute(
+ drmaa_job_template_t *jt,
+ const char *name, char *value, size_t value_len,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The function drmaa_set_vector_attribute() SHALL set the vector attribute,
+ * @a name, in the job template, @a jt, to the value(s), @a value. The DRMAA
+ * implementation MUST accept value values that are arrays of one or more
+ * strings terminated by a @c NULL entry.
+ * @addtogroup drmaa_jobt
+ */
+int drmaa_set_vector_attribute(
+ drmaa_job_template_t *jt,
+ const char *name, const char *value[],
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The function drmaa_get_vector_attribute() SHALL store in @a values an
+ * opaque values string vector containing the values of the vector attribute,
+ * @a name's, value in the given job template.
+ * @addtogroup drmaa_jobt
+ */
+int drmaa_get_vector_attribute(
+ drmaa_job_template_t *jt,
+ const char *name, drmaa_attr_values_t **values,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+
+
+/**
+ * The function drmaa_get_attribute_names() SHALL return the set of supported
+ * scalar attribute names in an opaque names string vector stored in
+ * @a values. This vector SHALL include all required scalar attributes, all
+ * supported optional scalar attributes, all DRM-specific scalar attributes,
+ * and no unsupported optional attributes.
+ */
+int drmaa_get_attribute_names(
+ drmaa_attr_names_t **values,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The function drmaa_get_vector_attribute_names() SHALL return the set
+ * of supported vector attribute names in an opaque names string vector
+ * stored in @a values. This vector SHALL include all required vector
+ * attributes, all supported optional vector attributes, all DRM-specific
+ * vector attributes, and no unsupported optional attributes.
+ */
+int drmaa_get_vector_attribute_names(
+ drmaa_attr_names_t **values,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * @defgroup drmaa_viter Vector iteration functions.
+ * @ingroup drmaa
+ *
+ * The drmaa_get_next_<i>X</i>() functions SHALL store up to @a value_len
+ * bytes of the next attribute name / attribute value / job identifier
+ * from the @a values opaque string vector in the @a value buffer.
+ * The opaque string vector's internal iterator SHALL then be moved forward
+ * to the next entry. If there are no more values those functions return
+ * @ref DRMAA_ERRNO_INVALID_ARGUMENT (but this is outside DRMAA specification).
+ *
+ * The drmaa_get_num_<i>X</i>() functions SHALL store the number of elements
+ * in the space provided by @a size.
+ *
+ * The drmaa_release_<i>X</i>() functions free the memory used by the
+ * @a values opaque string vector. All memory used by strings contained
+ * therein is also freed.
+ */
+/* @addtogroup drmaa_viter @{ */
+int drmaa_get_next_attr_name( drmaa_attr_names_t* values,
+ char *value, size_t value_len );
+int drmaa_get_next_attr_value( drmaa_attr_values_t* values,
+ char *value, size_t value_len );
+int drmaa_get_next_job_id( drmaa_job_ids_t* values,
+ char *value, size_t value_len );
+int drmaa_get_num_attr_names( drmaa_attr_names_t* values, size_t *size );
+int drmaa_get_num_attr_values(drmaa_attr_values_t* values, size_t *size );
+int drmaa_get_num_job_ids( drmaa_job_ids_t* values, size_t *size );
+void drmaa_release_attr_names( drmaa_attr_names_t* values );
+void drmaa_release_attr_values( drmaa_attr_values_t* values );
+void drmaa_release_job_ids( drmaa_job_ids_t* values );
+/* @} */
+
+/**
+ * The drmaa_run_job() function submits a single job with the attributes
+ * defined in the job template, @a jt. Upon success, up to @a job_id_len
+ * characters of the submitted job's job identifier are stored in the buffer,
+ * @a job_id.
+ */
+int drmaa_run_job(
+ char *job_id, size_t job_id_len, const drmaa_job_template_t *jt,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The drmaa_run_bulk_jobs() function submits a set of parametric jobs which
+ * can be run concurrently. The attributes defined in the job template,
+ * @a jt are used for every parametric job in the set. Each job in the
+ * set is identical except for it's index. The first parametric job has an
+ * index equal to @a start. The next job has an index equal to @a start +
+ * @a incr, and so on. The last job has an index equal to <code>start + n *
+ * incr</code>, where @c n is equal to <code>(end - start) / incr</code>.
+ * Note that the value of the last job's index may not be equal to end if the
+ * difference between @a start and @a end is not evenly divisble by @a incr.
+ * The smallest valid value for @a start is 1. The largest valid value for
+ * @a end is 2147483647 (2^31-1). The @a start value must be less than or
+ * equal to the @a end value, and only positive index numbers are allowed.
+ * The index number can be determined by the job in an implementation
+ * specific fashion. On success, an opaque job id string vector containing
+ * job identifiers for all submitted jobs SHALL be returned into @a job_ids.
+ * The job identifiers in the opaque job id string vector can be extracted
+ * using the drmaa_get_next_job_id() function. The caller is responsible
+ * for releasing the opaque job id string vector returned into @a job_ids
+ * using the drmaa_release_job_ids() function.
+ */
+int drmaa_run_bulk_jobs(
+ drmaa_job_ids_t **jobids,
+ const drmaa_job_template_t *jt,
+ int start, int end, int incr,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The drmaa_control() function SHALL enact the action indicated
+ * by @a action on the job specified by the job identifier, @a jobid.
+ * The action parameter's value may be one of the following:
+ * - DRMAA_CONTROL_SUSPEND
+ * - DRMAA_CONTROL_RESUME
+ * - DRMAA_CONTROL_HOLD
+ * - DRMAA_CONTROL_RELEASE
+ * - DRMAA_CONTROL_TERMINATE
+ * The drmaa_control() function SHALL return after the DRM system has
+ * acknowledged the command, not necessarily after the desired action has
+ * been performed. If @a jobid is DRMAA_JOB_IDS_SESSION_ALL, this function
+ * SHALL perform the specified action on all jobs submitted during this
+ * session as of this function is called.
+ */
+int drmaa_control(
+ const char *job_id, int action,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The drmaa_job_ps() function SHALL store in @a remote_ps the program
+ * status of the job identified by @a job_id. The possible values of
+ * a program's staus are:
+ * - DRMAA_PS_UNDETERMINED
+ * - DRMAA_PS_QUEUED_ACTIVE
+ * - DRMAA_PS_SYSTEM_ON_HOLD
+ * - DRMAA_PS_USER_ON_HOLD
+ * - DRMAA_PS_USER_SYSTEM_ON_HOLD
+ * - DRMAA_PS_RUNNING
+ * - DRMAA_PS_SYSTEM_SUSPENDED
+ * - DRMAA_PS_USER_SUSPENDED
+ * - DRMAA_PS_DONE
+ * - DRMAA_PS_FAILED
+ * Terminated jobs have a status of DRMAA_PS_FAILED.
+ */
+int drmaa_job_ps(
+ const char *job_id, int *remote_ps,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The drmaa_synchronize() function SHALL cause the calling thread to
+ * block until all jobs specified by @a job_ids have finished execution.
+ * If @a job_ids contains DRMAA_JOB_IDS_SESSION_ALL, then this function
+ * SHALL wait for all jobs submitted during this DRMAA session as of the
+ * point in time when drmaa_synchronize() is called. To avoid thread race
+ * conditions in multithreaded applications, the DRMAA implementation user
+ * should explicitly synchronize this call with any other job submission
+ * calls or control calls that may change the number of remote jobs.
+ *
+ * The @a timeout parameter value indicates how many seconds to remain
+ * blocked in this call waiting for results to become available, before
+ * returning with a DRMAA_ERRNO_EXIT_TIMEOUT error code. The value,
+ * DRMAA_TIMEOUT_WAIT_FOREVER, MAY be specified to wait indefinitely for
+ * a result. The value, DRMAA_TIMEOUT_NO_WAIT, MAY be specified to return
+ * immediately with a DRMAA_ERRNO_EXIT_TIMEOUT error code if no result is
+ * available. If the call exits before the timeout has elapsed, all the
+ * jobs have been waited on or there was an interrupt. The caller should
+ * check system time before and after this call in order to be sure of how
+ * much time has passed. The @a dispose parameter specifies how to treat
+ * the reaping of the remote job's internal data record, which includes a
+ * record of the job's consumption of system resources during its execution
+ * and other statistical information. If the @a dispose parameter's value
+ * is 1, the DRMAA implementation SHALL dispose of the job's data record at
+ * the end of the drmaa_synchroniize() call. If the @a dispose parameter's
+ * value is 0, the data record SHALL be left for future access via the
+ * drmaa_wait() method.
+ */
+int drmaa_synchronize(
+ const char *job_ids[], signed long timeout, int dispose,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+/**
+ * The drmaa_wait() function SHALL wait for a job identified by @a job_id
+ * to finish execution or fail. If the special string, JOB_IDS_SESSION_ANY,
+ * is provided as the job_id, this function will wait for any job from the
+ * session to finish execution or fail. In this case, any job for which exit
+ * status information is available will satisfy the requirement, including
+ * jobs which preivously finished but have never been the subject of a
+ * drmaa_wait() call. This routine is modeled on the @c wait3 POSIX routine.
+ *
+ * The @a timeout parameter value indicates how many seconds
+ * to remain blocked in this call waiting for a result, before
+ * returning with a DRMAA_ERRNO_EXIT_TIMEOUT error code. The value,
+ * DRMAA_TIMEOUT_WAIT_FOREVER, MAY be specified to wait indefinitely for
+ * a result. The value, DRMAA_TIMEOUT_NO_WAIT, MAY be specified to return
+ * immediately with a DRMAA_ERRNO_EXIT_TIMEOUT error code if no result is
+ * available. If the call exits before the timeout has elapsed, the job
+ * has been successfully waited on or there was an interrupt. The caller
+ * should check system time before and after this call in order to be sure
+ * of how much time has passed.
+ *
+ * Upon success, drmaa_wait() fills @a job_id_out with up to @a
+ * job_id_out_len characters of the waited job's id, stat with the
+ * a code that includes information about the conditions under which
+ * the job terminated, and @a rusage with an array of <name>=<value>
+ * strings that describe the amount of resources consumed by the job
+ * and are implementation defined. The @a stat parameter is further
+ * described below. The @a rusage parameter's values may be accessed via
+ * drmaa_get_next_attr_value().
+ *
+ * The drmaa_wait() function reaps job data records on a successful
+ * call, so any subsequent calls to drmaa_wait() will fail, returning
+ * a DRMAA_ERRNO_INVALID_JOB error code, meaning that the job's data
+ * record has already been reaped. This error code is the same as
+ * if the job were unknown. If drmaa_wait() exists due to a timeout,
+ * DRMAA_ERRNO_EXIT_TIMEOUT is returned and no rusage information is reaped.
+ * (The only case where drmaa_wait() can be successfully called on a single
+ * job more than once is when the previous call(s) to drmaa_wait() returned
+ * DRMAA_ERRNO_EXIT_TIMEOUT.)
+ *
+ * The stat parameter, set by a successful call to drmaa_wait(), is used
+ * to retrieve further input about the exit condition of the waited
+ * job, identified by job_id_out, through the following functions:
+ * drmaa_wifexited(), drmaa_wexitstatus(), drmaa_wifsignaled(),
+ * drmaa_wtermsig(),drmaa_wcoredump() and drmaa_wifaborted().
+ */
+int drmaa_wait(
+ const char *job_id,
+ char *job_id_out, size_t job_id_out_len, int *stat,
+ signed long timeout, drmaa_attr_values_t **rusage,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+int drmaa_wifexited( int *exited, int stat,
+ char *error_diagnosis, size_t error_diag_len );
+int drmaa_wexitstatus( int *exit_status, int stat,
+ char *error_diagnosis, size_t error_diag_len );
+int drmaa_wifsignaled( int *signaled, int stat,
+ char *error_diagnosis, size_t error_diag_len );
+int drmaa_wtermsig( char *signal, size_t signal_len, int stat,
+ char *error_diagnosis, size_t error_diag_len );
+int drmaa_wcoredump( int *core_dumped, int stat,
+ char *error_diagnosis, size_t error_diag_len );
+int drmaa_wifaborted( int *aborted, int stat,
+ char *error_diagnosis, size_t error_diag_len );
+
+/**
+ * The drmaa_strerror() function SHALL return the error string describing
+ * the DRMAA error number @a drmaa_errno.
+ */
+const char *drmaa_strerror( int drmaa_errno );
+
+/**
+ * The drmaa_get_contact() function, if called before drmaa_init(), SHALL
+ * return a string containing a comma-delimited list of default DRMAA
+ * implementation contacts strings, one per DRM implementation provided.
+ * If called after drmaa_init(), drmaa_get_contacts() SHALL return the
+ * contact string for the DRM system for which the library has been
+ * initialized.
+ */
+int drmaa_get_contact( char *contact, size_t contact_len,
+ char *error_diagnosis, size_t error_diag_len );
+
+/**
+ * The drmaa_version() function SHALL set major and minor to the major and
+ * minor versions of the DRMAA C binding specification implemented by the
+ * DRMAA implementation.
+ */
+int drmaa_version( unsigned int *major, unsigned int *minor,
+ char *error_diagnosis, size_t error_diag_len );
+
+/**
+ * The drmaa_get_DRM_system() function, if called before drmaa_init(),
+ * SHALL return a string containing a comma-delimited list of DRM system
+ * identifiers, one per DRM system implementation provided. If called after
+ * drmaa_init(), drmaa_get_DRM_system() SHALL return the selected DRM system.
+ */
+int drmaa_get_DRM_system( char *drm_system, size_t drm_system_len,
+ char *error_diagnosis, size_t error_diag_len );
+
+/**
+ * The drmaa_get_DRMAA_implementation() function, if called before
+ * drmaa_init(), SHALL return a string containing a comma-delimited list of
+ * DRMAA implementations, one per DRMAA implementation provided. If called
+ * after drmaa_init(), drmaa_get_DRMAA_implementation() SHALL return the
+ * selected DRMAA implementation.
+ */
+int drmaa_get_DRMAA_implementation( char *drmaa_impl, size_t drmaa_impl_len,
+ char *error_diagnosis, size_t error_diag_len );
+
+/* @} */
+
+
+
+
+int
+drmaa_read_configuration_file(
+ const char *filename, int must_exist,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+int
+drmaa_read_configuration(
+ const char *configuration, size_t conf_len,
+ char *error_diagnosis, size_t error_diag_len
+ );
+
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+#endif /* __DRMAA_H */
+
diff --git a/pre-inst-env.in b/pre-inst-env.in
new file mode 100644
index 0000000..1556fcd
--- /dev/null
+++ b/pre-inst-env.in
@@ -0,0 +1,14 @@
+
+#!/bin/sh
+
+abs_top_srcdir="`cd "@abs_top_srcdir@" > /dev/null; pwd`"
+abs_top_builddir="`cd "@abs_top_builddir@" > /dev/null; pwd`"
+
+GUILE_LOAD_COMPILED_PATH="$abs_top_builddir${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_LOAD_COMPILED_PATH"
+GUILE_LOAD_PATH="$abs_top_builddir:$abs_top_srcdir${GUILE_LOAD_PATH:+:}:$GUILE_LOAD_PATH"
+export GUILE_LOAD_COMPILED_PATH GUILE_LOAD_PATH
+
+PATH="$abs_top_builddir/scripts:$PATH"
+export PATH
+
+exec "$@"