source: trunk/geant4/config/liblist.c @ 661

Last change on this file since 661 was 593, checked in by garnier, 17 years ago

r627@mac-90108: laurentgarnier | 2007-11-09 07:57:42 +0100
modif dans les includes directives

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