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 list used by the DLRegister 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 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 Vec 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 Mat 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 DM 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 KSP 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 SNES 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 TS 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 #else /* not using dynamic libraries */ 112 113 #undef __FUNCT__ 114 #define __FUNCT__ "PetscInitalize_DynamicLibraries" 115 PetscErrorCode PETSC_DLLEXPORT PetscInitialize_DynamicLibraries(void) 116 { 117 PetscErrorCode ierr; 118 119 PetscFunctionBegin; 120 /* 121 This just initializes the most basic PETSc stuff. 122 123 The classes, from PetscDraw to PetscTS, are initialized the first 124 time an XXCreate() is called. 125 */ 126 ierr = PetscInitializePackage(PETSC_NULL);CHKERRQ(ierr); 127 PetscFunctionReturn(0); 128 } 129 130 #endif 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 PetscTruth flg; 141 142 PetscFunctionBegin; 143 ierr = PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);CHKERRQ(ierr); 144 if (flg) { ierr = PetscDLLibraryPrintPath(DLLibrariesLoaded);CHKERRQ(ierr); } 145 ierr = PetscDLLibraryClose(DLLibrariesLoaded);CHKERRQ(ierr); 146 PetscFunctionReturn(0); 147 } 148 149 /* ------------------------------------------------------------------------------*/ 150 struct _n_PetscFList { 151 void (*routine)(void); /* the routine */ 152 char *path; /* path of link library containing routine */ 153 char *name; /* string to identify routine */ 154 char *rname; /* routine name in dynamic library */ 155 PetscFList next; /* next pointer */ 156 PetscFList next_list; /* used to maintain list of all lists for freeing */ 157 }; 158 159 /* 160 Keep a linked list of PetscFLists so that we can destroy all the left-over ones. 161 */ 162 static PetscFList dlallhead = 0; 163 164 #undef __FUNCT__ 165 #define __FUNCT__ "PetscFListAdd" 166 /*@C 167 PetscFListAddDynamic - Given a routine and a string id, saves that routine in the 168 specified registry. 169 170 Not Collective 171 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) 177 178 Notes: 179 To remove a registered routine, pass in a PETSC_NULL rname and fnc(). 180 181 Users who wish to register new classes for use by a particular PETSc 182 component (e.g., SNES) should generally call the registration routine 183 for that particular component (e.g., SNESRegisterDynamic()) instead of 184 calling PetscFListAddDynamic() directly. 185 186 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 187 occuring in pathname will be replaced with appropriate values. 188 189 Level: developer 190 191 .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(), 192 PCRegisterDynamic(), TSRegisterDynamic(), PetscFList 193 @*/ 194 PetscErrorCode PETSC_DLLEXPORT PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void)) 195 { 196 PetscFList entry,ne; 197 PetscErrorCode ierr; 198 char *fpath,*fname; 199 200 PetscFunctionBegin; 201 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 PetscTruth 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 = PetscStrfree(ne->path);CHKERRQ(ierr); 231 ierr = PetscStrfree(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 250 PetscFunctionReturn(0); 251 } 252 253 #undef __FUNCT__ 254 #define __FUNCT__ "PetscFListDestroy" 255 /*@ 256 PetscFListDestroy - Destroys a list of registered routines. 257 258 Input Parameter: 259 . fl - pointer to list 260 261 Level: developer 262 263 .seealso: PetscFListAddDynamic(), PetscFList 264 @*/ 265 PetscErrorCode PETSC_DLLEXPORT PetscFListDestroy(PetscFList *fl) 266 { 267 PetscFList next,entry,tmp = dlallhead; 268 PetscErrorCode ierr; 269 270 PetscFunctionBegin; 271 CHKMEMQ; 272 if (!*fl) PetscFunctionReturn(0); 273 274 if (!dlallhead) { 275 PetscFunctionReturn(0); 276 } 277 278 /* 279 Remove this entry from the master DL list (if it is in it) 280 */ 281 if (dlallhead == *fl) { 282 if (dlallhead->next_list) { 283 dlallhead = dlallhead->next_list; 284 } else { 285 dlallhead = 0; 286 } 287 } else { 288 while (tmp->next_list != *fl) { 289 tmp = tmp->next_list; 290 if (!tmp->next_list) break; 291 } 292 if (tmp->next_list) tmp->next_list = tmp->next_list->next_list; 293 } 294 295 /* free this list */ 296 entry = *fl; 297 while (entry) { 298 next = entry->next; 299 ierr = PetscStrfree(entry->path);CHKERRQ(ierr); 300 ierr = PetscFree(entry->name);CHKERRQ(ierr); 301 ierr = PetscFree(entry->rname);CHKERRQ(ierr); 302 ierr = PetscFree(entry);CHKERRQ(ierr); 303 entry = next; 304 } 305 *fl = 0; 306 PetscFunctionReturn(0); 307 } 308 309 /* 310 Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc. 311 */ 312 #undef __FUNCT__ 313 #define __FUNCT__ "PetscFListDestroyAll" 314 PetscErrorCode PETSC_DLLEXPORT PetscFListDestroyAll(void) 315 { 316 PetscFList tmp2,tmp1 = dlallhead; 317 PetscErrorCode ierr; 318 319 PetscFunctionBegin; 320 while (tmp1) { 321 tmp2 = tmp1->next_list; 322 ierr = PetscFListDestroy(&tmp1);CHKERRQ(ierr); 323 tmp1 = tmp2; 324 } 325 dlallhead = 0; 326 PetscFunctionReturn(0); 327 } 328 329 #undef __FUNCT__ 330 #define __FUNCT__ "PetscFListFind" 331 /*@C 332 PetscFListFind - Given a name, finds the matching routine. 333 334 Input Parameters: 335 + fl - pointer to list 336 . comm - processors looking for routine 337 - name - name string 338 339 Output Parameters: 340 . r - the routine 341 342 Level: developer 343 344 .seealso: PetscFListAddDynamic(), PetscFList 345 @*/ 346 PetscErrorCode PETSC_DLLEXPORT PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],void (**r)(void)) 347 { 348 PetscFList entry = fl; 349 PetscErrorCode ierr; 350 char *function,*path; 351 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 352 char *newpath; 353 #endif 354 PetscTruth flg,f1,f2,f3; 355 356 PetscFunctionBegin; 357 if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name"); 358 359 *r = 0; 360 ierr = PetscFListGetPathAndFunction(name,&path,&function);CHKERRQ(ierr); 361 362 /* 363 If path then append it to search libraries 364 */ 365 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 366 if (path) { 367 ierr = PetscDLLibraryAppend(comm,&DLLibrariesLoaded,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 = (PetscTruth) ((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 = (PetscTruth) (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 394 if (entry->routine) { 395 *r = entry->routine; 396 ierr = PetscStrfree(path);CHKERRQ(ierr); 397 ierr = PetscFree(function);CHKERRQ(ierr); 398 PetscFunctionReturn(0); 399 } 400 401 if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */ 402 ierr = PetscFree(function);CHKERRQ(ierr); 403 ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr); 404 } 405 406 /* it is not yet in memory so load from dynamic library */ 407 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 408 newpath = path; 409 if (!path) newpath = entry->path; 410 ierr = PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);CHKERRQ(ierr); 411 if (*r) { 412 entry->routine = *r; 413 ierr = PetscStrfree(path);CHKERRQ(ierr); 414 ierr = PetscFree(function);CHKERRQ(ierr); 415 PetscFunctionReturn(0); 416 } else { 417 PetscErrorPrintf("Unable to find function. Search path:\n"); 418 ierr = PetscDLLibraryPrintPath(DLLibrariesLoaded);CHKERRQ(ierr); 419 SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname); 420 } 421 #endif 422 } 423 entry = entry->next; 424 } 425 426 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 427 /* Function never registered; try for it anyway */ 428 ierr = PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);CHKERRQ(ierr); 429 ierr = PetscStrfree(path);CHKERRQ(ierr); 430 if (*r) { 431 ierr = PetscFListAdd(&fl,name,name,*r);CHKERRQ(ierr); 432 } 433 #endif 434 ierr = PetscFree(function);CHKERRQ(ierr); 435 PetscFunctionReturn(0); 436 } 437 438 #undef __FUNCT__ 439 #define __FUNCT__ "PetscFListView" 440 /*@ 441 PetscFListView - prints out contents of an PetscFList 442 443 Collective over MPI_Comm 444 445 Input Parameters: 446 + list - the list of functions 447 - viewer - currently ignored 448 449 Level: developer 450 451 .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList 452 @*/ 453 PetscErrorCode PETSC_DLLEXPORT PetscFListView(PetscFList list,PetscViewer viewer) 454 { 455 PetscErrorCode ierr; 456 PetscTruth iascii; 457 458 PetscFunctionBegin; 459 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 460 PetscValidPointer(list,1); 461 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2); 462 463 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 464 if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported"); 465 466 while (list) { 467 if (list->path) { 468 ierr = PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);CHKERRQ(ierr); 469 } else { 470 ierr = PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);CHKERRQ(ierr); 471 } 472 list = list->next; 473 } 474 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 475 PetscFunctionReturn(0); 476 } 477 478 #undef __FUNCT__ 479 #define __FUNCT__ "PetscFListGet" 480 /*@ 481 PetscFListGet - Gets an array the contains the entries in PetscFList, this is used 482 by help etc. 483 484 Collective over MPI_Comm 485 486 Input Parameter: 487 . list - list of types 488 489 Output Parameter: 490 + array - array of names 491 - n - length of array 492 493 Notes: 494 This allocates the array so that must be freed. BUT the individual entries are 495 not copied so should not be freed. 496 497 Level: developer 498 499 .seealso: PetscFListAddDynamic(), PetscFList 500 @*/ 501 PetscErrorCode PETSC_DLLEXPORT PetscFListGet(PetscFList list,char ***array,int *n) 502 { 503 PetscErrorCode ierr; 504 PetscInt count = 0; 505 PetscFList klist = list; 506 507 PetscFunctionBegin; 508 while (list) { 509 list = list->next; 510 count++; 511 } 512 ierr = PetscMalloc((count+1)*sizeof(char *),array);CHKERRQ(ierr); 513 count = 0; 514 while (klist) { 515 (*array)[count] = klist->name; 516 klist = klist->next; 517 count++; 518 } 519 (*array)[count] = 0; 520 *n = count+1; 521 522 PetscFunctionReturn(0); 523 } 524 525 526 #undef __FUNCT__ 527 #define __FUNCT__ "PetscFListPrintTypes" 528 /*@C 529 PetscFListPrintTypes - 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 542 Level: developer 543 544 .seealso: PetscFListAddDynamic(), PetscFList 545 @*/ 546 PetscErrorCode PETSC_DLLEXPORT PetscFListPrintTypes(PetscFList list,MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[]) 547 { 548 PetscErrorCode ierr; 549 PetscInt count = 0; 550 char p[64]; 551 552 PetscFunctionBegin; 553 if (!fd) fd = PETSC_STDOUT; 554 555 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 556 if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);} 557 ierr = PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);CHKERRQ(ierr); 558 559 while (list) { 560 ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr); 561 list = list->next; 562 count++; 563 if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n ");CHKERRQ(ierr);} 564 } 565 ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr); 566 PetscFunctionReturn(0); 567 } 568 569 #undef __FUNCT__ 570 #define __FUNCT__ "PetscFListDuplicate" 571 /*@ 572 PetscFListDuplicate - Creates a new list from a given object list. 573 574 Input Parameters: 575 . fl - pointer to list 576 577 Output Parameters: 578 . nl - the new list (should point to 0 to start, otherwise appends) 579 580 Level: developer 581 582 .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy() 583 584 @*/ 585 PetscErrorCode PETSC_DLLEXPORT PetscFListDuplicate(PetscFList fl,PetscFList *nl) 586 { 587 PetscErrorCode ierr; 588 char path[PETSC_MAX_PATH_LEN]; 589 590 PetscFunctionBegin; 591 while (fl) { 592 /* this is silly, rebuild the complete pathname */ 593 if (fl->path) { 594 ierr = PetscStrcpy(path,fl->path);CHKERRQ(ierr); 595 ierr = PetscStrcat(path,":");CHKERRQ(ierr); 596 ierr = PetscStrcat(path,fl->name);CHKERRQ(ierr); 597 } else { 598 ierr = PetscStrcpy(path,fl->name);CHKERRQ(ierr); 599 } 600 ierr = PetscFListAdd(nl,path,fl->rname,fl->routine);CHKERRQ(ierr); 601 fl = fl->next; 602 } 603 PetscFunctionReturn(0); 604 } 605 606 607 #undef __FUNCT__ 608 #define __FUNCT__ "PetscFListConcat" 609 /* 610 PetscFListConcat - joins name of a libary, and the path where it is located 611 into a single string. 612 613 Input Parameters: 614 . path - path to the library name. 615 . name - name of the library 616 617 Output Parameters: 618 . fullname - the name that is the union of the path and the library name, 619 delimited by a semicolon, i.e., path:name 620 621 Notes: 622 If the path is NULL, assumes that the name, specified also includes 623 the path as path:name 624 625 */ 626 PetscErrorCode PETSC_DLLEXPORT PetscFListConcat(const char path[],const char name[],char fullname[]) 627 { 628 PetscErrorCode ierr; 629 PetscFunctionBegin; 630 if (path) { 631 ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr); 632 ierr = PetscStrcat(fullname,":");CHKERRQ(ierr); 633 ierr = PetscStrcat(fullname,name);CHKERRQ(ierr); 634 } else { 635 ierr = PetscStrcpy(fullname,name);CHKERRQ(ierr); 636 } 637 PetscFunctionReturn(0); 638 } 639