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