ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
liblist.c
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file liblist.c
1 
2 /*
3 Given a "libname.map" file on standard input and a list or directory
4 of .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>.
13 The .d files are specified in the argument(s).
14 The libname.map is on standard input.
15 
16 Usage:
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
23 where:
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 
28 Frank 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 
44 extern char *optarg;
45 extern int optind, opterr, optopt;
46 
47 char** 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 
126 int 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);
426  bufferPtr=buffer;
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 }