Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:16:08

0001 
0002 /*
0003 Given a "libname.map" file on standard input and a list or directory
0004 of .d dependency files liblist produces:
0005   a) without -l option, a library list ordered according to the libname.map,
0006      giving a warning if conflicting dependencies are found in the .d files.
0007   b) with -l option, another libname.map, ordered according firstly to the
0008      original libname.map file, then reordered according to the dependencies
0009      found in the .d files.  This option is used for compiling the file
0010      libname.map from all the dependencies.
0011   c) with -m <lpath> option, the whole existing libraries list ordered
0012      according to the libname.map, where libraries are placed in <lpath>.
0013 The .d files are specified in the argument(s).
0014 The libname.map is on standard input.
0015 
0016 Usage:
0017   liblist *.d < libname.map
0018   liblist -d <ddir> < libname.map
0019   liblist -l *.d < libname.map
0020   liblist -ld <ddir> < libname.map
0021   liblist -l -d <ddir> < libname.map
0022   liblist -m <lpath> < libname.map
0023 where:
0024   <ddir>  is a directory name of a directory which is recursively
0025           searched for dependency files
0026   <lpath> is the path where libraries are located
0027 
0028 Frank Behner, John Allison 13th February 1999.
0029 */
0030 
0031 #include <stdio.h>
0032 #include <string.h>
0033 #include <unistd.h>
0034 #include <dirent.h>
0035 #include <sys/stat.h>
0036 #include <unistd.h>
0037 #include <errno.h>
0038 #include <stdlib.h>
0039 
0040 #define BUFSIZE 1000000
0041 #define TRIGSIZE 1000
0042 #define NLIBMAX 200
0043 
0044 extern char *optarg;
0045 extern int optind, opterr, optopt;
0046 
0047 char** parsedir(char *directory,int *argc)
0048 {
0049   DIR *actualdir;
0050   FILE *actualfile;
0051   struct dirent *entry; 
0052   char *buffer=0;
0053   struct stat status;
0054   char **targv=0,**ptr,**phelp;
0055   int len,targc,s;
0056 
0057   /*Open the actual directory*/
0058   actualdir=opendir(directory);
0059 
0060   if(!actualdir) return targv;
0061 
0062   /*Loop over all entries */
0063   for(entry=readdir(actualdir);entry!=NULL;entry=readdir(actualdir))
0064     {
0065       /* Throw away . and .. */
0066       if(strcmp(entry->d_name,".")==0 ||
0067      strcmp(entry->d_name,"..")==0) continue;
0068       /* Obtain the status information of that entry */
0069       if(buffer) free(buffer);
0070       buffer=(char*) malloc((strlen(directory)+
0071                  strlen(entry->d_name)+2)*sizeof(char));
0072       strcpy(buffer,directory);
0073       strcat(buffer,"/");
0074       strcat(buffer,entry->d_name);
0075       s=stat(buffer,&status);
0076       if(s==0)
0077     {
0078       if(S_ISDIR(status.st_mode))
0079         {
0080           /* a directory, so we are going recursive*/
0081           targc=0;
0082           ptr=parsedir(buffer,&targc);
0083           if(targc)
0084         {
0085           phelp=targv;
0086           targv=(char**) malloc((*argc+targc)*sizeof(char*));
0087           memcpy(targv,phelp,*argc*sizeof(char*));
0088           memcpy(&targv[*argc],ptr,targc*sizeof(char*));
0089           *argc+=targc;
0090           free(phelp);
0091           free(ptr);
0092         }
0093         }
0094       else if(S_ISREG(status.st_mode))
0095         {
0096           /* a regular file is it .d? */
0097           len=strlen(entry->d_name);
0098           if(entry->d_name[len-2]=='.' && entry->d_name[len-1]=='d')
0099         {
0100           phelp=targv;
0101           targv=(char**) malloc((*argc+1)*sizeof(char*));
0102           memcpy(targv,phelp,*argc*sizeof(char*));
0103           targv[*argc]=strdup(buffer);
0104           (*argc)++;
0105           free(phelp);
0106         }
0107         }
0108     }
0109       else
0110     {
0111       fprintf
0112         (stderr,
0113          "  No status - perhaps file %s does not exist.\n",
0114          directory);
0115       exit(1);
0116     }
0117     }
0118 
0119   if(buffer) free(buffer);
0120   closedir(actualdir);
0121 
0122   return targv;
0123 }
0124         
0125  
0126 int main (int argc, char** argv) {
0127 
0128   char static buffer[BUFSIZE],*bufferPtr,workbuf[256];
0129   char *ptr,*p,**pp,**pp1,**pp2,*directory=0,*libpath=0;
0130   char **rargv;
0131   char *libname=0;
0132   int i,optl=0,optm=0,swapping,c,rargc;
0133   FILE *fp;
0134 
0135 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
0136   char *ntg4tmp=0,*ntg4tmp1=0;
0137   int nti; 
0138 #endif
0139 
0140   struct libmap_
0141     {
0142       char *lib;      /* Library name, e.g., G4run. */
0143       char *trigger;  /* Source directory, e.g., source/run/.  */
0144       int used;       /* True if used by these dependency files.  */
0145       char **uses;    /* List of library names which this library uses.  */
0146       struct libmap_ *next;
0147   };
0148 
0149   struct libmap_ *libmap=0,*libmapPtr=0,*libmapPtr1=0,*libmapPtr2=0,
0150     *prevPtr1,*prevPtr2,*tmpp,*userLibmapPtr;
0151 
0152   while((c=getopt(argc,argv,"ld: m:"))!=EOF)
0153     {
0154       switch(c)
0155     {
0156     case 'l':
0157       optl=1;
0158       break;
0159     case 'd':
0160       directory=strdup(optarg);
0161       break;
0162         case 'm':
0163           optm=1;
0164       libpath=strdup(optarg);
0165           break;
0166     }
0167     }
0168       
0169   /*Adjust parameters after parsing options */
0170 
0171   if(optind<argc)
0172     {
0173       rargv=&argv[optind];
0174       rargc=argc-optind;
0175     }
0176   else
0177     {
0178       rargv=0;
0179       rargc=0;
0180     }
0181 
0182   if(directory)
0183     {
0184       if(rargc==0)
0185     {
0186       rargv=parsedir(directory,&rargc);
0187     }
0188       else
0189     {
0190       fprintf
0191         (stderr,
0192          "  ERROR: If you specify a directory don't also specify files\n");
0193       exit(1);
0194     }
0195     }
0196 
0197   if(optl)fprintf(stderr,"  Reading library name map file...\n");
0198   while (!feof(stdin))
0199     {
0200       /* Get library name... */
0201       fgets(buffer,BUFSIZE,stdin);
0202       if(feof(stdin)) break;
0203       if (strlen(buffer) >= BUFSIZE-1)
0204       {
0205          fprintf(stderr,
0206        " Internal ERROR: BUFSIZE too small to read library name map file\n");
0207      exit(1);
0208       }
0209            /* discarded trailing \n, as gets() was doing */
0210       if ( buffer[strlen(buffer)-1] == '\n') 
0211         {   buffer[strlen(buffer)-1]='\0'; }  
0212 
0213       ptr=strtok(buffer,":\n");
0214 
0215       /* Check for duplicate names... */
0216       for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next)
0217     {
0218       if(strcmp(libmapPtr1->lib,ptr)==0)
0219         {
0220           fprintf(stderr,"  ERROR: Duplicate library name: %s\n",ptr);
0221           fprintf(stderr,
0222               "  Perhaps a duplicate subdirectory with"
0223               " a GNUmakefile with the same library name.\n"
0224               );
0225           exit(1);
0226         }
0227     }
0228 
0229       if(libmap)
0230     {
0231       libmapPtr->next=(struct libmap_*) malloc(sizeof(struct libmap_));
0232       libmapPtr=libmapPtr->next;
0233     }
0234       else /* First time through anchor libmapPtr to libmap. */
0235     {
0236       libmap=(struct libmap_*) malloc(sizeof(struct libmap_));
0237       libmapPtr=libmap;
0238     }
0239       libmapPtr->next=0;      
0240       libmapPtr->lib=strdup(ptr);
0241       libmapPtr->used=0;
0242       libmapPtr->uses=(char**)calloc(NLIBMAX,sizeof(char*));
0243 
0244       /* If option -l not specified, fill uses list... */
0245       if(!optl && !optm)
0246     {
0247       pp=libmapPtr->uses;
0248       if(ptr)
0249         {
0250           ptr=strtok(NULL," \n");
0251           while (ptr)
0252         {
0253           *pp=strdup(ptr);
0254           pp++;
0255           ptr=strtok(NULL," \n");
0256         }
0257         }
0258     }
0259 
0260       if(!optm)
0261         {
0262           /* Get directory name... */
0263           fgets(buffer,BUFSIZE,stdin);
0264       if (strlen(buffer) >= BUFSIZE-1)
0265       {
0266              fprintf(stderr,
0267            " Internal ERROR: BUFSIZE too small to read directory name\n");
0268          exit(1);
0269       }
0270            /* discarded trailing \n, as gets() was doing */
0271           if ( buffer[strlen(buffer)-1] == '\n') 
0272              {   buffer[strlen(buffer)-1]='\0'; }  
0273 
0274           ptr=strtok(buffer,"/");
0275           if(!ptr)
0276         {
0277           fprintf(stderr,"  ERROR: \"/\" before \"source\" expected.\n");
0278           exit(1);
0279         }
0280           while(ptr&&strcmp (ptr,"source"))ptr=strtok(NULL,"/");
0281           ptr=strtok(NULL,"/");
0282           if(!ptr)
0283         {
0284           fprintf(stderr,"  ERROR: \"source\" expected.\n");
0285           exit(1);
0286         }
0287           libmapPtr->trigger=(char*)malloc(TRIGSIZE);
0288       if(strlen(ptr)>TRIGSIZE)
0289           {
0290             fprintf(stderr,"  ERROR: String overflow for: %s\n", ptr);
0291             exit(1);
0292           }
0293           strcpy(libmapPtr->trigger,ptr);
0294           ptr=strtok(NULL,"/");
0295           while(ptr&&strcmp(ptr,"GNUmakefile"))
0296         {
0297           strcat(libmapPtr->trigger,"/");
0298           strcat(libmapPtr->trigger,ptr);
0299           ptr=strtok(NULL,"/");
0300         }
0301           if(!ptr)
0302         {
0303           fprintf
0304             (stderr,
0305              "  ERROR: \"source/<unique-sub-path>/GNUmakefile\" expected.\n");
0306           exit(1);
0307         }
0308     }
0309     }
0310 
0311   if(optl)fprintf(stderr,"  Reading dependency files...\n");
0312 
0313 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
0314       ntg4tmp=getenv("G4TMP");
0315       if ( ! ntg4tmp ) 
0316         {
0317            fprintf(stderr,"  ERROR: Cannot find environment variable G4TMP\n");
0318            exit(1);
0319         }
0320       ntg4tmp1=strdup(ntg4tmp);
0321 #endif
0322 
0323   for(i=0;i<rargc;i++)
0324     {
0325       fp=fopen(rargv[i],"r");
0326       fgets(buffer,BUFSIZE,fp);
0327 
0328 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
0329       ptr=strchr(ntg4tmp1,':');
0330 
0331       while ( ptr=strchr(buffer,'\\') ) *ptr='/';
0332  
0333       while (ntg4tmp1!=NULL &&  (ptr=strstr(buffer,ntg4tmp1))!=NULL )
0334         {
0335           for(nti=0;nti<strlen(ntg4tmp1);nti++) ptr[nti]=' ';
0336         }
0337 #endif
0338      
0339       /* Clip target out of dependency file... */
0340       ptr=strtok(buffer,":");
0341       
0342       /* Look for a "user" library... */
0343       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0344     {
0345       if(strlen(libmapPtr->lib)>256)
0346           {
0347             fprintf(stderr,"  ERROR: String overflow for: %s\n", libmapPtr->lib);
0348             exit(1);
0349           }
0350           strcpy(workbuf,libmapPtr->lib);
0351       /* Add trailing "/" to distinguish track/ and tracking/, etc. */
0352       strcat(workbuf,"/");
0353       if(strstr(ptr,workbuf)) break;
0354     }
0355       if(libmapPtr)
0356     {
0357       userLibmapPtr=libmapPtr;
0358     }
0359       else
0360     {
0361       userLibmapPtr=0;
0362     }
0363 
0364       if(!optm)
0365     {
0366       /* Look for a "used" library and add it to the "user" uses list... */
0367       bufferPtr=strtok(NULL,"\n");  /* Start *after* ":". */
0368       if (!bufferPtr) 
0369         {
0370           fprintf(stderr,"  WARNING: It seems there is nothing after \':\' in dependency file %s.\n", rargv[i]);
0371         }
0372       else {
0373       do
0374         {
0375           for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0376             {
0377           /* Look for trigger string. */
0378               if(strlen(libmapPtr->trigger)>256)
0379                   {
0380                     fprintf(stderr,"  ERROR: String overflow for: %s\n", libmapPtr->trigger);
0381                     exit(1);
0382                   }
0383                   strcpy(workbuf,libmapPtr->trigger);
0384           strcat(workbuf,"/include");
0385           ptr=strstr(bufferPtr,workbuf);
0386           if(ptr && (userLibmapPtr != libmapPtr))
0387             {
0388               libmapPtr->used=1;
0389               if(userLibmapPtr)
0390                 {
0391               for(pp=userLibmapPtr->uses;*pp;pp++)
0392                 {
0393                   if(strcmp(*pp,libmapPtr->lib)==0)break;
0394                 }
0395               if(!*pp)*pp=libmapPtr->lib;
0396                 }
0397             }
0398           /* Also look for library name in case header files are
0399              placed in temporary directories under a subdirectory
0400              with the same name as the library name.  This can
0401              happen with Objectivity which makes header files
0402              from .ddl files and places them in a temporary
0403              directory. */
0404               if(strlen(libmapPtr->lib)>256)
0405                   {
0406                     fprintf(stderr,"  ERROR: String overflow for: %s\n", libmapPtr->lib);
0407                     exit(1);
0408                   }
0409           strcpy(workbuf,libmapPtr->lib);
0410           strcat(workbuf,"/");
0411           ptr=strstr(bufferPtr,workbuf);
0412           if(ptr && (userLibmapPtr != libmapPtr))
0413             {
0414               libmapPtr->used=1;
0415               if(userLibmapPtr)
0416                 {
0417               for(pp=userLibmapPtr->uses;*pp;pp++)
0418                 {
0419                   if(strcmp(*pp,libmapPtr->lib)==0)break;
0420                 }
0421               if(!*pp)*pp=libmapPtr->lib;
0422                 }
0423             }
0424             }
0425           fgets(buffer,BUFSIZE,fp);
0426           bufferPtr=buffer;
0427 
0428 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
0429           while ( ptr=strchr(buffer,'\\') ) *ptr='/';
0430 
0431           while (ntg4tmp1 &&  (ptr=strstr(buffer,ntg4tmp1)) )
0432             {
0433           for(nti=0;nti<strlen(ntg4tmp1);nti++) ptr[nti]=' ';
0434             }
0435 #endif
0436 
0437         } while(!feof(fp));
0438       fclose(fp);
0439         }
0440       }
0441     }
0442 
0443 #if defined ( _WIN32 ) || defined ( __CYGWIN__ ) || defined ( __CYGWIN32__ )
0444       free(ntg4tmp1);
0445 #endif
0446 
0447   if(optl) /* This option is used for compiling the file libname.map
0448           from all the dependencies. */
0449     {
0450       fprintf(stderr,"  Checking for circular dependencies...\n");
0451       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0452     {
0453       for(pp=libmapPtr->uses;*pp;pp++)
0454         {
0455           for(libmapPtr1=libmap;libmapPtr1!=libmapPtr;
0456           libmapPtr1=libmapPtr1->next)
0457         {
0458           if(strcmp(libmapPtr1->lib,*pp)==0)
0459             {
0460               for(pp1=libmapPtr1->uses;*pp1;pp1++)
0461             {
0462               if(strcmp(*pp1,libmapPtr->lib)==0)break;
0463             }
0464               if(*pp1)
0465             {
0466               fprintf
0467                 (stderr,
0468                  "  WARNING: %s and %s use each other.\n",
0469                  libmapPtr->lib,
0470                  libmapPtr1->lib);
0471             }
0472             }
0473           else 
0474             {
0475               /* Not right yet...
0476               for(pp1=libmapPtr1->uses;*pp1;pp1++)
0477             {
0478               for(libmapPtr0=libmap;libmapPtr0!=libmapPtr1;
0479                   libmapPtr0=libmapPtr0->next)
0480                 {
0481                   if(libmapPtr0==*pp)
0482                 {
0483                   fprintf
0484                     (stderr,
0485                      "  WARNING: triangular dependecy:\n"
0486                      "  %s uses %s uses %s uses %s.\n",
0487                      libmapPtr->lib,
0488                      libmapPtr1->lib,
0489                      libmapPtr0->lib,
0490                      libmapPtr->lib);
0491                 }
0492                 }
0493             }
0494               */
0495             }
0496         }
0497         }
0498     }
0499 
0500       fprintf(stderr,"  Reordering according to dependencies...\n");
0501       do
0502     {
0503       swapping=0;
0504       prevPtr2=0;
0505       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0506         {
0507           for(pp=libmapPtr->uses;*pp;pp++)
0508         {
0509           prevPtr1=0;
0510           for(libmapPtr1=libmap;libmapPtr1!=libmapPtr;
0511               libmapPtr1=libmapPtr1->next)
0512             {
0513               if(strcmp(libmapPtr1->lib,*pp)==0)
0514             {
0515               /* Check that 1st doesn't use 2nd... */
0516               for(pp1=libmapPtr1->uses;*pp1;pp1++)
0517                 {
0518                   if(strcmp(*pp1,libmapPtr->lib)==0)break;
0519                 }
0520               if(!*pp1) /* If not... */
0521                 {
0522                   swapping=1;
0523                   /* Make previous of 1st now point to 2nd... */
0524                   if(prevPtr1)
0525                 {
0526                   prevPtr1->next=libmapPtr;
0527                 }
0528                   else
0529                 {
0530                   libmap=libmapPtr;
0531                 }
0532                   /* Make 2nd now point to what 1st did, unless
0533                  it's adjacent, in which case make it point
0534                  to 1st itself... */
0535                   tmpp=libmapPtr->next;
0536                   if(libmapPtr1->next==libmapPtr)
0537                 {
0538                   libmapPtr->next=libmapPtr1;
0539                 }
0540                   else
0541                 {
0542                   libmapPtr->next=libmapPtr1->next;
0543                 }
0544                   /* Make previous of 2nd point to 1st, unless
0545                  it's adjacent, in which case leave it... */
0546                   if(libmapPtr1->next!=libmapPtr)
0547                 {
0548                   prevPtr2->next=libmapPtr1;
0549                 }
0550                   /* Make 1st now point to what 2nd did... */
0551                   libmapPtr1->next=tmpp;
0552                   break;
0553                 }
0554             }
0555               prevPtr1=libmapPtr1;
0556             }
0557           if(swapping)break;
0558         }
0559           prevPtr2=libmapPtr;
0560           if(swapping)break;
0561         }
0562     }while(swapping);
0563 
0564       fprintf(stderr,"  Writing new library map file...\n");
0565       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0566     {
0567       printf("%s:",libmapPtr->lib);
0568       for(pp=libmapPtr->uses;*pp;pp++)
0569         {
0570           printf(" %s",*pp);
0571         }
0572       printf("\n");
0573       printf("source/%s/GNUmakefile\n",libmapPtr->trigger);
0574     }
0575     }
0576   else if (optm)
0577     {
0578       /* create tmp. string libname */ 
0579       int libname_usable_size=24;
0580       if ( ! libname ) libname=malloc(libname_usable_size+16);
0581 
0582       /* Write out full library list... */      
0583       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0584       {
0585     if ( strlen(libpath)+strlen(libmapPtr->lib) > libname_usable_size ) {
0586       libname_usable_size=(strlen(libpath)+strlen(libmapPtr->lib))*2;
0587       free(libname);
0588       libname=malloc(libname_usable_size+16);
0589     }
0590         /* Check existance of libraries and print out only installed ones */
0591       
0592     
0593     snprintf(libname, libname_usable_size+16, "%s/lib%s.a", libpath, libmapPtr->lib);
0594         if (access(libname,R_OK))
0595     {
0596       snprintf(libname, libname_usable_size+16, "%s/lib%s.so", libpath, libmapPtr->lib);
0597           if (!access(libname,R_OK))
0598       {
0599             printf("-l%s ",libmapPtr->lib);
0600       }
0601           else  /* case MacOS .dylib */
0602           {
0603         snprintf(libname, libname_usable_size+16, "%s/lib%s.dylib", libpath, libmapPtr->lib);
0604             if (!access(libname,R_OK))
0605         {
0606               printf("-l%s ",libmapPtr->lib);
0607         }
0608           }
0609     }
0610         else
0611     {
0612           printf("-l%s ",libmapPtr->lib);
0613     }
0614     libmapPtr=libmapPtr->next;
0615       }
0616     }
0617   else
0618     {
0619       /* Add dependent libraries... */
0620       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0621     {
0622       if(libmapPtr->used)
0623         {
0624           for(pp=libmapPtr->uses;*pp;pp++)
0625         {
0626           for(libmapPtr1=libmap;libmapPtr1;libmapPtr1=libmapPtr1->next)
0627             {
0628               if(strcmp(libmapPtr1->lib,*pp)==0)
0629             {
0630               libmapPtr1->used=1;
0631             }
0632             }
0633         }         
0634         }
0635     }
0636 
0637       /* Write out library list... */
0638       for(libmapPtr=libmap;libmapPtr;libmapPtr=libmapPtr->next)
0639     {
0640       if(libmapPtr->used)
0641         {
0642           printf("-l%s ",libmapPtr->lib);
0643         }
0644     }
0645     }
0646       
0647   exit(0);
0648   
0649 }