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_USE_DYNAMIC_LIBRARIES) 12 13 #if defined(PETSC_HAVE_PWD_H) 14 #include <pwd.h> 15 #endif 16 #include <ctype.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #if defined(PETSC_HAVE_UNISTD_H) 20 #include <unistd.h> 21 #endif 22 #if defined(PETSC_HAVE_STDLIB_H) 23 #include <stdlib.h> 24 #endif 25 #if defined(PETSC_HAVE_SYS_UTSNAME_H) 26 #include <sys/utsname.h> 27 #endif 28 #if defined(PETSC_HAVE_WINDOWS_H) 29 #include <windows.h> 30 #endif 31 #include <fcntl.h> 32 #include <time.h> 33 #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H) 34 #include <sys/systeminfo.h> 35 #endif 36 #if defined(PETSC_HAVE_DLFCN_H) 37 #include <dlfcn.h> 38 #endif 39 40 #endif 41 42 43 /* 44 Contains the list of registered CCA components 45 */ 46 PetscFList CCAList = 0; 47 48 49 /* ------------------------------------------------------------------------------*/ 50 /* 51 Code to maintain a list of opened dynamic libraries and load symbols 52 */ 53 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 54 struct _n_PetscDLLibrary { 55 PetscDLLibrary next; 56 void *handle; 57 char libname[PETSC_MAX_PATH_LEN]; 58 }; 59 60 EXTERN_C_BEGIN 61 EXTERN PetscErrorCode Petsc_DelTag(MPI_Comm,int,void*,void*); 62 EXTERN_C_END 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "PetscDLLibraryPrintPath" 66 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrintPath(void) 67 { 68 PetscDLLibrary libs; 69 70 PetscFunctionBegin; 71 libs = DLLibrariesLoaded; 72 while (libs) { 73 PetscErrorPrintf(" %s\n",libs->libname); 74 libs = libs->next; 75 } 76 PetscFunctionReturn(0); 77 } 78 79 #undef __FUNCT__ 80 #define __FUNCT__ "PetscDLLibraryRetrieve" 81 /*@C 82 PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 83 (if it is remote), indicates if it exits and its local name. 84 85 Collective on MPI_Comm 86 87 Input Parameters: 88 + comm - processors that are opening the library 89 - libname - name of the library, can be relative or absolute 90 91 Output Parameter: 92 . handle - library handle 93 94 Level: developer 95 96 Notes: 97 [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 98 99 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 100 occuring in directoryname and filename will be replaced with appropriate values. 101 @*/ 102 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,int llen,PetscTruth *found) 103 { 104 char *par2,buff[10],*en,*gz; 105 PetscErrorCode ierr; 106 size_t len1,len2,len; 107 PetscTruth tflg,flg; 108 109 PetscFunctionBegin; 110 /* 111 make copy of library name and replace $PETSC_ARCH and 112 so we can add to the end of it to look for something like .so.1.0 etc. 113 */ 114 ierr = PetscStrlen(libname,&len);CHKERRQ(ierr); 115 len = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 116 ierr = PetscMalloc(len*sizeof(char),&par2);CHKERRQ(ierr); 117 ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr); 118 119 /* 120 Remove any file: header 121 */ 122 ierr = PetscStrncmp(par2,"file:",5,&tflg);CHKERRQ(ierr); 123 if (tflg) { 124 ierr = PetscStrcpy(par2,par2+5);CHKERRQ(ierr); 125 } 126 127 /* strip out .a from it if user put it in by mistake */ 128 ierr = PetscStrlen(par2,&len);CHKERRQ(ierr); 129 if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0; 130 131 /* remove .gz if it ends library name */ 132 ierr = PetscStrstr(par2,".gz",&gz);CHKERRQ(ierr); 133 if (gz) { 134 ierr = PetscStrlen(gz,&len);CHKERRQ(ierr); 135 if (len == 3) { 136 *gz = 0; 137 } 138 } 139 140 /* see if library name does already not have suffix attached */ 141 ierr = PetscStrcpy(buff,".");CHKERRQ(ierr); 142 ierr = PetscStrcat(buff,PETSC_SLSUFFIX);CHKERRQ(ierr); 143 ierr = PetscStrstr(par2,buff,&en);CHKERRQ(ierr); 144 if (en) { 145 ierr = PetscStrlen(en,&len1);CHKERRQ(ierr); 146 ierr = PetscStrlen(PETSC_SLSUFFIX,&len2);CHKERRQ(ierr); 147 flg = (PetscTruth) (len1 != 1 + len2); 148 } else { 149 flg = PETSC_TRUE; 150 } 151 if (flg) { 152 ierr = PetscStrcat(par2,".");CHKERRQ(ierr); 153 ierr = PetscStrcat(par2,PETSC_SLSUFFIX);CHKERRQ(ierr); 154 } 155 156 /* put the .gz back on if it was there */ 157 if (gz) { 158 ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr); 159 } 160 161 ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr); 162 ierr = PetscFree(par2);CHKERRQ(ierr); 163 PetscFunctionReturn(0); 164 } 165 166 167 #undef __FUNCT__ 168 #define __FUNCT__ "PetscDLLibraryOpen" 169 /*@C 170 PetscDLLibraryOpen - Opens a dynamic link library 171 172 Collective on MPI_Comm 173 174 Input Parameters: 175 + comm - processors that are opening the library 176 - libname - name of the library, can be relative or absolute 177 178 Output Parameter: 179 . handle - library handle 180 181 Level: developer 182 183 Notes: 184 [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 185 186 ${PETSC_ARCH} occuring in directoryname and filename 187 will be replaced with the appropriate value. 188 @*/ 189 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryOpen(MPI_Comm comm,const char libname[],void **handle) 190 { 191 PetscErrorCode ierr; 192 char *par2,registername[128],*ptr,*ptrp; 193 PetscTruth foundlibrary; 194 PetscErrorCode (*func)(const char*) = NULL; 195 size_t len; 196 197 PetscFunctionBegin; 198 *handle = NULL; 199 ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&par2);CHKERRQ(ierr); 200 ierr = PetscDLLibraryRetrieve(comm,libname,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr); 201 if (!foundlibrary) { 202 SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s\n",libname); 203 } 204 205 /* Eventually config/configure.py should determine if the system needs an executable dynamic library */ 206 #define PETSC_USE_NONEXECUTABLE_SO 207 #if !defined(PETSC_USE_NONEXECUTABLE_SO) 208 ierr = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr); 209 if (!foundlibrary) { 210 SETERRQ2(PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s\n",libname,par2); 211 } 212 #endif 213 214 /* 215 Mode indicates symbols required by symbol loaded with dlsym() 216 are only loaded when required (not all together) also indicates 217 symbols required can be contained in other libraries also opened 218 with dlopen() 219 */ 220 ierr = PetscInfo1(0,"Opening %s\n",libname);CHKERRQ(ierr); 221 #if defined(PETSC_HAVE_LOADLIBRARY) 222 *handle = LoadLibrary(par2); 223 #elif defined(PETSC_HAVE_RTLD_GLOBAL) 224 *handle = dlopen(par2,RTLD_LAZY | RTLD_GLOBAL); 225 #else 226 *handle = dlopen(par2,RTLD_LAZY); 227 #endif 228 229 if (!*handle) { 230 #if defined(PETSC_HAVE_DLERROR) 231 SETERRQ3(PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n %s\n Error message from dlopen() %s\n",libname,par2,dlerror()); 232 #elif defined(PETSC_HAVE_GETLASTERROR) 233 { 234 DWORD erc; 235 char *buff; 236 erc = GetLastError(); 237 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 238 NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 239 ierr = PetscError(__LINE__,__FUNCT__,__FILE__,__SDIR__,PETSC_ERR_FILE_OPEN,1, 240 "Unable to open dynamic library:\n %s\n %s\n Error message from LoadLibrary() %s\n",libname,par2,buff); 241 LocalFree(buff); 242 return(ierr); 243 } 244 #endif 245 } 246 247 /* build name of symbol to look for based on libname */ 248 ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr); 249 /* look for libXXXXX.YYY and extract out the XXXXXX */ 250 ierr = PetscStrrstr(libname,"lib",&ptr);CHKERRQ(ierr); 251 if (!ptr) SETERRQ1(PETSC_ERR_ARG_WRONG,"Dynamic library name must have lib prefix:%s",libname); 252 ierr = PetscStrchr(ptr+3,'.',&ptrp);CHKERRQ(ierr); 253 if (ptrp) { 254 len = ptrp - ptr - 3; 255 } else { 256 ierr = PetscStrlen(ptr+3,&len);CHKERRQ(ierr); 257 } 258 ierr = PetscStrncat(registername,ptr+3,len);CHKERRQ(ierr); 259 260 #if defined(PETSC_HAVE_GETPROCADDRESS) 261 func = (PetscErrorCode (*)(const char *)) GetProcAddress((HMODULE)*handle,registername); 262 #else 263 func = (PetscErrorCode (*)(const char *)) dlsym(*handle,registername); 264 #endif 265 if (func) { 266 ierr = (*func)(libname);CHKERRQ(ierr); 267 ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr); 268 } else { 269 SETERRQ2(PETSC_ERR_FILE_UNEXPECTED,"Able to locate dynamic library %s, but cannot load symbol %s\n",libname,registername); 270 } 271 ierr = PetscFree(par2);CHKERRQ(ierr); 272 PetscFunctionReturn(0); 273 } 274 275 #undef __FUNCT__ 276 #define __FUNCT__ "PetscDLLibrarySym" 277 /*@C 278 PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 279 280 Collective on MPI_Comm 281 282 Input Parameter: 283 + comm - communicator that will open the library 284 . inlist - list of already open libraries that may contain symbol (checks here before path) 285 . path - optional complete library name 286 - insymbol - name of symbol 287 288 Output Parameter: 289 . value 290 291 Level: developer 292 293 Notes: Symbol can be of the form 294 [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 295 296 Will attempt to (retrieve and) open the library if it is not yet been opened. 297 298 @*/ 299 PetscErrorCode PETSC_DLLEXPORT PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *inlist,const char path[],const char insymbol[],void **value) 300 { 301 char *par1,*symbol; 302 PetscErrorCode ierr; 303 size_t len; 304 PetscDLLibrary nlist,prev,list; 305 306 PetscFunctionBegin; 307 if (inlist) list = *inlist; else list = PETSC_NULL; 308 *value = 0; 309 310 /* make copy of symbol so we can edit it in place */ 311 ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr); 312 ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr); 313 ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr); 314 315 /* 316 If symbol contains () then replace with a NULL, to support functionname() 317 */ 318 ierr = PetscStrchr(symbol,'(',&par1);CHKERRQ(ierr); 319 if (par1) *par1 = 0; 320 321 322 /* 323 Function name does include library 324 ------------------------------------- 325 */ 326 if (path && path[0] != '\0') { 327 void *handle; 328 329 /* 330 Look if library is already opened and in path 331 */ 332 nlist = list; 333 prev = 0; 334 while (nlist) { 335 PetscTruth match; 336 337 ierr = PetscStrcmp(nlist->libname,path,&match);CHKERRQ(ierr); 338 if (match) { 339 handle = nlist->handle; 340 goto done; 341 } 342 prev = nlist; 343 nlist = nlist->next; 344 } 345 ierr = PetscDLLibraryOpen(comm,path,&handle);CHKERRQ(ierr); 346 347 ierr = PetscNew(struct _n_PetscDLLibrary,&nlist);CHKERRQ(ierr); 348 nlist->next = 0; 349 nlist->handle = handle; 350 ierr = PetscStrcpy(nlist->libname,path);CHKERRQ(ierr); 351 352 if (prev) { 353 prev->next = nlist; 354 } else { 355 if (inlist) *inlist = nlist; 356 else {ierr = PetscDLLibraryClose(nlist);CHKERRQ(ierr);} 357 } 358 ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr); 359 360 done:; 361 #if defined(PETSC_HAVE_GETPROCADDRESS) 362 *value = GetProcAddress((HMODULE)handle,symbol); 363 #else 364 *value = dlsym(handle,symbol); 365 #endif 366 if (!*value) { 367 SETERRQ2(PETSC_ERR_PLIB,"Unable to locate function %s in dynamic library %s",insymbol,path); 368 } 369 ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr); 370 371 /* 372 Function name does not include library so search path 373 ----------------------------------------------------- 374 */ 375 } else { 376 while (list) { 377 #if defined(PETSC_HAVE_GETPROCADDRESS) 378 *value = GetProcAddress((HMODULE)list->handle,symbol); 379 #else 380 *value = dlsym(list->handle,symbol); 381 #endif 382 if (*value) { 383 ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr); 384 break; 385 } 386 list = list->next; 387 } 388 if (!*value) { 389 #if defined(PETSC_HAVE_GETPROCADDRESS) 390 *value = GetProcAddress(GetCurrentProcess(),symbol); 391 #else 392 *value = dlsym(0,symbol); 393 #endif 394 if (*value) { 395 ierr = PetscInfo1(0,"Loading function %s from object code\n",symbol);CHKERRQ(ierr); 396 } 397 } 398 } 399 400 ierr = PetscFree(symbol);CHKERRQ(ierr); 401 PetscFunctionReturn(0); 402 } 403 404 #undef __FUNCT__ 405 #define __FUNCT__ "PetscDLLibraryAppend" 406 /*@C 407 PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 408 of the search path. 409 410 Collective on MPI_Comm 411 412 Input Parameters: 413 + comm - MPI communicator 414 - libname - name of the library 415 416 Output Parameter: 417 . outlist - list of libraries 418 419 Level: developer 420 421 Notes: if library is already in path will not add it. 422 @*/ 423 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[]) 424 { 425 PetscDLLibrary list,prev; 426 void* handle; 427 PetscErrorCode ierr; 428 size_t len; 429 PetscTruth match,dir; 430 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s; 431 PetscToken *token; 432 433 PetscFunctionBegin; 434 435 /* is libname a directory? */ 436 ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr); 437 if (dir) { 438 ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr); 439 ierr = PetscStrcpy(program,libname);CHKERRQ(ierr); 440 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 441 if (program[len-1] == '/') { 442 ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 443 } else { 444 ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 445 } 446 ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 447 448 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 449 if (!dir) PetscFunctionReturn(0); 450 found = buf; 451 } else { 452 found = (char*)libname; 453 } 454 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 455 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 456 457 ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 458 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 459 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 460 if (s) s[0] = 0; 461 while (libname1) { 462 463 /* see if library was already open then we are done */ 464 list = prev = *outlist; 465 match = PETSC_FALSE; 466 while (list) { 467 468 ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr); 469 if (match) break; 470 prev = list; 471 list = list->next; 472 } 473 if (!match) { 474 475 ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr); 476 477 ierr = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr); 478 list->next = 0; 479 list->handle = handle; 480 ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr); 481 482 if (!*outlist) { 483 *outlist = list; 484 } else { 485 prev->next = list; 486 } 487 ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname1);CHKERRQ(ierr); 488 } 489 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 490 if (libname1) { 491 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 492 if (s) s[0] = 0; 493 } 494 } 495 ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 496 PetscFunctionReturn(0); 497 } 498 499 #undef __FUNCT__ 500 #define __FUNCT__ "PetscDLLibraryPrepend" 501 /*@C 502 PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 503 the search path. 504 505 Collective on MPI_Comm 506 507 Input Parameters: 508 + comm - MPI communicator 509 - libname - name of the library 510 511 Output Parameter: 512 . outlist - list of libraries 513 514 Level: developer 515 516 Notes: If library is already in path will remove old reference. 517 518 @*/ 519 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[]) 520 { 521 PetscDLLibrary list,prev; 522 void* handle; 523 PetscErrorCode ierr; 524 size_t len; 525 PetscTruth match,dir; 526 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s; 527 PetscToken *token; 528 529 PetscFunctionBegin; 530 531 /* is libname a directory? */ 532 ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr); 533 if (dir) { 534 ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr); 535 ierr = PetscStrcpy(program,libname);CHKERRQ(ierr); 536 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 537 if (program[len-1] == '/') { 538 ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 539 } else { 540 ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 541 } 542 ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 543 544 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 545 if (!dir) PetscFunctionReturn(0); 546 found = buf; 547 } else { 548 found = (char*)libname; 549 } 550 551 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 552 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 553 554 ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 555 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 556 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 557 if (s) s[0] = 0; 558 while (libname1) { 559 /* see if library was already open and move it to the front */ 560 list = *outlist; 561 prev = 0; 562 match = PETSC_FALSE; 563 while (list) { 564 565 ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr); 566 if (match) { 567 if (prev) prev->next = list->next; 568 list->next = *outlist; 569 *outlist = list; 570 break; 571 } 572 prev = list; 573 list = list->next; 574 } 575 if (!match) { 576 /* open the library and add to front of list */ 577 ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr); 578 579 ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname1);CHKERRQ(ierr); 580 581 ierr = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr); 582 list->handle = handle; 583 list->next = *outlist; 584 ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr); 585 *outlist = list; 586 } 587 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 588 if (libname1) { 589 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 590 if (s) s[0] = 0; 591 } 592 } 593 ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 594 PetscFunctionReturn(0); 595 } 596 597 #undef __FUNCT__ 598 #define __FUNCT__ "PetscDLLibraryClose" 599 /*@C 600 PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 601 602 Collective on PetscDLLibrary 603 604 Input Parameter: 605 . next - library list 606 607 Level: developer 608 609 @*/ 610 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryClose(PetscDLLibrary next) 611 { 612 PetscDLLibrary prev; 613 PetscErrorCode ierr; 614 615 PetscFunctionBegin; 616 617 while (next) { 618 prev = next; 619 next = next->next; 620 /* free the space in the prev data-structure */ 621 ierr = PetscFree(prev);CHKERRQ(ierr); 622 } 623 PetscFunctionReturn(0); 624 } 625 626 #undef __FUNCT__ 627 #define __FUNCT__ "PetscDLLibraryCCAAppend" 628 /*@C 629 PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end 630 of the search path. 631 632 Collective on MPI_Comm 633 634 Input Parameters: 635 + comm - MPI communicator 636 - libname - name of directory to check 637 638 Output Parameter: 639 . outlist - list of libraries 640 641 Level: developer 642 643 Notes: if library is already in path will not add it. 644 @*/ 645 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[]) 646 { 647 PetscErrorCode ierr; 648 size_t l; 649 PetscTruth dir; 650 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2; 651 char *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib; 652 FILE *fp; 653 PetscToken *token1,*token2; 654 655 PetscFunctionBegin; 656 657 /* is dirname a directory? */ 658 ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr); 659 if (!dir) PetscFunctionReturn(0); 660 661 ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr); 662 ierr = PetscStrcpy(program,dirname);CHKERRQ(ierr); 663 ierr = PetscStrcat(program,"/*.cca");CHKERRQ(ierr); 664 665 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 666 if (!dir) PetscFunctionReturn(0); 667 668 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 669 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 670 ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr); 671 ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 672 while (libname1) { 673 fp = fopen(libname1,"r"); if (!fp) continue; 674 while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) { 675 if (found[0] == '!') continue; 676 ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr); 677 if (f2) { /* found library name */ 678 if (found[0] == '/') { 679 lib = found; 680 } else { 681 ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr); 682 ierr = PetscStrlen(libname,&l);CHKERRQ(ierr); 683 if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);} 684 ierr = PetscStrcat(libname,found);CHKERRQ(ierr); 685 lib = libname; 686 } 687 ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr); 688 } else { 689 ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr); 690 ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr); 691 ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr); 692 ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr); 693 ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr); 694 ierr = PetscTokenDestroy(token2);CHKERRQ(ierr); 695 } 696 } 697 fclose(fp); 698 ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 699 } 700 ierr = PetscTokenDestroy(token1);CHKERRQ(ierr); 701 PetscFunctionReturn(0); 702 } 703 704 705 #endif 706 707 708