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