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