source: trunk/config/liblist.c@ 1243

Last change on this file since 1243 was 850, checked in by garnier, 17 years ago

geant4.8.2 beta

File size: 15.0 KB
RevLine 
[850]1/* $Id: liblist.c,v 1.21 2008/05/20 13:33:34 gunter 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... */
[761]202 fgets(buffer,BUFSIZE,stdin);
[472]203 if(feof(stdin)) break;
[761]204 if (strlen(buffer) >= BUFSIZE-1)
205 {
206 fprintf(stderr,
207 " Internal ERROR: BUFSIZE too small to read library name map file\n");
208 exit(1);
209 }
[850]210 /* discarded trailing \n, as gets() was doing */
[761]211 if ( buffer[strlen(buffer)-1] == '\n')
[850]212 { buffer[strlen(buffer)-1]='\0'; }
[761]213
[472]214 ptr=strtok(buffer,":\n");
215
216 /* Check for duplicate names... */
217 for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next)
218 {
219 if(strcmp(libmapPtr1->lib,ptr)==0)
220 {
221 fprintf(stderr," ERROR: Duplicate library name: %s\n",ptr);
222 fprintf(stderr,
223 " Perhaps a duplicate subdirectory with"
224 " a GNUmakefile with the same library name.\n"
225 );
226 exit(1);
227 }
228 }
229
230 if(libmap)
231 {
232 libmapPtr->next=(struct libmap_*) malloc(sizeof(struct libmap_));
233 libmapPtr=libmapPtr->next;
234 }
235 else /* First time through anchor libmapPtr to libmap. */
236 {
237 libmap=(struct libmap_*) malloc(sizeof(struct libmap_));
238 libmapPtr=libmap;
239 }
240 libmapPtr->next=0;
241 libmapPtr->lib=strdup(ptr);
242 libmapPtr->used=0;
243 libmapPtr->uses=(char**)calloc(NLIBMAX,sizeof(char*));
244
245 /* If option -l not specified, fill uses list... */
246 if(!optl && !optm)
247 {
248 pp=libmapPtr->uses;
249 if(ptr)
250 {
251 ptr=strtok(NULL," \n");
252 while (ptr)
253 {
254 *pp=strdup(ptr);
255 pp++;
256 ptr=strtok(NULL," \n");
257 }
258 }
259 }
260
261 if(!optm)
262 {
263 /* Get directory name... */
[761]264 fgets(buffer,BUFSIZE,stdin);
265 if (strlen(buffer) >= BUFSIZE-1)
266 {
267 fprintf(stderr,
268 " Internal ERROR: BUFSIZE too small to read directory name\n");
269 exit(1);
270 }
[850]271 /* discarded trailing \n, as gets() was doing */
[761]272 if ( buffer[strlen(buffer)-1] == '\n')
[850]273 { buffer[strlen(buffer)-1]='\0'; }
[761]274
[472]275 ptr=strtok(buffer,"/");
276 if(!ptr)
277 {
278 fprintf(stderr," ERROR: \"/\" before \"source\" expected.\n");
279 exit(1);
280 }
281 while(ptr&&strcmp (ptr,"source"))ptr=strtok(NULL,"/");
282 ptr=strtok(NULL,"/");
283 if(!ptr)
284 {
285 fprintf(stderr," ERROR: \"source\" expected.\n");
286 exit(1);
287 }
288 libmapPtr->trigger=(char*)malloc(TRIGSIZE);
289 strcpy(libmapPtr->trigger,ptr);
290 ptr=strtok(NULL,"/");
291 while(ptr&&strcmp(ptr,"GNUmakefile"))
292 {
293 strcat(libmapPtr->trigger,"/");
294 strcat(libmapPtr->trigger,ptr);
295 ptr=strtok(NULL,"/");
296 }
297 if(!ptr)
298 {
299 fprintf
300 (stderr,
301 " ERROR: \"source/<unique-sub-path>/GNUmakefile\" expected.\n");
302 exit(1);
303 }
304 }
305 }
306
307 if(optl)fprintf(stderr," Reading dependency files...\n");
308
309#if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
310 ntg4tmp=getenv("G4TMP");
311 if ( ! ntg4tmp )
312 {
313 fprintf(stderr," ERROR: Cannot find environment variable G4TMP\n");
314 exit(1);
315 }
316 ntg4tmp1=strdup(ntg4tmp);
317#endif
318
319 for(i=0;i<rargc;i++)
320 {
321 fp=fopen(rargv[i],"r");
322 fgets(buffer,BUFSIZE,fp);
323
324#if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
325 ptr=strchr(ntg4tmp1,':');
326
327 while ( ptr=strchr(buffer,'\\') ) *ptr='/';
328
329 while (ntg4tmp1!=NULL && (ptr=strstr(buffer,ntg4tmp1))!=NULL )
330 {
331 for(nti=0;nti<strlen(ntg4tmp1);nti++) ptr[nti]=' ';
332 }
333#endif
334
335 /* Clip target out of dependency file... */
336 ptr=strtok(buffer,":");
337
338 /* Look for a "user" library... */
339 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
340 {
341 strcpy(workbuf,libmapPtr->lib);
342 /* Add trailing "/" to distinguish track/ and tracking/, etc. */
343 strcat(workbuf,"/");
344 if(strstr(ptr,workbuf)) break;
345 }
346 if(libmapPtr)
347 {
348 userLibmapPtr=libmapPtr;
349 }
350 else
351 {
352 userLibmapPtr=0;
353 }
354
355 if(!optm)
356 {
357 /* Look for a "used" library and add it to the "user" uses list... */
358 bufferPtr=strtok(NULL,"\n"); /* Start *after* ":". */
359 if (!bufferPtr)
360 {
361 fprintf(stderr," WARNING: It seems there is nothing after \':\' in dependency file %s.\n", rargv[i]);
362 }
363 else {
364 do
365 {
366 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
367 {
368 /* Look for trigger string. */
369 strcpy(workbuf,libmapPtr->trigger);
370 strcat(workbuf,"/include");
371 ptr=strstr(bufferPtr,workbuf);
372 if(ptr && (userLibmapPtr != libmapPtr))
373 {
374 libmapPtr->used=1;
375 if(userLibmapPtr)
376 {
377 for(pp=userLibmapPtr->uses;*pp;pp++)
378 {
379 if(strcmp(*pp,libmapPtr->lib)==0)break;
380 }
381 if(!*pp)*pp=libmapPtr->lib;
382 }
383 }
384 /* Also look for library name in case header files are
385 placed in temporary directories under a subdirectory
386 with the same name as the library name. This can
387 happen with Objectivity which makes header files
388 from .ddl files and places them in a temporary
389 directory. */
390 strcpy(workbuf,libmapPtr->lib);
391 strcat(workbuf,"/");
392 ptr=strstr(bufferPtr,workbuf);
393 if(ptr && (userLibmapPtr != libmapPtr))
394 {
395 libmapPtr->used=1;
396 if(userLibmapPtr)
397 {
398 for(pp=userLibmapPtr->uses;*pp;pp++)
399 {
400 if(strcmp(*pp,libmapPtr->lib)==0)break;
401 }
402 if(!*pp)*pp=libmapPtr->lib;
403 }
404 }
405 }
406 fgets(buffer,BUFSIZE,fp);
407 bufferPtr=buffer;
408
409#if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
410 while ( ptr=strchr(buffer,'\\') ) *ptr='/';
411
412 while (ntg4tmp1 && (ptr=strstr(buffer,ntg4tmp1)) )
413 {
414 for(nti=0;nti<strlen(ntg4tmp1);nti++) ptr[nti]=' ';
415 }
416#endif
417
418 } while(!feof(fp));
419 fclose(fp);
420 }
421 }
422 }
423
424#if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
425 free(ntg4tmp1);
426#endif
427
428 if(optl) /* This option is used for compiling the file libname.map
429 from all the dependencies. */
430 {
431 fprintf(stderr," Checking for circular dependencies...\n");
432 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
433 {
434 for(pp=libmapPtr->uses;*pp;pp++)
435 {
436 for(libmapPtr1=libmap;libmapPtr1!=libmapPtr;
437 libmapPtr1=libmapPtr1->next)
438 {
439 if(strcmp(libmapPtr1->lib,*pp)==0)
440 {
441 for(pp1=libmapPtr1->uses;*pp1;pp1++)
442 {
443 if(strcmp(*pp1,libmapPtr->lib)==0)break;
444 }
445 if(*pp1)
446 {
447 fprintf
448 (stderr,
449 " WARNING: %s and %s use each other.\n",
450 libmapPtr->lib,
451 libmapPtr1->lib);
452 }
453 }
454 else
455 {
456 /* Not right yet...
457 for(pp1=libmapPtr1->uses;*pp1;pp1++)
458 {
459 for(libmapPtr0=libmap;libmapPtr0!=libmapPtr1;
460 libmapPtr0=libmapPtr0->next)
461 {
462 if(libmapPtr0==*pp)
463 {
464 fprintf
465 (stderr,
466 " WARNING: triangular dependecy:\n"
467 " %s uses %s uses %s uses %s.\n",
468 libmapPtr->lib,
469 libmapPtr1->lib,
470 libmapPtr0->lib,
471 libmapPtr->lib);
472 }
473 }
474 }
475 */
476 }
477 }
478 }
479 }
480
481 fprintf(stderr," Reordering according to dependencies...\n");
482 do
483 {
484 swapping=0;
485 prevPtr2=0;
486 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
487 {
488 for(pp=libmapPtr->uses;*pp;pp++)
489 {
490 prevPtr1=0;
491 for(libmapPtr1=libmap;libmapPtr1!=libmapPtr;
492 libmapPtr1=libmapPtr1->next)
493 {
494 if(strcmp(libmapPtr1->lib,*pp)==0)
495 {
496 /* Check that 1st doesn't use 2nd... */
497 for(pp1=libmapPtr1->uses;*pp1;pp1++)
498 {
499 if(strcmp(*pp1,libmapPtr->lib)==0)break;
500 }
501 if(!*pp1) /* If not... */
502 {
503 swapping=1;
504 /* Make previous of 1st now point to 2nd... */
505 if(prevPtr1)
506 {
507 prevPtr1->next=libmapPtr;
508 }
509 else
510 {
511 libmap=libmapPtr;
512 }
513 /* Make 2nd now point to what 1st did, unless
514 it's adjacent, in which case make it point
515 to 1st itself... */
516 tmpp=libmapPtr->next;
517 if(libmapPtr1->next==libmapPtr)
518 {
519 libmapPtr->next=libmapPtr1;
520 }
521 else
522 {
523 libmapPtr->next=libmapPtr1->next;
524 }
525 /* Make previous of 2nd point to 1st, unless
526 it's adjacent, in which case leave it... */
527 if(libmapPtr1->next!=libmapPtr)
528 {
529 prevPtr2->next=libmapPtr1;
530 }
531 /* Make 1st now point to what 2nd did... */
532 libmapPtr1->next=tmpp;
533 break;
534 }
535 }
536 prevPtr1=libmapPtr1;
537 }
538 if(swapping)break;
539 }
540 prevPtr2=libmapPtr;
541 if(swapping)break;
542 }
543 }while(swapping);
544
545 fprintf(stderr," Writing new library map file...\n");
546 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
547 {
548 printf("%s:",libmapPtr->lib);
549 for(pp=libmapPtr->uses;*pp;pp++)
550 {
551 printf(" %s",*pp);
552 }
553 printf("\n");
554 printf("source/%s/GNUmakefile\n",libmapPtr->trigger);
555 }
556 }
557 else if (optm)
558 {
559 /* Write out full library list... */
560 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
561 {
562 /* Check existance of libraries and print out only installed ones */
563 sprintf(libname, "%s/lib%s.a", libpath, libmapPtr->lib);
564 if (access(libname,R_OK))
565 {
566 sprintf(libname, "%s/lib%s.so", libpath, libmapPtr->lib);
567 if (!access(libname,R_OK))
568 {
569 printf("-l%s ",libmapPtr->lib);
570 }
[483]571 else /* case MacOS .dylib */
572 {
573 sprintf(libname, "%s/lib%s.dylib", libpath, libmapPtr->lib);
574 if (!access(libname,R_OK))
575 {
576 printf("-l%s ",libmapPtr->lib);
577 }
578 }
[472]579 }
580 else
581 {
582 printf("-l%s ",libmapPtr->lib);
583 }
584 libmapPtr=libmapPtr->next;
585 }
586 }
587 else
588 {
589 /* Add dependent libraries... */
590 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
591 {
592 if(libmapPtr->used)
593 {
594 for(pp=libmapPtr->uses;*pp;pp++)
595 {
596 for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next)
597 {
598 if(strcmp(libmapPtr1->lib,*pp)==0)
599 {
600 libmapPtr1->used=1;
601 }
602 }
603 }
604 }
605 }
606
607 /* Write out library list... */
608 for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
609 {
610 if(libmapPtr->used)
611 {
612 printf("-l%s ",libmapPtr->lib);
613 }
614 }
615 }
616
617 exit(0);
618
619}
Note: See TracBrowser for help on using the repository browser.