xref: /petsc/src/sys/dll/dl.c (revision e5bd52469b00a8f2942d86b46a52285e84b32048)
1e5c89e4eSSatish Balay #define PETSC_DLL
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay       Routines for opening dynamic link libraries (DLLs), keeping a searchable
4e5c89e4eSSatish Balay    path of DLLs, obtaining remote DLLs via a URL and opening them locally.
5e5c89e4eSSatish Balay */
6e5c89e4eSSatish Balay 
7e5c89e4eSSatish Balay #include "petsc.h"
8e5c89e4eSSatish Balay #include "petscsys.h"
9e5c89e4eSSatish Balay #include "petscfix.h"
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
12e5c89e4eSSatish Balay 
13e5c89e4eSSatish Balay #if defined(PETSC_HAVE_PWD_H)
14e5c89e4eSSatish Balay #include <pwd.h>
15e5c89e4eSSatish Balay #endif
16e5c89e4eSSatish Balay #include <ctype.h>
17e5c89e4eSSatish Balay #include <sys/types.h>
18e5c89e4eSSatish Balay #include <sys/stat.h>
19e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
20e5c89e4eSSatish Balay #include <unistd.h>
21e5c89e4eSSatish Balay #endif
22e5c89e4eSSatish Balay #if defined(PETSC_HAVE_STDLIB_H)
23e5c89e4eSSatish Balay #include <stdlib.h>
24e5c89e4eSSatish Balay #endif
25e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_UTSNAME_H)
26e5c89e4eSSatish Balay #include <sys/utsname.h>
27e5c89e4eSSatish Balay #endif
28e5c89e4eSSatish Balay #if defined(PETSC_HAVE_WINDOWS_H)
29e5c89e4eSSatish Balay #include <windows.h>
30e5c89e4eSSatish Balay #endif
31e5c89e4eSSatish Balay #include <fcntl.h>
32e5c89e4eSSatish Balay #include <time.h>
33e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
34e5c89e4eSSatish Balay #include <sys/systeminfo.h>
35e5c89e4eSSatish Balay #endif
36e5c89e4eSSatish Balay 
37e5c89e4eSSatish Balay #endif
38e5c89e4eSSatish Balay 
39e5c89e4eSSatish Balay #include "petscfix.h"
40e5c89e4eSSatish Balay 
41e5c89e4eSSatish Balay 
42e5c89e4eSSatish Balay /*
43e5c89e4eSSatish Balay    Contains the list of registered CCA components
44e5c89e4eSSatish Balay */
45e5c89e4eSSatish Balay PetscFList CCAList = 0;
46e5c89e4eSSatish Balay 
47e5c89e4eSSatish Balay 
48e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
49e5c89e4eSSatish Balay /*
50e5c89e4eSSatish Balay       Code to maintain a list of opened dynamic libraries and load symbols
51e5c89e4eSSatish Balay */
52e5c89e4eSSatish Balay #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
53e5c89e4eSSatish Balay #if defined(PETSC_HAVE_DLFCN_H)
54e5c89e4eSSatish Balay #include <dlfcn.h>
55e5c89e4eSSatish Balay #endif
56*e5bd5246SBarry Smith struct _n_PetscDLLibrary {
57*e5bd5246SBarry Smith   PetscDLLibrary next;
58e5c89e4eSSatish Balay   void           *handle;
59e5c89e4eSSatish Balay   char           libname[PETSC_MAX_PATH_LEN];
60e5c89e4eSSatish Balay };
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay EXTERN_C_BEGIN
63e5c89e4eSSatish Balay EXTERN PetscErrorCode Petsc_DelTag(MPI_Comm,int,void*,void*);
64e5c89e4eSSatish Balay EXTERN_C_END
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay #undef __FUNCT__
67e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrintPath"
68e5c89e4eSSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrintPath(void)
69e5c89e4eSSatish Balay {
70*e5bd5246SBarry Smith   PetscDLLibrary libs;
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay   PetscFunctionBegin;
73e5c89e4eSSatish Balay   libs = DLLibrariesLoaded;
74e5c89e4eSSatish Balay   while (libs) {
75e5c89e4eSSatish Balay     PetscErrorPrintf("  %s\n",libs->libname);
76e5c89e4eSSatish Balay     libs = libs->next;
77e5c89e4eSSatish Balay   }
78e5c89e4eSSatish Balay   PetscFunctionReturn(0);
79e5c89e4eSSatish Balay }
80e5c89e4eSSatish Balay 
81e5c89e4eSSatish Balay #undef __FUNCT__
82e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryRetrieve"
83e5c89e4eSSatish Balay /*@C
84e5c89e4eSSatish Balay    PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location
85e5c89e4eSSatish Balay      (if it is remote), indicates if it exits and its local name.
86e5c89e4eSSatish Balay 
87e5c89e4eSSatish Balay      Collective on MPI_Comm
88e5c89e4eSSatish Balay 
89e5c89e4eSSatish Balay    Input Parameters:
90e5c89e4eSSatish Balay +   comm - processors that are opening the library
91e5c89e4eSSatish Balay -   libname - name of the library, can be relative or absolute
92e5c89e4eSSatish Balay 
93e5c89e4eSSatish Balay    Output Parameter:
94e5c89e4eSSatish Balay .   handle - library handle
95e5c89e4eSSatish Balay 
96e5c89e4eSSatish Balay    Level: developer
97e5c89e4eSSatish Balay 
98e5c89e4eSSatish Balay    Notes:
99e5c89e4eSSatish Balay    [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0]
100e5c89e4eSSatish Balay 
101e5c89e4eSSatish Balay    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
102e5c89e4eSSatish Balay    occuring in directoryname and filename will be replaced with appropriate values.
103e5c89e4eSSatish Balay @*/
104e5c89e4eSSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,int llen,PetscTruth *found)
105e5c89e4eSSatish Balay {
106e5c89e4eSSatish Balay   char           *par2,buff[10],*en,*gz;
107e5c89e4eSSatish Balay   PetscErrorCode ierr;
108e5c89e4eSSatish Balay   size_t         len1,len2,len;
109e5c89e4eSSatish Balay   PetscTruth     tflg,flg;
110e5c89e4eSSatish Balay 
111e5c89e4eSSatish Balay   PetscFunctionBegin;
112e5c89e4eSSatish Balay   /*
113e5c89e4eSSatish Balay      make copy of library name and replace $PETSC_ARCH and and
114e5c89e4eSSatish Balay      so we can add to the end of it to look for something like .so.1.0 etc.
115e5c89e4eSSatish Balay   */
116e5c89e4eSSatish Balay   ierr = PetscStrlen(libname,&len);CHKERRQ(ierr);
117e5c89e4eSSatish Balay   len  = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
118e5c89e4eSSatish Balay   ierr = PetscMalloc(len*sizeof(char),&par2);CHKERRQ(ierr);
119e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr);
120e5c89e4eSSatish Balay 
121e5c89e4eSSatish Balay   /*
122e5c89e4eSSatish Balay      Remove any file: header
123e5c89e4eSSatish Balay   */
124e5c89e4eSSatish Balay   ierr = PetscStrncmp(par2,"file:",5,&tflg);CHKERRQ(ierr);
125e5c89e4eSSatish Balay   if (tflg) {
126e5c89e4eSSatish Balay     ierr = PetscStrcpy(par2,par2+5);CHKERRQ(ierr);
127e5c89e4eSSatish Balay   }
128e5c89e4eSSatish Balay 
129e5c89e4eSSatish Balay   /* strip out .a from it if user put it in by mistake */
130e5c89e4eSSatish Balay   ierr    = PetscStrlen(par2,&len);CHKERRQ(ierr);
131e5c89e4eSSatish Balay   if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0;
132e5c89e4eSSatish Balay 
133e5c89e4eSSatish Balay   /* remove .gz if it ends library name */
134e5c89e4eSSatish Balay   ierr = PetscStrstr(par2,".gz",&gz);CHKERRQ(ierr);
135e5c89e4eSSatish Balay   if (gz) {
136e5c89e4eSSatish Balay     ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
137e5c89e4eSSatish Balay     if (len == 3) {
138e5c89e4eSSatish Balay       *gz = 0;
139e5c89e4eSSatish Balay     }
140e5c89e4eSSatish Balay   }
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay   /* see if library name does already not have suffix attached */
143e5c89e4eSSatish Balay   ierr = PetscStrcpy(buff,".");CHKERRQ(ierr);
144e5c89e4eSSatish Balay   ierr = PetscStrcat(buff,PETSC_SLSUFFIX);CHKERRQ(ierr);
145e5c89e4eSSatish Balay   ierr = PetscStrstr(par2,buff,&en);CHKERRQ(ierr);
146e5c89e4eSSatish Balay   if (en) {
147e5c89e4eSSatish Balay     ierr = PetscStrlen(en,&len1);CHKERRQ(ierr);
148e5c89e4eSSatish Balay     ierr = PetscStrlen(PETSC_SLSUFFIX,&len2);CHKERRQ(ierr);
149e5c89e4eSSatish Balay     flg = (PetscTruth) (len1 != 1 + len2);
150e5c89e4eSSatish Balay   } else {
151e5c89e4eSSatish Balay     flg = PETSC_TRUE;
152e5c89e4eSSatish Balay   }
153e5c89e4eSSatish Balay   if (flg) {
154e5c89e4eSSatish Balay     ierr = PetscStrcat(par2,".");CHKERRQ(ierr);
155e5c89e4eSSatish Balay     ierr = PetscStrcat(par2,PETSC_SLSUFFIX);CHKERRQ(ierr);
156e5c89e4eSSatish Balay   }
157e5c89e4eSSatish Balay 
158e5c89e4eSSatish Balay   /* put the .gz back on if it was there */
159e5c89e4eSSatish Balay   if (gz) {
160e5c89e4eSSatish Balay     ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr);
161e5c89e4eSSatish Balay   }
162e5c89e4eSSatish Balay 
163e5c89e4eSSatish Balay   ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr);
164e5c89e4eSSatish Balay   ierr = PetscFree(par2);CHKERRQ(ierr);
165e5c89e4eSSatish Balay   PetscFunctionReturn(0);
166e5c89e4eSSatish Balay }
167e5c89e4eSSatish Balay 
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay #undef __FUNCT__
170e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryOpen"
171e5c89e4eSSatish Balay /*@C
172e5c89e4eSSatish Balay    PetscDLLibraryOpen - Opens a dynamic link library
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay      Collective on MPI_Comm
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay    Input Parameters:
177e5c89e4eSSatish Balay +   comm - processors that are opening the library
178e5c89e4eSSatish Balay -   libname - name of the library, can be relative or absolute
179e5c89e4eSSatish Balay 
180e5c89e4eSSatish Balay    Output Parameter:
181e5c89e4eSSatish Balay .   handle - library handle
182e5c89e4eSSatish Balay 
183e5c89e4eSSatish Balay    Level: developer
184e5c89e4eSSatish Balay 
185e5c89e4eSSatish Balay    Notes:
186e5c89e4eSSatish Balay    [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0]
187e5c89e4eSSatish Balay 
188e5c89e4eSSatish Balay    ${PETSC_ARCH} occuring in directoryname and filename
189e5c89e4eSSatish Balay    will be replaced with the appropriate value.
190e5c89e4eSSatish Balay @*/
191e5c89e4eSSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryOpen(MPI_Comm comm,const char libname[],void **handle)
192e5c89e4eSSatish Balay {
193e5c89e4eSSatish Balay   PetscErrorCode ierr;
194e5c89e4eSSatish Balay   char           *par2,registername[128],*ptr,*ptrp;
195e5c89e4eSSatish Balay   PetscTruth     foundlibrary;
196e5c89e4eSSatish Balay   PetscErrorCode (*func)(const char*) = NULL;
197e5c89e4eSSatish Balay   size_t         len;
198e5c89e4eSSatish Balay 
199e5c89e4eSSatish Balay   PetscFunctionBegin;
200e5c89e4eSSatish Balay   *handle = NULL;
201e5c89e4eSSatish Balay   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&par2);CHKERRQ(ierr);
202e5c89e4eSSatish Balay   ierr = PetscDLLibraryRetrieve(comm,libname,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr);
203e5c89e4eSSatish Balay   if (!foundlibrary) {
204e5c89e4eSSatish Balay     SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n  %s\n",libname);
205e5c89e4eSSatish Balay   }
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay   /* Eventually config/configure.py should determine if the system needs an executable dynamic library */
208e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO
209e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO)
210e5c89e4eSSatish Balay   ierr  = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr);
211e5c89e4eSSatish Balay   if (!foundlibrary) {
212e5c89e4eSSatish Balay     SETERRQ2(PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n  %s\n  %s\n",libname,par2);
213e5c89e4eSSatish Balay   }
214e5c89e4eSSatish Balay #endif
215e5c89e4eSSatish Balay 
216e5c89e4eSSatish Balay   /*
217e5c89e4eSSatish Balay       Mode indicates symbols required by symbol loaded with dlsym()
218e5c89e4eSSatish Balay      are only loaded when required (not all together) also indicates
219e5c89e4eSSatish Balay      symbols required can be contained in other libraries also opened
220e5c89e4eSSatish Balay      with dlopen()
221e5c89e4eSSatish Balay   */
222ae15b995SBarry Smith   ierr = PetscInfo1(0,"Opening %s\n",libname);CHKERRQ(ierr);
223e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LOADLIBRARY)
224e5c89e4eSSatish Balay   *handle = LoadLibrary(par2);
225e5c89e4eSSatish Balay #else
226e5c89e4eSSatish Balay #if defined(PETSC_HAVE_RTLD_GLOBAL)
227e5c89e4eSSatish Balay   *handle = dlopen(par2,RTLD_LAZY | RTLD_GLOBAL);
228e5c89e4eSSatish Balay #else
229e5c89e4eSSatish Balay   *handle = dlopen(par2,RTLD_LAZY);
230e5c89e4eSSatish Balay #endif
231e5c89e4eSSatish Balay #endif
232e5c89e4eSSatish Balay   if (!*handle) {
233e5c89e4eSSatish Balay #if defined(PETSC_HAVE_DLERROR)
234e5c89e4eSSatish Balay     SETERRQ3(PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  %s\n  Error message from dlopen() %s\n",libname,par2,dlerror());
235e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_GETLASTERROR)
236e5c89e4eSSatish Balay     {
237e5c89e4eSSatish Balay       DWORD erc;
238e5c89e4eSSatish Balay       char  *buff;
239e5c89e4eSSatish Balay       erc   = GetLastError();
240e5c89e4eSSatish Balay       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
241e5c89e4eSSatish Balay                     NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
242e5c89e4eSSatish Balay       ierr = PetscError(__LINE__,__FUNCT__,__FILE__,__SDIR__,PETSC_ERR_FILE_OPEN,1,
243e5c89e4eSSatish Balay                         "Unable to open dynamic library:\n  %s\n  %s\n  Error message from LoadLibrary() %s\n",libname,par2,buff);
244e5c89e4eSSatish Balay       LocalFree(buff);
245e5c89e4eSSatish Balay       return(ierr);
246e5c89e4eSSatish Balay     }
247e5c89e4eSSatish Balay #endif
248e5c89e4eSSatish Balay   }
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay   /* build name of symbol to look for based on libname */
251e5c89e4eSSatish Balay   ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr);
252e5c89e4eSSatish Balay   /* look for libXXXXX.YYY and extract out the XXXXXX */
253e5c89e4eSSatish Balay   ierr = PetscStrrstr(libname,"lib",&ptr);CHKERRQ(ierr);
254e5c89e4eSSatish Balay   if (!ptr) SETERRQ1(PETSC_ERR_ARG_WRONG,"Dynamic library name must have lib prefix:%s",libname);
255e5c89e4eSSatish Balay   ierr = PetscStrchr(ptr+3,'.',&ptrp);CHKERRQ(ierr);
256e5c89e4eSSatish Balay   if (ptrp) {
25719bdad02SBarry Smith     len = ptrp - ptr - 3;
258e5c89e4eSSatish Balay   } else {
259e5c89e4eSSatish Balay     ierr = PetscStrlen(ptr+3,&len);CHKERRQ(ierr);
260e5c89e4eSSatish Balay   }
261e5c89e4eSSatish Balay   ierr = PetscStrncat(registername,ptr+3,len);CHKERRQ(ierr);
262e5c89e4eSSatish Balay 
263e5c89e4eSSatish Balay #if defined(PETSC_HAVE_GETPROCADDRESS)
264e5c89e4eSSatish Balay   func = (PetscErrorCode (*)(const char *)) GetProcAddress((HMODULE)*handle,registername);
265e5c89e4eSSatish Balay #else
266e5c89e4eSSatish Balay   func = (PetscErrorCode (*)(const char *)) dlsym(*handle,registername);
267e5c89e4eSSatish Balay #endif
268e5c89e4eSSatish Balay   if (func) {
269e5c89e4eSSatish Balay     ierr = (*func)(libname);CHKERRQ(ierr);
270ae15b995SBarry Smith     ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr);
271e5c89e4eSSatish Balay   } else {
272e5c89e4eSSatish Balay     SETERRQ2(PETSC_ERR_FILE_UNEXPECTED,"Able to locate dynamic library %s, but cannot load symbol  %s\n",libname,registername);
273e5c89e4eSSatish Balay   }
274e5c89e4eSSatish Balay   ierr = PetscFree(par2);CHKERRQ(ierr);
275e5c89e4eSSatish Balay   PetscFunctionReturn(0);
276e5c89e4eSSatish Balay }
277e5c89e4eSSatish Balay 
278e5c89e4eSSatish Balay #undef __FUNCT__
279e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibrarySym"
280e5c89e4eSSatish Balay /*@C
281e5c89e4eSSatish Balay    PetscDLLibrarySym - Load a symbol from the dynamic link libraries.
282e5c89e4eSSatish Balay 
283e5c89e4eSSatish Balay    Collective on MPI_Comm
284e5c89e4eSSatish Balay 
285e5c89e4eSSatish Balay    Input Parameter:
286*e5bd5246SBarry Smith +  comm - communicator that will open the library
287*e5bd5246SBarry Smith .  inlist - list of already open libraries that may contain symbol (checks here before path)
288*e5bd5246SBarry Smith .  path     - optional complete library name
289e5c89e4eSSatish Balay -  insymbol - name of symbol
290e5c89e4eSSatish Balay 
291e5c89e4eSSatish Balay    Output Parameter:
292e5c89e4eSSatish Balay .  value
293e5c89e4eSSatish Balay 
294e5c89e4eSSatish Balay    Level: developer
295e5c89e4eSSatish Balay 
296e5c89e4eSSatish Balay    Notes: Symbol can be of the form
297e5c89e4eSSatish Balay         [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional
298e5c89e4eSSatish Balay 
299e5c89e4eSSatish Balay         Will attempt to (retrieve and) open the library if it is not yet been opened.
300e5c89e4eSSatish Balay 
301e5c89e4eSSatish Balay @*/
302*e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *inlist,const char path[],const char insymbol[],void **value)
303e5c89e4eSSatish Balay {
304e5c89e4eSSatish Balay   char           *par1,*symbol;
305e5c89e4eSSatish Balay   PetscErrorCode ierr;
306e5c89e4eSSatish Balay   size_t         len;
307*e5bd5246SBarry Smith   PetscDLLibrary nlist,prev,list;
308e5c89e4eSSatish Balay 
309e5c89e4eSSatish Balay   PetscFunctionBegin;
310e5c89e4eSSatish Balay   if (inlist) list = *inlist; else list = PETSC_NULL;
311e5c89e4eSSatish Balay   *value = 0;
312e5c89e4eSSatish Balay 
313e5c89e4eSSatish Balay   /* make copy of symbol so we can edit it in place */
314e5c89e4eSSatish Balay   ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr);
315e5c89e4eSSatish Balay   ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr);
316e5c89e4eSSatish Balay   ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr);
317e5c89e4eSSatish Balay 
318e5c89e4eSSatish Balay   /*
319e5c89e4eSSatish Balay       If symbol contains () then replace with a NULL, to support functionname()
320e5c89e4eSSatish Balay   */
321e5c89e4eSSatish Balay   ierr = PetscStrchr(symbol,'(',&par1);CHKERRQ(ierr);
322e5c89e4eSSatish Balay   if (par1) *par1 = 0;
323e5c89e4eSSatish Balay 
324e5c89e4eSSatish Balay 
325e5c89e4eSSatish Balay   /*
326e5c89e4eSSatish Balay        Function name does include library
327e5c89e4eSSatish Balay        -------------------------------------
328e5c89e4eSSatish Balay   */
329e5c89e4eSSatish Balay   if (path && path[0] != '\0') {
330e5c89e4eSSatish Balay     void *handle;
331e5c89e4eSSatish Balay 
332e5c89e4eSSatish Balay     /*
333e5c89e4eSSatish Balay         Look if library is already opened and in path
334e5c89e4eSSatish Balay     */
335e5c89e4eSSatish Balay     nlist = list;
336e5c89e4eSSatish Balay     prev  = 0;
337e5c89e4eSSatish Balay     while (nlist) {
338e5c89e4eSSatish Balay       PetscTruth match;
339e5c89e4eSSatish Balay 
340e5c89e4eSSatish Balay       ierr = PetscStrcmp(nlist->libname,path,&match);CHKERRQ(ierr);
341e5c89e4eSSatish Balay       if (match) {
342e5c89e4eSSatish Balay         handle = nlist->handle;
343e5c89e4eSSatish Balay         goto done;
344e5c89e4eSSatish Balay       }
345e5c89e4eSSatish Balay       prev  = nlist;
346e5c89e4eSSatish Balay       nlist = nlist->next;
347e5c89e4eSSatish Balay     }
348e5c89e4eSSatish Balay     ierr = PetscDLLibraryOpen(comm,path,&handle);CHKERRQ(ierr);
349e5c89e4eSSatish Balay 
350*e5bd5246SBarry Smith     ierr          = PetscNew(struct _n_PetscDLLibrary,&nlist);CHKERRQ(ierr);
351e5c89e4eSSatish Balay     nlist->next   = 0;
352e5c89e4eSSatish Balay     nlist->handle = handle;
353e5c89e4eSSatish Balay     ierr = PetscStrcpy(nlist->libname,path);CHKERRQ(ierr);
354e5c89e4eSSatish Balay 
355e5c89e4eSSatish Balay     if (prev) {
356e5c89e4eSSatish Balay       prev->next = nlist;
357e5c89e4eSSatish Balay     } else {
358e5c89e4eSSatish Balay       if (inlist) *inlist = nlist;
359e5c89e4eSSatish Balay       else {ierr = PetscDLLibraryClose(nlist);CHKERRQ(ierr);}
360e5c89e4eSSatish Balay     }
361ae15b995SBarry Smith     ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr);
362e5c89e4eSSatish Balay 
363e5c89e4eSSatish Balay     done:;
364e5c89e4eSSatish Balay #if defined(PETSC_HAVE_GETPROCADDRESS)
365e5c89e4eSSatish Balay     *value   = GetProcAddress((HMODULE)handle,symbol);
366e5c89e4eSSatish Balay #else
367e5c89e4eSSatish Balay     *value   = dlsym(handle,symbol);
368e5c89e4eSSatish Balay #endif
369e5c89e4eSSatish Balay     if (!*value) {
370e5c89e4eSSatish Balay       SETERRQ2(PETSC_ERR_PLIB,"Unable to locate function %s in dynamic library %s",insymbol,path);
371e5c89e4eSSatish Balay     }
372ae15b995SBarry Smith     ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr);
373e5c89e4eSSatish Balay 
374e5c89e4eSSatish Balay   /*
375e5c89e4eSSatish Balay        Function name does not include library so search path
376e5c89e4eSSatish Balay        -----------------------------------------------------
377e5c89e4eSSatish Balay   */
378e5c89e4eSSatish Balay   } else {
379e5c89e4eSSatish Balay     while (list) {
380e5c89e4eSSatish Balay #if defined(PETSC_HAVE_GETPROCADDRESS)
381e5c89e4eSSatish Balay       *value = GetProcAddress((HMODULE)list->handle,symbol);
382e5c89e4eSSatish Balay #else
383e5c89e4eSSatish Balay       *value =  dlsym(list->handle,symbol);
384e5c89e4eSSatish Balay #endif
385e5c89e4eSSatish Balay       if (*value) {
386ae15b995SBarry Smith         ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr);
387e5c89e4eSSatish Balay         break;
388e5c89e4eSSatish Balay       }
389e5c89e4eSSatish Balay       list = list->next;
390e5c89e4eSSatish Balay     }
391e5c89e4eSSatish Balay     if (!*value) {
392e5c89e4eSSatish Balay #if defined(PETSC_HAVE_GETPROCADDRESS)
393e5c89e4eSSatish Balay       *value = GetProcAddress(GetCurrentProcess(),symbol);
394e5c89e4eSSatish Balay #else
395e5c89e4eSSatish Balay       *value = dlsym(0,symbol);
396e5c89e4eSSatish Balay #endif
397e5c89e4eSSatish Balay       if (*value) {
398ae15b995SBarry Smith         ierr = PetscInfo1(0,"Loading function %s from object code\n",symbol);CHKERRQ(ierr);
399e5c89e4eSSatish Balay       }
400e5c89e4eSSatish Balay     }
401e5c89e4eSSatish Balay   }
402e5c89e4eSSatish Balay 
403e5c89e4eSSatish Balay   ierr = PetscFree(symbol);CHKERRQ(ierr);
404e5c89e4eSSatish Balay   PetscFunctionReturn(0);
405e5c89e4eSSatish Balay }
406e5c89e4eSSatish Balay 
407e5c89e4eSSatish Balay #undef __FUNCT__
408e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryAppend"
409e5c89e4eSSatish Balay /*@C
410e5c89e4eSSatish Balay      PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end
411e5c89e4eSSatish Balay                 of the search path.
412e5c89e4eSSatish Balay 
413e5c89e4eSSatish Balay      Collective on MPI_Comm
414e5c89e4eSSatish Balay 
415e5c89e4eSSatish Balay      Input Parameters:
416e5c89e4eSSatish Balay +     comm - MPI communicator
417e5c89e4eSSatish Balay -     libname - name of the library
418e5c89e4eSSatish Balay 
419e5c89e4eSSatish Balay      Output Parameter:
420e5c89e4eSSatish Balay .     outlist - list of libraries
421e5c89e4eSSatish Balay 
422e5c89e4eSSatish Balay      Level: developer
423e5c89e4eSSatish Balay 
424e5c89e4eSSatish Balay      Notes: if library is already in path will not add it.
425e5c89e4eSSatish Balay @*/
426*e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[])
427e5c89e4eSSatish Balay {
428*e5bd5246SBarry Smith   PetscDLLibrary list,prev;
429e5c89e4eSSatish Balay   void*          handle;
430e5c89e4eSSatish Balay   PetscErrorCode ierr;
431e5c89e4eSSatish Balay   size_t         len;
432e5c89e4eSSatish Balay   PetscTruth     match,dir;
433e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s;
434e5c89e4eSSatish Balay   PetscToken     *token;
435e5c89e4eSSatish Balay 
436e5c89e4eSSatish Balay   PetscFunctionBegin;
437e5c89e4eSSatish Balay 
438e5c89e4eSSatish Balay   /* is libname a directory? */
439e5c89e4eSSatish Balay   ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr);
440e5c89e4eSSatish Balay   if (dir) {
441ae15b995SBarry Smith     ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr);
442e5c89e4eSSatish Balay     ierr  = PetscStrcpy(program,libname);CHKERRQ(ierr);
443e5c89e4eSSatish Balay     ierr  = PetscStrlen(program,&len);CHKERRQ(ierr);
444e5c89e4eSSatish Balay     if (program[len-1] == '/') {
445e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"*.");CHKERRQ(ierr);
446e5c89e4eSSatish Balay     } else {
447e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"/*.");CHKERRQ(ierr);
448e5c89e4eSSatish Balay     }
449e5c89e4eSSatish Balay     ierr  = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr);
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay     ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
452e5c89e4eSSatish Balay     if (!dir) PetscFunctionReturn(0);
453e5c89e4eSSatish Balay     found = buf;
454e5c89e4eSSatish Balay   } else {
455e5c89e4eSSatish Balay     found = (char*)libname;
456e5c89e4eSSatish Balay   }
457e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
458e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
459e5c89e4eSSatish Balay 
460e5c89e4eSSatish Balay   ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr);
461e5c89e4eSSatish Balay   ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr);
462e5c89e4eSSatish Balay   ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr);
463e5c89e4eSSatish Balay   if (s) s[0] = 0;
464e5c89e4eSSatish Balay   while (libname1) {
465e5c89e4eSSatish Balay 
466e5c89e4eSSatish Balay     /* see if library was already open then we are done */
467e5c89e4eSSatish Balay     list  = prev = *outlist;
468e5c89e4eSSatish Balay     match = PETSC_FALSE;
469e5c89e4eSSatish Balay     while (list) {
470e5c89e4eSSatish Balay 
471e5c89e4eSSatish Balay       ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr);
472e5c89e4eSSatish Balay       if (match) break;
473e5c89e4eSSatish Balay       prev = list;
474e5c89e4eSSatish Balay       list = list->next;
475e5c89e4eSSatish Balay     }
476e5c89e4eSSatish Balay     if (!match) {
477e5c89e4eSSatish Balay 
478e5c89e4eSSatish Balay       ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr);
479e5c89e4eSSatish Balay 
480*e5bd5246SBarry Smith       ierr         = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr);
481e5c89e4eSSatish Balay       list->next   = 0;
482e5c89e4eSSatish Balay       list->handle = handle;
483e5c89e4eSSatish Balay       ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr);
484e5c89e4eSSatish Balay 
485e5c89e4eSSatish Balay       if (!*outlist) {
486e5c89e4eSSatish Balay 	*outlist   = list;
487e5c89e4eSSatish Balay       } else {
488e5c89e4eSSatish Balay 	prev->next = list;
489e5c89e4eSSatish Balay       }
490ae15b995SBarry Smith       ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname1);CHKERRQ(ierr);
491e5c89e4eSSatish Balay     }
492e5c89e4eSSatish Balay     ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr);
493e5c89e4eSSatish Balay     if (libname1) {
494e5c89e4eSSatish Balay       ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr);
495e5c89e4eSSatish Balay       if (s) s[0] = 0;
496e5c89e4eSSatish Balay     }
497e5c89e4eSSatish Balay   }
498e5c89e4eSSatish Balay   ierr = PetscTokenDestroy(token);CHKERRQ(ierr);
499e5c89e4eSSatish Balay   PetscFunctionReturn(0);
500e5c89e4eSSatish Balay }
501e5c89e4eSSatish Balay 
502e5c89e4eSSatish Balay #undef __FUNCT__
503e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrepend"
504e5c89e4eSSatish Balay /*@C
505e5c89e4eSSatish Balay      PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of
506e5c89e4eSSatish Balay                  the search path.
507e5c89e4eSSatish Balay 
508e5c89e4eSSatish Balay      Collective on MPI_Comm
509e5c89e4eSSatish Balay 
510e5c89e4eSSatish Balay      Input Parameters:
511e5c89e4eSSatish Balay +     comm - MPI communicator
512e5c89e4eSSatish Balay -     libname - name of the library
513e5c89e4eSSatish Balay 
514e5c89e4eSSatish Balay      Output Parameter:
515e5c89e4eSSatish Balay .     outlist - list of libraries
516e5c89e4eSSatish Balay 
517e5c89e4eSSatish Balay      Level: developer
518e5c89e4eSSatish Balay 
519e5c89e4eSSatish Balay      Notes: If library is already in path will remove old reference.
520e5c89e4eSSatish Balay 
521e5c89e4eSSatish Balay @*/
522*e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[])
523e5c89e4eSSatish Balay {
524*e5bd5246SBarry Smith   PetscDLLibrary list,prev;
525e5c89e4eSSatish Balay   void*          handle;
526e5c89e4eSSatish Balay   PetscErrorCode ierr;
527e5c89e4eSSatish Balay   size_t         len;
528e5c89e4eSSatish Balay   PetscTruth     match,dir;
529e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s;
530e5c89e4eSSatish Balay   PetscToken     *token;
531e5c89e4eSSatish Balay 
532e5c89e4eSSatish Balay   PetscFunctionBegin;
533e5c89e4eSSatish Balay 
534e5c89e4eSSatish Balay   /* is libname a directory? */
535e5c89e4eSSatish Balay   ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr);
536e5c89e4eSSatish Balay   if (dir) {
537ae15b995SBarry Smith     ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr);
538e5c89e4eSSatish Balay     ierr  = PetscStrcpy(program,libname);CHKERRQ(ierr);
539e5c89e4eSSatish Balay     ierr  = PetscStrlen(program,&len);CHKERRQ(ierr);
540e5c89e4eSSatish Balay     if (program[len-1] == '/') {
541e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"*.");CHKERRQ(ierr);
542e5c89e4eSSatish Balay     } else {
543e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"/*.");CHKERRQ(ierr);
544e5c89e4eSSatish Balay     }
545e5c89e4eSSatish Balay     ierr  = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr);
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay     ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
548e5c89e4eSSatish Balay     if (!dir) PetscFunctionReturn(0);
549e5c89e4eSSatish Balay     found = buf;
550e5c89e4eSSatish Balay   } else {
551e5c89e4eSSatish Balay     found = (char*)libname;
552e5c89e4eSSatish Balay   }
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
555e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay   ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr);
558e5c89e4eSSatish Balay   ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr);
559e5c89e4eSSatish Balay   ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr);
560e5c89e4eSSatish Balay   if (s) s[0] = 0;
561e5c89e4eSSatish Balay   while (libname1) {
562e5c89e4eSSatish Balay     /* see if library was already open and move it to the front */
563e5c89e4eSSatish Balay     list  = *outlist;
564e5c89e4eSSatish Balay     prev  = 0;
565e5c89e4eSSatish Balay     match = PETSC_FALSE;
566e5c89e4eSSatish Balay     while (list) {
567e5c89e4eSSatish Balay 
568e5c89e4eSSatish Balay       ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr);
569e5c89e4eSSatish Balay       if (match) {
570e5c89e4eSSatish Balay 	if (prev) prev->next = list->next;
571e5c89e4eSSatish Balay 	list->next = *outlist;
572e5c89e4eSSatish Balay 	*outlist   = list;
573e5c89e4eSSatish Balay 	break;
574e5c89e4eSSatish Balay       }
575e5c89e4eSSatish Balay       prev = list;
576e5c89e4eSSatish Balay       list = list->next;
577e5c89e4eSSatish Balay     }
578e5c89e4eSSatish Balay     if (!match) {
579e5c89e4eSSatish Balay       /* open the library and add to front of list */
580e5c89e4eSSatish Balay       ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr);
581e5c89e4eSSatish Balay 
582ae15b995SBarry Smith       ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname1);CHKERRQ(ierr);
583e5c89e4eSSatish Balay 
584*e5bd5246SBarry Smith       ierr         = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr);
585e5c89e4eSSatish Balay       list->handle = handle;
586e5c89e4eSSatish Balay       list->next   = *outlist;
587e5c89e4eSSatish Balay       ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr);
588e5c89e4eSSatish Balay       *outlist     = list;
589e5c89e4eSSatish Balay     }
590e5c89e4eSSatish Balay     ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr);
591e5c89e4eSSatish Balay     if (libname1) {
592e5c89e4eSSatish Balay       ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr);
593e5c89e4eSSatish Balay       if (s) s[0] = 0;
594e5c89e4eSSatish Balay     }
595e5c89e4eSSatish Balay   }
596e5c89e4eSSatish Balay   ierr = PetscTokenDestroy(token);CHKERRQ(ierr);
597e5c89e4eSSatish Balay   PetscFunctionReturn(0);
598e5c89e4eSSatish Balay }
599e5c89e4eSSatish Balay 
600e5c89e4eSSatish Balay #undef __FUNCT__
601e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryClose"
602e5c89e4eSSatish Balay /*@C
603e5c89e4eSSatish Balay      PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries.
604e5c89e4eSSatish Balay 
605e5c89e4eSSatish Balay     Collective on PetscDLLibrary
606e5c89e4eSSatish Balay 
607e5c89e4eSSatish Balay     Input Parameter:
608e5c89e4eSSatish Balay .     next - library list
609e5c89e4eSSatish Balay 
610e5c89e4eSSatish Balay      Level: developer
611e5c89e4eSSatish Balay 
612e5c89e4eSSatish Balay @*/
613*e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryClose(PetscDLLibrary next)
614e5c89e4eSSatish Balay {
615*e5bd5246SBarry Smith   PetscDLLibrary prev;
616e5c89e4eSSatish Balay   PetscErrorCode ierr;
617e5c89e4eSSatish Balay 
618e5c89e4eSSatish Balay   PetscFunctionBegin;
619e5c89e4eSSatish Balay 
620e5c89e4eSSatish Balay   while (next) {
621e5c89e4eSSatish Balay     prev = next;
622e5c89e4eSSatish Balay     next = next->next;
623e5c89e4eSSatish Balay     /* free the space in the prev data-structure */
624e5c89e4eSSatish Balay     ierr = PetscFree(prev);CHKERRQ(ierr);
625e5c89e4eSSatish Balay   }
626e5c89e4eSSatish Balay   PetscFunctionReturn(0);
627e5c89e4eSSatish Balay }
628e5c89e4eSSatish Balay 
629e5c89e4eSSatish Balay #undef __FUNCT__
630e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryCCAAppend"
631e5c89e4eSSatish Balay /*@C
632e5c89e4eSSatish Balay      PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end
633e5c89e4eSSatish Balay                 of the search path.
634e5c89e4eSSatish Balay 
635e5c89e4eSSatish Balay      Collective on MPI_Comm
636e5c89e4eSSatish Balay 
637e5c89e4eSSatish Balay      Input Parameters:
638e5c89e4eSSatish Balay +     comm - MPI communicator
639e5c89e4eSSatish Balay -     libname - name of directory to check
640e5c89e4eSSatish Balay 
641e5c89e4eSSatish Balay      Output Parameter:
642e5c89e4eSSatish Balay .     outlist - list of libraries
643e5c89e4eSSatish Balay 
644e5c89e4eSSatish Balay      Level: developer
645e5c89e4eSSatish Balay 
646e5c89e4eSSatish Balay      Notes: if library is already in path will not add it.
647e5c89e4eSSatish Balay @*/
648*e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[])
649e5c89e4eSSatish Balay {
650e5c89e4eSSatish Balay   PetscErrorCode ierr;
651e5c89e4eSSatish Balay   size_t         l;
652e5c89e4eSSatish Balay   PetscTruth     dir;
653e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2;
654e5c89e4eSSatish Balay   char           *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib;
655e5c89e4eSSatish Balay   FILE           *fp;
656e5c89e4eSSatish Balay   PetscToken     *token1,*token2;
657e5c89e4eSSatish Balay 
658e5c89e4eSSatish Balay   PetscFunctionBegin;
659e5c89e4eSSatish Balay 
660e5c89e4eSSatish Balay   /* is dirname a directory? */
661e5c89e4eSSatish Balay   ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr);
662e5c89e4eSSatish Balay   if (!dir) PetscFunctionReturn(0);
663e5c89e4eSSatish Balay 
664ae15b995SBarry Smith   ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr);
665e5c89e4eSSatish Balay   ierr  = PetscStrcpy(program,dirname);CHKERRQ(ierr);
666e5c89e4eSSatish Balay   ierr  = PetscStrcat(program,"/*.cca");CHKERRQ(ierr);
667e5c89e4eSSatish Balay 
668e5c89e4eSSatish Balay   ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
669e5c89e4eSSatish Balay   if (!dir) PetscFunctionReturn(0);
670e5c89e4eSSatish Balay 
671e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
672e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
673e5c89e4eSSatish Balay   ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr);
674e5c89e4eSSatish Balay   ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr);
675e5c89e4eSSatish Balay   while (libname1) {
676e5c89e4eSSatish Balay     fp    = fopen(libname1,"r"); if (!fp) continue;
677e5c89e4eSSatish Balay     while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) {
678e5c89e4eSSatish Balay       if (found[0] == '!') continue;
679e5c89e4eSSatish Balay       ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr);
680e5c89e4eSSatish Balay       if (f2) { /* found library name */
681e5c89e4eSSatish Balay         if (found[0] == '/') {
682e5c89e4eSSatish Balay           lib = found;
683e5c89e4eSSatish Balay         } else {
684e5c89e4eSSatish Balay           ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr);
685e5c89e4eSSatish Balay           ierr = PetscStrlen(libname,&l);CHKERRQ(ierr);
686e5c89e4eSSatish Balay           if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);}
687e5c89e4eSSatish Balay           ierr = PetscStrcat(libname,found);CHKERRQ(ierr);
688e5c89e4eSSatish Balay           lib  = libname;
689e5c89e4eSSatish Balay         }
690e5c89e4eSSatish Balay         ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr);
691e5c89e4eSSatish Balay       } else {
692ae15b995SBarry Smith         ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr);
693e5c89e4eSSatish Balay         ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr);
694e5c89e4eSSatish Balay         ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr);
695e5c89e4eSSatish Balay         ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr);
696e5c89e4eSSatish Balay         ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr);
697e5c89e4eSSatish Balay         ierr = PetscTokenDestroy(token2);CHKERRQ(ierr);
698e5c89e4eSSatish Balay       }
699e5c89e4eSSatish Balay     }
700e5c89e4eSSatish Balay     fclose(fp);
701e5c89e4eSSatish Balay     ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr);
702e5c89e4eSSatish Balay   }
703e5c89e4eSSatish Balay   ierr = PetscTokenDestroy(token1);CHKERRQ(ierr);
704e5c89e4eSSatish Balay   PetscFunctionReturn(0);
705e5c89e4eSSatish Balay }
706e5c89e4eSSatish Balay 
707e5c89e4eSSatish Balay 
708e5c89e4eSSatish Balay #endif
709e5c89e4eSSatish Balay 
710e5c89e4eSSatish Balay 
711