1 #define PETSC_DLL 2 /* 3 Routines for opening dynamic link libraries (DLLs), keeping a searchable 4 path of DLLs, obtaining remote DLLs via a URL and opening them locally. 5 */ 6 7 #include "petsc.h" 8 #include "petscsys.h" 9 #include "petscfix.h" 10 11 #if defined(PETSC_HAVE_PWD_H) 12 #include <pwd.h> 13 #endif 14 #include <ctype.h> 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #if defined(PETSC_HAVE_UNISTD_H) 18 #include <unistd.h> 19 #endif 20 #if defined(PETSC_HAVE_STDLIB_H) 21 #include <stdlib.h> 22 #endif 23 #if defined(PETSC_HAVE_SYS_UTSNAME_H) 24 #include <sys/utsname.h> 25 #endif 26 #include <fcntl.h> 27 #include <time.h> 28 #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H) 29 #include <sys/systeminfo.h> 30 #endif 31 32 33 /* 34 Contains the list of registered CCA components 35 */ 36 PetscFList CCAList = 0; 37 38 39 /* ------------------------------------------------------------------------------*/ 40 /* 41 Code to maintain a list of opened dynamic libraries and load symbols 42 */ 43 struct _n_PetscDLLibrary { 44 PetscDLLibrary next; 45 PetscDLHandle handle; 46 char libname[PETSC_MAX_PATH_LEN]; 47 }; 48 49 EXTERN_C_BEGIN 50 EXTERN PetscErrorCode Petsc_DelTag(MPI_Comm,int,void*,void*); 51 EXTERN_C_END 52 53 #undef __FUNCT__ 54 #define __FUNCT__ "PetscDLLibraryPrintPath" 55 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrintPath(void) 56 { 57 PetscDLLibrary libs; 58 59 PetscFunctionBegin; 60 libs = DLLibrariesLoaded; 61 while (libs) { 62 PetscErrorPrintf(" %s\n",libs->libname); 63 libs = libs->next; 64 } 65 PetscFunctionReturn(0); 66 } 67 68 #undef __FUNCT__ 69 #define __FUNCT__ "PetscDLLibraryRetrieve" 70 /*@C 71 PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 72 (if it is remote), indicates if it exits and its local name. 73 74 Collective on MPI_Comm 75 76 Input Parameters: 77 + comm - processors that are opening the library 78 - libname - name of the library, can be relative or absolute 79 80 Output Parameter: 81 . handle - library handle 82 83 Level: developer 84 85 Notes: 86 [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 87 88 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 89 occuring in directoryname and filename will be replaced with appropriate values. 90 @*/ 91 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,size_t llen,PetscTruth *found) 92 { 93 char *par2,buff[10],*en,*gz; 94 PetscErrorCode ierr; 95 size_t len1,len2,len; 96 PetscTruth tflg,flg; 97 98 PetscFunctionBegin; 99 /* 100 make copy of library name and replace $PETSC_ARCH etc 101 so we can add to the end of it to look for something like .so.1.0 etc. 102 */ 103 ierr = PetscStrlen(libname,&len);CHKERRQ(ierr); 104 len = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 105 ierr = PetscMalloc(len*sizeof(char),&par2);CHKERRQ(ierr); 106 ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr); 107 108 /* 109 Remove any file: header 110 */ 111 ierr = PetscStrncmp(par2,"file:",5,&tflg);CHKERRQ(ierr); 112 if (tflg) { 113 ierr = PetscStrcpy(par2,par2+5);CHKERRQ(ierr); 114 } 115 116 /* strip out .a from it if user put it in by mistake */ 117 ierr = PetscStrlen(par2,&len);CHKERRQ(ierr); 118 if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0; 119 120 /* remove .gz if it ends library name */ 121 ierr = PetscStrstr(par2,".gz",&gz);CHKERRQ(ierr); 122 if (gz) { 123 ierr = PetscStrlen(gz,&len);CHKERRQ(ierr); 124 if (len == 3) { 125 *gz = 0; 126 } 127 } 128 129 /* see if library name does already not have suffix attached */ 130 ierr = PetscStrcpy(buff,".");CHKERRQ(ierr); 131 ierr = PetscStrcat(buff,PETSC_SLSUFFIX);CHKERRQ(ierr); 132 ierr = PetscStrstr(par2,buff,&en);CHKERRQ(ierr); 133 if (en) { 134 ierr = PetscStrlen(en,&len1);CHKERRQ(ierr); 135 ierr = PetscStrlen(PETSC_SLSUFFIX,&len2);CHKERRQ(ierr); 136 flg = (PetscTruth) (len1 != 1 + len2); 137 } else { 138 flg = PETSC_TRUE; 139 } 140 if (flg) { 141 ierr = PetscStrcat(par2,".");CHKERRQ(ierr); 142 ierr = PetscStrcat(par2,PETSC_SLSUFFIX);CHKERRQ(ierr); 143 } 144 145 /* put the .gz back on if it was there */ 146 if (gz) { 147 ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr); 148 } 149 150 ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr); 151 ierr = PetscFree(par2);CHKERRQ(ierr); 152 PetscFunctionReturn(0); 153 } 154 155 156 #undef __FUNCT__ 157 #define __FUNCT__ "PetscDLLibraryOpen" 158 /*@C 159 PetscDLLibraryOpen - Opens a PETSc dynamic link library 160 161 Collective on MPI_Comm 162 163 Input Parameters: 164 + comm - processors that are opening the library 165 - libname - name of the library, can be relative or absolute 166 167 Output Parameter: 168 . handle - library handle 169 170 Level: developer 171 172 Notes: 173 [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 174 175 ${PETSC_ARCH} occuring in directoryname and filename 176 will be replaced with the appropriate value. 177 @*/ 178 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryOpen(MPI_Comm comm,const char libname[],PetscDLHandle *handle) 179 { 180 PetscErrorCode ierr; 181 char *par2,registername[128],*ptr,*ptrp; 182 PetscTruth foundlibrary; 183 PetscErrorCode (*func)(const char*) = NULL; 184 size_t len; 185 186 PetscFunctionBegin; 187 PetscValidPointer(handle, 3); 188 189 *handle = PETSC_NULL; 190 ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&par2);CHKERRQ(ierr); 191 ierr = PetscDLLibraryRetrieve(comm,libname,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr); 192 if (!foundlibrary) SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s\n",libname); 193 194 /* Eventually config/configure.py should determine if the system needs an executable dynamic library */ 195 #define PETSC_USE_NONEXECUTABLE_SO 196 #if !defined(PETSC_USE_NONEXECUTABLE_SO) 197 ierr = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr); 198 if (!foundlibrary) SETERRQ2(PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s\n",libname,par2); 199 #endif 200 201 ierr = PetscInfo1(0,"Opening %s\n",libname);CHKERRQ(ierr); 202 ierr = PetscDLOpen(par2, PETSC_DL_GLOBAL, handle);CHKERRQ(ierr); 203 /* build name of symbol to look for based on libname */ 204 ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr); 205 /* look for libXXXXX.YYY and extract out the XXXXXX */ 206 ierr = PetscStrrstr(libname,"lib",&ptr);CHKERRQ(ierr); 207 if (!ptr) SETERRQ1(PETSC_ERR_ARG_WRONG,"Dynamic library name must have lib prefix:%s",libname); 208 ierr = PetscStrchr(ptr+3,'.',&ptrp);CHKERRQ(ierr); 209 if (ptrp) { 210 len = ptrp - ptr - 3; 211 } else { 212 ierr = PetscStrlen(ptr+3,&len);CHKERRQ(ierr); 213 } 214 ierr = PetscStrncat(registername,ptr+3,len);CHKERRQ(ierr); 215 ierr = PetscDLSym(*handle,registername, (void**)&func);CHKERRQ(ierr); 216 if (func) { 217 ierr = (*func)(libname);CHKERRQ(ierr); 218 ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr); 219 } else { 220 SETERRQ2(PETSC_ERR_FILE_UNEXPECTED,"Able to locate dynamic library %s, but cannot load symbol %s\n",libname,registername); 221 } 222 ierr = PetscFree(par2);CHKERRQ(ierr); 223 PetscFunctionReturn(0); 224 } 225 226 #undef __FUNCT__ 227 #define __FUNCT__ "PetscDLLibrarySym" 228 /*@C 229 PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 230 231 Collective on MPI_Comm 232 233 Input Parameter: 234 + comm - communicator that will open the library 235 . inlist - list of already open libraries that may contain symbol (checks here before path) 236 . path - optional complete library name 237 - insymbol - name of symbol 238 239 Output Parameter: 240 . value 241 242 Level: developer 243 244 Notes: Symbol can be of the form 245 [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 246 247 Will attempt to (retrieve and) open the library if it is not yet been opened. 248 249 @*/ 250 PetscErrorCode PETSC_DLLEXPORT PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *inlist,const char path[],const char insymbol[],void **value) 251 { 252 char *par1,*symbol; 253 PetscErrorCode ierr; 254 size_t len; 255 PetscDLLibrary nlist,prev,list; 256 257 PetscFunctionBegin; 258 if (inlist) list = *inlist; else list = PETSC_NULL; 259 *value = 0; 260 261 /* make copy of symbol so we can edit it in place */ 262 ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr); 263 ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr); 264 ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr); 265 266 /* 267 If symbol contains () then replace with a NULL, to support functionname() 268 */ 269 ierr = PetscStrchr(symbol,'(',&par1);CHKERRQ(ierr); 270 if (par1) *par1 = 0; 271 272 273 /* 274 Function name does include library 275 ------------------------------------- 276 */ 277 if (path && path[0] != '\0') { 278 PetscDLHandle handle; 279 280 /* 281 Look if library is already opened and in path 282 */ 283 nlist = list; 284 prev = 0; 285 while (nlist) { 286 PetscTruth match; 287 288 ierr = PetscStrcmp(nlist->libname,path,&match);CHKERRQ(ierr); 289 if (match) { 290 handle = nlist->handle; 291 goto done; 292 } 293 prev = nlist; 294 nlist = nlist->next; 295 } 296 ierr = PetscDLLibraryOpen(comm,path,&handle);CHKERRQ(ierr); 297 298 ierr = PetscNew(struct _n_PetscDLLibrary,&nlist);CHKERRQ(ierr); 299 nlist->next = 0; 300 nlist->handle = handle; 301 ierr = PetscStrcpy(nlist->libname,path);CHKERRQ(ierr); 302 303 if (prev) { 304 prev->next = nlist; 305 } else { 306 if (inlist) *inlist = nlist; 307 else {ierr = PetscDLLibraryClose(nlist);CHKERRQ(ierr);} 308 } 309 ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr); 310 311 done:; 312 ierr = PetscDLSym(handle,symbol,value);CHKERRQ(ierr); 313 if (!*value) { 314 SETERRQ2(PETSC_ERR_PLIB,"Unable to locate function %s in dynamic library %s",insymbol,path); 315 } 316 ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr); 317 318 /* 319 Function name does not include library so search path 320 ----------------------------------------------------- 321 */ 322 } else { 323 while (list) { 324 ierr = PetscDLSym(list->handle,symbol,value);CHKERRQ(ierr); 325 if (*value) { 326 ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr); 327 break; 328 } 329 list = list->next; 330 } 331 if (!*value) { 332 ierr = PetscDLSym(PETSC_NULL,symbol,value);CHKERRQ(ierr); 333 if (*value) { 334 ierr = PetscInfo1(0,"Loading function %s from object code\n",symbol);CHKERRQ(ierr); 335 } 336 } 337 } 338 339 ierr = PetscFree(symbol);CHKERRQ(ierr); 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNCT__ 344 #define __FUNCT__ "PetscDLLibraryAppend" 345 /*@C 346 PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 347 of the search path. 348 349 Collective on MPI_Comm 350 351 Input Parameters: 352 + comm - MPI communicator 353 - libname - name of the library 354 355 Output Parameter: 356 . outlist - list of libraries 357 358 Level: developer 359 360 Notes: if library is already in path will not add it. 361 @*/ 362 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[]) 363 { 364 PetscDLLibrary list,prev; 365 void* handle; 366 PetscErrorCode ierr; 367 size_t len; 368 PetscTruth match,dir; 369 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s; 370 PetscToken token; 371 372 PetscFunctionBegin; 373 374 /* is libname a directory? */ 375 ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr); 376 if (dir) { 377 ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr); 378 ierr = PetscStrcpy(program,libname);CHKERRQ(ierr); 379 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 380 if (program[len-1] == '/') { 381 ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 382 } else { 383 ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 384 } 385 ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 386 387 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 388 if (!dir) PetscFunctionReturn(0); 389 found = buf; 390 } else { 391 found = (char*)libname; 392 } 393 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 394 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 395 396 ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 397 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 398 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 399 if (s) s[0] = 0; 400 while (libname1) { 401 402 /* see if library was already open then we are done */ 403 list = prev = *outlist; 404 match = PETSC_FALSE; 405 while (list) { 406 407 ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr); 408 if (match) break; 409 prev = list; 410 list = list->next; 411 } 412 if (!match) { 413 414 ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr); 415 416 ierr = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr); 417 list->next = 0; 418 list->handle = handle; 419 ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr); 420 421 if (!*outlist) { 422 *outlist = list; 423 } else { 424 prev->next = list; 425 } 426 ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname1);CHKERRQ(ierr); 427 } 428 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 429 if (libname1) { 430 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 431 if (s) s[0] = 0; 432 } 433 } 434 ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 435 PetscFunctionReturn(0); 436 } 437 438 #undef __FUNCT__ 439 #define __FUNCT__ "PetscDLLibraryPrepend" 440 /*@C 441 PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 442 the search path. 443 444 Collective on MPI_Comm 445 446 Input Parameters: 447 + comm - MPI communicator 448 - libname - name of the library 449 450 Output Parameter: 451 . outlist - list of libraries 452 453 Level: developer 454 455 Notes: If library is already in path will remove old reference. 456 457 @*/ 458 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[]) 459 { 460 PetscDLLibrary list,prev; 461 void* handle; 462 PetscErrorCode ierr; 463 size_t len; 464 PetscTruth match,dir; 465 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s; 466 PetscToken token; 467 468 PetscFunctionBegin; 469 470 /* is libname a directory? */ 471 ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr); 472 if (dir) { 473 ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr); 474 ierr = PetscStrcpy(program,libname);CHKERRQ(ierr); 475 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 476 if (program[len-1] == '/') { 477 ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 478 } else { 479 ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 480 } 481 ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 482 483 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 484 if (!dir) PetscFunctionReturn(0); 485 found = buf; 486 } else { 487 found = (char*)libname; 488 } 489 490 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 491 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 492 493 ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 494 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 495 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 496 if (s) s[0] = 0; 497 while (libname1) { 498 /* see if library was already open and move it to the front */ 499 list = *outlist; 500 prev = 0; 501 match = PETSC_FALSE; 502 while (list) { 503 504 ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr); 505 if (match) { 506 if (prev) prev->next = list->next; 507 list->next = *outlist; 508 *outlist = list; 509 break; 510 } 511 prev = list; 512 list = list->next; 513 } 514 if (!match) { 515 /* open the library and add to front of list */ 516 ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr); 517 518 ierr = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr); 519 list->next = 0; 520 list->handle = handle; 521 ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr); 522 523 ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname1);CHKERRQ(ierr); 524 list->next = *outlist; 525 *outlist = list; 526 527 528 } 529 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 530 if (libname1) { 531 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 532 if (s) s[0] = 0; 533 } 534 } 535 ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 536 PetscFunctionReturn(0); 537 } 538 539 #undef __FUNCT__ 540 #define __FUNCT__ "PetscDLLibraryClose" 541 /*@C 542 PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 543 544 Collective on PetscDLLibrary 545 546 Input Parameter: 547 . next - library list 548 549 Level: developer 550 551 @*/ 552 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryClose(PetscDLLibrary next) 553 { 554 PetscDLLibrary prev; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 while (next) { 559 prev = next; 560 next = next->next; 561 /* close the dynamic library */ 562 ierr = PetscDLClose(&prev->handle);CHKERRQ(ierr); 563 /* free the space in the prev data-structure */ 564 ierr = PetscFree(prev);CHKERRQ(ierr); 565 } 566 PetscFunctionReturn(0); 567 } 568 569 #undef __FUNCT__ 570 #define __FUNCT__ "PetscDLLibraryCCAAppend" 571 /*@C 572 PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end 573 of the search path. 574 575 Collective on MPI_Comm 576 577 Input Parameters: 578 + comm - MPI communicator 579 - libname - name of directory to check 580 581 Output Parameter: 582 . outlist - list of libraries 583 584 Level: developer 585 586 Notes: if library is already in path will not add it. 587 @*/ 588 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[]) 589 { 590 PetscErrorCode ierr; 591 size_t l; 592 PetscTruth dir; 593 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2; 594 char *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib; 595 FILE *fp; 596 PetscToken token1, token2; 597 int err; 598 599 PetscFunctionBegin; 600 /* is dirname a directory? */ 601 ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr); 602 if (!dir) PetscFunctionReturn(0); 603 604 ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr); 605 ierr = PetscStrcpy(program,dirname);CHKERRQ(ierr); 606 ierr = PetscStrcat(program,"/*.cca");CHKERRQ(ierr); 607 608 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 609 if (!dir) PetscFunctionReturn(0); 610 611 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 612 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 613 ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr); 614 ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 615 while (libname1) { 616 fp = fopen(libname1,"r"); if (!fp) continue; 617 while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) { 618 if (found[0] == '!') continue; 619 ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr); 620 if (f2) { /* found library name */ 621 if (found[0] == '/') { 622 lib = found; 623 } else { 624 ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr); 625 ierr = PetscStrlen(libname,&l);CHKERRQ(ierr); 626 if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);} 627 ierr = PetscStrcat(libname,found);CHKERRQ(ierr); 628 lib = libname; 629 } 630 ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr); 631 } else { 632 ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr); 633 ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr); 634 ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr); 635 ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr); 636 ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr); 637 ierr = PetscTokenDestroy(token2);CHKERRQ(ierr); 638 } 639 } 640 err = fclose(fp); 641 if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file"); 642 ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 643 } 644 ierr = PetscTokenDestroy(token1);CHKERRQ(ierr); 645 PetscFunctionReturn(0); 646 } 647