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: }