Actual source code: reg.c
1: /*$Id: reg.c,v 1.70 2001/04/10 19:34:28 bsmith Exp bsmith $*/
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
7: #include petscsys.h
9: int PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
10: {
11: char work[256],*lfunction,ierr;
14: PetscStrncpy(work,name,256);
15: PetscStrrchr(work,':',&lfunction);
16: if (lfunction != work) {
17: lfunction[-1] = 0;
18: PetscStrallocpy(work,path);
19: } else {
20: *path = 0;
21: }
22: PetscStrallocpy(lfunction,function);
23: return(0);
24: }
26: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
28: /*
29: This is the list used by the DLRegister routines
30: */
31: PetscDLLibraryList DLLibrariesLoaded = 0;
33: /*
34: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
35: search path.
36: */
37: int PetscInitialize_DynamicLibraries(void)
38: {
39: char *libname[32],libs[256],dlib[1024];
40: int nmax,i,ierr;
41: PetscTruth found;
45: nmax = 32;
46: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
47: for (i=0; i<nmax; i++) {
48: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
49: PetscFree(libname[i]);
50: }
52: PetscStrcpy(libs,PETSC_LIB_DIR);
53: PetscStrcat(libs,"/libpetsc");
54: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
55: if (found) {
56: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
57: } else {
58: SETERRQ1(1,"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.hn and rebuild libraries before moving",libs);
59: }
61: PetscStrcpy(libs,PETSC_LIB_DIR);
62: PetscStrcat(libs,"/libpetscvec");
63: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
64: if (found) {
65: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
66: }
68: PetscStrcpy(libs,PETSC_LIB_DIR);
69: PetscStrcat(libs,"/libpetscmat");
70: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
71: if (found) {
72: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
73: }
75: PetscStrcpy(libs,PETSC_LIB_DIR);
76: PetscStrcat(libs,"/libpetscdm");
77: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
78: if (found) {
79: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
80: }
82: PetscStrcpy(libs,PETSC_LIB_DIR);
83: PetscStrcat(libs,"/libpetscsles");
84: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
85: if (found) {
86: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
87: }
89: PetscStrcpy(libs,PETSC_LIB_DIR);
90: PetscStrcat(libs,"/libpetscsnes");
91: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
92: if (found) {
93: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
94: }
96: PetscStrcpy(libs,PETSC_LIB_DIR);
97: PetscStrcat(libs,"/libpetscts");
98: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
99: if (found) {
100: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
101: }
103: nmax = 32;
104: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
105: for (i=0; i<nmax; i++) {
106: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
107: PetscFree(libname[i]);
108: }
110: return(0);
111: }
113: /*
114: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
115: */
116: int PetscFinalize_DynamicLibraries(void)
117: {
121: PetscDLLibraryClose(DLLibrariesLoaded);
122: return(0);
123: }
125: #else /* not using dynamic libraries */
127: EXTERN int PetscDLLibraryRegister_Petsc(char *);
129: int PetscInitialize_DynamicLibraries(void)
130: {
134: /*
135: This just initializes the draw and viewer methods, since those
136: are ALWAYS available. The other classes are initialized the first
137: time an XXSetType() is called.
138: */
139: PetscDLLibraryRegister_Petsc(PETSC_NULL);
140: return(0);
141: }
142: int PetscFinalize_DynamicLibraries(void)
143: {
146: return(0);
147: }
148: #endif
150: /* ------------------------------------------------------------------------------*/
151: struct _PetscFList {
152: void (*routine)(); /* the routine */
153: char *path; /* path of link library containing routine */
154: char *name; /* string to identify routine */
155: char *rname; /* routine name in dynamic library */
156: PetscFList next; /* next pointer */
157: PetscFList next_list; /* used to maintain list of all lists for freeing */
158: };
160: /*
161: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
162: */
163: static PetscFList dlallhead = 0;
165: /*@C
166: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
167: specified registry.
169: Synopsis:
170: int PetscFListAddDynamic(PetscFList *fl,char *name,char *rname,int (*fnc)(void *))
172: Input Parameters:
173: + fl - pointer registry
174: . name - string to identify routine
175: . rname - routine name in dynamic library
176: - fnc - function pointer (optional if using dynamic libraries)
178: Notes:
179: Users who wish to register new methods for use by a particular PETSc
180: component (e.g., SNES) should generally call the registration routine
181: for that particular component (e.g., SNESRegisterDynamic()) instead of
182: calling PetscFListAddDynamic() directly.
184: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
185: occuring in pathname will be replaced with appropriate values.
187: Level: developer
189: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
190: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
191: @*/
192: int PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)())
193: {
194: PetscFList entry,ne;
195: int ierr;
196: char *fpath,*fname;
200: if (!*fl) {
201: ierr = PetscNew(struct _PetscFList,&entry);
202: ierr = PetscStrallocpy(name,&entry->name);
203: PetscFListGetPathAndFunction(rname,&fpath,&fname);
204: entry->path = fpath;
205: entry->rname = fname;
206: entry->routine = fnc;
207: entry->next = 0;
208: *fl = entry;
210: /* add this new list to list of all lists */
211: if (!dlallhead) {
212: dlallhead = *fl;
213: (*fl)->next_list = 0;
214: } else {
215: ne = dlallhead;
216: dlallhead = *fl;
217: (*fl)->next_list = ne;
218: }
219: } else {
220: /* search list to see if it is already there */
221: ne = *fl;
222: while (ne) {
223: PetscTruth founddup;
225: PetscStrcmp(ne->name,name,&founddup);
226: if (founddup) { /* found duplicate */
227: PetscFListGetPathAndFunction(rname,&fpath,&fname);
228: PetscStrfree(ne->path);
229: PetscStrfree(ne->rname);
230: ne->path = fpath;
231: ne->rname = fname;
232: ne->routine = fnc;
233: return(0);
234: }
235: if (ne->next) ne = ne->next; else break;
236: }
237: /* create new entry and add to end of list */
238: ierr = PetscNew(struct _PetscFList,&entry);
239: ierr = PetscStrallocpy(name,&entry->name);
240: ierr = PetscFListGetPathAndFunction(rname,&fpath,&fname);
241: entry->path = fpath;
242: entry->rname = fname;
243: entry->routine = fnc;
244: entry->next = 0;
245: ne->next = entry;
246: }
248: return(0);
249: }
251: /*@
252: PetscFListDestroy - Destroys a list of registered routines.
254: Input Parameter:
255: . fl - pointer to list
257: Level: developer
259: .seealso: PetscFListAddDynamic(), PetscFList
260: @*/
261: int PetscFListDestroy(PetscFList *fl)
262: {
263: PetscFList next,entry,tmp = dlallhead;
264: int ierr;
267: if (!*fl) return(0);
269: if (!dlallhead) {
270: return(0);
271: }
273: /*
274: Remove this entry from the master DL list (if it is in it)
275: */
276: if (dlallhead == *fl) {
277: if (dlallhead->next_list) {
278: dlallhead = dlallhead->next_list;
279: } else {
280: dlallhead = 0;
281: }
282: } else {
283: while (tmp->next_list != *fl) {
284: tmp = tmp->next_list;
285: if (!tmp->next_list) break;
286: }
287: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
288: }
290: /* free this list */
291: entry = *fl;
292: while (entry) {
293: next = entry->next;
294: PetscStrfree(entry->path);
295: PetscFree(entry->name);
296: PetscFree(entry->rname);
297: PetscFree(entry);
298: entry = next;
299: }
300: *fl = 0;
301: return(0);
302: }
304: /*
305: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
306: */
307: int PetscFListDestroyAll(void)
308: {
309: PetscFList tmp2,tmp1 = dlallhead;
310: int ierr;
313: while (tmp1) {
314: tmp2 = tmp1->next_list;
315: PetscFListDestroy(&tmp1);
316: tmp1 = tmp2;
317: }
318: dlallhead = 0;
319: return(0);
320: }
322: /*@
323: PetscFListFind - Given a name, finds the matching routine.
325: Input Parameters:
326: + comm - processors looking for routine
327: . fl - pointer to list
328: - name - name string
330: Output Parameters:
331: . r - the routine
333: Notes:
334: The routine id or name MUST have been registered with the PetscFList via
335: PetscFListAddDynamic() before PetscFListFind() can be called.
337: Level: developer
339: .seealso: PetscFListAddDynamic(), PetscFList
340: @*/
341: int PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)())
342: {
343: PetscFList entry = fl;
344: int ierr;
345: char *function,*path;
346: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
347: char *newpath;
348: #endif
349: PetscTruth flg,f1,f2,f3;
350:
352: if (!name) SETERRQ(1,"Trying to find routine with null name");
354: *r = 0;
355: PetscFListGetPathAndFunction(name,&path,&function);
357: /*
358: If path then append it to search libraries
359: */
360: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
361: if (path) {
362: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
363: }
364: #endif
366: while (entry) {
367: flg = PETSC_FALSE;
368: if (path && entry->path) {
369: PetscStrcmp(path,entry->path,&f1);
370: PetscStrcmp(function,entry->rname,&f2);
371: PetscStrcmp(function,entry->name,&f3);
372: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
373: } else if (!path) {
374: PetscStrcmp(function,entry->name,&f1);
375: PetscStrcmp(function,entry->rname,&f2);
376: flg = (PetscTruth) (f1 || f2);
377: }
379: if (flg) {
381: if (entry->routine) {
382: *r = entry->routine;
383: PetscStrfree(path);
384: PetscFree(function);
385: return(0);
386: }
388: /* it is not yet in memory so load from dynamic library */
389: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
390: newpath = path;
391: if (!path) newpath = entry->path;
392: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
393: if (*r) {
394: entry->routine = *r;
395: PetscStrfree(path);
396: PetscFree(function);
397: return(0);
398: } else {
399: PetscDLLibraryPrintPath();
400: SETERRQ1(1,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
401: }
402: #endif
403: }
404: entry = entry->next;
405: }
407: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
408: /* Function never registered; try for it anyway */
409: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
410: PetscStrfree(path);
411: if (*r) {
412: PetscFListAddDynamic(&fl,name,name,r);
413: PetscFree(function);
414: return(0);
415: }
416: #endif
418: /*
419: Do not generate error, just end
420: PetscErrorPrintf("Function name: %sn",function);
421: PetscDLLibraryPrintPath();
422: SETERRQ(1,"Unable to find function: either it is mis-spelled or dynamic library is not in path");
423: */
425: PetscFree(function);
426: return(0);
427: }
429: /*@
430: PetscFListView - prints out contents of an PetscFList
432: Collective over MPI_Comm
434: Input Parameters:
435: + list - the list of functions
436: - viewer - currently ignored
438: Level: developer
440: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
441: @*/
442: int PetscFListView(PetscFList list,PetscViewer viewer)
443: {
444: int ierr;
445: PetscTruth isascii;
448: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
451:
452: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
453: if (!isascii) SETERRQ(1,"Only ASCII viewer supported");
455: while (list) {
456: if (list->path) {
457: PetscViewerASCIIPrintf(viewer," %s %s %sn",list->path,list->name,list->rname);
458: } else {
459: PetscViewerASCIIPrintf(viewer," %s %sn",list->name,list->rname);
460: }
461: list = list->next;
462: }
463: PetscViewerASCIIPrintf(viewer,"n");
464: return(0);
465: }
467: /*@
468: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
469: by help etc.
471: Collective over MPI_Comm
473: Input Parameter:
474: . list - list of types
476: Output Parameter:
477: + array - array of names
478: - n - length of array
480: Notes:
481: This allocates the array so that must be freed. BUT the individual entries are
482: not copied so should not be freed.
484: Level: developer
486: .seealso: PetscFListAddDynamic(), PetscFList
487: @*/
488: int PetscFListGet(PetscFList list,char ***array,int *n)
489: {
490: int count = 0,ierr;
491: PetscFList klist = list;
494: while (list) {
495: list = list->next;
496: count++;
497: }
498: ierr = PetscMalloc((count+1)*sizeof(char *),array);
499: count = 0;
500: while (klist) {
501: (*array)[count] = klist->name;
502: klist = klist->next;
503: count++;
504: }
505: (*array)[count] = 0;
506: *n = count+1;
508: return(0);
509: }
512: /*@
513: PetscFListPrintTypes - Prints the methods available.
515: Collective over MPI_Comm
517: Input Parameters:
518: + comm - the communicator (usually MPI_COMM_WORLD)
519: . fd - file to print to, usually stdout
520: . prefix - prefix to prepend to name (optional)
521: . name - option string
522: - list - list of types
524: Level: developer
526: .seealso: PetscFListAddDynamic(), PetscFList
527: @*/
528: int PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],char *text,char *man,PetscFList list)
529: {
530: int ierr,count = 0;
531: char p[64];
534: if (!fd) fd = stdout;
536: PetscStrcpy(p,"-");
537: if (prefix) {PetscStrcat(p,prefix);}
538: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name,text);
540: while (list) {
541: PetscFPrintf(comm,fd," %s",list->name);
542: list = list->next;
543: count++;
544: if (count == 8) {PetscFPrintf(comm,fd,"n ");}
545: }
546: PetscFPrintf(comm,fd,"%sn",man);
547: return(0);
548: }
550: /*@
551: PetscFListDuplicate - Creates a new list from a given object list.
553: Input Parameters:
554: . fl - pointer to list
556: Output Parameters:
557: . nl - the new list (should point to 0 to start, otherwise appends)
559: Level: developer
561: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
563: @*/
564: int PetscFListDuplicate(PetscFList fl,PetscFList *nl)
565: {
566: int ierr;
567: char path[1024];
570: while (fl) {
571: /* this is silly, rebuild the complete pathname */
572: if (fl->path) {
573: PetscStrcpy(path,fl->path);
574: PetscStrcat(path,":");
575: PetscStrcat(path,fl->name);
576: } else {
577: PetscStrcpy(path,fl->name);
578: }
579: PetscFListAddDynamic(nl,path,fl->rname,fl->routine);
580: fl = fl->next;
581: }
582: return(0);
583: }
586: /*
587: PetscFListConcat - joins name of a libary, and the path where it is located
588: into a single string.
590: Input Parameters:
591: . path - path to the library name.
592: . name - name of the library
594: Output Parameters:
595: . fullname - the name that is the union of the path and the library name,
596: delimited by a semicolon, i.e., path:name
598: Notes:
599: If the path is NULL, assumes that the name, specified also includes
600: the path as path:name
602: */
603: int PetscFListConcat(const char path[],const char name[],char fullname[])
604: {
607: if (path) {
608: PetscStrcpy(fullname,path);
609: PetscStrcat(fullname,":");
610: PetscStrcat(fullname,name);
611: } else {
612: PetscStrcpy(fullname,name);
613: }
614: return(0);
615: }