[BACK]Return to arch.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/arch.c between version 1.69 and 1.70

version 1.69, 2007/09/17 09:28:36 version 1.70, 2007/09/17 10:06:44
Line 86 
Line 86 
 #include "ohash.h"  #include "ohash.h"
 #include "config.h"  #include "config.h"
 #include "defines.h"  #include "defines.h"
   #include "buf.h"
 #include "dir.h"  #include "dir.h"
 #include "direxpand.h"  #include "direxpand.h"
 #include "arch.h"  #include "arch.h"
Line 113 
Line 114 
 #define MACHINE_ARCH TARGET_MACHINE_ARCH  #define MACHINE_ARCH TARGET_MACHINE_ARCH
 #endif  #endif
   
 static struct ohash archives;   /* Archives we've already examined.  */  static struct ohash archives;   /* Archives we've already examined.  */
   
 typedef struct Arch_ {  typedef struct Arch_ {
         struct ohash members;   /* All the members of this archive, as          struct ohash members;   /* All the members of this archive, as
                                  * struct arch_member entries.  */                                   * struct arch_member entries.  */
         char name[1];           /* Archive name. */          char name[1];           /* Archive name. */
 } Arch;  } Arch;
   
Line 129 
Line 130 
 /* Each archive member is tied to an arch_member structure,  /* Each archive member is tied to an arch_member structure,
  * suitable for hashing.  */   * suitable for hashing.  */
 struct arch_member {  struct arch_member {
         TIMESTAMP mtime;        /* Member modification date.  */          TIMESTAMP mtime;                /* Member modification date.  */
         char date[AR_DATE_SIZE+1];          char date[AR_DATE_SIZE+1];      /* Same, before conversion to numeric
                                 /* Same, before conversion to numeric value.  */                                           * value.  */
         char name[1];           /* Member name.  */          char name[1];                   /* Member name.  */
 };  };
   
 static struct ohash_info members_info = {  static struct ohash_info members_info = {
Line 161 
Line 162 
     (defined(__OpenBSD__) && defined(__ELF__))      (defined(__OpenBSD__) && defined(__ELF__))
 #define SVR4ARCHIVES  #define SVR4ARCHIVES
 #endif  #endif
   static bool parse_archive(Buffer, const char **, Lst, SymTable *);
   static void add_archive_node(Lst, const char *);
   
 #ifdef SVR4ARCHIVES  #ifdef SVR4ARCHIVES
 struct SVR4namelist {  struct SVR4namelist {
         char *fnametab;         /* Extended name table strings */          char *fnametab;         /* Extended name table strings */
         size_t fnamesize;       /* Size of the string table */          size_t fnamesize;       /* Size of the string table */
 };  };
   
 static const char *svr4list = "Archive list";  static const char *svr4list = "Archive list";
Line 207 
Line 210 
 }  }
 #endif  #endif
   
   bool
   Arch_ParseArchive(const char **line, Lst nodes, SymTable *ctxt)
   {
           bool result;
           BUFFER expand;
   
           Buf_Init(&expand, MAKE_BSIZE);
           result = parse_archive(&expand, line, nodes, ctxt);
           Buf_Destroy(&expand);
           return result;
   }
   
 /* Side-effects: Some nodes may be created.  */  static void
 bool  add_archive_node(Lst nodes, const char *name)
 Arch_ParseArchive(char **linePtr,   /* Pointer to start of specification */  
     Lst nodeLst,                    /* Lst on which to place the nodes */  
     SymTable *ctxt)                 /* Context in which to expand variables */  
 {  {
         char *cp;               /* Pointer into line */          GNode *gn;
         GNode *gn;              /* New node */  
         char *libName;          /* Library-part of specification */  
         char *memberName;       /* Member-part of specification */  
         char nameBuf[MAKE_BSIZE]; /* temporary place for node name */  
         char saveChar;          /* Ending delimiter of member-name */  
         bool subLibName;        /* true if libName should have/had  
                                  * variable substitution performed on it */  
   
         libName = *linePtr;          gn = Targ_FindNode(name, TARG_CREATE);
           gn->type |= OP_ARCHV;
           Lst_AtEnd(nodes, gn);
   }
   
         subLibName = false;  static bool
   parse_archive(Buffer expand, const char **linePtr, Lst nodeLst, SymTable *ctxt)
   {
           const char *cp;         /* Pointer into line */
           const char *lib;        /* Library-part of specification */
           const char *elib;
           const char *member;     /* Member-part of specification */
           const char *emember;
           bool subst_lib;
   
         for (cp = libName; *cp != '(' && *cp != '\0';) {          /* figure out the library name part */
           lib = *linePtr;
           subst_lib = false;
   
           for (cp = lib; *cp != '(' && *cp != '\0';) {
                 if (*cp == '$') {                  if (*cp == '$') {
                         if (!Var_ParseSkip(&cp, ctxt))                          if (!Var_ParseSkip(&cp, ctxt))
                                 return false;                                  return false;
                         subLibName = true;                          subst_lib = true;
                 } else                  } else
                         cp++;                          cp++;
         }          }
   
         *cp++ = '\0';          elib = cp;
         if (subLibName)          if (subst_lib) {
                 libName = Var_Subst(libName, ctxt, true);                  lib = Var_Substi(lib, elib, ctxt, true);
                   elib = lib + strlen(lib);
           }
   
           cp++;
           /* iterate on members, that may be separated by spaces */
         for (;;) {          for (;;) {
                 /* First skip to the start of the member's name, mark that                  /* First skip to the start of the member's name, mark that
                  * place and skip to the end of it (either white-space or                   * place and skip to the end of it (either white-space or
                  * a close paren).  */                   * a close paren).  */
                 bool doSubst = false;   /* true if need to substitute in                  bool subst_member = false;
                                          * memberName */  
   
                 while (isspace(*cp))                  while (isspace(*cp))
                         cp++;                          cp++;
                 memberName = cp;                  member = cp;
                 while (*cp != '\0' && *cp != ')' && !isspace(*cp)) {                  while (*cp != '\0' && *cp != ')' && !isspace(*cp)) {
                         if (*cp == '$') {                          if (*cp == '$') {
                                 if (!Var_ParseSkip(&cp, ctxt))                                  if (!Var_ParseSkip(&cp, ctxt))
                                         return false;                                          return false;
                                 doSubst = true;                                  subst_member = true;
                         } else                          } else
                                 cp++;                                  cp++;
                 }                  }
Line 270 
Line 291 
                 }                  }
   
                 /* If we didn't move anywhere, we must be done.  */                  /* If we didn't move anywhere, we must be done.  */
                 if (cp == memberName)                  if (cp == member)
                         break;                          break;
   
                 saveChar = *cp;                  emember = cp;
                 *cp = '\0';  
   
                 /* XXX: This should be taken care of intelligently by                  /* XXX: This should be taken care of intelligently by
                  * SuffExpandChildren, both for the archive and the member                   * SuffExpandChildren, both for the archive and the member
Line 286 
Line 306 
                  * but them's the breaks -- we need to do this since                   * but them's the breaks -- we need to do this since
                  * SuffExpandChildren calls us, otherwise we could assume the                   * SuffExpandChildren calls us, otherwise we could assume the
                  * thing would be taken care of later.  */                   * thing would be taken care of later.  */
                 if (doSubst) {                  if (subst_member) {
                         char *buf;                          const char *oldMemberName = member;
                         char *sacrifice;                          const char *result;
                         char *oldMemberName = memberName;  
                         size_t length;  
   
                         memberName = Var_Subst(memberName, ctxt, true);                          member = Var_Substi(member, emember, ctxt, true);
   
                         /* Now form an archive spec and recurse to deal with                          /* Now form an archive spec and recurse to deal with
                          * nested variables and multi-word variable values....                           * nested variables and multi-word variable values....
                          * The results are just placed at the end of the                           * The results are just placed at the end of the
                          * nodeLst we're returning.  */                           * nodeLst we're returning.  */
                         length = strlen(memberName)+strlen(libName)+3;                          Buf_Addi(expand, lib, elib);
                         buf = sacrifice = emalloc(length);                          Buf_AddChar(expand, '(');
                           Buf_AddString(expand, member);
                           Buf_AddChar(expand, ')');
                           result = Buf_Retrieve(expand);
   
                         snprintf(buf, length, "%s(%s)", libName, memberName);                          if (strchr(member, '$') &&
                               memcmp(member, oldMemberName,
                         if (strchr(memberName, '$') &&                                  emember - oldMemberName) == 0) {
                                 strcmp(memberName, oldMemberName) == 0) {  
                                 /* Must contain dynamic sources, so we can't                                  /* Must contain dynamic sources, so we can't
                                  * deal with it now.  Just create an ARCHV node                                   * deal with it now.  let SuffExpandChildren
                                  * for the thing and let SuffExpandChildren                                   * handle it later  */
                                  * handle it...  */                                  add_archive_node(nodeLst, result);
                                 gn = Targ_FindNode(buf, TARG_CREATE);                          } else if (!Arch_ParseArchive(&result, nodeLst, ctxt))
   
                                 if (gn == NULL) {  
                                         free(buf);  
                                         return false;  
                                 } else {  
                                         gn->type |= OP_ARCHV;  
                                         Lst_AtEnd(nodeLst, gn);  
                                 }  
                         } else if (!Arch_ParseArchive(&sacrifice, nodeLst,  
                             ctxt)) {  
                                 /* Error in nested call -- free buffer and  
                                  * return false ourselves.  */  
                                 free(buf);  
                                 return false;                                  return false;
                         }                          Buf_Reset(expand);
                         /* Free buffer and continue with our work.      */                  } else if (Dir_HasWildcardsi(member, emember)) {
                         free(buf);                          LIST  members;
                 } else if (Dir_HasWildcards(memberName)) {                          char  *m;
                         LIST members;  
                         char *member;  
   
                         Lst_Init(&members);                          Lst_Init(&members);
   
                         Dir_Expand(memberName, defaultPath, &members);                          Dir_Expandi(member, emember, defaultPath, &members);
                         while ((member = (char *)Lst_DeQueue(&members))                          while ((m = (char *)Lst_DeQueue(&members)) != NULL) {
                             != NULL) {                                  Buf_Addi(expand, lib, elib);
                                 snprintf(nameBuf, MAKE_BSIZE, "%s(%s)",                                  Buf_AddChar(expand, '(');
                                     libName, member);                                  Buf_AddString(expand, m);
                                 free(member);                                  Buf_AddChar(expand, ')');
                                 gn = Targ_FindNode(nameBuf, TARG_CREATE);                                  free(m);
                                 /* We've found the node, but have to make sure                                  add_archive_node(nodeLst, Buf_Retrieve(expand));
                                  * the rest of the world knows it's an archive                                  Buf_Reset(expand);
                                  * member, without having to constantly check  
                                  * for parentheses, so we type the thing with  
                                  * the OP_ARCHV bit before we place it on the  
                                  * end of the provided list.  */  
                                 gn->type |= OP_ARCHV;  
                                 Lst_AtEnd(nodeLst, gn);  
                         }                          }
                 } else {                  } else {
                         snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName,                          Buf_Addi(expand, lib, elib);
                             memberName);                          Buf_AddChar(expand, '(');
                         gn = Targ_FindNode(nameBuf, TARG_CREATE);                          Buf_Addi(expand, member, emember);
                         /* We've found the node, but have to make sure the rest                          Buf_AddChar(expand, ')');
                          * of the world knows it's an archive member, without                          add_archive_node(nodeLst, Buf_Retrieve(expand));
                          * having to constantly check for parentheses, so we                          Buf_Reset(expand);
                          * type the thing with the OP_ARCHV bit before we place  
                          * it on the end of the provided list.  */  
                         gn->type |= OP_ARCHV;  
                         Lst_AtEnd(nodeLst, gn);  
                 }                  }
                 if (doSubst)                  if (subst_member)
                         free(memberName);                          free((char *)member);
   
                 *cp = saveChar;  
         }          }
   
         /* If substituted libName, free it now, since we need it no longer.  */          if (subst_lib)
         if (subLibName)                  free((char *)lib);
                 free(libName);  
   
         /* We promised the pointer would be set up at the next non-space, so          /* We promised the pointer would be set up at the next non-space, so
          * we must advance cp there before setting *linePtr... (note that on           * we must advance cp there before setting *linePtr... (note that on
Line 397 
Line 390 
 static Arch *  static Arch *
 read_archive(const char *archive, const char *earchive)  read_archive(const char *archive, const char *earchive)
 {  {
         FILE *arch;             /* Stream to archive */          FILE *arch;       /* Stream to archive */
         char magic[SARMAG];          char magic[SARMAG];
         Arch *ar;          Arch *ar;
 #ifdef SVR4ARCHIVES  #ifdef SVR4ARCHIVES
Line 424 
Line 417 
   
         for (;;) {          for (;;) {
                 size_t n;                  size_t n;
                 struct ar_hdr arHeader;                  struct ar_hdr arHeader; /* Archive-member header */
                                 /* Archive-member header for reading archive */                  off_t size;             /* Size of archive member */
                 off_t size;     /* Size of archive member */  
                 char buffer[PATH_MAX];                  char buffer[PATH_MAX];
                 char *memberName;                  char *memberName;       /* Current member name while hashing. */
                                 /* Current member name while hashing. */  
                 char *cp;                  char *cp;
   
                 memberName = buffer;                  memberName = buffer;
Line 448 
Line 439 
   
                 if (memcmp(arHeader.ar_fmag, ARFMAG, sizeof(arHeader.ar_fmag))                  if (memcmp(arHeader.ar_fmag, ARFMAG, sizeof(arHeader.ar_fmag))
                     != 0) {                      != 0) {
                         /* The header is bogus.  */                          /* header is bogus.  */
                         break;                          break;
                 } else {                  } else {
                         /* We need to advance the stream's pointer to the start                          /* We need to advance the stream's pointer to the start
Line 474 
Line 465 
                                 /* SVR4 magic mode.  */                                  /* SVR4 magic mode.  */
                                 memberName = ArchSVR4Entry(&list, memberName,                                  memberName = ArchSVR4Entry(&list, memberName,
                                     size, arch);                                      size, arch);
                                 if (memberName == NULL) /* Invalid data */                                  if (memberName == NULL)
                                           /* Invalid data */
                                         break;                                          break;
                                 else if (memberName == svr4list)                                  else if (memberName == svr4list)
                                     /* List of files entry */                                          /* List of files entry */
                                         continue;                                          continue;
                                 /* Got the entry.  */                                  /* Got the entry.  */
                                 /* XXX this assumes further processing, such as                                  /* XXX this assumes further processing, such as
Line 546 
Line 538 
  */   */
 static TIMESTAMP  static TIMESTAMP
 ArchMTimeMember(  ArchMTimeMember(
     const char    *archive,   /* Path to the archive */      const char *archive,        /* Path to the archive */
     const char    *member,    /* Name of member. If it is a path, only the      const char *member,         /* Name of member. If it is a path, only the
                                * last component is used. */                                   * last component is used. */
     bool          hash)       /* true if archive should be hashed if not      bool hash)                  /* true if archive should be hashed if not
                                * already so. */                                   * already so. */
 {  {
         FILE *arch;             /* Stream to archive */          FILE *arch;             /* Stream to archive */
         Arch *ar;               /* Archive descriptor */          Arch *ar;               /* Archive descriptor */
         unsigned int slot;      /* Place of archive in the archives hash */          unsigned int slot;      /* Place of archive in the archives hash */
         const char *end = NULL;          const char *end = NULL;
         const char *cp;          const char *cp;
Line 600 
Line 592 
                 struct arch_member *he;                  struct arch_member *he;
                 end = NULL;                  end = NULL;
   
                 he = ohash_find(&ar->members,                  he = ohash_find(&ar->members, ohash_qlookupi(&ar->members,
                     ohash_qlookupi(&ar->members, member, &end));                      member, &end));
                 if (he != NULL)                  if (he != NULL)
                         return mtime_of_member(he);                          return mtime_of_member(he);
                 else {                  else {
Line 699 
Line 691 
         if (entry >= l->fnamesize) {          if (entry >= l->fnamesize) {
                 if (DEBUG(ARCH))                  if (DEBUG(ARCH))
                         printf("SVR4 entry offset /%s is greater than %lu\n",                          printf("SVR4 entry offset /%s is greater than %lu\n",
                            name, (u_long)l->fnamesize);                              name, (u_long)l->fnamesize);
                 return NULL;                  return NULL;
         }          }
   
Line 734 
Line 726 
     struct ar_hdr *arHeaderPtr,/* Pointer to header structure to be filled in */      struct ar_hdr *arHeaderPtr,/* Pointer to header structure to be filled in */
     const char    *mode)      /* mode for opening the stream */      const char    *mode)      /* mode for opening the stream */
 {  {
         FILE *arch;       /* Stream to archive */          FILE *    arch;       /* Stream to archive */
         char *cp;          char      *cp;
         char magic[SARMAG];          char      magic[SARMAG];
         size_t length;          size_t    length;
 #ifdef SVR4ARCHIVES  #ifdef SVR4ARCHIVES
         struct SVR4namelist list;          struct SVR4namelist list;
   
Line 770 
Line 762 
         /* Error handling is simpler than for read_archive, since we just          /* Error handling is simpler than for read_archive, since we just
          * look for a given member.  */           * look for a given member.  */
         while (fread(arHeaderPtr, sizeof(struct ar_hdr), 1, arch) == 1) {          while (fread(arHeaderPtr, sizeof(struct ar_hdr), 1, arch) == 1) {
                 off_t size;     /* Size of archive member */                  off_t size;       /* Size of archive member */
                 char *memberName;                  char *memberName;
   
                 if (memcmp(arHeaderPtr->ar_fmag, ARFMAG,                  if (memcmp(arHeaderPtr->ar_fmag, ARFMAG,
Line 809 
Line 801 
                  */                   */
                 if (memberName[0] == '/') {                  if (memberName[0] == '/') {
                         /* svr4 magic mode.  */                          /* svr4 magic mode.  */
                         memberName = ArchSVR4Entry(&list,                          memberName = ArchSVR4Entry(&list, arHeaderPtr->ar_name,
                             arHeaderPtr->ar_name, size, arch);                              size, arch);
                         if (memberName == NULL) /* Invalid data */                          if (memberName == NULL)
                                   /* Invalid data */
                                 break;                                  break;
                         else if (memberName == svr4list)                          else if (memberName == svr4list)
                             /* List of files entry */                                  /* List of files entry */
                                 continue;                                  continue;
                         /* Got the entry.  */                          /* Got the entry.  */
                         if (strcmp(memberName, member) == 0) {                          if (strcmp(memberName, member) == 0) {
Line 874 
Line 867 
   
         arch = ArchFindMember(archive, member, &arHeader, "r+");          arch = ArchFindMember(archive, member, &arHeader, "r+");
         if (arch != NULL) {          if (arch != NULL) {
                 snprintf(arHeader.ar_date, sizeof(arHeader.ar_date), "%-12ld",                  snprintf(arHeader.ar_date, sizeof(arHeader.ar_date),
                     (long) timestamp2time_t(now));                      "%-12ld", (long) timestamp2time_t(now));
                 if (fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR) == 0)                  if (fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR) == 0)
                         (void)fwrite(&arHeader, sizeof(struct ar_hdr), 1, arch);                          (void)fwrite(&arHeader, sizeof(struct ar_hdr), 1, arch);
                 fclose(arch);                  fclose(arch);
Line 903 
Line 896 
         if (gn->path != NULL) {          if (gn->path != NULL) {
                 ArchTouch(gn->path, RANLIBMAG);                  ArchTouch(gn->path, RANLIBMAG);
                 set_times(gn->path);                  set_times(gn->path);
     }          }
 #endif  #endif
 }  }
   

Legend:
Removed from v.1.69  
changed lines
  Added in v.1.70