source: trunk/geant4/config/liblist.c@ 487

Last change on this file since 487 was 483, checked in by garnier, 18 years ago

r569@mac-90108: laurentgarnier | 2007-06-05 15:53:34 +0200
version contre geant4.8.2.p01

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