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