source: trunk/config/liblist.c @ 1349

Last change on this file since 1349 was 1349, checked in by garnier, 13 years ago

update

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