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