Geant4 Cross Reference |
1 2 /* 3 Given a "libname.map" file on standard input and a list or directory 4 of .d dependency files liblist produces: 5 a) without -l option, a library list ordered according to the libname.map, 6 giving a warning if conflicting dependencies are found in the .d files. 7 b) with -l option, another libname.map, ordered according firstly to the 8 original libname.map file, then reordered according to the dependencies 9 found in the .d files. This option is used for compiling the file 10 libname.map from all the dependencies. 11 c) with -m <lpath> option, the whole existing libraries list ordered 12 according to the libname.map, where libraries are placed in <lpath>. 13 The .d files are specified in the argument(s). 14 The libname.map is on standard input. 15 16 Usage: 17 liblist *.d < libname.map 18 liblist -d <ddir> < libname.map 19 liblist -l *.d < libname.map 20 liblist -ld <ddir> < libname.map 21 liblist -l -d <ddir> < libname.map 22 liblist -m <lpath> < libname.map 23 where: 24 <ddir> is a directory name of a directory which is recursively 25 searched for dependency files 26 <lpath> is the path where libraries are located 27 28 Frank Behner, John Allison 13th February 1999. 29 */ 30 31 #include <stdio.h> 32 #include <string.h> 33 #include <unistd.h> 34 #include <dirent.h> 35 #include <sys/stat.h> 36 #include <unistd.h> 37 #include <errno.h> 38 #include <stdlib.h> 39 40 #define BUFSIZE 1000000 41 #define TRIGSIZE 1000 42 #define NLIBMAX 200 43 44 extern char *optarg; 45 extern int optind, opterr, optopt; 46 47 char** parsedir(char *directory,int *argc) 48 { 49 DIR *actualdir; 50 FILE *actualfile; 51 struct dirent *entry; 52 char *buffer=0; 53 struct stat status; 54 char **targv=0,**ptr,**phelp; 55 int len,targc,s; 56 57 /*Open the actual directory*/ 58 actualdir=opendir(directory); 59 60 if(!actualdir) return targv; 61 62 /*Loop over all entries */ 63 for(entry=readdir(actualdir);entry!=NULL;entry=readdir(actualdir)) 64 { 65 /* Throw away . and .. */ 66 if(strcmp(entry->d_name,".")==0 || 67 strcmp(entry->d_name,"..")==0) continue; 68 /* Obtain the status information of that entry */ 69 if(buffer) free(buffer); 70 buffer=(char*) malloc((strlen(directory)+ 71 strlen(entry->d_name)+2)*sizeof(char)); 72 strcpy(buffer,directory); 73 strcat(buffer,"/"); 74 strcat(buffer,entry->d_name); 75 s=stat(buffer,&status); 76 if(s==0) 77 { 78 if(S_ISDIR(status.st_mode)) 79 { 80 /* a directory, so we are going recursive*/ 81 targc=0; 82 ptr=parsedir(buffer,&targc); 83 if(targc) 84 { 85 phelp=targv; 86 targv=(char**) malloc((*argc+targc)*sizeof(char*)); 87 memcpy(targv,phelp,*argc*sizeof(char*)); 88 memcpy(&targv[*argc],ptr,targc*sizeof(char*)); 89 *argc+=targc; 90 free(phelp); 91 free(ptr); 92 } 93 } 94 else if(S_ISREG(status.st_mode)) 95 { 96 /* a regular file is it .d? */ 97 len=strlen(entry->d_name); 98 if(entry->d_name[len-2]=='.' && entry->d_name[len-1]=='d') 99 { 100 phelp=targv; 101 targv=(char**) malloc((*argc+1)*sizeof(char*)); 102 memcpy(targv,phelp,*argc*sizeof(char*)); 103 targv[*argc]=strdup(buffer); 104 (*argc)++; 105 free(phelp); 106 } 107 } 108 } 109 else 110 { 111 fprintf 112 (stderr, 113 " No status - perhaps file %s does not exist.\n", 114 directory); 115 exit(1); 116 } 117 } 118 119 if(buffer) free(buffer); 120 closedir(actualdir); 121 122 return targv; 123 } 124 125 126 int main (int argc, char** argv) { 127 128 char static buffer[BUFSIZE],*bufferPtr,workbuf[256]; 129 char *ptr,*p,**pp,**pp1,**pp2,*directory=0,*libpath=0; 130 char **rargv; 131 char *libname=0; 132 int i,optl=0,optm=0,swapping,c,rargc; 133 FILE *fp; 134 135 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ ) 136 char *ntg4tmp=0,*ntg4tmp1=0; 137 int nti; 138 #endif 139 140 struct libmap_ 141 { 142 char *lib; /* Library name, e.g., G4run. */ 143 char *trigger; /* Source directory, e.g., source/run/. */ 144 int used; /* True if used by these dependency files. */ 145 char **uses; /* List of library names which this library uses. */ 146 struct libmap_ *next; 147 }; 148 149 struct libmap_ *libmap=0,*libmapPtr=0,*libmapPtr1=0,*libmapPtr2=0, 150 *prevPtr1,*prevPtr2,*tmpp,*userLibmapPtr; 151 152 while((c=getopt(argc,argv,"ld: m:"))!=EOF) 153 { 154 switch(c) 155 { 156 case 'l': 157 optl=1; 158 break; 159 case 'd': 160 directory=strdup(optarg); 161 break; 162 case 'm': 163 optm=1; 164 libpath=strdup(optarg); 165 break; 166 } 167 } 168 169 /*Adjust parameters after parsing options */ 170 171 if(optind<argc) 172 { 173 rargv=&argv[optind]; 174 rargc=argc-optind; 175 } 176 else 177 { 178 rargv=0; 179 rargc=0; 180 } 181 182 if(directory) 183 { 184 if(rargc==0) 185 { 186 rargv=parsedir(directory,&rargc); 187 } 188 else 189 { 190 fprintf 191 (stderr, 192 " ERROR: If you specify a directory don't also specify files\n"); 193 exit(1); 194 } 195 } 196 197 if(optl)fprintf(stderr," Reading library name map file...\n"); 198 while (!feof(stdin)) 199 { 200 /* Get library name... */ 201 fgets(buffer,BUFSIZE,stdin); 202 if(feof(stdin)) break; 203 if (strlen(buffer) >= BUFSIZE-1) 204 { 205 fprintf(stderr, 206 " Internal ERROR: BUFSIZE too small to read library name map file\n"); 207 exit(1); 208 } 209 /* discarded trailing \n, as gets() was doing */ 210 if ( buffer[strlen(buffer)-1] == '\n') 211 { buffer[strlen(buffer)-1]='\0'; } 212 213 ptr=strtok(buffer,":\n"); 214 215 /* Check for duplicate names... */ 216 for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next) 217 { 218 if(strcmp(libmapPtr1->lib,ptr)==0) 219 { 220 fprintf(stderr," ERROR: Duplicate library name: %s\n",ptr); 221 fprintf(stderr, 222 " Perhaps a duplicate subdirectory with" 223 " a GNUmakefile with the same library name.\n" 224 ); 225 exit(1); 226 } 227 } 228 229 if(libmap) 230 { 231 libmapPtr->next=(struct libmap_*) malloc(sizeof(struct libmap_)); 232 libmapPtr=libmapPtr->next; 233 } 234 else /* First time through anchor libmapPtr to libmap. */ 235 { 236 libmap=(struct libmap_*) malloc(sizeof(struct libmap_)); 237 libmapPtr=libmap; 238 } 239 libmapPtr->next=0; 240 libmapPtr->lib=strdup(ptr); 241 libmapPtr->used=0; 242 libmapPtr->uses=(char**)calloc(NLIBMAX,sizeof(char*)); 243 244 /* If option -l not specified, fill uses list... */ 245 if(!optl && !optm) 246 { 247 pp=libmapPtr->uses; 248 if(ptr) 249 { 250 ptr=strtok(NULL," \n"); 251 while (ptr) 252 { 253 *pp=strdup(ptr); 254 pp++; 255 ptr=strtok(NULL," \n"); 256 } 257 } 258 } 259 260 if(!optm) 261 { 262 /* Get directory name... */ 263 fgets(buffer,BUFSIZE,stdin); 264 if (strlen(buffer) >= BUFSIZE-1) 265 { 266 fprintf(stderr, 267 " Internal ERROR: BUFSIZE too small to read directory name\n"); 268 exit(1); 269 } 270 /* discarded trailing \n, as gets() was doing */ 271 if ( buffer[strlen(buffer)-1] == '\n') 272 { buffer[strlen(buffer)-1]='\0'; } 273 274 ptr=strtok(buffer,"/"); 275 if(!ptr) 276 { 277 fprintf(stderr," ERROR: \"/\" before \"source\" expected.\n"); 278 exit(1); 279 } 280 while(ptr&&strcmp (ptr,"source"))ptr=strtok(NULL,"/"); 281 ptr=strtok(NULL,"/"); 282 if(!ptr) 283 { 284 fprintf(stderr," ERROR: \"source\" expected.\n"); 285 exit(1); 286 } 287 libmapPtr->trigger=(char*)malloc(TRIGSIZE); 288 if(strlen(ptr)>TRIGSIZE) 289 { 290 fprintf(stderr," ERROR: String overflow for: %s\n", ptr); 291 exit(1); 292 } 293 strcpy(libmapPtr->trigger,ptr); 294 ptr=strtok(NULL,"/"); 295 while(ptr&&strcmp(ptr,"GNUmakefile")) 296 { 297 strcat(libmapPtr->trigger,"/"); 298 strcat(libmapPtr->trigger,ptr); 299 ptr=strtok(NULL,"/"); 300 } 301 if(!ptr) 302 { 303 fprintf 304 (stderr, 305 " ERROR: \"source/<unique-sub-path>/GNUmakefile\" expected.\n"); 306 exit(1); 307 } 308 } 309 } 310 311 if(optl)fprintf(stderr," Reading dependency files...\n"); 312 313 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ ) 314 ntg4tmp=getenv("G4TMP"); 315 if ( ! ntg4tmp ) 316 { 317 fprintf(stderr," ERROR: Cannot find environment variable G4TMP\n"); 318 exit(1); 319 } 320 ntg4tmp1=strdup(ntg4tmp); 321 #endif 322 323 for(i=0;i<rargc;i++) 324 { 325 fp=fopen(rargv[i],"r"); 326 fgets(buffer,BUFSIZE,fp); 327 328 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ ) 329 ptr=strchr(ntg4tmp1,':'); 330 331 while ( ptr=strchr(buffer,'\\') ) *ptr='/'; 332 333 while (ntg4tmp1!=NULL && (ptr=strstr(buffer,ntg4tmp1))!=NULL ) 334 { 335 for(nti=0;nti<strlen(ntg4tmp1);nti++) ptr[nti]=' '; 336 } 337 #endif 338 339 /* Clip target out of dependency file... */ 340 ptr=strtok(buffer,":"); 341 342 /* Look for a "user" library... */ 343 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 344 { 345 if(strlen(libmapPtr->lib)>256) 346 { 347 fprintf(stderr," ERROR: String overflow for: %s\n", libmapPtr->lib); 348 exit(1); 349 } 350 strcpy(workbuf,libmapPtr->lib); 351 /* Add trailing "/" to distinguish track/ and tracking/, etc. */ 352 strcat(workbuf,"/"); 353 if(strstr(ptr,workbuf)) break; 354 } 355 if(libmapPtr) 356 { 357 userLibmapPtr=libmapPtr; 358 } 359 else 360 { 361 userLibmapPtr=0; 362 } 363 364 if(!optm) 365 { 366 /* Look for a "used" library and add it to the "user" uses list... */ 367 bufferPtr=strtok(NULL,"\n"); /* Start *after* ":". */ 368 if (!bufferPtr) 369 { 370 fprintf(stderr," WARNING: It seems there is nothing after \':\' in dependency file %s.\n", rargv[i]); 371 } 372 else { 373 do 374 { 375 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 376 { 377 /* Look for trigger string. */ 378 if(strlen(libmapPtr->trigger)>256) 379 { 380 fprintf(stderr," ERROR: String overflow for: %s\n", libmapPtr->trigger); 381 exit(1); 382 } 383 strcpy(workbuf,libmapPtr->trigger); 384 strcat(workbuf,"/include"); 385 ptr=strstr(bufferPtr,workbuf); 386 if(ptr && (userLibmapPtr != libmapPtr)) 387 { 388 libmapPtr->used=1; 389 if(userLibmapPtr) 390 { 391 for(pp=userLibmapPtr->uses;*pp;pp++) 392 { 393 if(strcmp(*pp,libmapPtr->lib)==0)break; 394 } 395 if(!*pp)*pp=libmapPtr->lib; 396 } 397 } 398 /* Also look for library name in case header files are 399 placed in temporary directories under a subdirectory 400 with the same name as the library name. This can 401 happen with Objectivity which makes header files 402 from .ddl files and places them in a temporary 403 directory. */ 404 if(strlen(libmapPtr->lib)>256) 405 { 406 fprintf(stderr," ERROR: String overflow for: %s\n", libmapPtr->lib); 407 exit(1); 408 } 409 strcpy(workbuf,libmapPtr->lib); 410 strcat(workbuf,"/"); 411 ptr=strstr(bufferPtr,workbuf); 412 if(ptr && (userLibmapPtr != libmapPtr)) 413 { 414 libmapPtr->used=1; 415 if(userLibmapPtr) 416 { 417 for(pp=userLibmapPtr->uses;*pp;pp++) 418 { 419 if(strcmp(*pp,libmapPtr->lib)==0)break; 420 } 421 if(!*pp)*pp=libmapPtr->lib; 422 } 423 } 424 } 425 fgets(buffer,BUFSIZE,fp); 426 bufferPtr=buffer; 427 428 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ ) 429 while ( ptr=strchr(buffer,'\\') ) *ptr='/'; 430 431 while (ntg4tmp1 && (ptr=strstr(buffer,ntg4tmp1)) ) 432 { 433 for(nti=0;nti<strlen(ntg4tmp1);nti++) ptr[nti]=' '; 434 } 435 #endif 436 437 } while(!feof(fp)); 438 fclose(fp); 439 } 440 } 441 } 442 443 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ ) 444 free(ntg4tmp1); 445 #endif 446 447 if(optl) /* This option is used for compiling the file libname.map 448 from all the dependencies. */ 449 { 450 fprintf(stderr," Checking for circular dependencies...\n"); 451 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 452 { 453 for(pp=libmapPtr->uses;*pp;pp++) 454 { 455 for(libmapPtr1=libmap;libmapPtr1!=libmapPtr; 456 libmapPtr1=libmapPtr1->next) 457 { 458 if(strcmp(libmapPtr1->lib,*pp)==0) 459 { 460 for(pp1=libmapPtr1->uses;*pp1;pp1++) 461 { 462 if(strcmp(*pp1,libmapPtr->lib)==0)break; 463 } 464 if(*pp1) 465 { 466 fprintf 467 (stderr, 468 " WARNING: %s and %s use each other.\n", 469 libmapPtr->lib, 470 libmapPtr1->lib); 471 } 472 } 473 else 474 { 475 /* Not right yet... 476 for(pp1=libmapPtr1->uses;*pp1;pp1++) 477 { 478 for(libmapPtr0=libmap;libmapPtr0!=libmapPtr1; 479 libmapPtr0=libmapPtr0->next) 480 { 481 if(libmapPtr0==*pp) 482 { 483 fprintf 484 (stderr, 485 " WARNING: triangular dependecy:\n" 486 " %s uses %s uses %s uses %s.\n", 487 libmapPtr->lib, 488 libmapPtr1->lib, 489 libmapPtr0->lib, 490 libmapPtr->lib); 491 } 492 } 493 } 494 */ 495 } 496 } 497 } 498 } 499 500 fprintf(stderr," Reordering according to dependencies...\n"); 501 do 502 { 503 swapping=0; 504 prevPtr2=0; 505 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 506 { 507 for(pp=libmapPtr->uses;*pp;pp++) 508 { 509 prevPtr1=0; 510 for(libmapPtr1=libmap;libmapPtr1!=libmapPtr; 511 libmapPtr1=libmapPtr1->next) 512 { 513 if(strcmp(libmapPtr1->lib,*pp)==0) 514 { 515 /* Check that 1st doesn't use 2nd... */ 516 for(pp1=libmapPtr1->uses;*pp1;pp1++) 517 { 518 if(strcmp(*pp1,libmapPtr->lib)==0)break; 519 } 520 if(!*pp1) /* If not... */ 521 { 522 swapping=1; 523 /* Make previous of 1st now point to 2nd... */ 524 if(prevPtr1) 525 { 526 prevPtr1->next=libmapPtr; 527 } 528 else 529 { 530 libmap=libmapPtr; 531 } 532 /* Make 2nd now point to what 1st did, unless 533 it's adjacent, in which case make it point 534 to 1st itself... */ 535 tmpp=libmapPtr->next; 536 if(libmapPtr1->next==libmapPtr) 537 { 538 libmapPtr->next=libmapPtr1; 539 } 540 else 541 { 542 libmapPtr->next=libmapPtr1->next; 543 } 544 /* Make previous of 2nd point to 1st, unless 545 it's adjacent, in which case leave it... */ 546 if(libmapPtr1->next!=libmapPtr) 547 { 548 prevPtr2->next=libmapPtr1; 549 } 550 /* Make 1st now point to what 2nd did... */ 551 libmapPtr1->next=tmpp; 552 break; 553 } 554 } 555 prevPtr1=libmapPtr1; 556 } 557 if(swapping)break; 558 } 559 prevPtr2=libmapPtr; 560 if(swapping)break; 561 } 562 }while(swapping); 563 564 fprintf(stderr," Writing new library map file...\n"); 565 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 566 { 567 printf("%s:",libmapPtr->lib); 568 for(pp=libmapPtr->uses;*pp;pp++) 569 { 570 printf(" %s",*pp); 571 } 572 printf("\n"); 573 printf("source/%s/GNUmakefile\n",libmapPtr->trigger); 574 } 575 } 576 else if (optm) 577 { 578 /* create tmp. string libname */ 579 int libname_usable_size=24; 580 if ( ! libname ) libname=malloc(libname_usable_size+16); 581 582 /* Write out full library list... */ 583 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 584 { 585 if ( strlen(libpath)+strlen(libmapPtr->lib) > libname_usable_size ) { 586 libname_usable_size=(strlen(libpath)+strlen(libmapPtr->lib))*2; 587 free(libname); 588 libname=malloc(libname_usable_size+16); 589 } 590 /* Check existance of libraries and print out only installed ones */ 591 592 593 snprintf(libname, libname_usable_size+16, "%s/lib%s.a", libpath, libmapPtr->lib); 594 if (access(libname,R_OK)) 595 { 596 snprintf(libname, libname_usable_size+16, "%s/lib%s.so", libpath, libmapPtr->lib); 597 if (!access(libname,R_OK)) 598 { 599 printf("-l%s ",libmapPtr->lib); 600 } 601 else /* case MacOS .dylib */ 602 { 603 snprintf(libname, libname_usable_size+16, "%s/lib%s.dylib", libpath, libmapPtr->lib); 604 if (!access(libname,R_OK)) 605 { 606 printf("-l%s ",libmapPtr->lib); 607 } 608 } 609 } 610 else 611 { 612 printf("-l%s ",libmapPtr->lib); 613 } 614 libmapPtr=libmapPtr->next; 615 } 616 } 617 else 618 { 619 /* Add dependent libraries... */ 620 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 621 { 622 if(libmapPtr->used) 623 { 624 for(pp=libmapPtr->uses;*pp;pp++) 625 { 626 for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next) 627 { 628 if(strcmp(libmapPtr1->lib,*pp)==0) 629 { 630 libmapPtr1->used=1; 631 } 632 } 633 } 634 } 635 } 636 637 /* Write out library list... */ 638 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next) 639 { 640 if(libmapPtr->used) 641 { 642 printf("-l%s ",libmapPtr->lib); 643 } 644 } 645 } 646 647 exit(0); 648 649 } 650