home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bsd
/
src
/
make
/
make-amiga
/
arch.c
next >
Wrap
C/C++ Source or Header
|
1993-09-23
|
30KB
|
952 lines
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
* Copyright (c) 1988, 1989 by Adam de Boor
* Copyright (c) 1989 by Berkeley Softworks
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)arch.c 5.7 (Berkeley) 12/28/90";
#endif /* not lint */
/*-
* 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_MemTime 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<name> format.
*
* Arch_LibOODate Special function to decide if a library node
* is out-of-date.
*
* Arch_Init Initialize this module.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <ctype.h>
#include <ar.h>
#include <ranlib.h>
#include <stdio.h>
#include "make.h"
#include "hash.h"
static Lst archives; /* Lst of archives we've already examined */
typedef struct Arch {
char *name; /* Name of archive */
Hash_Table members; /* All the members of the archive described
* by <name, struct ar_hdr *> key/value pairs */
} Arch;
static FILE *ArchFindMember();
/*-
*-----------------------------------------------------------------------
* 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 */
GNode *ctxt; /* Context in which to expand variables */
{
register char *cp; /* Pointer into line */
GNode *gn; /* New node */
char *libName; /* Library-part of specification */
char *memName; /* Member-part of specification */
char nameBuf[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'; cp++) {
if (*cp == '$') {
/*
* Variable spec, so call the Var module to parse the puppy
* so we can safely advance beyond it...
*/
int length;
Boolean freeIt;
char *result;
result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
if (result == var_Error) {
return(FAILURE);
} else {
subLibName = TRUE;
}
if (freeIt) {
free(result);
}
cp += length-1;
}
}
*cp++ = '\0';
if (subLibName) {
libName = Var_Subst(libName, ctxt, TRUE);
}
while (1) {
/*
* 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 == '$') {
/*
* Variable spec, so call the Var module to parse the puppy
* so we can safely advance beyond it...
*/
int length;
Boolean freeIt;
char *result;
result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
if (result == var_Error) {
return(FAILURE);
} else {
doSubst = TRUE;
}
if (freeIt) {
free(result);
}
cp += length;
} else {
cp++;
}
}
/*
* If the specification ends without a closing parenthesis,
* chances are there's something wrong (like a missing backslash),
* so it's better to return failure than allow such things to happen
*/
if (*cp == '\0') {
printf("No closing parenthesis in archive specification\n");
return (FAILURE);
}
/*
* If we didn't move anywhere, we must be done
*/
if (cp == memName) {
break;
}
saveChar = *cp;
*cp = '\0';
/*
* XXX: This should be taken care of intelligently by
* SuffExpandChildren, both for the archive and the member portions.
*/
/*
* If member contains variables, try and substitute for them.
* This will slow down archive specs with dynamic sources, of course,
* since we'll be (non-)substituting them three times, but them's
* the breaks -- we need to do this since SuffExpandChildren calls
* us, otherwise we could assume the thing woul