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

Last change on this file since 794 was 761, checked in by garnier, 16 years ago

modif depuis que mon mac a plante : mise a jour des moc en mieux

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