xref: /petsc/src/sys/dll/reg.c (revision a58c3bc3391eee32bc3fd94ac7edeea38fe57aae)
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 PetscDLLibrary 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   CHKMEMQ;
311   if (!*fl) PetscFunctionReturn(0);
312 
313   if (!dlallhead) {
314     PetscFunctionReturn(0);
315   }
316 
317   /*
318        Remove this entry from the master DL list (if it is in it)
319   */
320   if (dlallhead == *fl) {
321     if (dlallhead->next_list) {
322       dlallhead = dlallhead->next_list;
323     } else {
324       dlallhead = 0;
325     }
326   } else {
327     while (tmp->next_list != *fl) {
328       tmp = tmp->next_list;
329       if (!tmp->next_list) break;
330     }
331     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
332   }
333 
334   /* free this list */
335   entry = *fl;
336   while (entry) {
337     next = entry->next;
338     ierr = PetscStrfree(entry->path);CHKERRQ(ierr);
339     ierr = PetscFree(entry->name);CHKERRQ(ierr);
340     ierr = PetscFree(entry->rname);CHKERRQ(ierr);
341     ierr = PetscFree(entry);CHKERRQ(ierr);
342     entry = next;
343   }
344   *fl = 0;
345   PetscFunctionReturn(0);
346 }
347 
348 /*
349    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
350 */
351 #undef __FUNCT__
352 #define __FUNCT__ "PetscFListDestroyAll"
353 PetscErrorCode PETSC_DLLEXPORT PetscFListDestroyAll(void)
354 {
355   PetscFList     tmp2,tmp1 = dlallhead;
356   PetscErrorCode ierr;
357 
358   PetscFunctionBegin;
359   while (tmp1) {
360     tmp2 = tmp1->next_list;
361     ierr = PetscFListDestroy(&tmp1);CHKERRQ(ierr);
362     tmp1 = tmp2;
363   }
364   dlallhead = 0;
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "PetscFListFind"
370 /*@C
371     PetscFListFind - Given a name, finds the matching routine.
372 
373     Input Parameters:
374 +   comm - processors looking for routine
375 .   fl   - pointer to list
376 -   name - name string
377 
378     Output Parameters:
379 .   r - the routine
380 
381     Level: developer
382 
383 .seealso: PetscFListAddDynamic(), PetscFList
384 @*/
385 PetscErrorCode PETSC_DLLEXPORT PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
386 {
387   PetscFList     entry = fl;
388   PetscErrorCode ierr;
389   char           *function,*path;
390 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
391   char           *newpath;
392 #endif
393   PetscTruth   flg,f1,f2,f3;
394 
395   PetscFunctionBegin;
396   if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
397 
398   *r = 0;
399   ierr = PetscFListGetPathAndFunction(name,&path,&function);CHKERRQ(ierr);
400 
401   /*
402         If path then append it to search libraries
403   */
404 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
405   if (path) {
406     ierr = PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);CHKERRQ(ierr);
407   }
408 #endif
409 
410   while (entry) {
411     flg = PETSC_FALSE;
412     if (path && entry->path) {
413       ierr = PetscStrcmp(path,entry->path,&f1);CHKERRQ(ierr);
414       ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr);
415       ierr = PetscStrcmp(function,entry->name,&f3);CHKERRQ(ierr);
416       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
417     } else if (!path) {
418       ierr = PetscStrcmp(function,entry->name,&f1);CHKERRQ(ierr);
419       ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr);
420       flg =  (PetscTruth) (f1 || f2);
421     } else {
422       ierr = PetscStrcmp(function,entry->name,&flg);CHKERRQ(ierr);
423       if (flg) {
424         ierr = PetscFree(function);CHKERRQ(ierr);
425         ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr);
426       } else {
427         ierr = PetscStrcmp(function,entry->rname,&flg);CHKERRQ(ierr);
428       }
429     }
430 
431     if (flg) {
432 
433       if (entry->routine) {
434         *r   = entry->routine;
435         ierr = PetscStrfree(path);CHKERRQ(ierr);
436         ierr = PetscFree(function);CHKERRQ(ierr);
437         PetscFunctionReturn(0);
438       }
439 
440       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
441         ierr = PetscFree(function);CHKERRQ(ierr);
442         ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr);
443       }
444 
445       /* it is not yet in memory so load from dynamic library */
446 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
447       newpath = path;
448       if (!path) newpath = entry->path;
449       ierr = PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);CHKERRQ(ierr);
450       if (*r) {
451         entry->routine = *r;
452         ierr = PetscStrfree(path);CHKERRQ(ierr);
453         ierr = PetscFree(function);CHKERRQ(ierr);
454         PetscFunctionReturn(0);
455       } else {
456         PetscErrorPrintf("Unable to find function. Search path:\n");
457         ierr = PetscDLLibraryPrintPath();CHKERRQ(ierr);
458         SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
459       }
460 #endif
461     }
462     entry = entry->next;
463   }
464 
465 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
466   /* Function never registered; try for it anyway */
467   ierr = PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);CHKERRQ(ierr);
468   ierr = PetscStrfree(path);CHKERRQ(ierr);
469   if (*r) {
470     ierr = PetscFListAdd(&fl,name,name,*r);CHKERRQ(ierr);
471   }
472 #endif
473   ierr = PetscFree(function);CHKERRQ(ierr);
474   PetscFunctionReturn(0);
475 }
476 
477 #undef __FUNCT__
478 #define __FUNCT__ "PetscFListView"
479 /*@
480    PetscFListView - prints out contents of an PetscFList
481 
482    Collective over MPI_Comm
483 
484    Input Parameters:
485 +  list - the list of functions
486 -  viewer - currently ignored
487 
488    Level: developer
489 
490 .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
491 @*/
492 PetscErrorCode PETSC_DLLEXPORT PetscFListView(PetscFList list,PetscViewer viewer)
493 {
494   PetscErrorCode ierr;
495   PetscTruth     iascii;
496 
497   PetscFunctionBegin;
498   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
499   PetscValidPointer(list,1);
500   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
501 
502   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
503   if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");
504 
505   while (list) {
506     if (list->path) {
507       ierr = PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);CHKERRQ(ierr);
508     } else {
509       ierr = PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);CHKERRQ(ierr);
510     }
511     list = list->next;
512   }
513   ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
514   PetscFunctionReturn(0);
515 }
516 
517 #undef __FUNCT__
518 #define __FUNCT__ "PetscFListGet"
519 /*@
520    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
521          by help etc.
522 
523    Collective over MPI_Comm
524 
525    Input Parameter:
526 .  list   - list of types
527 
528    Output Parameter:
529 +  array - array of names
530 -  n - length of array
531 
532    Notes:
533        This allocates the array so that must be freed. BUT the individual entries are
534     not copied so should not be freed.
535 
536    Level: developer
537 
538 .seealso: PetscFListAddDynamic(), PetscFList
539 @*/
540 PetscErrorCode PETSC_DLLEXPORT PetscFListGet(PetscFList list,char ***array,int *n)
541 {
542   PetscErrorCode ierr;
543   PetscInt       count = 0;
544   PetscFList     klist = list;
545 
546   PetscFunctionBegin;
547   while (list) {
548     list = list->next;
549     count++;
550   }
551   ierr  = PetscMalloc((count+1)*sizeof(char *),array);CHKERRQ(ierr);
552   count = 0;
553   while (klist) {
554     (*array)[count] = klist->name;
555     klist = klist->next;
556     count++;
557   }
558   (*array)[count] = 0;
559   *n = count+1;
560 
561   PetscFunctionReturn(0);
562 }
563 
564 
565 #undef __FUNCT__
566 #define __FUNCT__ "PetscFListPrintTypes"
567 /*@C
568    PetscFListPrintTypes - Prints the methods available.
569 
570    Collective over MPI_Comm
571 
572    Input Parameters:
573 +  comm   - the communicator (usually MPI_COMM_WORLD)
574 .  fd     - file to print to, usually stdout
575 .  prefix - prefix to prepend to name (optional)
576 .  name   - option string (for example, "-ksp_type")
577 .  text - short description of the object (for example, "Krylov solvers")
578 .  man - name of manual page that discusses the object (for example, "KSPCreate")
579 -  list   - list of types
580 
581    Level: developer
582 
583 .seealso: PetscFListAddDynamic(), PetscFList
584 @*/
585 PetscErrorCode PETSC_DLLEXPORT PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
586 {
587   PetscErrorCode ierr;
588   PetscInt       count = 0;
589   char           p[64];
590 
591   PetscFunctionBegin;
592   if (!fd) fd = stdout;
593 
594   ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
595   if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);}
596   ierr = PetscFPrintf(comm,fd,"  %s%s %s:(one of)",p,name+1,text);CHKERRQ(ierr);
597 
598   while (list) {
599     ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr);
600     list = list->next;
601     count++;
602     if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n     ");CHKERRQ(ierr);}
603   }
604   ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr);
605   PetscFunctionReturn(0);
606 }
607 
608 #undef __FUNCT__
609 #define __FUNCT__ "PetscFListDuplicate"
610 /*@
611     PetscFListDuplicate - Creates a new list from a given object list.
612 
613     Input Parameters:
614 .   fl   - pointer to list
615 
616     Output Parameters:
617 .   nl - the new list (should point to 0 to start, otherwise appends)
618 
619     Level: developer
620 
621 .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
622 
623 @*/
624 PetscErrorCode PETSC_DLLEXPORT PetscFListDuplicate(PetscFList fl,PetscFList *nl)
625 {
626   PetscErrorCode ierr;
627   char           path[PETSC_MAX_PATH_LEN];
628 
629   PetscFunctionBegin;
630   while (fl) {
631     /* this is silly, rebuild the complete pathname */
632     if (fl->path) {
633       ierr = PetscStrcpy(path,fl->path);CHKERRQ(ierr);
634       ierr = PetscStrcat(path,":");CHKERRQ(ierr);
635       ierr = PetscStrcat(path,fl->name);CHKERRQ(ierr);
636     } else {
637       ierr = PetscStrcpy(path,fl->name);CHKERRQ(ierr);
638     }
639     ierr = PetscFListAdd(nl,path,fl->rname,fl->routine);CHKERRQ(ierr);
640     fl   = fl->next;
641   }
642   PetscFunctionReturn(0);
643 }
644 
645 
646 #undef __FUNCT__
647 #define __FUNCT__ "PetscFListConcat"
648 /*
649     PetscFListConcat - joins name of a libary, and the path where it is located
650     into a single string.
651 
652     Input Parameters:
653 .   path   - path to the library name.
654 .   name   - name of the library
655 
656     Output Parameters:
657 .   fullname - the name that is the union of the path and the library name,
658                delimited by a semicolon, i.e., path:name
659 
660     Notes:
661     If the path is NULL, assumes that the name, specified also includes
662     the path as path:name
663 
664 */
665 PetscErrorCode PETSC_DLLEXPORT PetscFListConcat(const char path[],const char name[],char fullname[])
666 {
667   PetscErrorCode ierr;
668   PetscFunctionBegin;
669   if (path) {
670     ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr);
671     ierr = PetscStrcat(fullname,":");CHKERRQ(ierr);
672     ierr = PetscStrcat(fullname,name);CHKERRQ(ierr);
673   } else {
674     ierr = PetscStrcpy(fullname,name);CHKERRQ(ierr);
675   }
676   PetscFunctionReturn(0);
677 }
678