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