source: trunk/config/liblist.c @ 1017

Last change on this file since 1017 was 850, checked in by garnier, 16 years ago

geant4.8.2 beta

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