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