source: trunk/config/liblist.c@ 817

Last change on this file since 817 was 761, checked in by garnier, 18 years ago

modif depuis que mon mac a plante : mise a jour des moc en mieux

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