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