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 etc 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) SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s\n",libname); 202 203 /* Eventually config/configure.py should determine if the system needs an executable dynamic library */ 204 #define PETSC_USE_NONEXECUTABLE_SO 205 #if !defined(PETSC_USE_NONEXECUTABLE_SO) 206 ierr = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr); 207 if (!foundlibrary) SETERRQ2(PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s\n",libname,par2); 208 #endif 209 210 /* 211 Mode indicates symbols required by symbol loaded with dlsym() 212 are only loaded when required (not all together) also indicates 213 symbols required can be contained in other libraries also opened 214 with dlopen() 215 */ 216 ierr = PetscInfo1(0,"Opening %s\n",libname);CHKERRQ(ierr); 217 #if defined(PETSC_HAVE_LOADLIBRARY) 218 *handle = LoadLibrary(par2); 219 #elif defined(PETSC_HAVE_RTLD_GLOBAL) 220 *handle = dlopen(par2,RTLD_LAZY | RTLD_GLOBAL); 221 #else 222 *handle = dlopen(par2,RTLD_LAZY); 223 #endif 224 225 if (!*handle) { 226 #if defined(PETSC_HAVE_DLERROR) 227 SETERRQ3(PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n %s\n Error message from dlopen() %s\n",libname,par2,dlerror()); 228 #elif defined(PETSC_HAVE_GETLASTERROR) 229 { 230 DWORD erc; 231 char *buff; 232 erc = GetLastError(); 233 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 234 NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 235 ierr = PetscError(__LINE__,__FUNCT__,__FILE__,__SDIR__,PETSC_ERR_FILE_OPEN,1, 236 "Unable to open dynamic library:\n %s\n %s\n Error message from LoadLibrary() %s\n",libname,par2,buff); 237 LocalFree(buff); 238 return(ierr); 239 } 240 #endif 241 } 242 243 /* build name of symbol to look for based on libname */ 244 ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr); 245 /* look for libXXXXX.YYY and extract out the XXXXXX */ 246 ierr = PetscStrrstr(libname,"lib",&ptr);CHKERRQ(ierr); 247 if (!ptr) SETERRQ1(PETSC_ERR_ARG_WRONG,"Dynamic library name must have lib prefix:%s",libname); 248 ierr = PetscStrchr(ptr+3,'.',&ptrp);CHKERRQ(ierr); 249 if (ptrp) { 250 len = ptrp - ptr - 3; 251 } else { 252 ierr = PetscStrlen(ptr+3,&len);CHKERRQ(ierr); 253 } 254 ierr = PetscStrncat(registername,ptr+3,len);CHKERRQ(ierr); 255 256 #if defined(PETSC_HAVE_GETPROCADDRESS) 257 func = (PetscErrorCode (*)(const char *)) GetProcAddress((HMODULE)*handle,registername); 258 #else 259 func = (PetscErrorCode (*)(const char *)) dlsym(*handle,registername); 260 #endif 261 if (func) { 262 ierr = (*func)(libname);CHKERRQ(ierr); 263 ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr); 264 } else { 265 SETERRQ2(PETSC_ERR_FILE_UNEXPECTED,"Able to locate dynamic library %s, but cannot load symbol %s\n",libname,registername); 266 } 267 ierr = PetscFree(par2);CHKERRQ(ierr); 268 PetscFunctionReturn(0); 269 } 270 271 #undef __FUNCT__ 272 #define __FUNCT__ "PetscDLLibrarySym" 273 /*@C 274 PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 275 276 Collective on MPI_Comm 277 278 Input Parameter: 279 + comm - communicator that will open the library 280 . inlist - list of already open libraries that may contain symbol (checks here before path) 281 . path - optional complete library name 282 - insymbol - name of symbol 283 284 Output Parameter: 285 . value 286 287 Level: developer 288 289 Notes: Symbol can be of the form 290 [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 291 292 Will attempt to (retrieve and) open the library if it is not yet been opened. 293 294 @*/ 295 PetscErrorCode PETSC_DLLEXPORT PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *inlist,const char path[],const char insymbol[],void **value) 296 { 297 char *par1,*symbol; 298 PetscErrorCode ierr; 299 size_t len; 300 PetscDLLibrary nlist,prev,list; 301 302 PetscFunctionBegin; 303 if (inlist) list = *inlist; else list = PETSC_NULL; 304 *value = 0; 305 306 /* make copy of symbol so we can edit it in place */ 307 ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr); 308 ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr); 309 ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr); 310 311 /* 312 If symbol contains () then replace with a NULL, to support functionname() 313 */ 314 ierr = PetscStrchr(symbol,'(',&par1);CHKERRQ(ierr); 315 if (par1) *par1 = 0; 316 317 318 /* 319 Function name does include library 320 ------------------------------------- 321 */ 322 if (path && path[0] != '\0') { 323 void *handle; 324 325 /* 326 Look if library is already opened and in path 327 */ 328 nlist = list; 329 prev = 0; 330 while (nlist) { 331 PetscTruth match; 332 333 ierr = PetscStrcmp(nlist->libname,path,&match);CHKERRQ(ierr); 334 if (match) { 335 handle = nlist->handle; 336 goto done; 337 } 338 prev = nlist; 339 nlist = nlist->next; 340 } 341 ierr = PetscDLLibraryOpen(comm,path,&handle);CHKERRQ(ierr); 342 343 ierr = PetscNew(struct _n_PetscDLLibrary,&nlist);CHKERRQ(ierr); 344 nlist->next = 0; 345 nlist->handle = handle; 346 ierr = PetscStrcpy(nlist->libname,path);CHKERRQ(ierr); 347 348 if (prev) { 349 prev->next = nlist; 350 } else { 351 if (inlist) *inlist = nlist; 352 else {ierr = PetscDLLibraryClose(nlist);CHKERRQ(ierr);} 353 } 354 ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr); 355 356 done:; 357 #if defined(PETSC_HAVE_GETPROCADDRESS) 358 *value = GetProcAddress((HMODULE)handle,symbol); 359 #else 360 *value = dlsym(handle,symbol); 361 #endif 362 if (!*value) { 363 SETERRQ2(PETSC_ERR_PLIB,"Unable to locate function %s in dynamic library %s",insymbol,path); 364 } 365 ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr); 366 367 /* 368 Function name does not include library so search path 369 ----------------------------------------------------- 370 */ 371 } else { 372 while (list) { 373 #if defined(PETSC_HAVE_GETPROCADDRESS) 374 *value = GetProcAddress((HMODULE)list->handle,symbol); 375 #else 376 *value = dlsym(list->handle,symbol); 377 #endif 378 if (*value) { 379 ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr); 380 break; 381 } 382 list = list->next; 383 } 384 if (!*value) { 385 #if defined(PETSC_HAVE_GETPROCADDRESS) 386 *value = GetProcAddress(GetCurrentProcess(),symbol); 387 #else 388 *value = dlsym(0,symbol); 389 #endif 390 if (*value) { 391 ierr = PetscInfo1(0,"Loading function %s from object code\n",symbol);CHKERRQ(ierr); 392 } 393 } 394 } 395 396 ierr = PetscFree(symbol);CHKERRQ(ierr); 397 PetscFunctionReturn(0); 398 } 399 400 #undef __FUNCT__ 401 #define __FUNCT__ "PetscDLLibraryAppend" 402 /*@C 403 PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 404 of the search path. 405 406 Collective on MPI_Comm 407 408 Input Parameters: 409 + comm - MPI communicator 410 - libname - 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 not add it. 418 @*/ 419 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[]) 420 { 421 PetscDLLibrary list,prev; 422 void* handle; 423 PetscErrorCode ierr; 424 size_t len; 425 PetscTruth match,dir; 426 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s; 427 PetscToken token; 428 429 PetscFunctionBegin; 430 431 /* is libname a directory? */ 432 ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr); 433 if (dir) { 434 ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr); 435 ierr = PetscStrcpy(program,libname);CHKERRQ(ierr); 436 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 437 if (program[len-1] == '/') { 438 ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 439 } else { 440 ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 441 } 442 ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 443 444 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 445 if (!dir) PetscFunctionReturn(0); 446 found = buf; 447 } else { 448 found = (char*)libname; 449 } 450 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 451 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 452 453 ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 454 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 455 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 456 if (s) s[0] = 0; 457 while (libname1) { 458 459 /* see if library was already open then we are done */ 460 list = prev = *outlist; 461 match = PETSC_FALSE; 462 while (list) { 463 464 ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr); 465 if (match) break; 466 prev = list; 467 list = list->next; 468 } 469 if (!match) { 470 471 ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr); 472 473 ierr = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr); 474 list->next = 0; 475 list->handle = handle; 476 ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr); 477 478 if (!*outlist) { 479 *outlist = list; 480 } else { 481 prev->next = list; 482 } 483 ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname1);CHKERRQ(ierr); 484 } 485 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 486 if (libname1) { 487 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 488 if (s) s[0] = 0; 489 } 490 } 491 ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 492 PetscFunctionReturn(0); 493 } 494 495 #undef __FUNCT__ 496 #define __FUNCT__ "PetscDLLibraryPrepend" 497 /*@C 498 PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 499 the search path. 500 501 Collective on MPI_Comm 502 503 Input Parameters: 504 + comm - MPI communicator 505 - libname - name of the library 506 507 Output Parameter: 508 . outlist - list of libraries 509 510 Level: developer 511 512 Notes: If library is already in path will remove old reference. 513 514 @*/ 515 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char libname[]) 516 { 517 PetscDLLibrary list,prev; 518 void* handle; 519 PetscErrorCode ierr; 520 size_t len; 521 PetscTruth match,dir; 522 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*found,*libname1,suffix[16],*s; 523 PetscToken token; 524 525 PetscFunctionBegin; 526 527 /* is libname a directory? */ 528 ierr = PetscTestDirectory(libname,'r',&dir);CHKERRQ(ierr); 529 if (dir) { 530 ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",libname);CHKERRQ(ierr); 531 ierr = PetscStrcpy(program,libname);CHKERRQ(ierr); 532 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 533 if (program[len-1] == '/') { 534 ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 535 } else { 536 ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 537 } 538 ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 539 540 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 541 if (!dir) PetscFunctionReturn(0); 542 found = buf; 543 } else { 544 found = (char*)libname; 545 } 546 547 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 548 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 549 550 ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 551 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 552 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 553 if (s) s[0] = 0; 554 while (libname1) { 555 /* see if library was already open and move it to the front */ 556 list = *outlist; 557 prev = 0; 558 match = PETSC_FALSE; 559 while (list) { 560 561 ierr = PetscStrcmp(list->libname,libname1,&match);CHKERRQ(ierr); 562 if (match) { 563 if (prev) prev->next = list->next; 564 list->next = *outlist; 565 *outlist = list; 566 break; 567 } 568 prev = list; 569 list = list->next; 570 } 571 if (!match) { 572 /* open the library and add to front of list */ 573 ierr = PetscDLLibraryOpen(comm,libname1,&handle);CHKERRQ(ierr); 574 575 ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname1);CHKERRQ(ierr); 576 577 ierr = PetscNew(struct _n_PetscDLLibrary,&list);CHKERRQ(ierr); 578 list->handle = handle; 579 list->next = *outlist; 580 ierr = PetscStrcpy(list->libname,libname1);CHKERRQ(ierr); 581 *outlist = list; 582 } 583 ierr = PetscTokenFind(token,&libname1);CHKERRQ(ierr); 584 if (libname1) { 585 ierr = PetscStrstr(libname1,suffix,&s);CHKERRQ(ierr); 586 if (s) s[0] = 0; 587 } 588 } 589 ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 590 PetscFunctionReturn(0); 591 } 592 593 #undef __FUNCT__ 594 #define __FUNCT__ "PetscDLLibraryClose" 595 /*@C 596 PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 597 598 Collective on PetscDLLibrary 599 600 Input Parameter: 601 . next - library list 602 603 Level: developer 604 605 @*/ 606 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryClose(PetscDLLibrary next) 607 { 608 PetscDLLibrary prev; 609 PetscErrorCode ierr; 610 611 PetscFunctionBegin; 612 while (next) { 613 prev = next; 614 next = next->next; 615 /* free the space in the prev data-structure */ 616 ierr = PetscFree(prev);CHKERRQ(ierr); 617 } 618 PetscFunctionReturn(0); 619 } 620 621 #undef __FUNCT__ 622 #define __FUNCT__ "PetscDLLibraryCCAAppend" 623 /*@C 624 PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end 625 of the search path. 626 627 Collective on MPI_Comm 628 629 Input Parameters: 630 + comm - MPI communicator 631 - libname - name of directory to check 632 633 Output Parameter: 634 . outlist - list of libraries 635 636 Level: developer 637 638 Notes: if library is already in path will not add it. 639 @*/ 640 PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[]) 641 { 642 PetscErrorCode ierr; 643 size_t l; 644 PetscTruth dir; 645 char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2; 646 char *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib; 647 FILE *fp; 648 PetscToken token1, token2; 649 int err; 650 651 PetscFunctionBegin; 652 /* is dirname a directory? */ 653 ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr); 654 if (!dir) PetscFunctionReturn(0); 655 656 ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr); 657 ierr = PetscStrcpy(program,dirname);CHKERRQ(ierr); 658 ierr = PetscStrcat(program,"/*.cca");CHKERRQ(ierr); 659 660 ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 661 if (!dir) PetscFunctionReturn(0); 662 663 ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 664 ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 665 ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr); 666 ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 667 while (libname1) { 668 fp = fopen(libname1,"r"); if (!fp) continue; 669 while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) { 670 if (found[0] == '!') continue; 671 ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr); 672 if (f2) { /* found library name */ 673 if (found[0] == '/') { 674 lib = found; 675 } else { 676 ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr); 677 ierr = PetscStrlen(libname,&l);CHKERRQ(ierr); 678 if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);} 679 ierr = PetscStrcat(libname,found);CHKERRQ(ierr); 680 lib = libname; 681 } 682 ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr); 683 } else { 684 ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr); 685 ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr); 686 ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr); 687 ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr); 688 ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr); 689 ierr = PetscTokenDestroy(token2);CHKERRQ(ierr); 690 } 691 } 692 err = fclose(fp); 693 if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file"); 694 ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 695 } 696 ierr = PetscTokenDestroy(token1);CHKERRQ(ierr); 697 PetscFunctionReturn(0); 698 } 699 700 701 #endif 702 703 704