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