Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
liblist.c
Go to the documentation of this file.
1 /* $Id: liblist.c 66368 2012-12-18 09:20:17Z gcosmo $ */
2 
3 /*
4 Given a "libname.map" file on standard input and a list or directory
5 of .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>.
14 The .d files are specified in the argument(s).
15 The libname.map is on standard input.
16 
17 Usage:
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
24 where:
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 
29 Frank 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 
45 extern char *optarg;
46 extern int optind, opterr, optopt;
47 
48 char** 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 
127 int 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=0;
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  /* create tmp. string libname */
580  int libname_usable_size=24;
581  if ( ! libname ) libname=malloc(libname_usable_size+16);
582 
583  /* Write out full library list... */
584  for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
585  {
586  if ( strlen(libpath)+strlen(libmapPtr->lib) > libname_usable_size ) {
587  libname_usable_size=(strlen(libpath)+strlen(libmapPtr->lib))*2;
588  free(libname);
589  libname=malloc(libname_usable_size+16);
590  }
591  /* Check existance of libraries and print out only installed ones */
592 
593 
594  sprintf(libname, "%s/lib%s.a", libpath, libmapPtr->lib);
595  if (access(libname,R_OK))
596  {
597  sprintf(libname, "%s/lib%s.so", libpath, libmapPtr->lib);
598  if (!access(libname,R_OK))
599  {
600  printf("-l%s ",libmapPtr->lib);
601  }
602  else /* case MacOS .dylib */
603  {
604  sprintf(libname, "%s/lib%s.dylib", libpath, libmapPtr->lib);
605  if (!access(libname,R_OK))
606  {
607  printf("-l%s ",libmapPtr->lib);
608  }
609  }
610  }
611  else
612  {
613  printf("-l%s ",libmapPtr->lib);
614  }
615  libmapPtr=libmapPtr->next;
616  }
617  }
618  else
619  {
620  /* Add dependent libraries... */
621  for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
622  {
623  if(libmapPtr->used)
624  {
625  for(pp=libmapPtr->uses;*pp;pp++)
626  {
627  for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next)
628  {
629  if(strcmp(libmapPtr1->lib,*pp)==0)
630  {
631  libmapPtr1->used=1;
632  }
633  }
634  }
635  }
636  }
637 
638  /* Write out library list... */
639  for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
640  {
641  if(libmapPtr->used)
642  {
643  printf("-l%s ",libmapPtr->lib);
644  }
645  }
646  }
647 
648  exit(0);
649 
650 }
int optind
void * calloc(size_t __nmemb, size_t __size)
Definition: hjmalloc.cc:67
const XML_Char * s
void free(void *__ptr)
Definition: hjmalloc.cc:140
const char * p
Definition: xmltok.h:285
#define buffer
Definition: xmlparse.cc:611
#define TRIGSIZE
Definition: liblist.c:42
#define NLIBMAX
Definition: liblist.c:43
int main(int argc, char **argv)
Definition: liblist.c:127
int opterr
#define bufferPtr
Definition: xmlparse.cc:612
int optopt
const XML_Char int len
char * optarg
char ** parsedir(char *directory, int *argc)
Definition: liblist.c:48
void * malloc(size_t __size)
Definition: hjmalloc.cc:30
#define BUFSIZE
Definition: liblist.c:41