Description: upstream -- ffam module -- system wide
 Implement a system wide scheme for the ffam module
 (TestU01 Guide, chapter 5), more precisely for accessing
 the so called parameters files with extension .par:
 - the parameters files are now called system wide as any system
 wide data files;
 - the shipped parameters files are gathered in PKGDATADIR/param
 (typically PKGDATADIR is /usr/share/testu01);
 - the parameters files are search with respect to a list of paths
 (or folders), the first paths are meant to be provided through
 the environment variable TESTU01_FFAM_PARAM_PATH while the last
 ones are custom encoded paths, the very last one being meant to
 be PKGDATADIR/param itself (the one just before it is typically
 meant to be its local version);
 - the folder where the parameters file was found is printed
 as any other typical TestU01 information;
 - the encoded part of the search paths and the list separator
 (typilcally `:' on UNIX or UNIX-like platforms) are defined
 in the platform-dependent configuration file `gdef.tex'
 (see MyLIB-C Guide, section gdef);
 - as for the original scheme, parameters files are first searched
 in the working directory.
 Meant to be submitted to the upstream.
Origin: debian
Forwarded: no-more-maintained-by-upstream
Author: Jerome Benoit <calculus@rezozer.net>
Last-Update: 2015-05-20

--- a/testu01/ffam.c
+++ b/testu01/ffam.c
@@ -35,6 +35,7 @@
 #include "unif01.h"
 
 #include <string.h>
+#include <argz.h>
 
 #define MAXCAR  256                /* Max length of a line */
 
@@ -109,6 +110,51 @@
 
 /*=========================================================================*/
 
+#ifdef SYSTEM_WIDE_SCHEME
+
+#define FFAM_ENVIRONMENT_TESTU01_FFAM_PARAM_PATH "TESTU01_FFAM_PARAM_PATH"
+
+static void ffam_OpenFile_SearchPathList_Next_CLEAR(void);
+
+static char *ffam_OpenFile_SearchPathList_Next_INTERNAL(const char *entry, int flag)
+{
+   static char *SearchPathList = NULL;
+   static size_t SearchPathListLength = 0;
+   char *next = NULL;
+
+   if (flag) {
+      util_Free (SearchPathList); SearchPathList = NULL; SearchPathListLength = 0;
+   }
+   else {
+      if (SearchPathList == NULL) {
+         const char * env_SearchPathList = getenv(FFAM_ENVIRONMENT_TESTU01_FFAM_PARAM_PATH);
+
+         if (env_SearchPathList != NULL) {
+            char * env_SearchPathList0 = strdup(env_SearchPathList);
+            char * dum = env_SearchPathList0 + strlen(env_SearchPathList0);
+            while (dum != env_SearchPathList0) { --dum; if ((*dum != LIST_SEPARATOR_CHAR) && (*dum != ' ')) break; *dum='\0'; }
+            argz_create_sep (env_SearchPathList0, LIST_SEPARATOR_CHAR, &SearchPathList, &SearchPathListLength);
+            util_Free (env_SearchPathList0);
+         }
+         argz_add_sep (&SearchPathList, &SearchPathListLength, SYSTEM_FFAM_PARAM_SEARCHPATHLIST, LIST_SEPARATOR_CHAR);
+
+			   atexit (ffam_OpenFile_SearchPathList_Next_CLEAR);
+      }
+
+		  next = argz_next (SearchPathList, SearchPathListLength, entry);
+   }
+   return next;
+}
+
+void ffam_OpenFile_SearchPathList_Next_CLEAR(void)
+{
+   ffam_OpenFile_SearchPathList_Next_INTERNAL (NULL,1);
+}
+
+#define ffam_OpenFile_SearchPathList_Next(Entry) ffam_OpenFile_SearchPathList_Next_INTERNAL(Entry,0)
+
+#endif /* SYSTEM_WIDE_SCHEME */
+
 FILE *ffam_OpenFile (char *filename, char *deffile)
 /*
  * Open the file filename if it exists; otherwise if filename == NULL, open
@@ -117,19 +163,42 @@
  */
 {
    FILE *f;
-   char path[MAXCAR + 1];         /* Directory of parameter files */
 
    /* Is the parameter filename in the current directory? */
    if (filename) {
       f = fopen (filename, "r");
-      if (f)
+      if (f) {
+#ifdef SYSTEM_WIDE_SCHEME
+         printf ("Can open file  %s  in working directory.\n", filename);
+#endif
          return f;
+      }
+#ifndef SYSTEM_WIDE_SCHEME
       else
          printf ("Cannot open file  %s  in current directory."
             " Searching directory param ...\n", filename);
+#endif
+   }
+
+#ifdef SYSTEM_WIDE_SCHEME
+
+   /*const*/ char *basefilename = (filename != NULL) ? filename : deffile;
+   char *path = NULL;
+   char *candidate = NULL;
+   while (( path = ffam_OpenFile_SearchPathList_Next(path) )) {
+      asprintf(&candidate, "%s" DIR_SEPARATOR "%s" , path, basefilename);
+      if (util_Freadable (candidate)) {
+         printf ("Can open file  %s  in directory  %s .\n", basefilename, path);
+         break;
+      }
    }
+   f = util_Fopen (candidate, "r");
+   util_Free (candidate);
+
+#else /* default */
 
    /* Build directory: "../param/" on Linux, "..\\param\\" on Windows */
+   char path[MAXCAR + 1];         /* Directory of parameter files */
    strncpy (path, "..", (size_t) 3);
    strncat (path, DIR_SEPARATOR, (size_t) 3);
    strncat (path, "param", (size_t) 6);
@@ -142,6 +211,9 @@
       strncat (path, filename, (size_t) MAXCAR - 20);
 
    f = util_Fopen (path, "r");
+
+#endif /* SYSTEM_WIDE_SCHEME */
+
    return f;
 }
 
--- a/mylib/gdef.tex
+++ b/mylib/gdef.tex
@@ -148,6 +148,12 @@
  \endtab
 \code
 
+#define SYSTEM_WIDE_SCHEME
+#define LIST_SEPARATOR_CHAR ':'
+#ifndef SYSTEM_FFAM_PARAM_SEARCHPATHLIST
+#define SYSTEM_FFAM_PARAM_SEARCHPATHLIST "/usr/local/share/" PACKAGE "/param:/usr/share/" PACKAGE "/param"
+#endif
+
 
 /* #undef USE_GMP */
 \endcode
--- a/mylib/util.c
+++ b/mylib/util.c
@@ -35,6 +35,9 @@
 #include <errno.h>
 #include <string.h>
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 #define MAXCAR 256                      /* Max length of a line of data */
 
@@ -42,6 +45,26 @@
 
 /************************************************************************/
 
+lebool util_Freadable (const char *path)
+{
+#ifdef HAVE_ACCESS
+   return (path)?((access(path, (F_OK | R_OK)))?FALSE:TRUE):FALSE;
+#else
+   if (path != NULL) {
+     FILE *f;
+     f = fopen (path, "r");
+     if (f != NULL) {
+        fclose (f);
+        return TRUE;
+     }
+     else
+        return FALSE;
+   }
+   else
+      return FALSE;
+#endif
+}
+
 FILE *util_Fopen (const char *path, const char *mode)
 {
    FILE *f;
--- a/mylib/util.tex
+++ b/mylib/util.tex
@@ -96,6 +96,12 @@
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \guisec{Prototypes}
+\code\hide
+
+lebool util_Freadable (const char *name);
+\endhide
+\endcode
+
 \code
 
 FILE * util_Fopen (const char *name, const char *mode);
--- a/configure.ac
+++ b/configure.ac
@@ -52,6 +52,7 @@
 # Checks for library functions.
 # AC_FUNC_MALLOC
 # AC_FUNC_REALLOC
+AC_CHECK_FUNCS([access])
 OLD_LIBS="$LIBS"
 LIBS="$LIBM $LIBS"
 AC_CHECK_FUNCS([random erf lgamma log1p])
