Geant4-11
liblist.c
Go to the documentation of this file.
1
2/*
3Given a "libname.map" file on standard input and a list or directory
4of .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>.
13The .d files are specified in the argument(s).
14The libname.map is on standard input.
15
16Usage:
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
23where:
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
28Frank 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
44extern char *optarg;
45extern int optind, opterr, optopt;
46
47char** 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 strncat(buffer,"/",1);
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
126int 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 strncat(libmapPtr->trigger,"/",1);
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 strncat(workbuf,"/",1);
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 strncat(workbuf,"/include",8);
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 strncat(workbuf,"/",1);
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);
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 sprintf(libname, "%s/lib%s.a", libpath, libmapPtr->lib);
594 if (access(libname,R_OK))
595 {
596 sprintf(libname, "%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 sprintf(libname, "%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}
static constexpr double s
Definition: G4SIunits.hh:154
char ** parsedir(char *directory, int *argc)
Definition: liblist.c:47
#define TRIGSIZE
Definition: liblist.c:41
int main(int argc, char **argv)
Definition: liblist.c:126
int optopt
Definition: liblist.c:45
#define NLIBMAX
Definition: liblist.c:42
int optind
char * optarg
int opterr
Definition: liblist.c:45
#define BUFSIZE
Definition: liblist.c:40
def exit()
Definition: g4zmq.py:99
#define buffer
Definition: xmlparse.cc:628
#define bufferPtr
Definition: xmlparse.cc:629