From 991ea53e4be4bb81e1bbb1a1c83473693d40cca6 Mon Sep 17 00:00:00 2001
From: Karl Wette <karl.wette@ligo.org>
Date: Thu, 18 May 2023 10:40:23 +1000
Subject: [PATCH] XLALFileResolvePathLong(): allow LAL_RELATIVE_DATA_PATH to be
 a path of relative locations

---
 lal/gnuscripts/lal.m4    | 20 +++++++++++---------
 lal/lib/support/FileIO.c | 36 ++++++++++++++++++++++--------------
 2 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/lal/gnuscripts/lal.m4 b/lal/gnuscripts/lal.m4
index 573c84cf41..c61d8dc305 100644
--- a/lal/gnuscripts/lal.m4
+++ b/lal/gnuscripts/lal.m4
@@ -1,6 +1,6 @@
 # lal.m4 - lal specific macros
 #
-# serial 23
+# serial 24
 
 AC_DEFUN([LAL_WITH_DEFAULT_DEBUG_LEVEL],[
   AC_ARG_WITH(
@@ -17,11 +17,13 @@ AC_DEFUN([LAL_WITH_DEFAULT_DEBUG_LEVEL],[
 AC_DEFUN([LAL_WITH_DATA_PATH],[
   AC_ARG_WITH(
     [relative_data_path],
-    AS_HELP_STRING([--with-relative-data-path],[set location relative to liblalsupport.so for LAL data path [default: none]]),
+    AS_HELP_STRING([--with-relative-data-path],[set locations relative to liblalsupport.so for LAL data path [default: none]]),
     [
-      AS_IF([test "x`expr "X${withval}" : ["^\(X\./.*$\)"]`" != "xX${withval}" && test "x`expr "X${withval}" : ["^\(X\.\./.*$\)"]`" != "xX${withval}"],[
-        AC_MSG_ERROR([bad relative path value '${withval}' for --with-relative-data-path])
-      ])
+      for n in `echo ${with_relative_data_path} | sed 's|:| |g'`; do
+        AS_IF([test "x`expr "X${n}" : ["^\(X\./.*$\)"]`" != "xX${n}" && test "x`expr "X${n}" : ["^\(X\.\./.*$\)"]`" != "xX${n}"],[
+          AC_MSG_ERROR([bad relative path value '${with_relative_data_path}' for --with-relative-data-path])
+        ])
+      done
       AC_DEFINE_UNQUOTED([LAL_RELATIVE_DATA_PATH],["${with_relative_data_path}"],[Set location relative to liblal.so for LAL data path])
     ]
   )
@@ -29,16 +31,16 @@ AC_DEFUN([LAL_WITH_DATA_PATH],[
     [fallback_data_path],
     AS_HELP_STRING([--with-fallback-data-path],[use hard-coded fallback location for LAL data path [default: yes]]),
     [
-      AS_CASE(["${withval}"],
+      AS_CASE(["${with_fallback_data_path}"],
         [yes],[:],
         [no],[:],
-        AC_MSG_ERROR([bad value '${withval}' for --with-fallback-data-path])
+        AC_MSG_ERROR([bad value '${with_fallback_data_path}' for --with-fallback-data-path])
       )
     ],[
-      withval=yes
+      with_fallback_data_path=yes
     ]
   )
-  AS_IF([test "X${withval}" = Xyes],[
+  AS_IF([test "X${with_fallback_data_path}" = Xyes],[
     AC_DEFINE_UNQUOTED([LAL_FALLBACK_DATA_PATH],[1],[Use hard-coded fallback location for LAL data path])
   ])
 ])
diff --git a/lal/lib/support/FileIO.c b/lal/lib/support/FileIO.c
index c17484f126..eb6db82a08 100644
--- a/lal/lib/support/FileIO.c
+++ b/lal/lib/support/FileIO.c
@@ -89,7 +89,7 @@ LALFILE *lalstderr( void )
  * ii) pure filename: try
  *     1) local dir, then
  *     2) search LAL_DATA_PATH, then
- *     3) try LAL_RELATIVE_DATA_PATH relative to location of to liblalsupport.so (if enabled), then
+ *     3) search LAL_RELATIVE_DATA_PATH relative to location of liblalsupport.so (if enabled), then
  *     4) try fallbackdir (if enabled/given)
  *     return first successful hit
  *
@@ -128,7 +128,7 @@ XLALFileResolvePathLong ( const char *fname,                //!< [in] filename o
       } // if not found
 
     } // end: if path given
-  else	// if pure filename given: try 1) local directory, then 2) scan LAL_DATA_PATH, then 3) LAL_RELATIVE_DATA_PATH (if enabled), then 4) try fallbackdir (if enabled/given)
+  else	// if pure filename given: try 1) local directory, then 2) scan LAL_DATA_PATH, then 3) scan LAL_RELATIVE_DATA_PATH (if enabled), then 4) try fallbackdir (if enabled/given)
     {
       FILE *tmp;
       char *resolveFname = NULL;
@@ -174,7 +174,7 @@ XLALFileResolvePathLong ( const char *fname,                //!< [in] filename o
 
         } // if LAL_DATA_PATH given
 
-      // ----- Strategy 3: try LAL_RELATIVE_DATA_PATH relative to location of to liblalsupport.so, if enabled
+      // ----- Strategy 3: scan LAL_RELATIVE_DATA_PATH relative to location of to liblalsupport.so, if enabled
 #ifndef LAL_RELATIVE_DATA_PATH
       XLALPrintInfo ( "%s(): skip strategy LAL_RELATIVE_DATA_PATH: disabled\n", __func__ );
 #else
@@ -193,20 +193,28 @@ XLALFileResolvePathLong ( const char *fname,                //!< [in] filename o
           module_path[module_path_length] = '\0';
           XLAL_CHECK_NULL ( module_dirname_length >= 0, XLAL_EERR );
           XLAL_CHECK_NULL ( module_dirname_length < module_path_length, XLAL_EERR );
-
-          // try path starting in directory containing liblalsupport.so, plus LAL_RELATIVE_DATA_PATH
-          XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, module_dirname_length + 1 + strlen(LAL_RELATIVE_DATA_PATH) + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
           module_path[module_dirname_length] = '\0';
-          sprintf ( resolveFname, "%s/%s/%s", module_path, LAL_RELATIVE_DATA_PATH, fname );
-          XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
-          if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
-            LALFclose ( tmp );
-            XLALFree ( module_path );
-            XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
-            return resolveFname;
-          } // if found
+
+          // try path starting in directory containing liblalsupport.so, plus path tokens from LAL_RELATIVE_DATA_PATH
+          TokenList *subPaths = NULL;
+          XLAL_CHECK_NULL ( XLALCreateTokenList ( &subPaths, LAL_RELATIVE_DATA_PATH, ":" ) == XLAL_SUCCESS, XLAL_EFUNC );
+          for ( UINT4 i = 0; i < subPaths->nTokens; i ++ )
+            {
+              const char *subPath_i = subPaths->tokens[i];
+              XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, module_dirname_length + 1 + strlen(subPath_i) + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
+              sprintf ( resolveFname, "%s/%s/%s", module_path, subPath_i, fname );
+              XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
+              if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
+                LALFclose ( tmp );
+                XLALFree ( module_path );
+                XLALDestroyTokenList ( subPaths );
+                XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
+                return resolveFname;
+              } // if found
+            }
 
           XLALFree ( module_path );
+          XLALDestroyTokenList ( subPaths );
 
         }
       }
-- 
GitLab