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