source: trunk/config/liblist.c@ 1353

Last change on this file since 1353 was 1349, checked in by garnier, 15 years ago

update

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