=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/arch.c,v retrieving revision 1.44 retrieving revision 1.45 diff -c -r1.44 -r1.45 *** src/usr.bin/make/arch.c 2001/05/03 13:41:00 1.44 --- src/usr.bin/make/arch.c 2001/05/23 12:34:39 1.45 *************** *** 1,5 **** /* $OpenPackages$ */ ! /* $OpenBSD: arch.c,v 1.44 2001/05/03 13:41:00 espie Exp $ */ /* $NetBSD: arch.c,v 1.17 1996/11/06 17:58:59 christos Exp $ */ /* --- 1,5 ---- /* $OpenPackages$ */ ! /* $OpenBSD: arch.c,v 1.45 2001/05/23 12:34:39 espie Exp $ */ /* $NetBSD: arch.c,v 1.17 1996/11/06 17:58:59 christos Exp $ */ /* *************** *** 66,146 **** * SUCH DAMAGE. */ ! /*- ! * arch.c -- ! * Functions to manipulate libraries, archives and their members. ! * * Once again, cacheing/hashing comes into play in the manipulation * of archives. The first time an archive is referenced, all of its members' * headers are read and hashed and the archive closed again. All hashed ! * archives are kept on a list which is searched each time an archive member ! * is referenced. * - * The interface to this module is: - * Arch_ParseArchive Given an archive specification, return a list - * of GNode's, one for each member in the spec. - * FAILURE is returned if the specification is - * invalid for some reason. - * - * Arch_Touch Alter the modification time of the archive - * member described by the given node to be - * the current time. - * - * Arch_TouchLib Update the modification time of the library - * described by the given node. This is special - * because it also updates the modification time - * of the library's table of contents. - * - * Arch_MTime Find the modification time of a member of - * an archive *in the archive*. The time is also - * placed in the member's GNode. Returns the - * modification time. - * - * Arch_MemMTime Find the modification time of a member of - * an archive. Called when the member doesn't - * already exist. Looks in the archive for the - * modification time. Returns the modification - * time. - * - * Arch_FindLib Search for a library along a path. The - * library name in the GNode should be in - * -l format. - * - * Arch_LibOODate Special function to decide if a library node - * is out-of-date. - * - * Arch_Init Initialize this module. - * - * Arch_End Cleanup this module. */ ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include "make.h" ! #include "ohash.h" ! #include "dir.h" ! #include "config.h" - #ifndef lint - #if 0 - static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; - #else - UNUSED - static char rcsid[] = "$OpenBSD: arch.c,v 1.44 2001/05/03 13:41:00 espie Exp $"; - #endif - #endif /* not lint */ - - #ifdef TARGET_MACHINE #undef MACHINE #define MACHINE TARGET_MACHINE --- 66,103 ---- * SUCH DAMAGE. */ ! /* * Once again, cacheing/hashing comes into play in the manipulation * of archives. The first time an archive is referenced, all of its members' * headers are read and hashed and the archive closed again. All hashed ! * archives are kept in a hash (archives) which is searched each time ! * an archive member is referenced. * */ ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include "ohash.h" ! #include "config.h" ! #include "defines.h" ! #include "dir.h" ! #include "arch.h" ! #include "var.h" ! #include "targ.h" ! #include "memory.h" ! #include "gnode.h" ! #include "timestamp.h" ! #include "lst.h" #ifdef TARGET_MACHINE #undef MACHINE #define MACHINE TARGET_MACHINE *************** *** 191,197 **** #ifdef CLEANUP static void ArchFree(Arch *); #endif ! static TIMESTAMP ArchMTimeMember(const char *, const char *, Boolean); static FILE *ArchFindMember(const char *, const char *, struct ar_hdr *, const char *); static void ArchTouch(const char *, const char *); #if defined(__svr4__) || defined(__SVR4) || \ --- 148,154 ---- #ifdef CLEANUP static void ArchFree(Arch *); #endif ! static TIMESTAMP ArchMTimeMember(const char *, const char *, bool); static FILE *ArchFindMember(const char *, const char *, struct ar_hdr *, const char *); static void ArchTouch(const char *, const char *); #if defined(__svr4__) || defined(__SVR4) || \ *************** *** 224,230 **** memcpy(n->date, &(hdr->ar_date), AR_DATE_SIZE); n->date[AR_DATE_SIZE] = '\0'; /* Don't compute mtime before it is needed. */ ! set_out_of_date(n->mtime); return n; } --- 181,187 ---- memcpy(n->date, &(hdr->ar_date), AR_DATE_SIZE); n->date[AR_DATE_SIZE] = '\0'; /* Don't compute mtime before it is needed. */ ! ts_set_out_of_date(n->mtime); return n; } *************** *** 233,239 **** struct arch_member *m; { if (is_out_of_date(m->mtime)) ! grab_date((time_t) strtol(m->date, NULL, 10), m->mtime); return m->mtime; } --- 190,196 ---- struct arch_member *m; { if (is_out_of_date(m->mtime)) ! ts_set_from_time_t((time_t) strtol(m->date, NULL, 10), m->mtime); return m->mtime; } *************** *** 263,285 **** ! /*- ! *----------------------------------------------------------------------- ! * Arch_ParseArchive -- ! * Parse the archive specification in the given line and find/create ! * the nodes for the specified archive members, placing their nodes ! * on the given list. ! * ! * Results: ! * SUCCESS if it was a valid specification. The linePtr is updated ! * to point to the first non-space after the archive spec. The ! * nodes for the members are placed on the given list. ! * ! * Side Effects: ! * Some nodes may be created. The given list is extended. ! *----------------------------------------------------------------------- ! */ ! ReturnStatus Arch_ParseArchive(linePtr, nodeLst, ctxt) char **linePtr; /* Pointer to start of specification */ Lst nodeLst; /* Lst on which to place the nodes */ --- 220,227 ---- ! /* Side-effects: Some nodes may be created. */ ! bool Arch_ParseArchive(linePtr, nodeLst, ctxt) char **linePtr; /* Pointer to start of specification */ Lst nodeLst; /* Lst on which to place the nodes */ *************** *** 291,335 **** char *memName; /* Member-part of specification */ char nameBuf[MAKE_BSIZE]; /* temporary place for node name */ char saveChar; /* Ending delimiter of member-name */ ! Boolean subLibName; /* TRUE if libName should have/had * variable substitution performed on it */ libName = *linePtr; ! subLibName = FALSE; for (cp = libName; *cp != '(' && *cp != '\0';) { if (*cp == '$') { ! ReturnStatus result; ! cp += Var_ParseSkip(cp, ctxt, &result); ! if (result == FAILURE) ! return FAILURE; ! subLibName = TRUE; } else cp++; } *cp++ = '\0'; if (subLibName) ! libName = Var_Subst(libName, ctxt, TRUE); for (;;) { /* First skip to the start of the member's name, mark that * place and skip to the end of it (either white-space or * a close paren). */ ! Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ while (*cp != '\0' && *cp != ')' && isspace(*cp)) cp++; memName = cp; while (*cp != '\0' && *cp != ')' && !isspace(*cp)) { if (*cp == '$') { ! ReturnStatus result; ! cp += Var_ParseSkip(cp, ctxt, &result); ! if (result == FAILURE) ! return FAILURE; ! doSubst = TRUE; } else cp++; } --- 233,277 ---- char *memName; /* 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; ! subLibName = false; for (cp = libName; *cp != '(' && *cp != '\0';) { if (*cp == '$') { ! bool ok; ! cp += Var_ParseSkip(cp, ctxt, &ok); ! if (ok == false) ! return false; ! subLibName = true; } else cp++; } *cp++ = '\0'; if (subLibName) ! libName = Var_Subst(libName, ctxt, true); for (;;) { /* First skip to the start of the member's name, mark that * place and skip to the end of it (either white-space or * a close paren). */ ! bool doSubst = false; /* true if need to substitute in memName */ while (*cp != '\0' && *cp != ')' && isspace(*cp)) cp++; memName = cp; while (*cp != '\0' && *cp != ')' && !isspace(*cp)) { if (*cp == '$') { ! bool ok; ! cp += Var_ParseSkip(cp, ctxt, &ok); ! if (ok == false) ! return false; ! doSubst = true; } else cp++; } *************** *** 340,346 **** * happen. */ if (*cp == '\0') { printf("No closing parenthesis in archive specification\n"); ! return FAILURE; } /* If we didn't move anywhere, we must be done. */ --- 282,288 ---- * happen. */ if (*cp == '\0') { printf("No closing parenthesis in archive specification\n"); ! return false; } /* If we didn't move anywhere, we must be done. */ *************** *** 364,370 **** char *sacrifice; char *oldMemName = memName; ! memName = Var_Subst(memName, ctxt, TRUE); /* Now form an archive spec and recurse to deal with nested * variables and multi-word variable values.... The results --- 306,312 ---- char *sacrifice; char *oldMemName = memName; ! memName = Var_Subst(memName, ctxt, true); /* Now form an archive spec and recurse to deal with nested * variables and multi-word variable values.... The results *************** *** 377,396 **** /* Must contain dynamic sources, so we can't deal with it now. * Just create an ARCHV node for the thing and let * SuffExpandChildren handle it... */ ! gn = Targ_FindNode(buf, NULL, TARG_CREATE); if (gn == NULL) { free(buf); ! return FAILURE; } else { gn->type |= OP_ARCHV; Lst_AtEnd(nodeLst, gn); } ! } else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) { ! /* Error in nested call -- free buffer and return FAILURE * ourselves. */ free(buf); ! return FAILURE; } /* Free buffer and continue with our work. */ free(buf); --- 319,338 ---- /* Must contain dynamic sources, so we can't deal with it now. * Just create an ARCHV node for the thing and let * SuffExpandChildren handle it... */ ! gn = Targ_FindNode(buf, TARG_CREATE); 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; } /* Free buffer and continue with our work. */ free(buf); *************** *** 400,410 **** Lst_Init(&members); ! Dir_Expand(memName, &dirSearchPath, &members); while ((member = (char *)Lst_DeQueue(&members)) != NULL) { snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, member); free(member); ! gn = Targ_FindNode(nameBuf, NULL, TARG_CREATE); /* We've found the node, but have to make sure the rest of * the world knows it's an archive member, without having * to constantly check for parentheses, so we type the --- 342,352 ---- Lst_Init(&members); ! Dir_Expand(memName, dirSearchPath, &members); while ((member = (char *)Lst_DeQueue(&members)) != NULL) { snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, member); free(member); ! gn = Targ_FindNode(nameBuf, TARG_CREATE); /* We've found the node, but have to make sure the rest of * the world knows it's an archive member, without having * to constantly check for parentheses, so we type the *************** *** 415,421 **** } } else { snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, memName); ! gn = Targ_FindNode(nameBuf, NULL, TARG_CREATE); /* We've found the node, but have to make sure the rest of the * world knows it's an archive member, without having to * constantly check for parentheses, so we type the thing with --- 357,363 ---- } } else { snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, memName); ! gn = Targ_FindNode(nameBuf, TARG_CREATE); /* We've found the node, but have to make sure the rest of the * world knows it's an archive member, without having to * constantly check for parentheses, so we type the thing with *************** *** 442,448 **** } while (*cp != '\0' && isspace(*cp)); *linePtr = cp; ! return SUCCESS; } /* Helper function: ar fields are not null terminated. */ --- 384,390 ---- } while (*cp != '\0' && isspace(*cp)); *linePtr = cp; ! return true; } /* Helper function: ar fields are not null terminated. */ *************** *** 598,604 **** * out of date). * * Side Effects: ! * Cache the whole archive contents if hash is TRUE. *----------------------------------------------------------------------- */ static TIMESTAMP --- 540,546 ---- * out of date). * * Side Effects: ! * Cache the whole archive contents if hash is true. *----------------------------------------------------------------------- */ static TIMESTAMP *************** *** 606,612 **** const char *archive; /* Path to the archive */ const char *member; /* Name of member. If it is a path, only the * last component is used. */ ! Boolean hash; /* TRUE if archive should be hashed if not * already so. */ { FILE * arch; /* Stream to archive */ --- 548,554 ---- const char *archive; /* Path to the archive */ const char *member; /* Name of member. If it is a path, only the * last component is used. */ ! bool hash; /* true if archive should be hashed if not * already so. */ { FILE * arch; /* Stream to archive */ *************** *** 616,622 **** const char *cp; TIMESTAMP result; ! set_out_of_date(result); /* Because of space constraints and similar things, files are archived * using their final path components, not the entire thing, so we need * to point 'member' to the final component, if there is one, to make --- 558,564 ---- const char *cp; TIMESTAMP result; ! ts_set_out_of_date(result); /* Because of space constraints and similar things, files are archived * using their final path components, not the entire thing, so we need * to point 'member' to the final component, if there is one, to make *************** *** 641,647 **** if (arch != NULL) { fclose(arch); ! grab_date( (time_t)strtol(sarh.ar_date, NULL, 10), result); } return result; } --- 583,589 ---- if (arch != NULL) { fclose(arch); ! ts_set_from_time_t( (time_t)strtol(sarh.ar_date, NULL, 10), result); } return result; } *************** *** 934,950 **** } } ! /*- ! *----------------------------------------------------------------------- ! * Arch_Touch -- ! * Touch a member of an archive. ! * * Side Effects: - * The 'time' field of the member's header is updated. * The modification time of the entire archive is also changed. * For a library, this could necessitate the re-ranlib'ing of the * whole thing. - *----------------------------------------------------------------------- */ void Arch_Touch(gn) --- 876,886 ---- } } ! /* * Side Effects: * The modification time of the entire archive is also changed. * For a library, this could necessitate the re-ranlib'ing of the * whole thing. */ void Arch_Touch(gn) *************** *** 953,969 **** ArchTouch(Varq_Value(ARCHIVE_INDEX, gn), Varq_Value(MEMBER_INDEX, gn)); } - /*- - *----------------------------------------------------------------------- - * Arch_TouchLib -- - * Given a node which represents a library, touch the thing, making - * sure that the table of contents also is touched. - * - * Side Effects: - * The modification time of the library and of the RANLIBMAG - * member are set to 'now'. - *----------------------------------------------------------------------- - */ void Arch_TouchLib(gn) GNode *gn; /* The node of the library to touch */ --- 889,894 ---- *************** *** 976,1018 **** #endif } - /*- - *----------------------------------------------------------------------- - * Arch_MTime -- - * Return the modification time of a member of an archive. - * - * Results: - * The modification time. - * - * Side Effects: - * The mtime field of the given node is filled in with the value - * returned by the function. - *----------------------------------------------------------------------- - */ TIMESTAMP Arch_MTime(gn) GNode *gn; /* Node describing archive member */ { gn->mtime = ArchMTimeMember(Varq_Value(ARCHIVE_INDEX, gn), Varq_Value(MEMBER_INDEX, gn), ! TRUE); return gn->mtime; } - /*- - *----------------------------------------------------------------------- - * Arch_MemMTime -- - * Given a non-existent archive member's node, get its modification - * time from its archived form, if it exists. - * - * Results: - * The modification time. - * - * Side Effects: - * The mtime field is filled in. - *----------------------------------------------------------------------- - */ TIMESTAMP Arch_MemMTime(gn) GNode *gn; --- 901,917 ---- #endif } TIMESTAMP Arch_MTime(gn) GNode *gn; /* Node describing archive member */ { gn->mtime = ArchMTimeMember(Varq_Value(ARCHIVE_INDEX, gn), Varq_Value(MEMBER_INDEX, gn), ! true); return gn->mtime; } TIMESTAMP Arch_MemMTime(gn) GNode *gn; *************** *** 1045,1072 **** } else if (pgn->make) { /* Something which isn't a library depends on the existence of * this target, so it needs to exist. */ ! set_out_of_date(gn->mtime); break; } } return gn->mtime; } ! /*- ! *----------------------------------------------------------------------- ! * Arch_FindLib -- ! * Search for a library along the given search path. ! * ! * Side Effects: ! * The node's 'path' field is set to the found path (including the ! * actual file name, not -l...). If the system can handle the -L ! * flag when linking (or we cannot find the library), we assume that ! * the user has placed the .LIBRARIES variable in the final linking ! * command (or the linker will know where to find it) and set the ! * TARGET variable for this node to be the node's name. Otherwise, ! * we set the TARGET variable to be the full path of the library, ! * as returned by Dir_FindFile. ! *----------------------------------------------------------------------- */ void Arch_FindLib(gn, path) --- 944,962 ---- } else if (pgn->make) { /* Something which isn't a library depends on the existence of * this target, so it needs to exist. */ ! ts_set_out_of_date(gn->mtime); break; } } return gn->mtime; } ! /* If the system can handle the -L flag when linking (or we cannot find ! * the library), we assume that the user has placed the .LIBRARIES variable ! * in the final linking command (or the linker will know where to find it) ! * and set the TARGET variable for this node to be the node's name. Otherwise, ! * we set the TARGET variable to be the full path of the library, ! * as returned by Dir_FindFile. */ void Arch_FindLib(gn, path) *************** *** 1118,1190 **** * TOC. * * Results: ! * TRUE if the library is out-of-date. FALSE otherwise. * * Side Effects: * The library will be hashed if it hasn't been already. *----------------------------------------------------------------------- */ ! Boolean Arch_LibOODate(gn) GNode *gn; /* The library's graph node */ { TIMESTAMP modTimeTOC; /* mod time of __.SYMDEF */ if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) ! return FALSE; ! if (is_before(now, gn->mtime) || is_before(gn->mtime, gn->cmtime) || is_out_of_date(gn->mtime)) ! return TRUE; #ifdef RANLIBMAG /* non existent libraries are always out-of-date. */ if (gn->path == NULL) ! return TRUE; ! modTimeTOC = ArchMTimeMember(gn->path, RANLIBMAG, FALSE); if (!is_out_of_date(modTimeTOC)) { if (DEBUG(ARCH) || DEBUG(MAKE)) printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); ! return is_before(modTimeTOC, gn->cmtime); } /* A library w/o a table of contents is out-of-date. */ if (DEBUG(ARCH) || DEBUG(MAKE)) printf("No t.o.c...."); ! return TRUE; #else ! return FALSE; #endif } - /*- - *----------------------------------------------------------------------- - * Arch_Init -- - * Initialize things for this module. - * - * Side Effects: - * The 'archives' hash is initialized. - *----------------------------------------------------------------------- - */ void Arch_Init() { ohash_init(&archives, 4, &arch_info); } ! ! ! /*- ! *----------------------------------------------------------------------- ! * Arch_End -- ! * Cleanup things for this module. ! * ! * Side Effects: ! * The 'archives' hash is freed ! *----------------------------------------------------------------------- ! */ void Arch_End() { - #ifdef CLEANUP Arch *e; unsigned int i; --- 1008,1060 ---- * TOC. * * Results: ! * true if the library is out-of-date. false otherwise. * * Side Effects: * The library will be hashed if it hasn't been already. *----------------------------------------------------------------------- */ ! bool Arch_LibOODate(gn) GNode *gn; /* The library's graph node */ { TIMESTAMP modTimeTOC; /* mod time of __.SYMDEF */ if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) ! return false; ! if (is_strictly_before(now, gn->mtime) || is_strictly_before(gn->mtime, gn->cmtime) || is_out_of_date(gn->mtime)) ! return true; #ifdef RANLIBMAG /* non existent libraries are always out-of-date. */ if (gn->path == NULL) ! return true; ! modTimeTOC = ArchMTimeMember(gn->path, RANLIBMAG, false); if (!is_out_of_date(modTimeTOC)) { if (DEBUG(ARCH) || DEBUG(MAKE)) printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); ! return is_strictly_before(modTimeTOC, gn->cmtime); } /* A library w/o a table of contents is out-of-date. */ if (DEBUG(ARCH) || DEBUG(MAKE)) printf("No t.o.c...."); ! return true; #else ! return false; #endif } void Arch_Init() { ohash_init(&archives, 4, &arch_info); } ! #ifdef CLEANUP void Arch_End() { Arch *e; unsigned int i; *************** *** 1192,1210 **** e = ohash_next(&archives, &i)) ArchFree(e); ohash_delete(&archives); - #endif } ! /*- ! *----------------------------------------------------------------------- ! * Arch_IsLib -- ! * Check if the node is a library ! * ! * Results: ! * True or False. ! *----------------------------------------------------------------------- ! */ ! Boolean Arch_IsLib(gn) GNode *gn; { --- 1062,1071 ---- e = ohash_next(&archives, &i)) ArchFree(e); ohash_delete(&archives); } + #endif ! bool Arch_IsLib(gn) GNode *gn; { *************** *** 1212,1222 **** int fd; if (gn->path == NULL || (fd = open(gn->path, O_RDONLY)) == -1) ! return FALSE; if (read(fd, buf, SARMAG) != SARMAG) { (void)close(fd); ! return FALSE; } (void)close(fd); --- 1073,1083 ---- int fd; if (gn->path == NULL || (fd = open(gn->path, O_RDONLY)) == -1) ! return false; if (read(fd, buf, SARMAG) != SARMAG) { (void)close(fd); ! return false; } (void)close(fd);