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