xref: /petsc/src/sys/dll/reg.c (revision 2cfcea2917e9827eeaf4fa9c2e8dd75b054ced7b)
1 #define PETSC_DLL
2 /*
3     Provides a general mechanism to allow one to register new routines in
4     dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
5 */
6 #include "petsc.h"           /*I "petsc.h" I*/
7 #include "petscsys.h"
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "PetscFListGetPathAndFunction"
11 PetscErrorCode PETSC_DLLEXPORT PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
12 {
13   PetscErrorCode ierr;
14   char work[PETSC_MAX_PATH_LEN],*lfunction;
15 
16   PetscFunctionBegin;
17   ierr = PetscStrncpy(work,name,256);CHKERRQ(ierr);
18   ierr = PetscStrchr(work,':',&lfunction);CHKERRQ(ierr);
19   if (lfunction != work && lfunction && lfunction[1] != ':') {
20     lfunction[0] = 0;
21     ierr = PetscStrallocpy(work,path);CHKERRQ(ierr);
22     ierr = PetscStrallocpy(lfunction+1,function);CHKERRQ(ierr);
23   } else {
24     *path = 0;
25     ierr = PetscStrallocpy(name,function);CHKERRQ(ierr);
26   }
27   PetscFunctionReturn(0);
28 }
29 
30 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
31 
32 /*
33     This is the list used by the DLRegister routines
34 */
35 PetscDLLibraryList DLLibrariesLoaded = 0;
36 
37 #undef __FUNCT__
38 #define __FUNCT__ "PetscInitialize_DynamicLibraries"
39 /*
40     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
41     search path.
42 */
43 PetscErrorCode PETSC_DLLEXPORT PetscInitialize_DynamicLibraries(void)
44 {
45   char           *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
46   PetscErrorCode ierr;
47   PetscInt       nmax,i;
48   PetscTruth     found;
49 
50   PetscFunctionBegin;
51 
52   nmax = 32;
53   ierr = PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);CHKERRQ(ierr);
54   for (i=0; i<nmax; i++) {
55     ierr = PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
56     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
57   }
58 
59   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
60   ierr = PetscStrcat(libs,"/libpetsc");CHKERRQ(ierr);
61   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
62   if (found) {
63     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
64   } else {
65     SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library %s \n You cannot move the dynamic libraries!\n or remove USE_DYNAMIC_LIBRARIES from ${PETSC_DIR}/bmake/$PETSC_ARCH/petscconf.h\n and rebuild libraries before moving",libs);
66   }
67 
68   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
69   ierr = PetscStrcat(libs,"/libpetscvec");CHKERRQ(ierr);
70   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
71   if (found) {
72     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
73   }
74 
75   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
76   ierr = PetscStrcat(libs,"/libpetscmat");CHKERRQ(ierr);
77   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
78   if (found) {
79     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
80   }
81 
82   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
83   ierr = PetscStrcat(libs,"/libpetscdm");CHKERRQ(ierr);
84   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
85   if (found) {
86     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
87   }
88 
89   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
90   ierr = PetscStrcat(libs,"/libpetscksp");CHKERRQ(ierr);
91   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
92   if (found) {
93     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
94   }
95 
96   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
97   ierr = PetscStrcat(libs,"/libpetscsnes");CHKERRQ(ierr);
98   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
99   if (found) {
100     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
101   }
102 
103   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
104   ierr = PetscStrcat(libs,"/libpetscts");CHKERRQ(ierr);
105   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
106   if (found) {
107     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
108   }
109 
110   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
111   ierr = PetscStrcat(libs,"/libpetscdm");CHKERRQ(ierr);
112   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
113   if (found) {
114     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
115   }
116 
117   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
118   ierr = PetscStrcat(libs,"/libpetscmesh");CHKERRQ(ierr);
119   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
120   if (found) {
121     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
122   }
123 
124   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}");CHKERRQ(ierr);
125   ierr = PetscStrcat(libs,"/libpetsccontrib");CHKERRQ(ierr);
126   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);CHKERRQ(ierr);
127   if (found) {
128     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);CHKERRQ(ierr);
129   }
130 
131   nmax = 32;
132   ierr = PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);CHKERRQ(ierr);
133   for (i=0; i<nmax; i++) {
134     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
135     ierr = PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
136     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
137   }
138 
139   PetscFunctionReturn(0);
140 }
141 
142 #undef __FUNCT__
143 #define __FUNCT__ "PetscFinalize_DynamicLibraries"
144 /*
145      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
146 */
147 PetscErrorCode PetscFinalize_DynamicLibraries(void)
148 {
149   PetscErrorCode ierr;
150   PetscTruth     flg;
151 
152   PetscFunctionBegin;
153   ierr = PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);CHKERRQ(ierr);
154   if (flg) {
155     ierr = PetscDLLibraryPrintPath();CHKERRQ(ierr);
156   }
157   ierr = PetscDLLibraryClose(DLLibrariesLoaded);CHKERRQ(ierr);
158   PetscFunctionReturn(0);
159 }
160 
161 #else /* not using dynamic libraries */
162 
163 #undef __FUNCT__
164 #define __FUNCT__ "PetscInitalize_DynamicLibraries"
165 PetscErrorCode PETSC_DLLEXPORT PetscInitialize_DynamicLibraries(void)
166 {
167   PetscErrorCode ierr;
168 
169   PetscFunctionBegin;
170   /*
171       This just initializes the draw and viewer methods, since those
172     are ALWAYS available. The other classes are initialized the first
173     time an XXSetType() is called.
174   */
175   ierr = PetscInitializePackage(PETSC_NULL);CHKERRQ(ierr);
176   PetscFunctionReturn(0);
177 }
178 #undef __FUNCT__
179 #define __FUNCT__ "PetscFinalize_DynamicLibraries"
180 PetscErrorCode PetscFinalize_DynamicLibraries(void)
181 {
182   PetscFunctionBegin;
183 
184   PetscFunctionReturn(0);
185 }
186 #endif
187 
188 /* ------------------------------------------------------------------------------*/
189 struct _n_PetscFList {
190   void        (*routine)(void);   /* the routine */
191   char        *path;              /* path of link library containing routine */
192   char        *name;              /* string to identify routine */
193   char        *rname;             /* routine name in dynamic library */
194   PetscFList  next;               /* next pointer */
195   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
196 };
197 
198 /*
199      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
200 */
201 static PetscFList   dlallhead = 0;
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "PetscFListAdd"
205 /*@C
206    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
207    specified registry.
208 
209      Not Collective
210 
211    Input Parameters:
212 +  fl    - pointer registry
213 .  name  - string to identify routine
214 .  rname - routine name in dynamic library
215 -  fnc   - function pointer (optional if using dynamic libraries)
216 
217    Notes:
218    To remove a registered routine, pass in a PETSC_NULL rname and fnc().
219 
220    Users who wish to register new classes for use by a particular PETSc
221    component (e.g., SNES) should generally call the registration routine
222    for that particular component (e.g., SNESRegisterDynamic()) instead of
223    calling PetscFListAddDynamic() directly.
224 
225    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
226   occuring in pathname will be replaced with appropriate values.
227 
228    Level: developer
229 
230 .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
231           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
232 @*/
233 PetscErrorCode PETSC_DLLEXPORT PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
234 {
235   PetscFList     entry,ne;
236   PetscErrorCode ierr;
237   char           *fpath,*fname;
238 
239   PetscFunctionBegin;
240 
241   if (!*fl) {
242     ierr           = PetscNew(struct _n_PetscFList,&entry);CHKERRQ(ierr);
243     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
244     ierr           = PetscFListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr);
245     entry->path    = fpath;
246     entry->rname   = fname;
247     entry->routine = fnc;
248     entry->next    = 0;
249     *fl = entry;
250 
251     /* add this new list to list of all lists */
252     if (!dlallhead) {
253       dlallhead        = *fl;
254       (*fl)->next_list = 0;
255     } else {
256       ne               = dlallhead;
257       dlallhead        = *fl;
258       (*fl)->next_list = ne;
259     }
260   } else {
261     /* search list to see if it is already there */
262     ne = *fl;
263     while (ne) {
264       PetscTruth founddup;
265 
266       ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr);
267       if (founddup) { /* found duplicate */
268         ierr = PetscFListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr);
269         ierr = PetscStrfree(ne->path);CHKERRQ(ierr);
270         ierr = PetscStrfree(ne->rname);CHKERRQ(ierr);
271         ne->path    = fpath;
272         ne->rname   = fname;
273         ne->routine = fnc;
274         PetscFunctionReturn(0);
275       }
276       if (ne->next) ne = ne->next; else break;
277     }
278     /* create new entry and add to end of list */
279     ierr           = PetscNew(struct _n_PetscFList,&entry);CHKERRQ(ierr);
280     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
281     ierr           = PetscFListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr);
282     entry->path    = fpath;
283     entry->rname   = fname;
284     entry->routine = fnc;
285     entry->next    = 0;
286     ne->next       = entry;
287   }
288 
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNCT__
293 #define __FUNCT__ "PetscFListDestroy"
294 /*@
295     PetscFListDestroy - Destroys a list of registered routines.
296 
297     Input Parameter:
298 .   fl  - pointer to list
299 
300     Level: developer
301 
302 .seealso: PetscFListAddDynamic(), PetscFList
303 @*/
304 PetscErrorCode PETSC_DLLEXPORT PetscFListDestroy(PetscFList *fl)
305 {
306   PetscFList     next,entry,tmp = dlallhead;
307   PetscErrorCode ierr;
308 
309   PetscFunctionBegin;
310   if (!*fl) PetscFunctionReturn(0);
311 
312   if (!dlallhead) {
313     PetscFunctionReturn(0);
314   }
315 
316   /*
317        Remove this entry from the master DL list (if it is in it)
318   */
319   if (dlallhead == *fl) {
320     if (dlallhead->next_list) {
321       dlallhead = dlallhead->next_list;
322     } else {
323       dlallhead = 0;
324     }
325   } else {
326     while (tmp->next_list != *fl) {
327       tmp = tmp->next_list;
328       if (!tmp->next_list) break;
329     }
330     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
331   }
332 
333   /* free this list */
334   entry = *fl;
335   while (entry) {
336     next = entry->next;
337     ierr = PetscStrfree(entry->path);CHKERRQ(ierr);
338     ierr = PetscFree(entry->name);CHKERRQ(ierr);
339     ierr = PetscFree(entry->rname);CHKERRQ(ierr);
340     ierr = PetscFree(entry);CHKERRQ(ierr);
341     entry = next;
342   }
343   *fl = 0;
344   PetscFunctionReturn(0);
345 }
346 
347 /*
348    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
349 */
350 #undef __FUNCT__
351 #define __FUNCT__ "PetscFListDestroyAll"
352 PetscErrorCode PETSC_DLLEXPORT PetscFListDestroyAll(void)
353 {
354   PetscFList     tmp2,tmp1 = dlallhead;
355   PetscErrorCode ierr;
356 
357   PetscFunctionBegin;
358   while (tmp1) {
359     tmp2 = tmp1->next_list;
360     ierr = PetscFListDestroy(&tmp1);CHKERRQ(ierr);
361     tmp1 = tmp2;
362   }
363   dlallhead = 0;
364   PetscFunctionReturn(0);
365 }
366 
367 #undef __FUNCT__
368 #define __FUNCT__ "PetscFListFind"
369 /*@C
370     PetscFListFind - Given a name, finds the matching routine.
371 
372     Input Parameters:
373 +   comm - processors looking for routine
374 .   fl   - pointer to list
375 -   name - name string
376 
377     Output Parameters:
378 .   r - the routine
379 
380     Level: developer
381 
382 .seealso: PetscFListAddDynamic(), PetscFList
383 @*/
384 PetscErrorCode PETSC_DLLEXPORT PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
385 {
386   PetscFList     entry = fl;
387   PetscErrorCode ierr;
388   char           *function,*path;
389 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
390   char           *newpath;
391 #endif
392   PetscTruth   flg,f1,f2,f3;
393 
394   PetscFunctionBegin;
395   if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
396 
397   *r = 0;
398   ierr = PetscFListGetPathAndFunction(name,&path,&function);CHKERRQ(ierr);
399 
400   /*
401         If path then append it to search libraries
402   */
403 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
404   if (path) {
405     ierr = PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);CHKERRQ(ierr);
406   }
407 #endif
408 
409   while (entry) {
410     flg = PETSC_FALSE;
411     if (path && entry->path) {
412       ierr = PetscStrcmp(path,entry->path,&f1);CHKERRQ(ierr);
413       ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr);
414       ierr = PetscStrcmp(function,entry->name,&f3);CHKERRQ(ierr);
415       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
416     } else if (!path) {
417       ierr = PetscStrcmp(function,entry->name,&f1);CHKERRQ(ierr);
418       ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr);
419       flg =  (PetscTruth) (f1 || f2);
420     } else {
421       ierr = PetscStrcmp(function,entry->name,&flg);CHKERRQ(ierr);
422       if (flg) {
423         ierr = PetscFree(function);CHKERRQ(ierr);
424         ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr);
425       } else {
426         ierr = PetscStrcmp(function,entry->rname,&flg);CHKERRQ(ierr);
427       }
428     }
429 
430     if (flg) {
431 
432       if (entry->routine) {
433         *r   = entry->routine;
434         ierr = PetscStrfree(path);CHKERRQ(ierr);
435         ierr = PetscFree(function);CHKERRQ(ierr);
436         PetscFunctionReturn(0);
437       }
438 
439       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
440         ierr = PetscFree(function);CHKERRQ(ierr);
441         ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr);
442       }
443 
444       /* it is not yet in memory so load from dynamic library */
445 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
446       newpath = path;
447       if (!path) newpath = entry->path;
448       ierr = PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);CHKERRQ(ierr);
449       if (*r) {
450         entry->routine = *r;
451         ierr = PetscStrfree(path);CHKERRQ(ierr);
452         ierr = PetscFree(function);CHKERRQ(ierr);
453         PetscFunctionReturn(0);
454       } else {
455         PetscErrorPrintf("Unable to find function. Search path:\n");
456         ierr = PetscDLLibraryPrintPath();CHKERRQ(ierr);
457         SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
458       }
459 #endif
460     }
461     entry = entry->next;
462   }
463 
464 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
465   /* Function never registered; try for it anyway */
466   ierr = PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);CHKERRQ(ierr);
467   ierr = PetscStrfree(path);CHKERRQ(ierr);
468   if (*r) {
469     ierr = PetscFListAdd(&fl,name,name,*r);CHKERRQ(ierr);
470   }
471 #endif
472   ierr = PetscFree(function);CHKERRQ(ierr);
473   PetscFunctionReturn(0);
474 }
475 
476 #undef __FUNCT__
477 #define __FUNCT__ "PetscFListView"
478 /*@
479    PetscFListView - prints out contents of an PetscFList
480 
481    Collective over MPI_Comm
482 
483    Input Parameters:
484 +  list - the list of functions
485 -  viewer - currently ignored
486 
487    Level: developer
488 
489 .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
490 @*/
491 PetscErrorCode PETSC_DLLEXPORT PetscFListView(PetscFList list,PetscViewer viewer)
492 {
493   PetscErrorCode ierr;
494   PetscTruth     iascii;
495 
496   PetscFunctionBegin;
497   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
498   PetscValidPointer(list,1);
499   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
500 
501   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
502   if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");
503 
504   while (list) {
505     if (list->path) {
506       ierr = PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);CHKERRQ(ierr);
507     } else {
508       ierr = PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);CHKERRQ(ierr);
509     }
510     list = list->next;
511   }
512   ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
513   PetscFunctionReturn(0);
514 }
515 
516 #undef __FUNCT__
517 #define __FUNCT__ "PetscFListGet"
518 /*@
519    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
520          by help etc.
521 
522    Collective over MPI_Comm
523 
524    Input Parameter:
525 .  list   - list of types
526 
527    Output Parameter:
528 +  array - array of names
529 -  n - length of array
530 
531    Notes:
532        This allocates the array so that must be freed. BUT the individual entries are
533     not copied so should not be freed.
534 
535    Level: developer
536 
537 .seealso: PetscFListAddDynamic(), PetscFList
538 @*/
539 PetscErrorCode PETSC_DLLEXPORT PetscFListGet(PetscFList list,char ***array,int *n)
540 {
541   PetscErrorCode ierr;
542   PetscInt       count = 0;
543   PetscFList     klist = list;
544 
545   PetscFunctionBegin;
546   while (list) {
547     list = list->next;
548     count++;
549   }
550   ierr  = PetscMalloc((count+1)*sizeof(char *),array);CHKERRQ(ierr);
551   count = 0;
552   while (klist) {
553     (*array)[count] = klist->name;
554     klist = klist->next;
555     count++;
556   }
557   (*array)[count] = 0;
558   *n = count+1;
559 
560   PetscFunctionReturn(0);
561 }
562 
563 
564 #undef __FUNCT__
565 #define __FUNCT__ "PetscFListPrintTypes"
566 /*@C
567    PetscFListPrintTypes - Prints the methods available.
568 
569    Collective over MPI_Comm
570 
571    Input Parameters:
572 +  comm   - the communicator (usually MPI_COMM_WORLD)
573 .  fd     - file to print to, usually stdout
574 .  prefix - prefix to prepend to name (optional)
575 .  name   - option string (for example, "-ksp_type")
576 .  text - short description of the object (for example, "Krylov solvers")
577 .  man - name of manual page that discusses the object (for example, "KSPCreate")
578 -  list   - list of types
579 
580    Level: developer
581 
582 .seealso: PetscFListAddDynamic(), PetscFList
583 @*/
584 PetscErrorCode PETSC_DLLEXPORT PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
585 {
586   PetscErrorCode ierr;
587   PetscInt       count = 0;
588   char           p[64];
589 
590   PetscFunctionBegin;
591   if (!fd) fd = stdout;
592 
593   ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
594   if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);}
595   ierr = PetscFPrintf(comm,fd,"  %s%s %s:(one of)",p,name+1,text);CHKERRQ(ierr);
596 
597   while (list) {
598     ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr);
599     list = list->next;
600     count++;
601     if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n     ");CHKERRQ(ierr);}
602   }
603   ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr);
604   PetscFunctionReturn(0);
605 }
606 
607 #undef __FUNCT__
608 #define __FUNCT__ "PetscFListDuplicate"
609 /*@
610     PetscFListDuplicate - Creates a new list from a given object list.
611 
612     Input Parameters:
613 .   fl   - pointer to list
614 
615     Output Parameters:
616 .   nl - the new list (should point to 0 to start, otherwise appends)
617 
618     Level: developer
619 
620 .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
621 
622 @*/
623 PetscErrorCode PETSC_DLLEXPORT PetscFListDuplicate(PetscFList fl,PetscFList *nl)
624 {
625   PetscErrorCode ierr;
626   char           path[PETSC_MAX_PATH_LEN];
627 
628   PetscFunctionBegin;
629   while (fl) {
630     /* this is silly, rebuild the complete pathname */
631     if (fl->path) {
632       ierr = PetscStrcpy(path,fl->path);CHKERRQ(ierr);
633       ierr = PetscStrcat(path,":");CHKERRQ(ierr);
634       ierr = PetscStrcat(path,fl->name);CHKERRQ(ierr);
635     } else {
636       ierr = PetscStrcpy(path,fl->name);CHKERRQ(ierr);
637     }
638     ierr = PetscFListAdd(nl,path,fl->rname,fl->routine);CHKERRQ(ierr);
639     fl   = fl->next;
640   }
641   PetscFunctionReturn(0);
642 }
643 
644 
645 #undef __FUNCT__
646 #define __FUNCT__ "PetscFListConcat"
647 /*
648     PetscFListConcat - joins name of a libary, and the path where it is located
649     into a single string.
650 
651     Input Parameters:
652 .   path   - path to the library name.
653 .   name   - name of the library
654 
655     Output Parameters:
656 .   fullname - the name that is the union of the path and the library name,
657                delimited by a semicolon, i.e., path:name
658 
659     Notes:
660     If the path is NULL, assumes that the name, specified also includes
661     the path as path:name
662 
663 */
664 PetscErrorCode PETSC_DLLEXPORT PetscFListConcat(const char path[],const char name[],char fullname[])
665 {
666   PetscErrorCode ierr;
667   PetscFunctionBegin;
668   if (path) {
669     ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr);
670     ierr = PetscStrcat(fullname,":");CHKERRQ(ierr);
671     ierr = PetscStrcat(fullname,name);CHKERRQ(ierr);
672   } else {
673     ierr = PetscStrcpy(fullname,name);CHKERRQ(ierr);
674   }
675   PetscFunctionReturn(0);
676 }
677