xref: /petsc/src/sys/dll/dl.c (revision bb84e0fd66efab3377a7a70d7fa706a11b52e505)
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"
97c4f633dSBarry Smith #include "../src/sys/dll/dlimpl.h"
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
12e5c89e4eSSatish Balay /*
13e5c89e4eSSatish Balay       Code to maintain a list of opened dynamic libraries and load symbols
14e5c89e4eSSatish Balay */
15e5bd5246SBarry Smith struct _n_PetscDLLibrary {
16e5bd5246SBarry Smith   PetscDLLibrary next;
17ebd79076SLisandro Dalcin   PetscDLHandle  handle;
18e5c89e4eSSatish Balay   char           libname[PETSC_MAX_PATH_LEN];
19e5c89e4eSSatish Balay };
20e5c89e4eSSatish Balay 
21e5c89e4eSSatish Balay #undef __FUNCT__
22e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrintPath"
235673baf8SLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrintPath(PetscDLLibrary libs)
24e5c89e4eSSatish Balay {
25e5c89e4eSSatish Balay   PetscFunctionBegin;
26e5c89e4eSSatish Balay   while (libs) {
27e5c89e4eSSatish Balay     PetscErrorPrintf("  %s\n",libs->libname);
28e5c89e4eSSatish Balay     libs = libs->next;
29e5c89e4eSSatish Balay   }
30e5c89e4eSSatish Balay   PetscFunctionReturn(0);
31e5c89e4eSSatish Balay }
32e5c89e4eSSatish Balay 
33e5c89e4eSSatish Balay #undef __FUNCT__
34e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryRetrieve"
35e5c89e4eSSatish Balay /*@C
36e5c89e4eSSatish Balay    PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location
37e5c89e4eSSatish Balay      (if it is remote), indicates if it exits and its local name.
38e5c89e4eSSatish Balay 
39e5c89e4eSSatish Balay      Collective on MPI_Comm
40e5c89e4eSSatish Balay 
41e5c89e4eSSatish Balay    Input Parameters:
42e5c89e4eSSatish Balay +   comm - processors that are opening the library
43e5c89e4eSSatish Balay -   libname - name of the library, can be relative or absolute
44e5c89e4eSSatish Balay 
45e5c89e4eSSatish Balay    Output Parameter:
46e5c89e4eSSatish Balay .   handle - library handle
47e5c89e4eSSatish Balay 
48e5c89e4eSSatish Balay    Level: developer
49e5c89e4eSSatish Balay 
50e5c89e4eSSatish Balay    Notes:
51e5c89e4eSSatish Balay    [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0]
52e5c89e4eSSatish Balay 
53e5c89e4eSSatish Balay    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
54e5c89e4eSSatish Balay    occuring in directoryname and filename will be replaced with appropriate values.
55e5c89e4eSSatish Balay @*/
56300a7f5bSBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,size_t llen,PetscTruth *found)
57e5c89e4eSSatish Balay {
58d46cf212SLisandro Dalcin   char           *buf,*par2,suffix[16],*gz,*so;
59d46cf212SLisandro Dalcin   size_t         len;
60e5c89e4eSSatish Balay   PetscErrorCode ierr;
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay   PetscFunctionBegin;
63e5c89e4eSSatish Balay   /*
64a523d312SBarry Smith      make copy of library name and replace $PETSC_ARCH etc
65e5c89e4eSSatish Balay      so we can add to the end of it to look for something like .so.1.0 etc.
66e5c89e4eSSatish Balay   */
67e5c89e4eSSatish Balay   ierr = PetscStrlen(libname,&len);CHKERRQ(ierr);
68e5c89e4eSSatish Balay   len  = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
69d46cf212SLisandro Dalcin   ierr = PetscMalloc(len*sizeof(char),&buf);CHKERRQ(ierr);
70d46cf212SLisandro Dalcin   par2 = buf;
71e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr);
72e5c89e4eSSatish Balay 
73d46cf212SLisandro Dalcin   /* temporarily remove .gz if it ends library name */
74d46cf212SLisandro Dalcin   ierr = PetscStrrstr(par2,".gz",&gz);CHKERRQ(ierr);
75e5c89e4eSSatish Balay   if (gz) {
76e5c89e4eSSatish Balay     ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
77d46cf212SLisandro Dalcin     if (len != 3) gz  = 0; /* do not end (exactly) with .gz */
78d46cf212SLisandro Dalcin     else          *gz = 0; /* ends with .gz, so remove it   */
79e5c89e4eSSatish Balay   }
803fa76a5bSLisandro Dalcin   /* strip out .a from it if user put it in by mistake */
813fa76a5bSLisandro Dalcin   ierr = PetscStrlen(par2,&len);CHKERRQ(ierr);
823fa76a5bSLisandro Dalcin   if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0;
833fa76a5bSLisandro Dalcin 
84e5c89e4eSSatish Balay 
85e5c89e4eSSatish Balay   /* see if library name does already not have suffix attached */
86b3bb0f5eSLisandro Dalcin   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
87b3bb0f5eSLisandro Dalcin   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
88b3bb0f5eSLisandro Dalcin   ierr = PetscStrrstr(par2,suffix,&so);CHKERRQ(ierr);
89d46cf212SLisandro Dalcin   /* and attach the suffix if it is not there */
90d46cf212SLisandro Dalcin   if (!so) { ierr = PetscStrcat(par2,suffix);CHKERRQ(ierr); }
91e5c89e4eSSatish Balay 
92d46cf212SLisandro Dalcin   /* restore the .gz suffix if it was there */
93d46cf212SLisandro Dalcin   if (gz) { ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr); }
94d46cf212SLisandro Dalcin 
95d46cf212SLisandro Dalcin   /* and finally retrieve the file */
96e5c89e4eSSatish Balay   ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr);
97d46cf212SLisandro Dalcin 
98d46cf212SLisandro Dalcin   ierr = PetscFree(buf);CHKERRQ(ierr);
99e5c89e4eSSatish Balay   PetscFunctionReturn(0);
100e5c89e4eSSatish Balay }
101e5c89e4eSSatish Balay 
102e5c89e4eSSatish Balay 
103e5c89e4eSSatish Balay #undef __FUNCT__
104e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryOpen"
105e5c89e4eSSatish Balay /*@C
106ebd79076SLisandro Dalcin    PetscDLLibraryOpen - Opens a PETSc dynamic link library
107e5c89e4eSSatish Balay 
108e5c89e4eSSatish Balay      Collective on MPI_Comm
109e5c89e4eSSatish Balay 
110e5c89e4eSSatish Balay    Input Parameters:
111e5c89e4eSSatish Balay +   comm - processors that are opening the library
1120f31fb7fSLisandro Dalcin -   path - name of the library, can be relative or absolute
113e5c89e4eSSatish Balay 
114e5c89e4eSSatish Balay    Output Parameter:
1150f31fb7fSLisandro Dalcin .   entry - a PETSc dynamic link library entry
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay    Level: developer
118e5c89e4eSSatish Balay 
119e5c89e4eSSatish Balay    Notes:
120*bb84e0fdSBarry Smith    [[<http,ftp>://hostname]/directoryname/]libbasename[.so.1.0]
121*bb84e0fdSBarry Smith 
122*bb84e0fdSBarry Smith    If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run
123*bb84e0fdSBarry Smith    when the library is opened.
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay    ${PETSC_ARCH} occuring in directoryname and filename
126e5c89e4eSSatish Balay    will be replaced with the appropriate value.
127*bb84e0fdSBarry Smith 
128*bb84e0fdSBarry Smith .seealso: PetscLoadDynamicLibrary(), PetscDLLibraryAppend()
129e5c89e4eSSatish Balay @*/
130b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryOpen(MPI_Comm comm,const char path[],PetscDLLibrary *entry)
131e5c89e4eSSatish Balay {
132e5c89e4eSSatish Balay   PetscErrorCode ierr;
133b3bb0f5eSLisandro Dalcin   PetscTruth     foundlibrary,match;
134b3bb0f5eSLisandro Dalcin   char           libname[PETSC_MAX_PATH_LEN],par2[PETSC_MAX_PATH_LEN],suffix[16],*s;
135b3bb0f5eSLisandro Dalcin   char           *basename,registername[128];
1365673baf8SLisandro Dalcin   PetscDLHandle  handle;
137e5c89e4eSSatish Balay   PetscErrorCode (*func)(const char*) = NULL;
138e5c89e4eSSatish Balay   size_t         len;
139e5c89e4eSSatish Balay 
140e5c89e4eSSatish Balay   PetscFunctionBegin;
14182a51d08SSatish Balay   PetscValidCharPointer(path,2);
1425673baf8SLisandro Dalcin   PetscValidPointer(entry,3);
143ebd79076SLisandro Dalcin 
1445673baf8SLisandro Dalcin   *entry = PETSC_NULL;
145e5c89e4eSSatish Balay 
146b3bb0f5eSLisandro Dalcin   /* retrieve the library */
147b3bb0f5eSLisandro Dalcin   ierr = PetscInfo1(0,"Retrieving %s\n",path);CHKERRQ(ierr);
148b3bb0f5eSLisandro Dalcin   ierr = PetscDLLibraryRetrieve(comm,path,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr);
149b3bb0f5eSLisandro Dalcin   if (!foundlibrary) SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n  %s\n",path);
150e5c89e4eSSatish Balay   /* Eventually config/configure.py should determine if the system needs an executable dynamic library */
151e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO
152e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO)
153e5c89e4eSSatish Balay   ierr  = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr);
154b3bb0f5eSLisandro Dalcin   if (!foundlibrary) SETERRQ2(PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n  %s\n  %s\n",path,par2);
155e5c89e4eSSatish Balay #endif
156e5c89e4eSSatish Balay 
1573fa76a5bSLisandro Dalcin   /* copy path and setup shared library suffix  */
158b3bb0f5eSLisandro Dalcin   ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
159b3bb0f5eSLisandro Dalcin   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
160b3bb0f5eSLisandro Dalcin   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
1613fa76a5bSLisandro Dalcin   /* remove wrong suffixes from libname */
1623fa76a5bSLisandro Dalcin   ierr = PetscStrrstr(libname,".gz",&s);CHKERRQ(ierr);
1633fa76a5bSLisandro Dalcin   if (s && s[3] == 0) s[0] = 0;
1643fa76a5bSLisandro Dalcin   ierr = PetscStrrstr(libname,".a",&s);CHKERRQ(ierr);
1653fa76a5bSLisandro Dalcin   if (s && s[2] == 0) s[0] = 0;
1663fa76a5bSLisandro Dalcin   /* remove shared suffix from libname */
167b3bb0f5eSLisandro Dalcin   ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr);
168b3bb0f5eSLisandro Dalcin   if (s) s[0] = 0;
169b3bb0f5eSLisandro Dalcin 
1705673baf8SLisandro Dalcin   /* open the dynamic library */
171b3bb0f5eSLisandro Dalcin   ierr = PetscInfo1(0,"Opening dynamic library %s\n",libname);CHKERRQ(ierr);
172b3bb0f5eSLisandro Dalcin   ierr = PetscDLOpen(par2,PETSC_DL_DECIDE,&handle);CHKERRQ(ierr);
173b3bb0f5eSLisandro Dalcin 
174b3bb0f5eSLisandro Dalcin   /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */
175b3bb0f5eSLisandro Dalcin   ierr = PetscStrrchr(libname,'/',&basename);CHKERRQ(ierr); /* XXX Windows ??? */
176b3bb0f5eSLisandro Dalcin   if (!basename) basename = libname;
177b3bb0f5eSLisandro Dalcin   ierr = PetscStrncmp(basename,"lib",3,&match);CHKERRQ(ierr);
178b3bb0f5eSLisandro Dalcin   if (match) {
179b3bb0f5eSLisandro Dalcin     basename = basename + 3;
180b3bb0f5eSLisandro Dalcin   } else {
181*bb84e0fdSBarry Smith     ierr = PetscInfo1(0,"Dynamic library %s does not have lib prefix\n",libname);CHKERRQ(ierr);
182e5c89e4eSSatish Balay   }
183b3bb0f5eSLisandro Dalcin   ierr = PetscStrlen(basename,&len);CHKERRQ(ierr);
184b3bb0f5eSLisandro Dalcin   ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr);
185b3bb0f5eSLisandro Dalcin   ierr = PetscStrncat(registername,basename,len);CHKERRQ(ierr);
186b3bb0f5eSLisandro Dalcin   ierr = PetscDLSym(handle,registername,(void**)&func);CHKERRQ(ierr);
187b3bb0f5eSLisandro Dalcin   if (func) {
1885673baf8SLisandro Dalcin     ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr);
1895673baf8SLisandro Dalcin     ierr = (*func)(libname);CHKERRQ(ierr);
190b3bb0f5eSLisandro Dalcin   } else {
191*bb84e0fdSBarry Smith     ierr = PetscInfo2(0,"Dynamic library %s does not have symbol %s\n",libname,registername);CHKERRQ(ierr);
192b3bb0f5eSLisandro Dalcin   }
1935673baf8SLisandro Dalcin 
1945673baf8SLisandro Dalcin   ierr = PetscNew(struct _n_PetscDLLibrary,entry);CHKERRQ(ierr);
1955673baf8SLisandro Dalcin   (*entry)->next   = 0;
196b3bb0f5eSLisandro Dalcin   (*entry)->handle = handle;
197b3bb0f5eSLisandro Dalcin   ierr = PetscStrcpy((*entry)->libname,libname);CHKERRQ(ierr);
1985673baf8SLisandro Dalcin 
199e5c89e4eSSatish Balay   PetscFunctionReturn(0);
200e5c89e4eSSatish Balay }
201e5c89e4eSSatish Balay 
202e5c89e4eSSatish Balay #undef __FUNCT__
203e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibrarySym"
204e5c89e4eSSatish Balay /*@C
205e5c89e4eSSatish Balay    PetscDLLibrarySym - Load a symbol from the dynamic link libraries.
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay    Collective on MPI_Comm
208e5c89e4eSSatish Balay 
209e5c89e4eSSatish Balay    Input Parameter:
210e5bd5246SBarry Smith +  comm - communicator that will open the library
2110f31fb7fSLisandro Dalcin .  outlist - list of already open libraries that may contain symbol (checks here before path)
212e5bd5246SBarry Smith .  path     - optional complete library name
213e5c89e4eSSatish Balay -  insymbol - name of symbol
214e5c89e4eSSatish Balay 
215e5c89e4eSSatish Balay    Output Parameter:
216e5c89e4eSSatish Balay .  value
217e5c89e4eSSatish Balay 
218e5c89e4eSSatish Balay    Level: developer
219e5c89e4eSSatish Balay 
220e5c89e4eSSatish Balay    Notes: Symbol can be of the form
221e5c89e4eSSatish Balay         [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional
222e5c89e4eSSatish Balay 
223e5c89e4eSSatish Balay         Will attempt to (retrieve and) open the library if it is not yet been opened.
224e5c89e4eSSatish Balay 
225e5c89e4eSSatish Balay @*/
226b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *outlist,const char path[],const char insymbol[],void **value)
227e5c89e4eSSatish Balay {
228b3bb0f5eSLisandro Dalcin   char           libname[PETSC_MAX_PATH_LEN],suffix[16],*symbol,*s;
229e5c89e4eSSatish Balay   size_t         len;
230e5bd5246SBarry Smith   PetscDLLibrary nlist,prev,list;
231b3bb0f5eSLisandro Dalcin   PetscErrorCode ierr;
232e5c89e4eSSatish Balay 
233e5c89e4eSSatish Balay   PetscFunctionBegin;
234b3bb0f5eSLisandro Dalcin   PetscValidPointer(outlist,2);
2355673baf8SLisandro Dalcin   if (path) PetscValidCharPointer(path,3);
2365673baf8SLisandro Dalcin   PetscValidCharPointer(insymbol,4);
2375673baf8SLisandro Dalcin   PetscValidPointer(value,5);
2385673baf8SLisandro Dalcin 
239b3bb0f5eSLisandro Dalcin   list   = *outlist;
240e5c89e4eSSatish Balay   *value = 0;
241e5c89e4eSSatish Balay 
242e5c89e4eSSatish Balay   /* make copy of symbol so we can edit it in place */
243e5c89e4eSSatish Balay   ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr);
244e5c89e4eSSatish Balay   ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr);
245e5c89e4eSSatish Balay   ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr);
246b3bb0f5eSLisandro Dalcin   /* If symbol contains () then replace with a NULL, to support functionname() */
247b3bb0f5eSLisandro Dalcin   ierr = PetscStrchr(symbol,'(',&s);CHKERRQ(ierr);
248b3bb0f5eSLisandro Dalcin   if (s) s[0] = 0;
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay   /*
251e5c89e4eSSatish Balay        Function name does include library
252e5c89e4eSSatish Balay        -------------------------------------
253e5c89e4eSSatish Balay   */
254e5c89e4eSSatish Balay   if (path && path[0] != '\0') {
255b3bb0f5eSLisandro Dalcin     /* copy path and remove suffix from libname */
256b3bb0f5eSLisandro Dalcin     ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
257b3bb0f5eSLisandro Dalcin     ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
258b3bb0f5eSLisandro Dalcin     ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
259b3bb0f5eSLisandro Dalcin     ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr);
260b3bb0f5eSLisandro Dalcin     if (s) s[0] = 0;
2615673baf8SLisandro Dalcin     /* Look if library is already opened and in path */
262e5c89e4eSSatish Balay     prev  = 0;
263b3bb0f5eSLisandro Dalcin     nlist = list;
264e5c89e4eSSatish Balay     while (nlist) {
265e5c89e4eSSatish Balay       PetscTruth match;
266b3bb0f5eSLisandro Dalcin       ierr = PetscStrcmp(nlist->libname,libname,&match);CHKERRQ(ierr);
2675673baf8SLisandro Dalcin       if (match) goto done;
268e5c89e4eSSatish Balay       prev  = nlist;
269e5c89e4eSSatish Balay       nlist = nlist->next;
270e5c89e4eSSatish Balay     }
271b3bb0f5eSLisandro Dalcin     /* open the library and append it to path */
2725673baf8SLisandro Dalcin     ierr = PetscDLLibraryOpen(comm,path,&nlist);CHKERRQ(ierr);
273ae15b995SBarry Smith     ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr);
2745673baf8SLisandro Dalcin     if (prev) { prev->next = nlist; }
275b3bb0f5eSLisandro Dalcin     else      { *outlist   = nlist; }
276e5c89e4eSSatish Balay 
277e5c89e4eSSatish Balay   done:;
2785673baf8SLisandro Dalcin     ierr = PetscDLSym(nlist->handle,symbol,value);CHKERRQ(ierr);
279e5c89e4eSSatish Balay     if (!*value) {
280e5c89e4eSSatish Balay       SETERRQ2(PETSC_ERR_PLIB,"Unable to locate function %s in dynamic library %s",insymbol,path);
281e5c89e4eSSatish Balay     }
282ae15b995SBarry Smith     ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr);
283e5c89e4eSSatish Balay 
284e5c89e4eSSatish Balay   /*
285e5c89e4eSSatish Balay        Function name does not include library so search path
286e5c89e4eSSatish Balay        -----------------------------------------------------
287e5c89e4eSSatish Balay   */
288e5c89e4eSSatish Balay   } else {
289e5c89e4eSSatish Balay     while (list) {
290ebd79076SLisandro Dalcin       ierr = PetscDLSym(list->handle,symbol,value);CHKERRQ(ierr);
291e5c89e4eSSatish Balay       if (*value) {
292b3bb0f5eSLisandro Dalcin         ierr = PetscInfo2(0,"Loading symbol %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr);
293e5c89e4eSSatish Balay         break;
294e5c89e4eSSatish Balay       }
295e5c89e4eSSatish Balay       list = list->next;
296e5c89e4eSSatish Balay     }
297e5c89e4eSSatish Balay     if (!*value) {
298ebd79076SLisandro Dalcin       ierr = PetscDLSym(PETSC_NULL,symbol,value);CHKERRQ(ierr);
299e5c89e4eSSatish Balay       if (*value) {
300b3bb0f5eSLisandro Dalcin         ierr = PetscInfo1(0,"Loading symbol %s from object code\n",symbol);CHKERRQ(ierr);
301e5c89e4eSSatish Balay       }
302e5c89e4eSSatish Balay     }
303e5c89e4eSSatish Balay   }
304e5c89e4eSSatish Balay 
305e5c89e4eSSatish Balay   ierr = PetscFree(symbol);CHKERRQ(ierr);
306e5c89e4eSSatish Balay   PetscFunctionReturn(0);
307e5c89e4eSSatish Balay }
308e5c89e4eSSatish Balay 
309e5c89e4eSSatish Balay #undef __FUNCT__
310e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryAppend"
311e5c89e4eSSatish Balay /*@C
312e5c89e4eSSatish Balay      PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end
313e5c89e4eSSatish Balay                 of the search path.
314e5c89e4eSSatish Balay 
315e5c89e4eSSatish Balay      Collective on MPI_Comm
316e5c89e4eSSatish Balay 
317e5c89e4eSSatish Balay      Input Parameters:
318e5c89e4eSSatish Balay +     comm - MPI communicator
3190f31fb7fSLisandro Dalcin -     path - name of the library
320e5c89e4eSSatish Balay 
321e5c89e4eSSatish Balay      Output Parameter:
322e5c89e4eSSatish Balay .     outlist - list of libraries
323e5c89e4eSSatish Balay 
324e5c89e4eSSatish Balay      Level: developer
325e5c89e4eSSatish Balay 
326e5c89e4eSSatish Balay      Notes: if library is already in path will not add it.
327*bb84e0fdSBarry Smith 
328*bb84e0fdSBarry Smith   If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run
329*bb84e0fdSBarry Smith       when the library is opened.
330*bb84e0fdSBarry Smith 
331*bb84e0fdSBarry Smith .seealso: PetscDLLibraryOpen()
332e5c89e4eSSatish Balay @*/
333b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[])
334e5c89e4eSSatish Balay {
335e5bd5246SBarry Smith   PetscDLLibrary list,prev;
336e5c89e4eSSatish Balay   PetscErrorCode ierr;
337e5c89e4eSSatish Balay   size_t         len;
338e5c89e4eSSatish Balay   PetscTruth     match,dir;
339b3bb0f5eSLisandro Dalcin   char           program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN];
340b3bb0f5eSLisandro Dalcin   char           *libname,suffix[16],*s;
3419c9d3cfdSBarry Smith   PetscToken     token;
342e5c89e4eSSatish Balay 
343e5c89e4eSSatish Balay   PetscFunctionBegin;
344b3bb0f5eSLisandro Dalcin   PetscValidPointer(outlist,2);
345e5c89e4eSSatish Balay 
346b3bb0f5eSLisandro Dalcin   /* is path a directory? */
347b3bb0f5eSLisandro Dalcin   ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr);
348e5c89e4eSSatish Balay   if (dir) {
349b3bb0f5eSLisandro Dalcin     ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr);
350b3bb0f5eSLisandro Dalcin     ierr  = PetscStrcpy(program,path);CHKERRQ(ierr);
351e5c89e4eSSatish Balay     ierr  = PetscStrlen(program,&len);CHKERRQ(ierr);
352e5c89e4eSSatish Balay     if (program[len-1] == '/') {
353e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"*.");CHKERRQ(ierr);
354e5c89e4eSSatish Balay     } else {
355e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"/*.");CHKERRQ(ierr);
356e5c89e4eSSatish Balay     }
357e5c89e4eSSatish Balay     ierr  = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr);
358e5c89e4eSSatish Balay 
359b3bb0f5eSLisandro Dalcin     ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
360e5c89e4eSSatish Balay     if (!dir) PetscFunctionReturn(0);
361e5c89e4eSSatish Balay   } else {
362b3bb0f5eSLisandro Dalcin     ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
363e5c89e4eSSatish Balay   }
364e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
365e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
366e5c89e4eSSatish Balay 
367e5c89e4eSSatish Balay   ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr);
368b3bb0f5eSLisandro Dalcin   ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
369b3bb0f5eSLisandro Dalcin   while (libname) {
370b3bb0f5eSLisandro Dalcin     /* remove suffix from libname */
371b3bb0f5eSLisandro Dalcin     ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr);
372e5c89e4eSSatish Balay     if (s) s[0] = 0;
373e5c89e4eSSatish Balay     /* see if library was already open then we are done */
374e5c89e4eSSatish Balay     list  = prev = *outlist;
375e5c89e4eSSatish Balay     match = PETSC_FALSE;
376e5c89e4eSSatish Balay     while (list) {
377b3bb0f5eSLisandro Dalcin       ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr);
378e5c89e4eSSatish Balay       if (match) break;
379e5c89e4eSSatish Balay       prev = list;
380e5c89e4eSSatish Balay       list = list->next;
381e5c89e4eSSatish Balay     }
382b3bb0f5eSLisandro Dalcin     /* restore suffix from libname */
383b3bb0f5eSLisandro Dalcin     if (s) s[0] = '.';
384e5c89e4eSSatish Balay     if (!match) {
3855673baf8SLisandro Dalcin       /* open the library and add to end of list */
386b3bb0f5eSLisandro Dalcin       ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr);
387b3bb0f5eSLisandro Dalcin       ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname);CHKERRQ(ierr);
388e5c89e4eSSatish Balay       if (!*outlist) {
389e5c89e4eSSatish Balay 	*outlist   = list;
390e5c89e4eSSatish Balay       } else {
391e5c89e4eSSatish Balay 	prev->next = list;
392e5c89e4eSSatish Balay       }
393e5c89e4eSSatish Balay     }
394b3bb0f5eSLisandro Dalcin     ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
395e5c89e4eSSatish Balay   }
396e5c89e4eSSatish Balay   ierr = PetscTokenDestroy(token);CHKERRQ(ierr);
397e5c89e4eSSatish Balay   PetscFunctionReturn(0);
398e5c89e4eSSatish Balay }
399e5c89e4eSSatish Balay 
400e5c89e4eSSatish Balay #undef __FUNCT__
401e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrepend"
402e5c89e4eSSatish Balay /*@C
403e5c89e4eSSatish Balay      PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of
404e5c89e4eSSatish Balay                  the search path.
405e5c89e4eSSatish Balay 
406e5c89e4eSSatish Balay      Collective on MPI_Comm
407e5c89e4eSSatish Balay 
408e5c89e4eSSatish Balay      Input Parameters:
409e5c89e4eSSatish Balay +     comm - MPI communicator
4100f31fb7fSLisandro Dalcin -     path - name of the library
411e5c89e4eSSatish Balay 
412e5c89e4eSSatish Balay      Output Parameter:
413e5c89e4eSSatish Balay .     outlist - list of libraries
414e5c89e4eSSatish Balay 
415e5c89e4eSSatish Balay      Level: developer
416e5c89e4eSSatish Balay 
417e5c89e4eSSatish Balay      Notes: If library is already in path will remove old reference.
418e5c89e4eSSatish Balay 
419e5c89e4eSSatish Balay @*/
420b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[])
421e5c89e4eSSatish Balay {
422e5bd5246SBarry Smith   PetscDLLibrary list,prev;
423e5c89e4eSSatish Balay   PetscErrorCode ierr;
424e5c89e4eSSatish Balay   size_t         len;
425e5c89e4eSSatish Balay   PetscTruth     match,dir;
426b3bb0f5eSLisandro Dalcin   char           program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN];
427b3bb0f5eSLisandro Dalcin   char           *libname,suffix[16],*s;
4285b096c79SMatthew Knepley   PetscToken     token;
429e5c89e4eSSatish Balay 
430e5c89e4eSSatish Balay   PetscFunctionBegin;
431b3bb0f5eSLisandro Dalcin   PetscValidPointer(outlist,2);
432e5c89e4eSSatish Balay 
433b3bb0f5eSLisandro Dalcin   /* is path a directory? */
434b3bb0f5eSLisandro Dalcin   ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr);
435e5c89e4eSSatish Balay   if (dir) {
436b3bb0f5eSLisandro Dalcin     ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr);
437b3bb0f5eSLisandro Dalcin     ierr  = PetscStrcpy(program,path);CHKERRQ(ierr);
438e5c89e4eSSatish Balay     ierr  = PetscStrlen(program,&len);CHKERRQ(ierr);
439e5c89e4eSSatish Balay     if (program[len-1] == '/') {
440e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"*.");CHKERRQ(ierr);
441e5c89e4eSSatish Balay     } else {
442e5c89e4eSSatish Balay       ierr  = PetscStrcat(program,"/*.");CHKERRQ(ierr);
443e5c89e4eSSatish Balay     }
444e5c89e4eSSatish Balay     ierr  = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr);
445e5c89e4eSSatish Balay 
446b3bb0f5eSLisandro Dalcin     ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
447e5c89e4eSSatish Balay     if (!dir) PetscFunctionReturn(0);
448e5c89e4eSSatish Balay   } else {
449b3bb0f5eSLisandro Dalcin     ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
450e5c89e4eSSatish Balay   }
451e5c89e4eSSatish Balay 
452e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
453e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
454e5c89e4eSSatish Balay 
455e5c89e4eSSatish Balay   ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr);
456b3bb0f5eSLisandro Dalcin   ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
457b3bb0f5eSLisandro Dalcin   while (libname) {
458b3bb0f5eSLisandro Dalcin     /* remove suffix from libname */
459b3bb0f5eSLisandro Dalcin     ierr = PetscStrstr(libname,suffix,&s);CHKERRQ(ierr);
460e5c89e4eSSatish Balay     if (s) s[0] = 0;
461e5c89e4eSSatish Balay     /* see if library was already open and move it to the front */
462e5c89e4eSSatish Balay     prev  = 0;
463b3bb0f5eSLisandro Dalcin     list  = *outlist;
464e5c89e4eSSatish Balay     match = PETSC_FALSE;
465e5c89e4eSSatish Balay     while (list) {
466b3bb0f5eSLisandro Dalcin       ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr);
467e5c89e4eSSatish Balay       if (match) {
468b3bb0f5eSLisandro Dalcin 	ierr = PetscInfo1(0,"Moving %s to begin of dynamic library search path\n",libname);CHKERRQ(ierr);
469e5c89e4eSSatish Balay 	if (prev) prev->next = list->next;
470b3bb0f5eSLisandro Dalcin 	if (prev) list->next = *outlist;
471e5c89e4eSSatish Balay 	*outlist = list;
472e5c89e4eSSatish Balay 	break;
473e5c89e4eSSatish Balay       }
474e5c89e4eSSatish Balay       prev = list;
475e5c89e4eSSatish Balay       list = list->next;
476e5c89e4eSSatish Balay     }
477b3bb0f5eSLisandro Dalcin     /* restore suffix from libname */
478b3bb0f5eSLisandro Dalcin     if (s) s[0] = '.';
479e5c89e4eSSatish Balay     if (!match) {
4805673baf8SLisandro Dalcin       /* open the library and add to front of list */
481b3bb0f5eSLisandro Dalcin       ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr);
482b3bb0f5eSLisandro Dalcin       ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname);CHKERRQ(ierr);
483ebd79076SLisandro Dalcin       list->next = *outlist;
484e5c89e4eSSatish Balay       *outlist   = list;
485e5c89e4eSSatish Balay     }
486b3bb0f5eSLisandro Dalcin     ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
487e5c89e4eSSatish Balay   }
488e5c89e4eSSatish Balay   ierr = PetscTokenDestroy(token);CHKERRQ(ierr);
489e5c89e4eSSatish Balay   PetscFunctionReturn(0);
490e5c89e4eSSatish Balay }
491e5c89e4eSSatish Balay 
492e5c89e4eSSatish Balay #undef __FUNCT__
493e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryClose"
494e5c89e4eSSatish Balay /*@C
495e5c89e4eSSatish Balay      PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries.
496e5c89e4eSSatish Balay 
497e5c89e4eSSatish Balay     Collective on PetscDLLibrary
498e5c89e4eSSatish Balay 
499e5c89e4eSSatish Balay     Input Parameter:
5003fa76a5bSLisandro Dalcin .     head - library list
501e5c89e4eSSatish Balay 
502e5c89e4eSSatish Balay      Level: developer
503e5c89e4eSSatish Balay 
504e5c89e4eSSatish Balay @*/
5050f31fb7fSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryClose(PetscDLLibrary list)
506e5c89e4eSSatish Balay {
5073fa76a5bSLisandro Dalcin   PetscTruth     done = PETSC_FALSE;
5080f31fb7fSLisandro Dalcin   PetscDLLibrary prev,tail;
509e5c89e4eSSatish Balay   PetscErrorCode ierr;
510e5c89e4eSSatish Balay 
511e5c89e4eSSatish Balay   PetscFunctionBegin;
5120f31fb7fSLisandro Dalcin   if (!list) PetscFunctionReturn(0);
5133fa76a5bSLisandro Dalcin   /* traverse the list in reverse order */
5143fa76a5bSLisandro Dalcin   while (!done) {
5150f31fb7fSLisandro Dalcin     if (!list->next) done = PETSC_TRUE;
5160f31fb7fSLisandro Dalcin     prev = tail = list;
5173fa76a5bSLisandro Dalcin     while (tail->next) {
5183fa76a5bSLisandro Dalcin       prev = tail;
5193fa76a5bSLisandro Dalcin       tail = tail->next;
520e5c89e4eSSatish Balay     }
5213fa76a5bSLisandro Dalcin     prev->next = 0;
5223fa76a5bSLisandro Dalcin     /* close the dynamic library and free the space in entry data-structure*/
5233fa76a5bSLisandro Dalcin     ierr = PetscInfo1(0,"Closing dynamic library %s\n",tail->libname);CHKERRQ(ierr);
5243fa76a5bSLisandro Dalcin     ierr = PetscDLClose(&tail->handle);CHKERRQ(ierr);
5253fa76a5bSLisandro Dalcin     ierr = PetscFree(tail);CHKERRQ(ierr);
5263fa76a5bSLisandro Dalcin   };
527e5c89e4eSSatish Balay   PetscFunctionReturn(0);
528e5c89e4eSSatish Balay }
529e5c89e4eSSatish Balay 
5303fa76a5bSLisandro Dalcin /* ------------------------------------------------------------------------------*/
5313fa76a5bSLisandro Dalcin 
5323fa76a5bSLisandro Dalcin /*
5333fa76a5bSLisandro Dalcin    Contains the list of registered CCA components
5343fa76a5bSLisandro Dalcin */
5353fa76a5bSLisandro Dalcin PetscFList CCAList = 0;
5363fa76a5bSLisandro Dalcin 
537e5c89e4eSSatish Balay #undef __FUNCT__
538e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryCCAAppend"
539e5c89e4eSSatish Balay /*@C
540e5c89e4eSSatish Balay      PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end
541e5c89e4eSSatish Balay                 of the search path.
542e5c89e4eSSatish Balay 
543e5c89e4eSSatish Balay      Collective on MPI_Comm
544e5c89e4eSSatish Balay 
545e5c89e4eSSatish Balay      Input Parameters:
546e5c89e4eSSatish Balay +     comm - MPI communicator
5470f31fb7fSLisandro Dalcin -     dirname - name of directory to check
548e5c89e4eSSatish Balay 
549e5c89e4eSSatish Balay      Output Parameter:
550e5c89e4eSSatish Balay .     outlist - list of libraries
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay      Level: developer
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay      Notes: if library is already in path will not add it.
555e5c89e4eSSatish Balay @*/
556e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[])
557e5c89e4eSSatish Balay {
558e5c89e4eSSatish Balay   PetscErrorCode ierr;
559e5c89e4eSSatish Balay   size_t         l;
560e5c89e4eSSatish Balay   PetscTruth     dir;
561e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2;
562e5c89e4eSSatish Balay   char           *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib;
563e5c89e4eSSatish Balay   FILE           *fp;
5645b096c79SMatthew Knepley   PetscToken     token1, token2;
565ed9cf6e9SBarry Smith   int            err;
566e5c89e4eSSatish Balay 
567e5c89e4eSSatish Balay   PetscFunctionBegin;
568e5c89e4eSSatish Balay   /* is dirname a directory? */
569e5c89e4eSSatish Balay   ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr);
570e5c89e4eSSatish Balay   if (!dir) PetscFunctionReturn(0);
571e5c89e4eSSatish Balay 
572ae15b995SBarry Smith   ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr);
573e5c89e4eSSatish Balay   ierr  = PetscStrcpy(program,dirname);CHKERRQ(ierr);
574e5c89e4eSSatish Balay   ierr  = PetscStrcat(program,"/*.cca");CHKERRQ(ierr);
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay   ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
577e5c89e4eSSatish Balay   if (!dir) PetscFunctionReturn(0);
578e5c89e4eSSatish Balay 
579e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
580e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
581e5c89e4eSSatish Balay   ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr);
582e5c89e4eSSatish Balay   ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr);
583e5c89e4eSSatish Balay   while (libname1) {
584e5c89e4eSSatish Balay     fp    = fopen(libname1,"r"); if (!fp) continue;
585e5c89e4eSSatish Balay     while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) {
586e5c89e4eSSatish Balay       if (found[0] == '!') continue;
587e5c89e4eSSatish Balay       ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr);
588e5c89e4eSSatish Balay       if (f2) { /* found library name */
589e5c89e4eSSatish Balay         if (found[0] == '/') {
590e5c89e4eSSatish Balay           lib = found;
591e5c89e4eSSatish Balay         } else {
592e5c89e4eSSatish Balay           ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr);
593e5c89e4eSSatish Balay           ierr = PetscStrlen(libname,&l);CHKERRQ(ierr);
594e5c89e4eSSatish Balay           if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);}
595e5c89e4eSSatish Balay           ierr = PetscStrcat(libname,found);CHKERRQ(ierr);
596e5c89e4eSSatish Balay           lib  = libname;
597e5c89e4eSSatish Balay         }
598e5c89e4eSSatish Balay         ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr);
599e5c89e4eSSatish Balay       } else {
600ae15b995SBarry Smith         ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr);
601e5c89e4eSSatish Balay         ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr);
602e5c89e4eSSatish Balay         ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr);
603e5c89e4eSSatish Balay         ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr);
604e5c89e4eSSatish Balay         ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr);
605e5c89e4eSSatish Balay         ierr = PetscTokenDestroy(token2);CHKERRQ(ierr);
606e5c89e4eSSatish Balay       }
607e5c89e4eSSatish Balay     }
608ed9cf6e9SBarry Smith     err = fclose(fp);
609ed9cf6e9SBarry Smith     if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
610e5c89e4eSSatish Balay     ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr);
611e5c89e4eSSatish Balay   }
612e5c89e4eSSatish Balay   ierr = PetscTokenDestroy(token1);CHKERRQ(ierr);
613e5c89e4eSSatish Balay   PetscFunctionReturn(0);
614e5c89e4eSSatish Balay }
615