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