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