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