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

Last change on this file since 493 was 483, checked in by garnier, 17 years ago

r569@mac-90108: laurentgarnier | 2007-06-05 15:53:34 +0200
version contre geant4.8.2.p01

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