diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2001-05-23 12:34:58 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2001-05-23 12:34:58 +0000 |
commit | db8e89b77998123612f763908cdd1c46cc7ea24f (patch) | |
tree | af42f9f2b44b6bae3a6ca23660ff612c49709e27 | |
parent | d0640eab6718b3ff0eeb66e78aa4d5d8a8ed3c24 (diff) |
Mostly clean-up:
- cut up those huge include files into separate interfaces for all modules.
Put the interface documentation there, and not with the implementation.
- light-weight includes for needed concrete types (lst_t.h, timestamp_t.h).
- cut out some more logically separate parts: cmd_exec, varname, parsevar,
timestamp.
- put all error handling functions together, so that we will be able to
clean them up.
- more systematic naming: functioni to handle interval, function to handle
string.
- put the init/end code apart to minimize coupling.
- kill weird types like ReturnStatus and Boolean. Use standard bool (with a
fallback for non-iso systems)
- better interface documentation for lots of subsystems.
As a result, make compilation goes somewhat faster (5%, even considering
the largish BSD copyrights to read). The corresponding preprocessed
source goes down from 1,5M to 1M.
A few minor code changes as well: Parse_DoVar is no longer destructive.
Parse_IsVar functionality is folded into Parse_DoVar (as it knows what an
assignment is), a few more interval handling functions. Avoid calling
XXX_End when they do nothing, just #define XXX_End to nothing.
Parse_DoVar is slightly more general: it will handle compound assignments
as long as they make sense, e.g., VAR +!= cmd
will work. As a side effect, VAR++=value now triggers an error
(two + in assignment).
- this stuff doesn't occur in portable Makefiles.
- writing VAR++ = value or VAR+ +=value disambiguates it.
- this is a good thing, it uncovered a bug in bsd.port.mk.
Tested by naddy@. Okayed millert@. I'll handle the fallback if there is
any. This went through a full make build anyways, including isakmpd
(without mickey's custom binutils, as he didn't see fit to share it with me).
79 files changed, 4377 insertions, 3675 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile index 9eee31f2b98..67d27fc3a6b 100644 --- a/usr.bin/make/Makefile +++ b/usr.bin/make/Makefile @@ -1,16 +1,20 @@ -# $OpenBSD: Makefile,v 1.26 2001/05/03 13:40:59 espie Exp $ +# $OpenBSD: Makefile,v 1.27 2001/05/23 12:34:39 espie Exp $ PROG= make CFLAGS+= -I${.OBJDIR} -I${.CURDIR} ${WARNINGS} -WARNINGS=-Wall -W -Wno-char-subscripts -Wstrict-prototypes -pedantic #-Wmissing-prototypes +WARNINGS=-Wall -W -Wno-char-subscripts -Wstrict-prototypes -pedantic -Wmissing-prototypes CFLAGS+=-DUSE_TIMESPEC +CFLAGS+=-DHAS_BOOL_H +CFLAGS+=-DHAS_PATHS_H .if (${MACHINE_ARCH} == "m88k") CFLAGS+=-O0 .endif -SRCS= arch.c buf.c compat.c cond.c dir.c error.c for.c job.c lowparse.c \ - main.c make.c parse.c str.c stats.c suff.c targ.c var.c varmodifiers.c #util.c +SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c error.c for.c \ + init.c job.c lowparse.c main.c make.c memory.c parse.c \ + parsevar.c str.c stats.c suff.c targ.c timestamp.c \ + var.c varmodifiers.c varname.c SRCS+= lstAddNew.c lstAppend.c lstConcat.c lstConcatDestroy.c \ lstDeQueue.c lstDestroy.c lstDupl.c lstFindFrom.c lstForEachFrom.c \ lstInit.c lstInsert.c lstMember.c lstRemove.c lstReplace.c lstSucc.c @@ -33,10 +37,10 @@ varhashconsts.h: generate condhashconsts.h: generate ${.OBJDIR}/generate 2 ${MAGICCONDSLOTS} >${.TARGET} -generate: generate.o stats.o error.o +generate: generate.o stats.o memory.o ${CC} -o ${.TARGET} ${CFLAGS} ${.ALLSRC} ${LDADD} -check: regress.o str.o error.o buf.o +check: regress.o str.o memory.o buf.o ${CC} -o ${.TARGET} ${CFLAGS} ${.ALLSRC} ${LDADD} regress: check diff --git a/usr.bin/make/arch.c b/usr.bin/make/arch.c index 0412720e2d9..c58d891fc67 100644 --- a/usr.bin/make/arch.c +++ b/usr.bin/make/arch.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: arch.c,v 1.44 2001/05/03 13:41:00 espie Exp $ */ +/* $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,80 +66,37 @@ * 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<name> format. - * - * Arch_LibOODate Special function to decide if a library node - * is out-of-date. + * archives are kept in a hash (archives) which is searched each time + * an archive member is referenced. * - * Arch_Init Initialize this module. - * - * Arch_End Cleanup this module. */ -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/param.h> -#include <assert.h> -#include <ctype.h> -#include <ar.h> -#include <utime.h> -#include <stdio.h> -#include <stddef.h> -#include <stdlib.h> -#include <fcntl.h> -#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 */ - +#include <sys/types.h> +#include <ar.h> +#include <assert.h> +#include <ctype.h> +#include <fcntl.h> +#include <limits.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#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 @@ -191,7 +148,7 @@ static Arch *read_archive(const char *, const char *); #ifdef CLEANUP static void ArchFree(Arch *); #endif -static TIMESTAMP ArchMTimeMember(const char *, const char *, Boolean); +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,7 +181,7 @@ new_arch_member(hdr, name) 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); + ts_set_out_of_date(n->mtime); return n; } @@ -233,7 +190,7 @@ mtime_of_member(m) struct arch_member *m; { if (is_out_of_date(m->mtime)) - grab_date((time_t) strtol(m->date, NULL, 10), m->mtime); + ts_set_from_time_t((time_t) strtol(m->date, NULL, 10), m->mtime); return m->mtime; } @@ -263,23 +220,8 @@ ArchFree(a) -/*- - *----------------------------------------------------------------------- - * 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 +/* 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,45 +233,45 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) 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 + bool subLibName; /* true if libName should have/had * variable substitution performed on it */ libName = *linePtr; - subLibName = FALSE; + subLibName = false; for (cp = libName; *cp != '(' && *cp != '\0';) { if (*cp == '$') { - ReturnStatus result; + bool ok; - cp += Var_ParseSkip(cp, ctxt, &result); - if (result == FAILURE) - return FAILURE; - subLibName = TRUE; + 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); + 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 */ + 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 == '$') { - ReturnStatus result; - cp += Var_ParseSkip(cp, ctxt, &result); - if (result == FAILURE) - return FAILURE; - doSubst = TRUE; + bool ok; + cp += Var_ParseSkip(cp, ctxt, &ok); + if (ok == false) + return false; + doSubst = true; } else cp++; } @@ -340,7 +282,7 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) * happen. */ if (*cp == '\0') { printf("No closing parenthesis in archive specification\n"); - return FAILURE; + return false; } /* If we didn't move anywhere, we must be done. */ @@ -364,7 +306,7 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) char *sacrifice; char *oldMemName = memName; - memName = Var_Subst(memName, ctxt, TRUE); + 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,20 +319,20 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) /* 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); + gn = Targ_FindNode(buf, TARG_CREATE); if (gn == NULL) { free(buf); - return FAILURE; + return false; } 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 + } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) { + /* Error in nested call -- free buffer and return false * ourselves. */ free(buf); - return FAILURE; + return false; } /* Free buffer and continue with our work. */ free(buf); @@ -400,11 +342,11 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) Lst_Init(&members); - Dir_Expand(memName, &dirSearchPath, &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); + 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,7 +357,7 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) } } else { snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, memName); - gn = Targ_FindNode(nameBuf, NULL, TARG_CREATE); + 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,7 +384,7 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) } while (*cp != '\0' && isspace(*cp)); *linePtr = cp; - return SUCCESS; + return true; } /* Helper function: ar fields are not null terminated. */ @@ -598,7 +540,7 @@ read_archive(archive, end) * out of date). * * Side Effects: - * Cache the whole archive contents if hash is TRUE. + * Cache the whole archive contents if hash is true. *----------------------------------------------------------------------- */ static TIMESTAMP @@ -606,7 +548,7 @@ ArchMTimeMember(archive, member, hash) 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 + bool hash; /* true if archive should be hashed if not * already so. */ { FILE * arch; /* Stream to archive */ @@ -616,7 +558,7 @@ ArchMTimeMember(archive, member, hash) const char *cp; TIMESTAMP result; - set_out_of_date(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,7 +583,7 @@ ArchMTimeMember(archive, member, hash) if (arch != NULL) { fclose(arch); - grab_date( (time_t)strtol(sarh.ar_date, NULL, 10), result); + ts_set_from_time_t( (time_t)strtol(sarh.ar_date, NULL, 10), result); } return result; } @@ -934,17 +876,11 @@ ArchTouch(archive, member) } } -/*- - *----------------------------------------------------------------------- - * 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) @@ -953,17 +889,6 @@ Arch_Touch(gn) 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 */ @@ -976,43 +901,17 @@ Arch_TouchLib(gn) #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); + 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; @@ -1045,28 +944,19 @@ Arch_MemMTime(gn) } 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); + ts_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. - *----------------------------------------------------------------------- +/* 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,73 +1008,53 @@ Arch_FindLib(gn, path) * TOC. * * Results: - * TRUE if the library is out-of-date. FALSE otherwise. + * true if the library is out-of-date. false otherwise. * * Side Effects: * The library will be hashed if it hasn't been already. *----------------------------------------------------------------------- */ -Boolean +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_before(now, gn->mtime) || is_before(gn->mtime, gn->cmtime) || + return false; + if (is_strictly_before(now, gn->mtime) || is_strictly_before(gn->mtime, gn->cmtime) || is_out_of_date(gn->mtime)) - return TRUE; + return true; #ifdef RANLIBMAG /* non existent libraries are always out-of-date. */ if (gn->path == NULL) - return TRUE; - modTimeTOC = ArchMTimeMember(gn->path, RANLIBMAG, FALSE); + 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); + 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; + return true; #else - return FALSE; + 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 - *----------------------------------------------------------------------- - */ +#ifdef CLEANUP void Arch_End() { -#ifdef CLEANUP Arch *e; unsigned int i; @@ -1192,19 +1062,10 @@ Arch_End() e = ohash_next(&archives, &i)) ArchFree(e); ohash_delete(&archives); -#endif } +#endif -/*- - *----------------------------------------------------------------------- - * Arch_IsLib -- - * Check if the node is a library - * - * Results: - * True or False. - *----------------------------------------------------------------------- - */ -Boolean +bool Arch_IsLib(gn) GNode *gn; { @@ -1212,11 +1073,11 @@ Arch_IsLib(gn) int fd; if (gn->path == NULL || (fd = open(gn->path, O_RDONLY)) == -1) - return FALSE; + return false; if (read(fd, buf, SARMAG) != SARMAG) { (void)close(fd); - return FALSE; + return false; } (void)close(fd); diff --git a/usr.bin/make/arch.h b/usr.bin/make/arch.h new file mode 100644 index 00000000000..da4789d72e0 --- /dev/null +++ b/usr.bin/make/arch.h @@ -0,0 +1,86 @@ +#ifndef ARCH_H +#define ARCH_H +/* $OpenPackages$ */ +/* $OpenBSD: arch.h,v 1.1 2001/05/23 12:34:40 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/*- + * arch -- + * Functions to manipulate libraries, archives and their members. + */ + +#ifndef TIMESTAMP_TYPE +#include "timestamp_t.h" +#endif + +/* Initialization and cleanup */ +extern void Arch_Init(void); +#ifdef CLEANUP +extern void Arch_End(void); +#else +#define Arch_End() +#endif + +/* ok = Arch_ParseArchive(&begin, nodeLst, ctxt); + * Given an archive specification, add list of corresponding GNodes to + * nodeLst, one for each member in the spec. + * false is returned if the specification is invalid for some reason. + * Side-effect: begin is bumped to the end of the specification. */ +extern bool Arch_ParseArchive(char **, Lst, SymTable *); +/* Arch_Touch(node); + * Alter the modification time of the archive member described by node + * to the current time. */ +extern void Arch_Touch(GNode *); +/* Arch_TouchLib(node); + * Update the modification time of the library described by node. + * This is distinct from Arch_Touch, as it also updates the mtime + * of the library's table of contents. */ +extern void Arch_TouchLib(GNode *); +/* stamp = Arch_MTime(node); + * Find the modification time of a member of an archive *in the + * archive*, and returns it. + * The time is also stored in the member's GNode. */ +extern TIMESTAMP Arch_MTime(GNode *); +/* stamp = Arch_MemMTime(node); + * Find the modification time of a member of an archive and returns it. + * To use when the member only exists within the archive. */ +extern TIMESTAMP Arch_MemMTime(GNode *); +/* Arch_FindLib(node, path); + * Search for a library node along a path, and fills the gnode's path + * field to the actual complete path. If we don't find it, we set the + * library name to libname.a, assuming some other mechanism will take + * care of finding it. The library name should be in -l<name> format. */ +extern void Arch_FindLib(GNode *, Lst); +/* bool = Arch_LibOODate(node); + * Decide whether a library node is out-of-date. */ +extern bool Arch_LibOODate(GNode *); + +/* bool = Arch_IsLib(node); + * Decide whether a node is a library. */ +extern bool Arch_IsLib(GNode *); + +#endif diff --git a/usr.bin/make/buf.c b/usr.bin/make/buf.c index 90a59933a43..0dd0a93ecbb 100644 --- a/usr.bin/make/buf.c +++ b/usr.bin/make/buf.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: buf.c,v 1.15 2001/05/03 13:41:01 espie Exp $ */ +/* $OpenBSD: buf.c,v 1.16 2001/05/23 12:34:40 espie Exp $ */ /* $NetBSD: buf.c,v 1.9 1996/12/31 17:53:21 christos Exp $ */ /* @@ -71,20 +71,13 @@ * Functions for automatically-expanded buffers. */ -#include "sprite.h" -#include "make.h" -#include "buf.h" -#include "stats.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: buf.c,v 1.15 2001/05/03 13:41:01 espie Exp $"; -#endif -#endif /* not lint */ - +#include <ctype.h> +#include <stddef.h> +#include "config.h" +#include "defines.h" +#include "buf.h" +#include "stats.h" +#include "memory.h" #ifdef STATS_BUF #define DO_STAT_BUF(bp, nb) \ @@ -95,8 +88,8 @@ static char rcsid[] = "$OpenBSD: buf.c,v 1.15 2001/05/03 13:41:01 espie Exp $"; #define DO_STAT_BUF(a, b) #endif -/* BufExpand -- - * Expand the given buffer to hold the given number of additional +/* BufExpand(bp, nb) + * Expand buffer bp to hold upto nb additional * chars. Makes sure there's room for an extra '\0' char at * the end of the buffer to terminate the string. */ #define BufExpand(bp,nb) \ @@ -117,7 +110,7 @@ do { \ #define BUF_DEF_SIZE 256 /* Default buffer size */ #define BUF_MARGIN 256 /* Make sure we are comfortable */ -/* Buf_AddChar hard case: buffer must be expanded to accommodate +/* the hard case for Buf_AddChar: buffer must be expanded to accommodate * one more char. */ void BufOverflow(bp) @@ -144,8 +137,8 @@ Buf_AddChars(bp, numBytes, bytesPtr) void Buf_Init(bp, size) - Buffer bp; /* New Buffer to initialize */ - size_t size; /* Initial size for the buffer */ + Buffer bp; + size_t size; { #ifdef STATS_BUF STAT_TOTAL_BUFS++; diff --git a/usr.bin/make/buf.h b/usr.bin/make/buf.h index 5940435768c..8a3a63c4174 100644 --- a/usr.bin/make/buf.h +++ b/usr.bin/make/buf.h @@ -1,5 +1,8 @@ +#ifndef _BUF_H +#define _BUF_H + /* $OpenPackages$ */ -/* $OpenBSD: buf.h,v 1.14 2001/05/03 13:41:01 espie Exp $ */ +/* $OpenBSD: buf.h,v 1.15 2001/05/23 12:34:40 espie Exp $ */ /* $NetBSD: buf.h,v 1.7 1996/12/31 17:53:22 christos Exp $ */ /* @@ -69,15 +72,14 @@ * from: @(#)buf.h 8.1 (Berkeley) 6/6/93 */ -/*- - * buf.h -- - * Header for users of the buf library. +/* + * buf + * Support for extensible char buffers. + * One adds chars to a buffer, then retrieves the contents using + * Buf_Retrieve (no copy involved), or releases the memory using + * Buf_Destroy. */ -#ifndef _BUF_H -#define _BUF_H - -#include "sprite.h" /* Internal data structures and functions. BUFFER is visible so * that users can allocate the memory themselves. */ @@ -87,28 +89,34 @@ typedef struct Buffer_ { char *endPtr; /* End of allocated space. */ } BUFFER; -typedef struct Buffer_ *Buffer; - /* Internal support for Buf_AddChar. */ extern void BufOverflow(Buffer); + /* User interface */ -/* Buf_AddChars -- Add a number of chars to the buffer. */ +/* Buf_AddChars(buf, n, str); + * Adds n chars to buffer buf starting from str. */ extern void Buf_AddChars(Buffer, size_t, const char *); -/* Buf_Reset -- Remove all chars from a buffer. */ +/* Buf_Reset(buf); + * Empties buffer. */ #define Buf_Reset(bp) ((void)((bp)->inPtr = (bp)->buffer)) -/* Buf_Size -- Return the number of chars in the given buffer. +/* n = Buf_Size(buf); + * Returns number of chars currently in buf. * Doesn't include the null-terminating char. */ #define Buf_Size(bp) ((size_t)((bp)->inPtr - (bp)->buffer)) -/* Buf_Init -- Initialize a buffer. If no initial size is given, - * a reasonable default is used. */ +/* Buf_Init(buf, init); + * Initializes a buffer, to hold approximately init chars. + * Set init to 0 if you have no idea. */ extern void Buf_Init(Buffer, size_t); -/* Buf_Destroy -- Nuke a buffer and all its resources. */ +/* Buf_Destroy(buf); + * Nukes a buffer and all its resources. */ #define Buf_Destroy(bp) ((void)free((bp)->buffer)) -/* Buf_Retrieve -- Retrieve data from a buffer, as a NULL terminated string. */ +/* str = Buf_Retrieve(buf); + * Retrieves data from a buffer, as a NULL terminated string. */ #define Buf_Retrieve(bp) (*(bp)->inPtr = '\0', (bp)->buffer) -/* Buf_AddChar -- Add a single char to buffer. */ +/* Buf_AddChar(buf, c); + * Adds a single char to buffer. */ #define Buf_AddChar(bp, byte) \ do { \ if ((bp)->endPtr - (bp)->inPtr <= 1) \ @@ -116,13 +124,18 @@ do { \ *(bp)->inPtr++ = (byte); \ } while (0) -/* Buf_AddSpace -- Add a space to buffer. */ +/* Buf_AddSpace(buf); + * Adds a space to buffer. */ #define Buf_AddSpace(b) Buf_AddChar((b), ' ') -/* Buf_AddString -- Add the contents of a NULL terminated string to buffer. */ +/* Buf_AddString(buf, str); + * Adds the contents of a NULL terminated string to buffer. */ #define Buf_AddString(b, s) Buf_AddChars((b), strlen(s), (s)) -/* Buf_AddInterval -- Add characters between pointers s and e to buffer. */ -#define Buf_AddInterval(b, s, e) Buf_AddChars((b), (e) - (s), (s)) +/* Buf_Addi(buf, s, e); + * Adds characters between s and e to buffer. */ +#define Buf_Addi(b, s, e) Buf_AddChars((b), (e) - (s), (s)) +/* Buf_KillTrailingSpaces(buf); + * Removes non-backslashed spaces at the end of a buffer. */ extern void Buf_KillTrailingSpaces(Buffer); #endif /* _BUF_H */ diff --git a/usr.bin/make/cmd_exec.c b/usr.bin/make/cmd_exec.c new file mode 100644 index 00000000000..7d27c330468 --- /dev/null +++ b/usr.bin/make/cmd_exec.c @@ -0,0 +1,143 @@ +/* $OpenPackages$ */ +/* $OpenBSD: cmd_exec.c,v 1.1 2001/05/23 12:34:40 espie Exp $ */ +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include "config.h" +#include "defines.h" +#include "cmd_exec.h" +#include "buf.h" +#include "memory.h" +#include "pathnames.h" + +char * +Cmd_Exec(cmd, err) + const char *cmd; + char **err; +{ + char *args[4]; /* Args for invoking the shell */ + int fds[2]; /* Pipe streams */ + pid_t cpid; /* Child PID */ + pid_t pid; /* PID from wait() */ + char *result; /* Result */ + int status; /* Command exit status */ + BUFFER buf; /* Buffer to store the result. */ + char *cp; /* Pointer into result. */ + ssize_t cc; /* Characters read from pipe. */ + size_t length; /* Total length of result. */ + + + *err = NULL; + + /* Set up arguments for the shell. */ + args[0] = "sh"; + args[1] = "-c"; + args[2] = (char *)cmd; + args[3] = NULL; + + /* Open a pipe for retrieving shell's output. */ + if (pipe(fds) == -1) { + *err = "Couldn't create pipe for \"%s\""; + goto bad; + } + + /* Fork */ + switch (cpid = vfork()) { + case 0: + /* Close input side of pipe */ + (void)close(fds[0]); + + /* Duplicate the output stream to the shell's output, then + * shut the extra thing down. Note we don't fetch the error + * stream: user can use redirection to grab it as this goes + * through /bin/sh. + */ + (void)dup2(fds[1], 1); + if (fds[1] != 1) + (void)close(fds[1]); + + (void)execv(_PATH_BSHELL, args); + _exit(1); + /*NOTREACHED*/ + + case -1: + *err = "Couldn't exec \"%s\""; + goto bad; + + default: + /* No need for the writing half. */ + (void)close(fds[1]); + + Buf_Init(&buf, MAKE_BSIZE); + + do { + char grab[BUFSIZ]; + + cc = read(fds[0], grab, sizeof(grab)); + if (cc > 0) + Buf_AddChars(&buf, cc, grab); + } + while (cc > 0 || (cc == -1 && errno == EINTR)); + + /* Close the input side of the pipe. */ + (void)close(fds[0]); + + /* Wait for the child to exit. */ + while ((pid = wait(&status)) != cpid && pid >= 0) + continue; + + if (cc == -1) + *err = "Couldn't read shell's output for \"%s\""; + + if (status) + *err = "\"%s\" returned non-zero status"; + + length = Buf_Size(&buf); + result = Buf_Retrieve(&buf); + + /* The result is null terminated, Convert newlines to spaces. */ + cp = result + length - 1; + + if (*cp == '\n') + /* A final newline is just stripped. */ + *cp-- = '\0'; + + while (cp >= result) { + if (*cp == '\n') + *cp = ' '; + cp--; + } + break; + } + return result; +bad: + return estrdup(""); +} + diff --git a/usr.bin/make/cmd_exec.h b/usr.bin/make/cmd_exec.h new file mode 100644 index 00000000000..061c1727340 --- /dev/null +++ b/usr.bin/make/cmd_exec.h @@ -0,0 +1,38 @@ +#ifndef CMD_EXEC_H +#define CMD_EXEC_H +/* $OpenPackages$ */ +/* $OpenBSD: cmd_exec.h,v 1.1 2001/05/23 12:34:40 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* output = Cmd_Exec(cmd, &err); + * execute the command in cmd, return the output of that command as + * a string. If an error occurs, Cmd_Exec returns an empty string, + * and err is filled with the reason for the command failure. + * The output result should always be freed by the caller. */ +extern char *Cmd_Exec(const char *, char **); + +#endif diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c index ce761a4ef64..c43c4e1a027 100644 --- a/usr.bin/make/compat.c +++ b/usr.bin/make/compat.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: compat.c,v 1.36 2001/05/03 13:41:02 espie Exp $ */ +/* $OpenBSD: compat.c,v 1.37 2001/05/23 12:34:40 espie Exp $ */ /* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */ /* @@ -40,40 +40,32 @@ * SUCH DAMAGE. */ -/*- - * compat.c -- - * The routines in this file implement the full-compatibility - * mode of PMake. Most of the special functionality of PMake - * is available in this mode. Things not supported: - * - different shells. - * - friendly variable substitution. - * - * Interface: - * Compat_Run Initialize things for this module and recreate - * thems as need creatin' - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <ctype.h> -#include <errno.h> -#include <signal.h> -#include <stddef.h> -#include <stdio.h> -#include "make.h" -#include "ohash.h" -#include "dir.h" -#include "job.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: compat.c,v 1.36 2001/05/03 13:41:02 espie Exp $"; -#endif -#endif /* not lint */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <ctype.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdio.h> +#include <unistd.h> +#include "config.h" +#include "defines.h" +#include "dir.h" +#include "job.h" +#include "compat.h" +#include "suff.h" +#include "var.h" +#include "targ.h" +#include "error.h" +#include "str.h" +#include "extern.h" +#include "memory.h" +#include "gnode.h" +#include "make.h" +#include "timestamp.h" +#include "lst.h" +#include "pathnames.h" /* The following array is used to make a fast determination of which * characters are interpreted specially by the shell. If a command @@ -114,7 +106,7 @@ CompatInterrupt(signo) /* Run .INTERRUPT only if hit with interrupt signal. */ if (signo == SIGINT) { - gn = Targ_FindNode(".INTERRUPT", NULL, TARG_NOCREATE); + gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); if (gn != NULL) Lst_Find(&gn->commands, CompatRunCommand, gn); } @@ -196,22 +188,22 @@ CompatRunCommand(cmdp, gnp) { char *cmdStart; /* Start of expanded command */ char *cp, *bp = NULL; - Boolean silent, /* Don't print command */ + bool silent, /* Don't print command */ errCheck, /* Check errors */ doExecute; /* Execute the command */ int reason; /* Reason for child's death */ int status; /* Description of child's death */ int cpid; /* Child actually found */ - ReturnStatus stat; /* Status of fork */ + int stat; /* Status of fork */ LstNode cmdNode; /* Node where current command is located */ char **av; /* Argument vector for thing to exec */ int argc; /* Number of arguments in av or 0 if not * dynamically allocated */ - Boolean local; /* TRUE if command should be executed + bool local; /* true if command should be executed * locally */ char *cmd = (char *)cmdp; GNode *gn = (GNode *)gnp; - static char *shargv[4] = { "/bin/sh" }; + static char *shargv[4] = { _PATH_BSHELL }; /* Avoid clobbered variable warnings by forcing the compiler * to ``unregister'' variables. */ @@ -224,7 +216,7 @@ CompatRunCommand(cmdp, gnp) doExecute = !noExecute; cmdNode = Lst_Member(&gn->commands, cmd); - cmdStart = Var_Subst(cmd, &gn->context, FALSE); + cmdStart = Var_Subst(cmd, &gn->context, false); /* brk_string will return an argv with a NULL in av[0], thus causing * execvp to choke and die horribly. Besides, how can we execute a null @@ -249,11 +241,11 @@ CompatRunCommand(cmdp, gnp) for (;; cmd++) { if (*cmd == '@') - silent = DEBUG(LOUD) ? FALSE : TRUE; + silent = DEBUG(LOUD) ? false : true; else if (*cmd == '-') - errCheck = FALSE; + errCheck = false; else if (*cmd == '+') - doExecute = TRUE; + doExecute = true; else break; } @@ -316,7 +308,7 @@ CompatRunCommand(cmdp, gnp) } } - local = TRUE; + local = true; /* Fork and execute the single command. If the fork fails, we abort. */ cpid = vfork(); @@ -412,16 +404,16 @@ CompatMake(gnp, pgnp) /* First mark ourselves to be made, then apply whatever transformations * the suffix module thinks are necessary. Once that's done, we can * descend and make all our children. If any of them has an error - * but the -k flag was given, our 'make' field will be set FALSE again. + * but the -k flag was given, our 'make' field will be set false again. * This is our signal to not attempt to do anything but abort our * parent as well. */ - gn->make = TRUE; + gn->make = true; gn->made = BEINGMADE; Suff_FindDeps(gn); Lst_ForEach(&gn->children, CompatMake, gn); if (!gn->make) { gn->made = ABORTED; - pgn->make = FALSE; + pgn->make = false; return; } @@ -525,17 +517,17 @@ CompatMake(gnp, pgnp) */ if (noExecute || is_out_of_date(Dir_MTime(gn))) gn->mtime = now; - if (is_before(gn->mtime, gn->cmtime)) + if (is_strictly_before(gn->mtime, gn->cmtime)) gn->mtime = gn->cmtime; if (DEBUG(MAKE)) printf("update time: %s\n", Targ_FmtTime(gn->mtime)); #endif if (!(gn->type & OP_EXEC)) { - pgn->childMade = TRUE; + pgn->childMade = true; Make_TimeStamp(pgn, gn); } } else if (keepgoing) - pgn->make = FALSE; + pgn->make = false; else { if (gn->lineno) @@ -550,7 +542,7 @@ CompatMake(gnp, pgnp) } else if (gn->made == ERROR) /* Already had an error when making this beastie. Tell the parent * to abort. */ - pgn->make = FALSE; + pgn->make = false; else { if (Lst_Member(&gn->iParents, pgn) != NULL) { Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn); @@ -559,11 +551,11 @@ CompatMake(gnp, pgnp) case BEINGMADE: Error("Graph cycles through %s\n", gn->name); gn->made = ERROR; - pgn->make = FALSE; + pgn->make = false; break; case MADE: if ((gn->type & OP_EXEC) == 0) { - pgn->childMade = TRUE; + pgn->childMade = true; Make_TimeStamp(pgn, gn); } break; @@ -577,15 +569,6 @@ CompatMake(gnp, pgnp) } } -/*- - *----------------------------------------------------------------------- - * Compat_Run -- - * Initialize this mode and start making. - * - * Side Effects: - * Guess what? - *----------------------------------------------------------------------- - */ void Compat_Run(targs) Lst targs; /* List of target nodes to re-create */ @@ -608,11 +591,11 @@ Compat_Run(targs) /* The null character serves as a sentinel in the string. */ meta[0] = 1; - ENDNode = Targ_FindNode(".END", NULL, TARG_CREATE); + ENDNode = Targ_FindNode(".END", TARG_CREATE); /* If the user has defined a .BEGIN target, execute the commands attached * to it. */ if (!queryFlag) { - gn = Targ_FindNode(".BEGIN", NULL, TARG_NOCREATE); + gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); if (gn != NULL) { Lst_Find(&gn->commands, CompatRunCommand, gn); if (gn->made == ERROR) { diff --git a/usr.bin/make/compat.h b/usr.bin/make/compat.h new file mode 100644 index 00000000000..df772d5a019 --- /dev/null +++ b/usr.bin/make/compat.h @@ -0,0 +1,43 @@ +#ifndef COMPAT_H +#define COMPAT_H +/* $OpenPackages$ */ +/* $OpenBSD: compat.h,v 1.1 2001/05/23 12:34:41 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* compat + * The routines in this module implement the full-compatibility + * mode of PMake. Most of the special functionality of PMake + * is available in this mode. Things not supported: + * - different shells. + * - friendly variable substitution. + */ + +/* Compat_Run(to_create); + * Run the actual make engine, to create targets that need to. */ +extern void Compat_Run(Lst); + +#endif diff --git a/usr.bin/make/cond.c b/usr.bin/make/cond.c index 93ad02834d5..66ee4b223ba 100644 --- a/usr.bin/make/cond.c +++ b/usr.bin/make/cond.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: cond.c,v 1.24 2001/05/03 13:41:02 espie Exp $ */ +/* $OpenBSD: cond.c,v 1.25 2001/05/23 12:34:41 espie Exp $ */ /* $NetBSD: cond.c,v 1.7 1996/11/06 17:59:02 christos Exp $ */ /* @@ -40,31 +40,24 @@ * SUCH DAMAGE. */ -/*- - * cond.c -- - * Functions to handle conditionals in a makefile. - * - * Interface: - * Cond_Eval Evaluate the conditional in the passed line. - * - */ - -#include <ctype.h> -#include <math.h> -#include <stddef.h> -#include "make.h" -#include "ohash.h" -#include "dir.h" -#include "buf.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: cond.c,v 1.24 2001/05/03 13:41:02 espie Exp $"; -#endif -#endif /* not lint */ +#include <ctype.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "dir.h" +#include "buf.h" +#include "cond.h" +#include "error.h" +#include "var.h" +#include "varname.h" +#include "targ.h" +#include "lowparse.h" +#include "str.h" +#include "main.h" +#include "gnode.h" +#include "lst.h" /* The parsing of conditional expressions is based on this grammar: @@ -92,7 +85,7 @@ static char rcsid[] = "$OpenBSD: cond.c,v 1.24 2001/05/03 13:41:02 espie Exp $"; * will return And for '&' and '&&', Or for '|' and '||', Not for '!', * LParen for '(', RParen for ')' and will evaluate the other terminal * symbols, using either the default function or the function given in the - * terminal, and return the result as either True or False. + * terminal, and return the result as either true or False. * * All Non-Terminal functions (CondE, CondF and CondT) return Err on error. */ typedef enum { @@ -103,39 +96,39 @@ typedef enum { * Structures to handle elegantly the different forms of #if's. The * last two fields are stored in condInvert and condDefProc, respectively. */ -static Boolean CondGetArg(const char **, struct Name *, - const char *, Boolean); -static Boolean CondDoDefined(struct Name *); -static Boolean CondDoMake(struct Name *); -static Boolean CondDoExists(struct Name *); -static Boolean CondDoTarget(struct Name *); -static Boolean CondCvtArg(const char *, double *); -static Token CondToken(Boolean); -static Token CondT(Boolean); -static Token CondF(Boolean); -static Token CondE(Boolean); -static Token CondHandleVarSpec(Boolean); -static Token CondHandleDefault(Boolean); +static bool CondGetArg(const char **, struct Name *, + const char *, bool); +static bool CondDoDefined(struct Name *); +static bool CondDoMake(struct Name *); +static bool CondDoExists(struct Name *); +static bool CondDoTarget(struct Name *); +static bool CondCvtArg(const char *, double *); +static Token CondToken(bool); +static Token CondT(bool); +static Token CondF(bool); +static Token CondE(bool); +static Token CondHandleVarSpec(bool); +static Token CondHandleDefault(bool); static const char *find_cond(const char *); static struct If { char *form; /* Form of if */ int formlen; /* Length of form */ - Boolean doNot; /* TRUE if default function should be negated */ - Boolean (*defProc)(struct Name *); + bool doNot; /* true if default function should be negated */ + bool (*defProc)(struct Name *); /* Default function to apply */ } ifs[] = { - { "ifdef", 5, FALSE, CondDoDefined }, - { "ifndef", 6, TRUE, CondDoDefined }, - { "ifmake", 6, FALSE, CondDoMake }, - { "ifnmake", 7, TRUE, CondDoMake }, - { "if", 2, FALSE, CondDoDefined }, - { NULL, 0, FALSE, NULL } + { "ifdef", 5, false, CondDoDefined }, + { "ifndef", 6, true, CondDoDefined }, + { "ifmake", 6, false, CondDoMake }, + { "ifnmake", 7, true, CondDoMake }, + { "if", 2, false, CondDoDefined }, + { NULL, 0, false, NULL } }; -static Boolean condInvert; /* Invert the default function */ -static Boolean (*condDefProc) /* Default function to apply */ +static bool condInvert; /* Invert the default function */ +static bool (*condDefProc) /* Default function to apply */ (struct Name *); static const char *condExpr; /* The expression to parse */ static Token condPushBack=None; /* Single push-back token used in @@ -144,13 +137,13 @@ static Token condPushBack=None; /* Single push-back token used in #define MAXIF 30 /* greatest depth of #if'ing */ static struct { - Boolean value; + bool value; unsigned long lineno; const char *filename; } condStack[MAXIF]; /* Stack of conditionals */ static int condTop = MAXIF; /* Top-most conditional */ static int skipIfLevel=0; /* Depth of skipped conditionals */ -static Boolean skipLine = FALSE; /* Whether the parse module is skipping +static bool skipLine = false; /* Whether the parse module is skipping * lines */ static const char * @@ -170,19 +163,19 @@ find_cond(p) * Find the argument of a built-in function. * * Results: - * TRUE if evaluation went okay + * true if evaluation went okay * * Side Effects: * The line pointer is set to point to the closing parenthesis of the * function call. The argument is filled. *----------------------------------------------------------------------- */ -static Boolean +static bool CondGetArg(linePtr, arg, func, parens) const char **linePtr; struct Name *arg; const char *func; - Boolean parens; /* TRUE if arg should be bounded by parens */ + bool parens; /* true if arg should be bounded by parens */ { const char *cp; @@ -201,28 +194,28 @@ CondGetArg(linePtr, arg, func, parens) * the word 'make' or 'defined' at the beginning of a symbol... */ arg->s = cp; arg->e = cp; - arg->tofree = FALSE; - return FALSE; + arg->tofree = false; + return false; } while (*cp == ' ' || *cp == '\t') cp++; - cp = Var_Name_Get(cp, arg, NULL, TRUE, find_cond); + cp = VarName_Get(cp, arg, NULL, true, find_cond); while (*cp == ' ' || *cp == '\t') cp++; if (parens && *cp != ')') { Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()", func); - return FALSE; + return false; } else if (parens) /* Advance pointer past close parenthesis. */ cp++; *linePtr = cp; - return TRUE; + return true; } /*- @@ -231,17 +224,17 @@ CondGetArg(linePtr, arg, func, parens) * Handle the 'defined' function for conditionals. * * Results: - * TRUE if the given variable is defined. + * true if the given variable is defined. *----------------------------------------------------------------------- */ -static Boolean +static bool CondDoDefined(arg) struct Name *arg; { - if (Var_Value_interval(arg->s, arg->e) != NULL) - return TRUE; + if (Var_Valuei(arg->s, arg->e) != NULL) + return true; else - return FALSE; + return false; } /*- @@ -250,21 +243,22 @@ CondDoDefined(arg) * Handle the 'make' function for conditionals. * * Results: - * TRUE if the given target is being made. + * true if the given target is being made. *----------------------------------------------------------------------- */ -static Boolean +static bool CondDoMake(arg) struct Name *arg; { LstNode ln; - for (ln = Lst_First(&create); ln != NULL; ln = Lst_Adv(ln)) { - if (Str_Matchi((char *)Lst_Datum(ln), arg->s, arg->e)) - return TRUE; + for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) { + char *s = (char *)Lst_Datum(ln); + if (Str_Matchi(s, strchr(s, '\0'), arg->s, arg->e)) + return true; } - return FALSE; + return false; } /*- @@ -273,22 +267,22 @@ CondDoMake(arg) * See if the given file exists. * * Results: - * TRUE if the file exists and FALSE if it does not. + * true if the file exists and false if it does not. *----------------------------------------------------------------------- */ -static Boolean +static bool CondDoExists(arg) struct Name *arg; { - Boolean result; + bool result; char *path; - path = Dir_FindFilei(arg->s, arg->e, &dirSearchPath); + path = Dir_FindFilei(arg->s, arg->e, dirSearchPath); if (path != NULL) { - result = TRUE; + result = true; free(path); } else { - result = FALSE; + result = false; } return result; } @@ -299,20 +293,20 @@ CondDoExists(arg) * See if the given node exists and is an actual target. * * Results: - * TRUE if the node exists as a target and FALSE if it does not. + * true if the node exists as a target and false if it does not. *----------------------------------------------------------------------- */ -static Boolean +static bool CondDoTarget(arg) struct Name *arg; { GNode *gn; - gn = Targ_FindNode(arg->s, arg->e, TARG_NOCREATE); + gn = Targ_FindNodei(arg->s, arg->e, TARG_NOCREATE); if (gn != NULL && !OP_NOP(gn->type)) - return TRUE; + return true; else - return FALSE; + return false; } @@ -332,7 +326,7 @@ CondDoTarget(arg) * Can change 'value' even if string is not a valid number. *----------------------------------------------------------------------- */ -static Boolean +static bool CondCvtArg(str, value) const char *str; double *value; @@ -347,11 +341,11 @@ CondCvtArg(str, value) else if (isxdigit(*str)) x = 10 + *str - isupper(*str) ? 'A' : 'a'; else - return FALSE; + return false; i = (i << 4) + x; } *value = (double) i; - return TRUE; + return true; } else { char *eptr; @@ -363,14 +357,14 @@ CondCvtArg(str, value) static Token CondHandleVarSpec(doEval) - Boolean doEval; + bool doEval; { Token t; char *lhs; const char *rhs; const char *op; size_t varSpecLen; - Boolean doFree; + bool doFree; /* Parse the variable spec and skip over it, saving its * value in lhs. */ @@ -398,7 +392,7 @@ CondHandleVarSpec(doEval) lhs = Buf_Retrieve(&buf); - doFree = TRUE; + doFree = true; } /* Skip whitespace to get to the operator. */ @@ -459,8 +453,7 @@ do_string_compare: if (*cp == '$') { size_t len; - if (Var_ParseBuffer(&buf, cp, NULL, doEval, &len) - == SUCCESS) { + if (Var_ParseBuffer(&buf, cp, NULL, doEval, &len)) { cp += len; continue; } @@ -501,7 +494,7 @@ do_string_compare: goto do_string_compare; if (*rhs == '$') { size_t len; - Boolean freeIt; + bool freeIt; string = Var_Parse(rhs, NULL, doEval,&len,&freeIt); if (string == var_Error) @@ -573,7 +566,7 @@ error: static struct operator { const char *s; size_t len; - Boolean (*proc)(struct Name *); + bool (*proc)(struct Name *); } ops[] = { {S("defined"), CondDoDefined}, {S("make"), CondDoMake}, @@ -583,11 +576,11 @@ static struct operator { }; static Token CondHandleDefault(doEval) - Boolean doEval; + bool doEval; { - Boolean t; - Boolean (*evalProc)(struct Name *); - Boolean invert = FALSE; + bool t; + bool (*evalProc)(struct Name *); + bool invert = false; struct Name arg; size_t arglen; @@ -596,7 +589,7 @@ CondHandleDefault(doEval) /* Use Var_Parse to parse the spec in parens and return * True if the resulting string is empty. */ size_t length; - Boolean doFree; + bool doFree; char *val; condExpr += 5; @@ -632,7 +625,7 @@ CondHandleDefault(doEval) for (op = ops; op != NULL; op++) if (strncmp(condExpr, op->s, op->len) == 0) { condExpr += op->len; - if (CondGetArg(&condExpr, &arg, op->s, TRUE)) + if (CondGetArg(&condExpr, &arg, op->s, true)) evalProc = op->proc; else condExpr -= op->len; @@ -644,19 +637,19 @@ CondHandleDefault(doEval) * function. We advance condExpr to the end of the symbol * by hand (the next whitespace, closing paren or * binary operator) and set to invert the evaluation - * function if condInvert is TRUE. */ + * function if condInvert is true. */ invert = condInvert; evalProc = condDefProc; /* XXX should we ignore problems now ? */ - CondGetArg(&condExpr, &arg, "", FALSE); + CondGetArg(&condExpr, &arg, "", false); } /* Evaluate the argument using the set function. If invert - * is TRUE, we invert the sense of the function. */ + * is true, we invert the sense of the function. */ t = (!doEval || (*evalProc)(&arg) ? (invert ? False : True) : (invert ? True : False)); - Var_Name_Free(&arg); + VarName_Free(&arg); return t; } @@ -674,7 +667,7 @@ CondHandleDefault(doEval) */ static Token CondToken(doEval) - Boolean doEval; + bool doEval; { if (condPushBack != None) { @@ -735,7 +728,7 @@ CondToken(doEval) */ static Token CondT(doEval) - Boolean doEval; + bool doEval; { Token t; @@ -776,7 +769,7 @@ CondT(doEval) */ static Token CondF(doEval) - Boolean doEval; + bool doEval; { Token l, o; @@ -793,7 +786,7 @@ CondF(doEval) if (l == True) l = CondF(doEval); else - (void)CondF(FALSE); + (void)CondF(false); } else /* F -> T. */ condPushBack = o; @@ -816,7 +809,7 @@ CondF(doEval) */ static Token CondE(doEval) - Boolean doEval; + bool doEval; { Token l, o; @@ -834,7 +827,7 @@ CondE(doEval) if (l == False) l = CondE(doEval); else - (void)CondE(FALSE); + (void)CondE(false); } else /* E -> F. */ condPushBack = o; @@ -842,30 +835,20 @@ CondE(doEval) return l; } -/*- - *----------------------------------------------------------------------- - * Cond_Eval -- - * Evaluate the conditional in the passed fragment. The fragment - * looks like this: +/* A conditional line looks like this: * <cond-type> <expr> * where <cond-type> is any of if, ifmake, ifnmake, ifdef, * ifndef, elif, elifmake, elifnmake, elifdef, elifndef * and <expr> consists of &&, ||, !, make(target), defined(variable) * and parenthetical groupings thereof. - * - * Results: - * COND_PARSE if should parse lines after the conditional - * COND_SKIP if should skip lines after the conditional - * COND_INVALID if not a valid conditional. - *----------------------------------------------------------------------- */ int Cond_Eval(line) - char *line; /* Line to parse */ + const char *line; /* Line to parse */ { struct If *ifp; - Boolean isElse; - Boolean value = FALSE; + bool isElse; + bool value = false; int level; /* Level at which to report errors. */ level = PARSE_FATAL; @@ -874,10 +857,10 @@ Cond_Eval(line) * otherwise, this is not our turf. */ /* Find what type of if we're dealing with. The result is left - * in ifp and isElse is set TRUE if it's an elif line. */ + * in ifp and isElse is set true if it's an elif line. */ if (line[0] == 'e' && line[1] == 'l') { line += 2; - isElse = TRUE; + isElse = true; } else if (strncmp(line, "endif", 5) == 0) { /* End of a conditional section. If skipIfLevel is non-zero, that * conditional was skipped, so lines following it should also be @@ -893,13 +876,13 @@ Cond_Eval(line) Parse_Error(level, "if-less endif"); return COND_INVALID; } else { - skipLine = FALSE; + skipLine = false; condTop += 1; return COND_PARSE; } } } else - isElse = FALSE; + isElse = false; /* Figure out what sort of conditional it is -- what its default * function is, etc. -- by looking in the table of valid "ifs" */ @@ -954,17 +937,17 @@ Cond_Eval(line) condExpr = line; condPushBack = None; - switch (CondE(TRUE)) { + switch (CondE(true)) { case True: - if (CondToken(TRUE) == EndOfFile) { - value = TRUE; + if (CondToken(true) == EndOfFile) { + value = true; break; } goto err; /* FALLTHROUGH */ case False: - if (CondToken(TRUE) == EndOfFile) { - value = FALSE; + if (CondToken(true) == EndOfFile) { + value = false; break; } /* FALLTHROUGH */ @@ -980,11 +963,11 @@ Cond_Eval(line) condTop -= 1; else if (skipIfLevel != 0 || condStack[condTop].value) { /* If this is an else-type conditional, it should only take effect - * if its corresponding if was evaluated and FALSE. If its if was - * TRUE or skipped, we return COND_SKIP (and start skipping in case + * if its corresponding if was evaluated and false. If its if was + * true or skipped, we return COND_SKIP (and start skipping in case * we weren't already), leaving the stack unmolested so later elif's * don't screw up... */ - skipLine = TRUE; + skipLine = true; return COND_SKIP; } @@ -1002,15 +985,6 @@ Cond_Eval(line) } } -/*- - *----------------------------------------------------------------------- - * Cond_End -- - * Make sure everything's clean at the end of a makefile. - * - * Side Effects: - * Parse_Error will be called if open conditionals are around. - *----------------------------------------------------------------------- - */ void Cond_End() { diff --git a/usr.bin/make/cond.h b/usr.bin/make/cond.h new file mode 100644 index 00000000000..7a98b3af0d5 --- /dev/null +++ b/usr.bin/make/cond.h @@ -0,0 +1,51 @@ +#ifndef COND_H +#define COND_H +/* $OpenPackages$ */ +/* $OpenBSD: cond.h,v 1.1 2001/05/23 12:34:41 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* cond + * Parse Makefile conditionals. + */ + +/* Values returned by Cond_Eval. */ +#define COND_PARSE 0 /* Parse the next lines */ +#define COND_SKIP 1 /* Skip the next lines */ +#define COND_INVALID 2 /* Not a conditional statement */ + +/* whattodo = Cond_Eval(line); + * Parses a conditional expression (without the leading dot), + * and returns a decision value. + * State is kept internally, since conditionals nest. */ +extern int Cond_Eval(const char *); + +/* Cond_End(); + * To call at end of parsing, checks that all conditionals were + * closed. */ +extern void Cond_End(void); + +#endif diff --git a/usr.bin/make/cond_int.h b/usr.bin/make/cond_int.h index 14fc951cc17..d00bed129f4 100644 --- a/usr.bin/make/cond_int.h +++ b/usr.bin/make/cond_int.h @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: cond_int.h,v 1.1 2001/05/03 13:41:02 espie Exp $ */ +/* $OpenBSD: cond_int.h,v 1.2 2001/05/23 12:34:41 espie Exp $ */ /* List of all keywords recognized by the make parser */ #define COND_IF "if" diff --git a/usr.bin/make/config.h b/usr.bin/make/config.h index 1b027104fe1..76c7adaa050 100644 --- a/usr.bin/make/config.h +++ b/usr.bin/make/config.h @@ -1,5 +1,8 @@ +#ifndef CONFIG_H +#define CONFIG_H + /* $OpenPackages$ */ -/* $OpenBSD: config.h,v 1.10 2001/05/03 13:41:03 espie Exp $ */ +/* $OpenBSD: config.h,v 1.11 2001/05/23 12:34:41 espie Exp $ */ /* $NetBSD: config.h,v 1.7 1996/11/06 17:59:03 christos Exp $ */ /* @@ -143,3 +146,16 @@ #define FEATURE_CONDINCLUDE 256 #define FEATURE_ASSIGN 512 #define FEATURE_EXECMOD 1024 + +/* + * There are several places where expandable buffers are used (parse.c and + * var.c). This constant is merely the starting point for those buffers. If + * lines tend to be much shorter than this, it would be best to reduce BSIZE. + * If longer, it should be increased. Reducing it will cause more copying to + * be done for longer lines, but will save space for shorter ones. In any + * case, it ought to be a power of two simply because most storage allocation + * schemes allocate in powers of two. + */ +#define MAKE_BSIZE 256 /* starting size for expandable buffers */ + +#endif diff --git a/usr.bin/make/defines.h b/usr.bin/make/defines.h new file mode 100644 index 00000000000..dbf14cab830 --- /dev/null +++ b/usr.bin/make/defines.h @@ -0,0 +1,105 @@ +#ifndef DEFINES_H +#define DEFINES_H + +/* $OpenPackages$ */ +/* $OpenBSD: defines.h,v 1.1 2001/05/23 12:34:41 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +#ifdef HAS_STDBOOL_H +# include <stdbool.h> +#else +typedef int bool; +# define false 0 +# define true 1 +#endif + +/* define common types in an opaque way */ +struct GNode_; +typedef struct GNode_ GNode; + +struct List_; +typedef struct List_ *Lst; + +struct SymTable_; +typedef struct SymTable_ SymTable; + +struct ohash; +typedef struct ohash GSymT; + +struct Buffer_; +typedef struct Buffer_ *Buffer; + +struct Name; + +struct ListNode_; +typedef struct ListNode_ *LstNode; + +/* some useful defines for gcc */ + +#ifdef __GNUC__ +# define UNUSED __attribute__((__unused__)) +# define HAS_INLINES +# define INLINE __inline__ +#else +# define UNUSED +#endif + +#ifdef HAS_INLINES +# ifndef INLINE +# define INLINE inline +# endif +#endif + +/* + * debug control: + * There is one bit per module. It is up to the module what debug + * information to print. + */ +extern int debug; +#define DEBUG_ARCH 0x0001 +#define DEBUG_COND 0x0002 +#define DEBUG_DIR 0x0004 +#define DEBUG_GRAPH1 0x0008 +#define DEBUG_GRAPH2 0x0010 +#define DEBUG_JOB 0x0020 +#define DEBUG_MAKE 0x0040 +#define DEBUG_SUFF 0x0080 +#define DEBUG_TARG 0x0100 +#define DEBUG_VAR 0x0200 +#define DEBUG_FOR 0x0400 +#define DEBUG_LOUD 0x0800 + +#ifdef __STDC__ +#define CONCAT(a,b) a##b +#else +#define I(a) a +#define CONCAT(a,b) I(a)b +#endif /* __STDC__ */ + +#define DEBUG(module) (debug & CONCAT(DEBUG_,module)) + +#endif diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c index 63b801818a2..bb1ba539bb6 100644 --- a/usr.bin/make/dir.c +++ b/usr.bin/make/dir.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: dir.c,v 1.31 2001/05/03 13:41:03 espie Exp $ */ +/* $OpenBSD: dir.c,v 1.32 2001/05/23 12:34:42 espie Exp $ */ /* $NetBSD: dir.c,v 1.14 1997/03/29 16:51:26 christos Exp $ */ /* @@ -66,65 +66,36 @@ * SUCH DAMAGE. */ -/*- - * dir.c -- - * Directory searching using wildcards and/or normal names... - * Used both for source wildcarding in the Makefile and for finding - * implicit sources. - * - * The interface for this module is: - * Dir_Init Initialize the module. - * - * Dir_End Cleanup the module. - * - * Dir_HasWildcards Returns TRUE if the name given it needs to - * be wildcard-expanded. - * - * Dir_Expand Given a pattern and a path, return a Lst of names - * which match the pattern on the search path. - * - * Dir_FindFile Searches for a file on a given search path. - * If it exists, the entire path is returned. - * Otherwise NULL is returned. - * - * Dir_MTime Return the modification time of a node. The file - * is searched for along the default search path. - * The path and mtime fields of the node are filled - * in. - * - * Dir_AddDir Add a directory to a search path. - * - * Dir_MakeFlags Given a search path and a command flag, create - * a string with each of the directories in the path - * preceded by the command flag and all of them - * separated by a space. - * - * Dir_Destroy Destroy an element of a search path. Frees up all - * things that can be freed for the element as long - * as the element is no longer referenced by any other - * search path. - * - * For debugging: - * Dir_PrintDirectories Print stats about the directory cache. - */ - -#include <stddef.h> -#include <stdio.h> #include <sys/types.h> -#include <dirent.h> #include <sys/stat.h> -#include "make.h" +#include <dirent.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "defines.h" #include "ohash.h" #include "dir.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: dir.c,v 1.31 2001/05/03 13:41:03 espie Exp $"; +#include "lst.h" +#include "memory.h" +#include "buf.h" +#include "gnode.h" +#include "arch.h" +#include "targ.h" +#include "error.h" +#include "str.h" +#include "timestamp.h" + + +typedef struct Path_ { + int refCount; /* Number of paths with this directory */ +#ifdef DEBUG_DIRECTORY_CACHE + int hits; /* the number of times a file in this + * directory has been found */ #endif -#endif /* not lint */ + struct ohash files; /* Hash table of files in directory */ + char name[1]; /* Name of directory */ +} Path; /* A search path consists of a Lst of Path structures. A Path structure * has in it the name of the directory and a hash table of all the files @@ -193,14 +164,17 @@ static char rcsid[] = "$OpenBSD: dir.c,v 1.31 2001/05/03 13:41:03 espie Exp $"; * sense to replace the access() with a stat() and record the mtime * in a cache for when Dir_MTime was actually called. */ -LIST dirSearchPath; /* main search path */ +static LIST thedirSearchPath; /* main search path */ +Lst dirSearchPath= &thedirSearchPath; +#ifdef DEBUG_DIRECTORY_CACHE /* Variables for gathering statistics on the efficiency of the hashing * mechanism. */ static int hits, /* Found in directory cache */ misses, /* Sad, but not evil misses */ nearmisses, /* Found under search path */ bigmisses; /* Sought by itself */ +#endif static Path *dot; /* contents of current directory */ @@ -211,15 +185,12 @@ struct file_stamp { static struct ohash openDirectories; /* cache all open directories */ -static struct ohash mtimes; /* Results of doing a last-resort stat in - * Dir_FindFile -- if we have to go to the - * system to find the file, we might as well - * have its mtime on record. XXX: If this is done - * way early, there's a chance other rules will - * have already updated the file, in which case - * we'll update it again. Generally, there won't - * be two rules to update a single file, so this - * should be ok, but... */ +/* Global structure used to cache mtimes. XXX We don't cache an mtime + * before a caller actually looks up for the given time, because of the + * possibility a caller might update the file and invalidate the cache + * entry, and we don't look up in this cache except as a last resort. + */ +static struct ohash mtimes; /* There are three distinct hash structures: @@ -235,21 +206,39 @@ static struct ohash_info file_info = { 0, static struct ohash_info dir_info = { offsetof(Path, name), NULL, hash_alloc, hash_free, element_alloc }; -static void record_stamp(const char *, TIMESTAMP); +/* add_file(path, name): add a file name to a path hash structure. */ static void add_file(Path *, const char *); -static char *find_file_hash(Path *, const char *, const char *, u_int32_t); -static struct file_stamp *find_stampi(const char *, const char *); -static void free_hash(struct ohash *); +/* n = find_file_hashi(p, name, end, hv): retrieve name in a path hash + * structure. */ +static char *find_file_hashi(Path *, const char *, const char *, u_int32_t); +/* stamp = find_stampi(name, end): look for (name, end) in the global + * cache. */ +static struct file_stamp *find_stampi(const char *, const char *); +/* record_stamp(name, timestamp): record timestamp for name in the global + * cache. */ +static void record_stamp(const char *, TIMESTAMP); +/* free_hash(o): free a ohash structure, where each element can be free'd. */ +static void free_hash(struct ohash *); -static Path *DirReaddir(const char *, const char *); -static void DirMatchFiles(const char *, Path *, Lst); -static void PathMatchFiles(const char *, Lst, Lst); +/* p = DirReaddiri(name, end): read an actual directory, caching results + * as we go. */ +static Path *DirReaddiri(const char *, const char *); +/* Handles wildcard expansion on a given directory. */ +static void DirMatchFilesi(const char *, const char *, Path *, Lst); +/* Handles simple wildcard expansion on a path. */ +static void PathMatchFilesi(const char *, const char *, Lst, Lst); +/* Handles wildcards expansion except for curly braces. */ +static void DirExpandWildi(const char *, const char *, Lst, Lst); +#define DirExpandWild(s, l1, l2) DirExpandWildi(s, strchr(s, '\0'), l1, l2) +/* Handles wildcard expansion including curly braces. */ +static void DirExpandCurlyi(const char *, const char *, Lst, Lst); + +/* Debugging: show each word in an expansion list. */ static void DirPrintWord(void *); +/* Debugging: show a dir name in a path. */ static void DirPrintDir(void *); -static void DirExpandWild(const char *, Lst, Lst); -static void DirExpandCurly(const char *, Lst, Lst); static void record_stamp(file, t) @@ -298,7 +287,7 @@ add_file(p, file) } static char * -find_file_hash(p, file, e, hv) +find_file_hashi(p, file, e, hv) Path *p; const char *file; const char *e; @@ -321,23 +310,19 @@ free_hash(h) ohash_delete(h); } -/*- - *----------------------------------------------------------------------- - * Dir_Init -- - * initialize things for this module - * - * Side Effects: - * cache the current directory - *----------------------------------------------------------------------- - */ + +/* Side Effects: cache the current directory */ void Dir_Init() { - Lst_Init(&dirSearchPath); + char *dotname = "."; + + Lst_Init(dirSearchPath); ohash_init(&openDirectories, 4, &dir_info); ohash_init(&mtimes, 4, &stamp_info); - dot = DirReaddir(".", NULL); + + dot = DirReaddiri(dotname, dotname+1); if (!dot) Error("Can't access current directory"); @@ -347,69 +332,58 @@ Dir_Init() dot->refCount++; } -/*- - *----------------------------------------------------------------------- - * Dir_End -- - * cleanup things for this module - *----------------------------------------------------------------------- - */ +#ifdef CLEANUP void Dir_End() { -#ifdef CLEANUP struct Path *p; unsigned int i; dot->refCount--; Dir_Destroy(dot); - Lst_Destroy(&dirSearchPath, Dir_Destroy); + Lst_Destroy(dirSearchPath, Dir_Destroy); for (p = ohash_first(&openDirectories, &i); p != NULL; p = ohash_next(&openDirectories, &i)) Dir_Destroy(p); ohash_delete(&openDirectories); free_hash(&mtimes); -#endif } +#endif -/*- - *----------------------------------------------------------------------- - * Dir_HasWildcards -- - * see if the given name has any wildcard characters in it - * be careful not to expand unmatching brackets or braces. - * XXX: This code is not 100% correct. ([^]] fails etc.) - *----------------------------------------------------------------------- - */ -Boolean -Dir_HasWildcards(name) - const char *name; /* name to check */ + +/* XXX: This code is not 100% correct ([^]] fails) */ +bool +Dir_HasWildcardsi(name, end) + const char *name; + const char *end; { const char *cp; - Boolean wild = FALSE; + bool wild = false; unsigned long brace = 0, bracket = 0; - for (cp = name; *cp != '\0'; cp++) { + for (cp = name; cp != end; cp++) { switch (*cp) { case '{': brace++; - wild = TRUE; + wild = true; break; case '}': if (brace == 0) - return FALSE; + return false; brace--; break; case '[': bracket++; - wild = TRUE; + wild = true; break; case ']': if (bracket == 0) - return FALSE; + return false; bracket--; break; case '?': case '*': - wild = TRUE; + wild = true; break; default: break; @@ -420,26 +394,24 @@ Dir_HasWildcards(name) /*- *----------------------------------------------------------------------- - * DirMatchFiles -- + * DirMatchFilesi -- * Given a pattern and a Path structure, see if any files * match the pattern and add their names to the 'expansions' list if * any do. This is incomplete -- it doesn't take care of patterns like * src / *src / *.c properly (just *.c on any of the directories), but it * will do for now. - * - * Side Effects: - * The directory will be fully hashed when this is done. *----------------------------------------------------------------------- */ static void -DirMatchFiles(pattern, p, expansions) +DirMatchFilesi(pattern, end, p, expansions) const char *pattern; /* Pattern to look for */ + const char *end; /* End of pattern */ Path *p; /* Directory to search */ Lst expansions; /* Place to store the results */ { unsigned int search; /* Index into the directory's table */ const char *entry; /* Current entry in the table */ - Boolean isDot; /* Is the directory "." ? */ + bool isDot; /* Is the directory "." ? */ isDot = p->name[0] == '.' && p->name[1] == '\0'; @@ -451,38 +423,32 @@ DirMatchFiles(pattern, p, expansions) * so they won't match `.*'. */ if (*pattern != '.' && *entry == '.') continue; - if (Str_Match(entry, pattern)) + if (Str_Matchi(entry, strchr(entry, '\0'), pattern, end)) Lst_AtEnd(expansions, - isDot ? estrdup(entry) : str_concat(p->name, entry, '/')); + isDot ? estrdup(entry) : Str_concat(p->name, entry, '/')); } } /*- *----------------------------------------------------------------------- - * PathMatchFiles -- + * PathMatchFilesi -- * Traverse directories in the path, calling DirMatchFiles for each. * NOTE: This doesn't handle patterns in directories. *----------------------------------------------------------------------- */ static void -PathMatchFiles(word, path, expansions) +PathMatchFilesi(word, end, path, expansions) const char *word; /* Word to expand */ + const char *end; /* End of word */ Lst path; /* Path on which to look */ Lst expansions; /* Place to store the result */ { LstNode ln; /* Current node */ for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) - DirMatchFiles(word, (Path *)Lst_Datum(ln), expansions); + DirMatchFilesi(word, end, (Path *)Lst_Datum(ln), expansions); } -/*- - *----------------------------------------------------------------------- - * DirPrintWord -- - * Print a word in the list of expansions. Callback for Dir_Expand - * when DEBUG(DIR), via Lst_ForEach. - *----------------------------------------------------------------------- - */ static void DirPrintWord(word) void *word; @@ -492,14 +458,19 @@ DirPrintWord(word) /*- *----------------------------------------------------------------------- - * DirExpandWild: + * DirExpandWildi: * Expand all wild cards in a fully qualified name, except for * curly braces. + * Side-effect: + * Will hash any directory in which a file is found, and add it to + * the path, on the assumption that future lookups will find files + * there as well. *----------------------------------------------------------------------- */ static void -DirExpandWild(word, path, expansions) +DirExpandWildi(word, end, path, expansions) const char *word; /* the word to expand */ + const char *end; /* end of word */ Lst path; /* the list of directories in which to find * the resulting files */ Lst expansions; /* the list on which to place the results */ @@ -507,19 +478,19 @@ DirExpandWild(word, path, expansions) const char *cp; const char *slash; /* keep track of first slash before wildcard */ - slash = strchr(word, '/'); + slash = memchr(word, '/', end - word); if (slash == NULL) { /* First the files in dot. */ - DirMatchFiles(word, dot, expansions); + DirMatchFilesi(word, end, dot, expansions); /* Then the files in every other directory on the path. */ - PathMatchFiles(word, path, expansions); + PathMatchFilesi(word, end, path, expansions); return; } /* The thing has a directory component -- find the first wildcard * in the string. */ slash = word; - for (cp = word; *cp; cp++) { + for (cp = word; cp != end; cp++) { if (*cp == '/') slash = cp; if (*cp == '?' || *cp == '[' || *cp == '*') { @@ -535,24 +506,26 @@ DirExpandWild(word, path, expansions) * i.e. if the path contains ../Etc/Object and we're * looking for Etc, it won't be found. */ if (dirpath != NULL) { - char *dp = &dirpath[strlen(dirpath) - 1]; + char *dp; LIST temp; - if (*dp == '/') - *dp = '\0'; + dp = strchr(dirpath, '\0'); + while (dp > dirpath && dp[-1] == '/') + dp--; + Lst_Init(&temp); - Dir_AddDir(&temp, dirpath, NULL); - PathMatchFiles(slash+1, &temp, expansions); + Dir_AddDiri(&temp, dirpath, dp); + PathMatchFilesi(slash+1, end, &temp, expansions); Lst_Destroy(&temp, NOFREE); } } else /* Start the search from the local directory. */ - PathMatchFiles(word, path, expansions); + PathMatchFilesi(word, end, path, expansions); return; } } /* Return the file -- this should never happen. */ - PathMatchFiles(word, path, expansions); + PathMatchFilesi(word, end, path, expansions); } /*- @@ -560,14 +533,15 @@ DirExpandWild(word, path, expansions) * DirExpandCurly -- * Expand curly braces like the C shell, and other wildcards as per * Str_Match. - * Note the special behavior: if curly expansion yields a result with + * XXX: if curly expansion yields a result with * no wildcards, the result is placed on the list WITHOUT CHECKING * FOR ITS EXISTENCE. *----------------------------------------------------------------------- */ static void -DirExpandCurly(word, path, expansions) +DirExpandCurlyi(word, endw, path, expansions) const char *word; /* Entire word to expand */ + const char *endw; /* End of word */ Lst path; /* Search path to use */ Lst expansions; /* Place to store the expansions */ { @@ -575,19 +549,19 @@ DirExpandCurly(word, path, expansions) * expansion before calling Dir_Expand */ LIST curled; /* Queue of words to expand */ char *toexpand; /* Current word to expand */ - Boolean dowild; /* Wildcard left after curlies ? */ + bool dowild; /* Wildcard left after curlies ? */ /* Determine once and for all if there is something else going on */ - dowild = FALSE; - for (cp2 = word; *cp2 != '\0'; cp2++) + dowild = false; + for (cp2 = word; cp2 != endw; cp2++) if (*cp2 == '*' || *cp2 == '?' || *cp2 == '[') { - dowild = TRUE; + dowild = true; break; } /* Prime queue with copy of initial word */ Lst_Init(&curled); - Lst_EnQueue(&curled, estrdup(word)); + Lst_EnQueue(&curled, Str_dupi(word, endw)); while ((toexpand = (char *)Lst_DeQueue(&curled)) != NULL) { const char *brace; const char *start; /* Start of current chunk of brace clause */ @@ -651,37 +625,29 @@ DirExpandCurly(word, path, expansions) } } -/*- - *----------------------------------------------------------------------- - * Dir_Expand -- - * Expand the given word into a list of words by globbing it looking - * in the directories on the given search path. - * - * Results: - * A list of words consisting of the files which exist along the search - * path matching the given pattern. - * - * Side Effects: - * Directories may be opened. - *----------------------------------------------------------------------- - */ +/* Side effects: + * Dir_Expandi will hash directories that were not yet visited */ void -Dir_Expand(word, path, expansions) +Dir_Expandi(word, end, path, expansions) const char *word; /* the word to expand */ + const char *end; /* end of word */ Lst path; /* the list of directories in which to find * the resulting files */ Lst expansions; /* the list on which to place the results */ { const char *cp; - if (DEBUG(DIR)) - printf("expanding \"%s\"...", word); + if (DEBUG(DIR)) { + char *s = Str_dupi(word, end); + printf("expanding \"%s\"...", s); + free(s); + } - cp = strchr(word, '{'); + cp = memchr(word, '{', end - word); if (cp) - DirExpandCurly(word, path, expansions); + DirExpandCurlyi(word, end, path, expansions); else - DirExpandWild(word, path, expansions); + DirExpandWildi(word, end, path, expansions); if (DEBUG(DIR)) { Lst_Every(expansions, DirPrintWord); @@ -689,51 +655,43 @@ Dir_Expand(word, path, expansions) } } + /*- - *----------------------------------------------------------------------- - * Dir_FindFilei -- - * Find the file with the given name along the given search path. - * - * Results: - * The path to the file or NULL. This path is guaranteed to be in a - * different part of memory than name and so may be safely free'd. - * * Side Effects: * If the file is found in a directory which is not on the path * already (either 'name' is absolute or it is a relative path * [ dir1/.../dirn/file ] which exists below one of the directories * already on the search path), its directory is added to the end * of the path on the assumption that there will be more files in - * that directory later on. Sometimes this is true. Sometimes not. - *----------------------------------------------------------------------- + * that directory later on. */ char * Dir_FindFilei(name, end, path) - const char *name; /* the file to find */ - const char *end; /* end of file name */ - Lst path; /* List of directories to search */ + const char *name; + const char *end; + Lst path; { + Path *p; /* current path member */ char *p1; /* pointer into p->name */ const char *p2; /* pointer into name */ LstNode ln; /* a list element */ char *file; /* the current filename to check */ char *temp; /* index into file */ - Path *p; /* current path member */ const char *cp; /* index of first slash, if any */ - Boolean hasSlash; + bool hasSlash; struct stat stb; /* Buffer for stat, if necessary */ struct file_stamp *entry; /* Entry for mtimes table */ - u_int32_t hv; - char *q; /* Copy of name, end */ + u_int32_t hv; /* hash value for last component in file name */ + char *q; /* Str_dupi(name, end) */ - /* Find the final component of the name and note whether it has a - * slash in it (the name, I mean). */ - cp = lastchar(name, end, '/'); + /* Find the final component of the name and note whether name has a + * slash in it */ + cp = Str_rchri(name, end, '/'); if (cp) { - hasSlash = TRUE; + hasSlash = true; cp++; } else { - hasSlash = FALSE; + hasSlash = false; cp = name; } @@ -742,29 +700,29 @@ Dir_FindFilei(name, end, path) if (DEBUG(DIR)) printf("Searching for %s...", name); /* No matter what, we always look for the file in the current directory - * before anywhere else and we *do not* add the ./ to it if it exists. - * This is so there are no conflicts between what the user specifies - * (fish.c) and what pmake finds (./fish.c). */ + * before anywhere else and we always return exactly what the caller + * specified. */ if ((!hasSlash || (cp - name == 2 && *name == '.')) && - find_file_hash(dot, cp, end, hv) != NULL) { + find_file_hashi(dot, cp, end, hv) != NULL) { if (DEBUG(DIR)) printf("in '.'\n"); +#ifdef DEBUG_DIRECTORY_CACHE hits++; dot->hits++; - return interval_dup(name, end); +#endif + return Str_dupi(name, end); } - /* We look through all the directories on the path seeking one which - * contains the final component of the given name and whose final - * component(s) match the name's initial component(s). If such a beast - * is found, we concatenate the directory name and the final component - * and return the resulting string. If we don't find any such thing, - * we go on to phase two... */ + /* Then, we look through all the directories on path, seeking one + * containing the final component of name and whose final + * component(s) match name's initial component(s). + * If found, we concatenate the directory name and the + * final component and return the resulting string. */ for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); if (DEBUG(DIR)) printf("%s...", p->name); - if (find_file_hash(p, cp, end, hv) != NULL) { + if (find_file_hashi(p, cp, end, hv) != NULL) { if (DEBUG(DIR)) printf("here..."); if (hasSlash) { @@ -786,11 +744,13 @@ Dir_FindFilei(name, end, path) continue; } } - file = str_concati(p->name, cp, end, '/'); + file = Str_concati(p->name, strchr(p->name, '\0'), cp, end, '/'); if (DEBUG(DIR)) printf("returning %s\n", file); +#ifdef DEBUG_DIRECTORY_CACHE p->hits++; hits++; +#endif return file; } else if (hasSlash) { /* If the file has a leading path component and that component @@ -806,36 +766,40 @@ Dir_FindFilei(name, end, path) } } - /* We didn't find the file on any existing members of the directory. - * If the name doesn't contain a slash, that means it doesn't exist. - * If it *does* contain a slash, however, there is still hope: it - * could be in a subdirectory of one of the members of the search - * path. (eg. /usr/include and sys/types.h. The above search would - * fail to turn up types.h in /usr/include, but it *is* in - * /usr/include/sys/types.h) If we find such a beast, we assume there - * will be more (what else can we assume?) and add all but the last - * component of the resulting name onto the search path (at the - * end). This phase is only performed if the file is *not* absolute. */ + /* We didn't find the file on any existing member of the path. + * If the name doesn't contain a slash, end of story. + * If it does contain a slash, however, it could be in a subdirectory + * of one of the members of the search path. (eg., for path=/usr/include + * and name=sys/types.h, the above search fails to turn up types.h + * in /usr/include, even though /usr/include/sys/types.h exists). + * + * We only perform this look-up for non-absolute file names. + * + * Whenever we score a hit, we assume there will be more matches from + * that directory, and append all but the last component of the + * resulting name onto the search path. */ if (!hasSlash) { if (DEBUG(DIR)) printf("failed.\n"); +#ifdef DEBUG_DIRECTORY_CACHE misses++; +#endif return NULL; } if (*name != '/') { - Boolean checkedDot = FALSE; + bool checkedDot = false; if (DEBUG(DIR)) printf("failed. Trying subdirectories..."); for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); if (p != dot) - file = str_concati(p->name, name, end, '/'); + file = Str_concati(p->name, strchr(p->name, '\0'), name, end, '/'); else { /* Checking in dot -- DON'T put a leading ./ on the thing. */ - file = interval_dup(name, end); - checkedDot = TRUE; + file = Str_dupi(name, end); + checkedDot = true; } if (DEBUG(DIR)) printf("checking %s...", file); @@ -843,19 +807,19 @@ Dir_FindFilei(name, end, path) if (stat(file, &stb) == 0) { TIMESTAMP mtime; - grab_stat(stb, mtime); + ts_set_from_stat(stb, mtime); if (DEBUG(DIR)) printf("got it.\n"); - /* We've found another directory to search. We know there's - * a slash in 'file' because we put one there. We call - * Dir_AddDir to add this new directory onto the existing - * search path. Once that's done, we return the file name, - * knowing that should a file in this directory ever be - * referenced again in such a manner, we will find it - * without having to do numerous access calls. Hurrah! */ + /* We've found another directory to search. We know there + * is a slash in 'file'. We call Dir_AddDiri to add the + * new directory onto the existing search path. Once + * that's done, we return the file name, knowing that + * should a file in this directory ever be referenced again + * in such a manner, we will find it without having to do + * numerous access calls. */ temp = strrchr(file, '/'); - Dir_AddDir(path, file, temp); + Dir_AddDiri(path, file, temp); /* Save the modification time so if it's needed, we don't have * to fetch it again. */ @@ -863,7 +827,9 @@ Dir_FindFilei(name, end, path) printf("Caching %s for %s\n", Targ_FmtTime(mtime), file); record_stamp(file, mtime); +#ifdef DEBUG_DIRECTORY_CACHE nearmisses++; +#endif return file; } else free(file); @@ -881,41 +847,24 @@ Dir_FindFilei(name, end, path) } } - /* Didn't find it that way, either. Sigh. Phase 3. Add its directory - * onto the search path in any case, just in case, then look for the - * thing in the hash table. If we find it, grand. We return a new - * copy of the name. Otherwise we sadly return a NULL pointer. Sigh. - * Note that if the directory holding the file doesn't exist, this will - * do an extra search of the final directory on the path. Unless something - * weird happens, this search won't succeed and life will be groovy. + /* Didn't find it that way, either. Last resort: look for the file + * in the global mtime cache, then on the disk. + * If this doesn't succeed, we finally return a NULL pointer. * - * Sigh. We cannot add the directory onto the search path because + * We cannot add this directory onto the search path because * of this amusing case: * $(INSTALLDIR)/$(FILE): $(FILE) * * $(FILE) exists in $(INSTALLDIR) but not in the current one. * When searching for $(FILE), we will find it in $(INSTALLDIR) * b/c we added it here. This is not good... */ -#ifdef notdef - Dir_AddDir(path, name, cp-1); - - bigmisses += 1; - ln = Lst_Last(path); - if (ln == NULL) - return NULL; - else - p = (Path *)Lst_Datum(ln); - - if (find_file_hash(p, cp, e, hv) != NULL) - return estrdup(name); - else - return NULL; -#else /* !notdef */ - q = interval_dup(name, end); + q = Str_dupi(name, end); if (DEBUG(DIR)) printf("Looking for \"%s\"...", q); +#ifdef DEBUG_DIRECTORY_CACHE bigmisses++; +#endif entry = find_stampi(name, end); if (entry != NULL) { if (DEBUG(DIR)) @@ -924,7 +873,7 @@ Dir_FindFilei(name, end, path) } else if (stat(q, &stb) == 0) { TIMESTAMP mtime; - grab_stat(stb, mtime); + ts_set_from_stat(stb, mtime); if (DEBUG(DIR)) printf("Caching %s for %s\n", Targ_FmtTime(mtime), q); @@ -936,78 +885,11 @@ Dir_FindFilei(name, end, path) free(q); return NULL; } -#endif /* notdef */ -} - -/*- - *----------------------------------------------------------------------- - * Dir_MTime -- - * Find the modification time of the file described by gn along the - * search path dirSearchPath. - * - * Results: - * The modification time or OUT_OF_DATE if it doesn't exist - * - * Side Effects: - * The modification time is placed in the node's mtime slot. - * If the node didn't have a path entry before, and Dir_FindFile - * found one for it, the full name is placed in the path slot. - *----------------------------------------------------------------------- - */ -TIMESTAMP -Dir_MTime(gn) - GNode *gn; /* the file whose modification time is - * desired */ -{ - char *fullName; /* the full pathname of name */ - struct stat stb; /* buffer for finding the mod time */ - struct file_stamp - *entry; - unsigned int slot; - TIMESTAMP mtime; - - if (gn->type & OP_ARCHV) - return Arch_MTime(gn); - - if (gn->path == NULL) { - fullName = Dir_FindFile(gn->name, &dirSearchPath); - if (fullName == NULL) - fullName = estrdup(gn->name); - } else - fullName = gn->path; - - slot = ohash_qlookup(&mtimes, fullName); - entry = ohash_find(&mtimes, slot); - if (entry != NULL) { - /* Only do this once -- the second time folks are checking to - * see if the file was actually updated, so we need to actually go - * to the file system. */ - if (DEBUG(DIR)) - printf("Using cached time %s for %s\n", - Targ_FmtTime(entry->mtime), fullName); - mtime = entry->mtime; - free(entry); - ohash_remove(&mtimes, slot); - } else if (stat(fullName, &stb) == 0) - grab_stat(stb, mtime); - else { - if (gn->type & OP_MEMBER) { - if (fullName != gn->path) - free(fullName); - return Arch_MemMTime(gn); - } else - set_out_of_date(mtime); - } - if (fullName && gn->path == NULL) - gn->path = fullName; - - gn->mtime = mtime; - return gn->mtime; } /* Read a directory, either from the disk, or from the cache. */ static Path * -DirReaddir(name, end) +DirReaddiri(name, end) const char *name; const char *end; { @@ -1023,7 +905,9 @@ DirReaddir(name, end) return p; p = ohash_create_entry(&dir_info, name, &end); +#ifdef DEBUG_DIRECTORY_CACHE p->hits = 0; +#endif p->refCount = 0; ohash_init(&p->files, 4, &file_info); @@ -1058,7 +942,7 @@ DirReaddir(name, end) /*- *----------------------------------------------------------------------- - * Dir_AddDir -- + * Dir_AddDiri -- * Add the given name to the end of the given path. The order of * the arguments is backwards so ParseDoDependency can do a * Lst_ForEach of its list of paths... @@ -1070,19 +954,19 @@ DirReaddir(name, end) */ void -Dir_AddDir(path, name, end) +Dir_AddDiri(path, name, end) Lst path; /* the path to which the directory should be added */ const char *name; /* the name of the directory to add */ const char *end; { Path *p; /* pointer to new Path structure */ - p = DirReaddir(name, end); + p = DirReaddiri(name, end); if (p == NULL) return; if (p->refCount == 0) Lst_AtEnd(path, p); - else if (Lst_AddNew(path, p) == FAILURE) + else if (!Lst_AddNew(path, p)) return; p->refCount++; } @@ -1185,12 +1069,12 @@ Dir_Concat(path1, path2) for (ln = Lst_First(path2); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); - if (Lst_AddNew(path1, p) == SUCCESS) + if (Lst_AddNew(path1, p)) p->refCount++; } } -/********** DEBUG INFO **********/ +#ifdef DEBUG_DIRECTORY_CACHE void Dir_PrintDirectories() { @@ -1207,6 +1091,7 @@ Dir_PrintDirectories() p = ohash_next(&openDirectories, &i)) printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); } +#endif static void DirPrintDir(p) @@ -1222,24 +1107,54 @@ Dir_PrintPath(path) Lst_Every(path, DirPrintDir); } -#ifndef USE_TIMESPEC -#include <sys/types.h> -#include <utime.h> -#endif -int -set_times(f) - const char *f; +TIMESTAMP +Dir_MTime(gn) + GNode *gn; /* the file whose modification time is + * desired */ { -#ifdef USE_TIMESPEC - struct timeval tv[2]; + char *fullName; /* the full pathname of name */ + struct stat stb; /* buffer for finding the mod time */ + struct file_stamp + *entry; + unsigned int slot; + TIMESTAMP mtime; - TIMESPEC_TO_TIMEVAL(&tv[0], &now); - TIMESPEC_TO_TIMEVAL(&tv[1], &now); - return utimes(f, tv); -#else - struct utimbuf times; + if (gn->type & OP_ARCHV) + return Arch_MTime(gn); - times.actime = times.modtime = now; - return utime(f, ×); -#endif + if (gn->path == NULL) { + fullName = Dir_FindFile(gn->name, dirSearchPath); + if (fullName == NULL) + fullName = estrdup(gn->name); + } else + fullName = gn->path; + + slot = ohash_qlookup(&mtimes, fullName); + entry = ohash_find(&mtimes, slot); + if (entry != NULL) { + /* Only do this once -- the second time folks are checking to + * see if the file was actually updated, so we need to actually go + * to the file system. */ + if (DEBUG(DIR)) + printf("Using cached time %s for %s\n", + Targ_FmtTime(entry->mtime), fullName); + mtime = entry->mtime; + free(entry); + ohash_remove(&mtimes, slot); + } else if (stat(fullName, &stb) == 0) + ts_set_from_stat(stb, mtime); + else { + if (gn->type & OP_MEMBER) { + if (fullName != gn->path) + free(fullName); + return Arch_MemMTime(gn); + } else + ts_set_out_of_date(mtime); + } + if (fullName && gn->path == NULL) + gn->path = fullName; + + gn->mtime = mtime; + return gn->mtime; } + diff --git a/usr.bin/make/dir.h b/usr.bin/make/dir.h index f7f595f052e..80e626395c8 100644 --- a/usr.bin/make/dir.h +++ b/usr.bin/make/dir.h @@ -1,5 +1,8 @@ +#ifndef DIR_H +#define DIR_H + /* $OpenPackages$ */ -/* $OpenBSD: dir.h,v 1.14 2001/05/03 13:41:04 espie Exp $ */ +/* $OpenBSD: dir.h,v 1.15 2001/05/23 12:34:42 espie Exp $ */ /* $NetBSD: dir.h,v 1.4 1996/11/06 17:59:05 christos Exp $ */ /* @@ -42,34 +45,124 @@ * from: @(#)dir.h 8.1 (Berkeley) 6/6/93 */ -/* dir.h -- - */ - -#ifndef DIR_H -#define DIR_H +#ifndef TIMESTAMP_TYPE +#include "timestamp_t.h" +#endif -typedef struct Path_ { - int refCount; /* Number of paths with this directory */ - int hits; /* the number of times a file in this - * directory has been found */ - struct ohash files; /* Hash table of files in directory */ - char name[1]; /* Name of directory */ -} Path; +/* dir -- + * Directory searching using wildcards and/or normal names... + * Used both for source wildcarding in the Makefile and for finding + * implicit sources. + */ +/* Dir_Init() + * Initialize the module. + */ extern void Dir_Init(void); + +/* Dir_End() + * Cleanup the module. + */ +#ifdef CLEANUP extern void Dir_End(void); -extern Boolean Dir_HasWildcards(const char *); -extern void Dir_Expand(const char *, Lst, Lst); +#else +#define Dir_End() +#endif + +/* + * Manipulating paths. By convention, the empty path always allows for + * finding files in the current directory. + */ + +/* Dir_AddDiri(path, name, end); + * Add directory (name, end) to a search path. + */ +extern void Dir_AddDiri(Lst, const char *, const char *); +#define Dir_AddDir(l, n) Dir_AddDiri(l, n, NULL) + +/* Dir_Concat(p1, p2); + * Concatenate two paths, adding dirs in p2 to the end of p1, but + * avoiding duplicates. + */ +extern void Dir_Concat(Lst, Lst); + +/* Dir_Destroy(d); + * Destroy a directory in a search path. + */ +extern void Dir_Destroy(void *); + +/* p2 = Dir_CopyDir(p); + * Return a copy of a directory. Callback to duplicate search paths. + */ +extern void *Dir_CopyDir(void *); + +/* Dir_PrintPath(p); + * Print the directory names along a given path. + */ +extern void Dir_PrintPath(Lst); + + +/* + * Handling file names, and looking them up in paths + */ + +/* boolean = Dir_HasWildcardsi(name, end) + * Returns true if (name, end) needs to be wildcard-expanded. + */ +extern bool Dir_HasWildcardsi(const char *, const char *); +#define Dir_HasWildcards(n) Dir_HasWildcardsi(n, strchr(n, '\0')) + +/* Dir_Expandi(pattern, endp, path, expansions); + * Expand (pattern, endp) to Lst of names matching on the search path. + * Put result in expansions. + */ +extern void Dir_Expandi(const char *, const char *, Lst, Lst); +#define Dir_Expand(n, l1, l2) Dir_Expandi(n, strchr(n, '\0'), l1, l2) + +/* fullname = Dir_FindFilei(name, end, path) + * Searches for a file (name, end) on a given search path. If it exists, + * return the fullname of the file, otherwise NULL. + * The fullname is always a copy, and the caller is responsible for + * free()ing it. + * Looking for a simple name always looks in the current directory. + * For complex names, the current directory search only occurs for + * paths with dot in them. + */ extern char *Dir_FindFilei(const char *, const char *, Lst); #define Dir_FindFile(n, e) Dir_FindFilei(n, strchr(n, '\0'), e) + +/* stamp = Dir_MTime(gn); + * Return the modification time of node gn, searching along + * the default search path. + * Side effect: the path and mtime fields of gn are filled in. + * Return specific value if file can't be found, to be tested by + * is_out_of_date(). + */ extern TIMESTAMP Dir_MTime(GNode *); -extern void Dir_AddDir(Lst, const char *, const char *); + + + + +/* + * Misc + */ + +/* string = Dir_MakeFlags(flag, path); + * Given a search path and a command flag, create a string with each + * of the directories in the path preceded by the command flag and all + * of them separated by spaces. + */ extern char *Dir_MakeFlags(const char *, Lst); -extern void Dir_Concat(Lst, Lst); + + +#ifdef DEBUG_DIRECTORY_CACHE +/* Dir_PrintDirectories(); + * Print stats about the directory cache. + */ extern void Dir_PrintDirectories(void); -extern void Dir_PrintPath(Lst); -extern void Dir_Destroy(void *); -extern void *Dir_CopyDir(void *); -extern int set_times(const char *); +#endif + +/* List of directories to search when looking for targets. */ +extern Lst dirSearchPath; #endif /* DIR_H */ diff --git a/usr.bin/make/error.c b/usr.bin/make/error.c index 595f639eaa9..b4fd3805249 100644 --- a/usr.bin/make/error.c +++ b/usr.bin/make/error.c @@ -1,14 +1,8 @@ -/* $OpenPackages$ */ -/* $OpenBSD: error.c,v 1.5 2001/05/03 13:41:04 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: error.c,v 1.6 2001/05/23 12:34:42 espie Exp $ */ /* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1989 by Berkeley Softworks - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Adam de Boor. + * Copyright (c) 2001 Marc Espie. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -18,177 +12,223 @@ * 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. + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. */ +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> #include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "error.h" -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else -#define UNUSED -#endif +#include "config.h" +#include "defines.h" +#include "error.h" +#include "job.h" +#include "targ.h" -static void enomem(size_t); +#include "lowparse.h" -/* - * emalloc -- - * malloc, but die on error. +int fatal_errors = 0; +static void ParseVErrorInternal(const char *, unsigned long, int, const char *, va_list); +/*- + * Error -- + * Print an error message given its format. */ -void * -emalloc(len) - size_t len; +/* VARARGS */ +void +#ifdef __STDC__ +Error(char *fmt, ...) +#else +Error(va_alist) + va_dcl +#endif { - void *p; + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + char *fmt; - if ((p = malloc(len)) == NULL) - enomem(len); - return p; + va_start(ap); + fmt = va_arg(ap, char *); +#endif + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); } -/* - * estrdup -- - * strdup, but die on error. +/*- + * Fatal -- + * Produce a Fatal error message. If jobs are running, waits for them + * to finish. + * + * Side Effects: + * The program exits */ -char * -estrdup(str) - const char *str; +/* VARARGS */ +void +#ifdef __STDC__ +Fatal(char *fmt, ...) +#else +Fatal(va_alist) + va_dcl +#endif { - char *p; - size_t size; + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + char *fmt; + + va_start(ap); + fmt = va_arg(ap, char *); +#endif + Job_Wait(); - size = strlen(str) + 1; + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); - p = emalloc(size); - memcpy(p, str, size); - return p; + if (DEBUG(GRAPH2)) + Targ_PrintGraph(2); + exit(2); /* Not 1 so -q can distinguish error */ } /* - * erealloc -- - * realloc, but die on error. + * Punt -- + * Major exception once jobs are being created. Kills all jobs, prints + * a message and exits. + * + * Side Effects: + * All children are killed indiscriminately and the program Lib_Exits */ -void * -erealloc(ptr, size) - void *ptr; - size_t size; +/* VARARGS */ +void +#ifdef __STDC__ +Punt(char *fmt, ...) +#else +Punt(va_alist) + va_dcl +#endif { - if ((ptr = realloc(ptr, size)) == NULL) - enomem(size); - return ptr; -} + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + char *fmt; -void * -ecalloc(s1, s2) - size_t s1; - size_t s2; -{ - void *p; + va_start(ap); + fmt = va_arg(ap, char *); +#endif - if ((p = calloc(s1, s2)) == NULL) - enomem(s1 * s2); - return p; -} + (void)fprintf(stderr, "make: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); -/* Support routines for hash tables. */ -void * -hash_alloc(s, u) - size_t s; - void *u UNUSED; -{ - return ecalloc(s, 1); + DieHorribly(); } +/*- + * DieHorribly -- + * Exit without giving a message. + * + * Side Effects: + * A big one... + */ void -hash_free(p, s, u) - void *p; - size_t s UNUSED; - void *u UNUSED; +DieHorribly() { - free(p); + Job_AbortAll(); + if (DEBUG(GRAPH2)) + Targ_PrintGraph(2); + exit(2); /* Not 1, so -q can distinguish error */ } -void * -element_alloc(s, u) - size_t s; - void *u UNUSED; -{ - return emalloc(s); -} - - - /* - * enomem -- - * die when out of memory. + * Finish -- + * Called when aborting due to errors in child shell to signal + * abnormal exit. + * + * Side Effects: + * The program exits */ void -enomem(size) - size_t size; +Finish(errors) + int errors; /* number of errors encountered in Make_Make */ { - fprintf(stderr, "make: %s (%lu)\n", strerror(errno), (u_long)size); - exit(2); + Fatal("%d error%s", errors, errors == 1 ? "" : "s"); } -/* - * esetenv -- - * change environment, die on error. + +/*- + * ParseVErrorInternal -- + * Error message abort function for parsing. Prints out the context + * of the error (line number and file) as well as the message with + * two optional arguments. + * + * Side Effects: + * "fatals" is incremented if the level is PARSE_FATAL. */ -void -esetenv(name, value) - const char *name; - const char *value; +/* VARARGS */ +static void +#ifdef __STDC__ +ParseVErrorInternal(const char *cfname, unsigned long clineno, int type, + const char *fmt, va_list ap) +#else +ParseVErrorInternal(va_alist) + va_dcl +#endif { - if (setenv(name, value, 1) == 0) - return; - - fprintf(stderr, "make: setenv failed (%s)\n", strerror(errno)); - exit(2); + (void)fprintf(stderr, "\"%s\", line %lu: ", cfname, clineno); + if (type == PARSE_WARNING) + (void)fprintf(stderr, "warning: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + if (type == PARSE_FATAL) + fatal_errors ++; } - -/* - * enunlink -- - * Remove a file carefully, avoiding directories. +/*- + * Parse_Error -- + * External interface to ParseVErrorInternal; uses the default filename + * Line number. */ -int -eunlink(file) - const char *file; +/* VARARGS */ +void +#ifdef __STDC__ +Parse_Error(int type, const char *fmt, ...) +#else +Parse_Error(va_alist) + va_dcl +#endif { - struct stat st; + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ + char *fmt; - if (lstat(file, &st) == -1) - return -1; + va_start(ap); + type = va_arg(ap, int); + fmt = va_arg(ap, char *); +#endif - if (S_ISDIR(st.st_mode)) { - errno = EISDIR; - return -1; - } - return unlink(file); + ParseVErrorInternal(Parse_Getfilename(), Parse_Getlineno(), type, fmt, ap); } diff --git a/usr.bin/make/error.h b/usr.bin/make/error.h index d78d5bd5026..095b9c7f3a2 100644 --- a/usr.bin/make/error.h +++ b/usr.bin/make/error.h @@ -1,14 +1,10 @@ -/* $OpenPackages$ */ -/* $OpenBSD: error.h,v 1.5 2001/05/03 13:41:05 espie Exp $ */ +#ifndef ERROR_H +#define ERROR_H +/* $OpenPackages$ */ +/* $OpenBSD: error.h,v 1.6 2001/05/23 12:34:42 espie Exp $ */ -/*- - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1989 by Berkeley Softworks - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Adam de Boor. +/* + * Copyright (c) 2001 Marc Espie. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -18,43 +14,47 @@ * 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. + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ +/* Error Print a tagged error message. The global + * MAKE variable must have been defined. This + * takes a format string and two optional + * arguments for it. + * + * Fatal Print an error message and exit. Also takes + * a format string and two arguments. + * + * Punt Aborts all jobs and exits with a message. Also + * takes a format string and two arguments. * - * from: @(#)nonints.h 8.3 (Berkeley) 3/19/94 + * Finish Finish things up by printing the number of + * errors which occured, as passed to it, and + * exiting. */ -#ifndef ERROR_H -#define ERROR_H -extern void *emalloc(size_t); -extern char *estrdup(const char *); -extern void *erealloc(void *, size_t); -extern void *ecalloc(size_t, size_t); -extern int eunlink(const char *); -extern void esetenv(const char *, const char *); - -/* efree(x) works when x==NULL. STDC behavior, may need some different - * definition for cross-builds on deficient systems */ -#define efree free +extern void Error(char *, ...); +extern void Fatal(char *, ...); +extern void Punt(char *, ...); +extern void DieHorribly(void); +extern void Finish(int); -extern void *hash_alloc(size_t, void *); -extern void hash_free(void *, size_t, void *); -extern void *element_alloc(size_t, void *); - -#endif /* ERROR_H */ +/* + * Error levels for parsing. PARSE_FATAL means the process cannot continue + * once the makefile has been parsed. PARSE_WARNING means it can. Passed + * as the first argument to Parse_Error. + */ +#define PARSE_WARNING 2 +#define PARSE_FATAL 1 +extern void Parse_Error(int, const char *, ...); +extern int fatal_errors; +#endif diff --git a/usr.bin/make/extern.h b/usr.bin/make/extern.h index fa147953930..9c94bccd45e 100644 --- a/usr.bin/make/extern.h +++ b/usr.bin/make/extern.h @@ -1,5 +1,8 @@ +#ifndef EXTERN_H +#define EXTERN_H + /* $OpenPackages$ */ -/* $OpenBSD: extern.h,v 1.37 2001/05/03 13:41:05 espie Exp $ */ +/* $OpenBSD: extern.h,v 1.38 2001/05/23 12:34:42 espie Exp $ */ /* $NetBSD: nonints.h,v 1.12 1996/11/06 17:59:19 christos Exp $ */ /*- @@ -42,149 +45,22 @@ * from: @(#)nonints.h 8.3 (Berkeley) 3/19/94 */ -/* arch.c */ -extern ReturnStatus Arch_ParseArchive(char **, Lst, SymTable *); -extern void Arch_Touch(GNode *); -extern void Arch_TouchLib(GNode *); -extern TIMESTAMP Arch_MTime(GNode *); -extern TIMESTAMP Arch_MemMTime(GNode *); -extern void Arch_FindLib(GNode *, Lst); -extern Boolean Arch_LibOODate(GNode *); -extern void Arch_Init(void); -extern void Arch_End(void); -extern Boolean Arch_IsLib(GNode *); - -/* compat.c */ -extern void Compat_Run(Lst); - -/* cond.c */ -extern int Cond_Eval(char *); -extern void Cond_End(void); - -#include "error.h" - -/* for.c */ -typedef struct For_ For; -extern For *For_Eval(const char *); -extern Boolean For_Accumulate(For *, const char *); -extern void For_Run (For *); - -/* main.c */ -extern void Main_ParseArgLine(char *); -extern char *Cmd_Exec(const char *, char **); -extern void Error(char *, ...); -extern void Fatal(char *, ...); -extern void Punt(char *, ...); -extern void DieHorribly(void); -extern void PrintAddr(void *); -extern void Finish(int); - -/* make.c */ -extern void Make_TimeStamp(GNode *, GNode *); -extern Boolean Make_OODate(GNode *); -extern void Make_HandleUse(GNode *, GNode *); -extern void Make_Update(GNode *); -extern void Make_DoAllVar(GNode *); -extern Boolean Make_Run(Lst); - -/* parse.c */ -extern void Parse_Error(int, char *, ...); -extern Boolean Parse_AnyExport(void); -extern Boolean Parse_IsVar(char *); -extern void Parse_DoVar(const char *, GSymT *); -extern void Parse_AddIncludeDir(const char *); -extern void Parse_File(char *, FILE *); -extern void Parse_Init(void); -extern void Parse_End(void); -extern void Parse_FromString(char *, unsigned long); -extern unsigned long Parse_Getlineno(void); -extern const char *Parse_Getfilename(void); -extern void Parse_MainName(Lst); - -/* stats.h */ -extern void Init_Stats(void); - -/* str.c */ -extern void str_init(void); -extern void str_end(void); -extern char *lastchar(const char *, const char *, int); -extern char *str_concati(const char *, const char *, const char *, int); -#define str_concat(s1, s2, sep) str_concati(s1, s2, strchr(s2, '\0'), sep) -extern char **brk_string(const char *, int *, char **); -extern const char *iterate_words(const char **); -extern Boolean Str_Matchi(const char *, const char *, const char *); -#define Str_Match(string, pattern) \ - Str_Matchi(string, pattern, strchr(pattern, '\0')) -extern const char *Str_SYSVMatch(const char *, const char *, size_t *); -extern void Str_SYSVSubst(Buffer, const char *, const char *, size_t); -extern char *interval_dup(const char *, const char *); -extern char *escape_dup(const char *, const char *, const char *); - -/* suff.c */ -extern void Suff_ClearSuffixes(void); -extern Boolean Suff_IsTransform(const char *); -extern GNode *Suff_AddTransform(const char *); -extern void Suff_EndTransform(void *); -extern void Suff_AddSuffix(char *); -extern Lst Suff_GetPath(char *); -extern void Suff_DoPaths(void); -extern void Suff_AddInclude(char *); -extern void Suff_AddLib(char *); -extern void Suff_FindDeps(GNode *); -extern void Suff_SetNull(char *); -extern void Suff_Init(void); -extern void Suff_End(void); -extern void Suff_PrintAll(void); - -/* targ.c */ -extern void Targ_Init(void); -extern void Targ_End(void); -extern GNode *Targ_NewGN(const char *, const char *); -extern GNode *Targ_FindNode(const char *, const char *, int); -extern void Targ_FindList(Lst, Lst); -extern Boolean Targ_Ignore(GNode *); -extern Boolean Targ_Silent(GNode *); -extern Boolean Targ_Precious(GNode *); -extern void Targ_SetMain(GNode *); -extern void Targ_PrintCmd(void *); -extern char *Targ_FmtTime(TIMESTAMP); -extern void Targ_PrintType(int); -extern void Targ_PrintGraph(int); - -/* var.c */ -extern void Var_Delete(const char *); -extern void Var_Set_interval(const char *, const char *, const char *, - GSymT *); -extern void Varq_Set(int, const char *, GNode *); -extern void Var_Append_interval(const char *, const char *, - const char *, GSymT *); -extern void Varq_Append(int, const char *, GNode *); -extern char *Var_Value_interval(const char *, const char *); -extern char *Varq_Value(int, GNode *); -extern char *Var_Parse(const char *, SymTable *, Boolean, size_t *, - Boolean *); -extern size_t Var_ParseSkip(const char *, SymTable *, ReturnStatus *); -extern ReturnStatus Var_ParseBuffer(Buffer, const char *, SymTable *, - Boolean, size_t *); -extern char *Var_Subst(const char *, SymTable *, Boolean); -extern void Var_SubstVar(Buffer, const char *, const char *, const char *); -extern void Var_Init(void); -extern void Var_End(void); -extern void Var_Dump(void); -extern void SymTable_Init(SymTable *); -extern void SymTable_Destroy(SymTable *); -#define Var_Set(n, v, ctxt) Var_Set_interval(n, NULL, v, ctxt) -#define Var_Append(n, v, ctxt) Var_Append_interval(n, NULL, v, ctxt) -#define Var_Value(n) Var_Value_interval(n, NULL) -extern void Var_AddCmdline(const char *); - -/* Used to store temporary names, after $ expansion */ -struct Name { - const char *s; - const char *e; - Boolean tofree; -}; - -extern const char *Var_Name_Get(const char *, struct Name *, SymTable *, - Boolean, const char *(*)(const char *)); -extern void Var_Name_Free(struct Name *); +extern bool compatMake; /* True if we are make compatible */ +extern bool ignoreErrors; /* True if should ignore all errors */ +extern bool beSilent; /* True if should print no commands */ +extern bool noExecute; /* True if should execute nothing */ +extern bool allPrecious; /* True if every target is precious */ +extern bool keepgoing; /* True if should continue on unaffected + * portions of the graph when have an error + * in one portion */ +extern bool touchFlag; /* true if targets should just be 'touched' + * if out of date. Set by the -t flag */ +extern bool usePipes; /* true if should capture the output of + * subshells by means of pipes. Otherwise it + * is routed to temporary files from which it + * is retrieved when the shell exits */ +extern bool queryFlag; /* true if we aren't supposed to really make + * anything, just see if the targets are out- + * of-date */ + +#endif diff --git a/usr.bin/make/for.c b/usr.bin/make/for.c index fb02b513ab2..4fac3299ce2 100644 --- a/usr.bin/make/for.c +++ b/usr.bin/make/for.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: for.c,v 1.24 2001/05/03 13:41:05 espie Exp $ */ +/* $OpenBSD: for.c,v 1.25 2001/05/23 12:34:42 espie Exp $ */ /* $NetBSD: for.c,v 1.4 1996/11/06 17:59:05 christos Exp $ */ /* @@ -62,31 +62,21 @@ * SUCH DAMAGE. */ -/*- - * for.c -- - * Functions to handle loops in a makefile. - * - * Interface: - * For_Eval Evaluate the .for in the passed line. - * For_Accumulate Add lines to an accumulating loop - * For_Run Run accumulated loop - * - */ - -#include <ctype.h> -#include <assert.h> -#include <stddef.h> -#include "make.h" -#include "buf.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: for.c,v 1.24 2001/05/03 13:41:05 espie Exp $"; -#endif -#endif /* not lint */ +#include <assert.h> +#include <ctype.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "buf.h" +#include "for.h" +#include "lst.h" +#include "error.h" +#include "var.h" +#include "lowparse.h" +#include "str.h" +#include "memory.h" /* * For statements are of the form: @@ -104,22 +94,28 @@ static char rcsid[] = "$OpenBSD: for.c,v 1.24 2001/05/03 13:41:05 espie Exp $"; /* State of a for loop. */ struct For_ { - char *text; /* unexpanded text */ - LIST vars; /* list of variables */ - LstNode var; /* current var */ - int nvars; /* total number of vars */ + char *text; /* Unexpanded text */ + LIST vars; /* List of variables */ + LstNode var; /* Current var */ + int nvars; /* Total number of vars */ LIST lst; /* List of items */ size_t guess; /* Estimated expansion size */ BUFFER buf; /* Accumulating text */ unsigned long lineno; /* Line number at start of loop */ unsigned long level; /* Nesting level */ - Boolean freeold; + bool freeold; }; +/* ForExec(value, handle); + * Expands next variable in loop sequence described by handle to value. */ static void ForExec(void *, void *); + +/* n = build_words_list(lst, s); + * Cuts string into words, pushes words into list, in reverse order, + * because Parse_FromString works as a stack. + * Returns the number of words. */ static unsigned long build_words_list(Lst, const char *); -/* Cut a string into words, stuff that into list. */ static unsigned long build_words_list(lst, s) Lst lst; @@ -132,25 +128,12 @@ build_words_list(lst, s) end = s; while ((wrd = iterate_words(&end)) != NULL) { - Lst_AtFront(lst, escape_dup(wrd, end, "\"'")); + Lst_AtFront(lst, escape_dupi(wrd, end, "\"'")); n++; } return n; } -/* - *----------------------------------------------------------------------- - * For_Eval -- - * Evaluate the for loop in the passed line. The line - * looks like this: - * .for <variable> in <varlist> - * - * Results: - * Loop structure, to accumulate further lines. - * NULL if this was not a for loop after all. - *----------------------------------------------------------------------- - */ - For * For_Eval(line) const char *line; /* Line to parse */ @@ -189,10 +172,10 @@ For_Eval(line) endVar = ptr++; while (*ptr && isspace(*ptr)) ptr++; - /* finished variable list */ + /* End of variable list ? */ if (endVar - wrd == 2 && wrd[0] == 'i' && wrd[1] == 'n') break; - Lst_AtEnd(&arg->vars, interval_dup(wrd, endVar)); + Lst_AtEnd(&arg->vars, Str_dupi(wrd, endVar)); arg->nvars++; } if (arg->nvars == 0) { @@ -201,7 +184,7 @@ For_Eval(line) } /* Make a list with the remaining words. */ - sub = Var_Subst(ptr, NULL, FALSE); + sub = Var_Subst(ptr, NULL, false); if (DEBUG(FOR)) { LstNode ln; (void)fprintf(stderr, "For: Iterator "); @@ -225,20 +208,7 @@ For_Eval(line) } -/*- - *----------------------------------------------------------------------- - * For_Accumulate -- - * Accumulate lines in a for loop, until we find the matching endfor. - * - * Results: - * TRUE: keep accumulating lines. - * FALSE: We found the matching .endfor - * - * Side Effects: - * Accumulate lines in arg. - *----------------------------------------------------------------------- - */ -Boolean +bool For_Accumulate(arg, line) For *arg; const char *line; /* Line to parse */ @@ -258,7 +228,7 @@ For_Accumulate(arg, line) (void)fprintf(stderr, "For: end for %lu\n", arg->level); /* If matching endfor, don't add line to buffer. */ if (--arg->level == 0) - return FALSE; + return false; } else if (strncmp(ptr, "for", 3) == 0 && isspace(ptr[3])) { @@ -269,23 +239,17 @@ For_Accumulate(arg, line) } Buf_AddString(&arg->buf, line); Buf_AddChar(&arg->buf, '\n'); - return TRUE; + return true; } #define GUESS_EXPANSION 32 -/*- - *----------------------------------------------------------------------- - * ForExec -- - * Expand the for loop for this index and push it in the Makefile - *----------------------------------------------------------------------- - */ static void -ForExec(namep, argp) - void *namep; +ForExec(valuep, argp) + void *valuep; void *argp; { - char *name = (char *)namep; + char *value = (char *)valuep; For *arg = (For *)argp; BUFFER buf; @@ -294,30 +258,24 @@ ForExec(namep, argp) if (arg->var == NULL) { arg->var = Lst_Last(&arg->vars); arg->text = Buf_Retrieve(&arg->buf); - arg->freeold = FALSE; + arg->freeold = false; } if (DEBUG(FOR)) - (void)fprintf(stderr, "--- %s = %s\n", (char *)Lst_Datum(arg->var), name); + (void)fprintf(stderr, "--- %s = %s\n", (char *)Lst_Datum(arg->var), + value); Buf_Init(&buf, arg->guess); - Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), name); + Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), value); if (arg->freeold) free(arg->text); arg->text = Buf_Retrieve(&buf); - arg->freeold = TRUE; + arg->freeold = true; arg->var = Lst_Rev(arg->var); if (arg->var == NULL) Parse_FromString(arg->text, arg->lineno); } -/*- - *----------------------------------------------------------------------- - * For_Run -- - * Run the for loop, pushing expanded lines for reparse - *----------------------------------------------------------------------- - */ - void For_Run(arg) For *arg; diff --git a/usr.bin/make/for.h b/usr.bin/make/for.h new file mode 100644 index 00000000000..32ae7421142 --- /dev/null +++ b/usr.bin/make/for.h @@ -0,0 +1,55 @@ +#ifndef FOR_H +#define FOR_H +/* $OpenPackages$ */ +/* $OpenBSD: for.h,v 1.1 2001/05/23 12:34:43 espie Exp $ */ +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + + +/* + * for + * Functions to handle loops in a makefile. + */ + +struct For_; +typedef struct For_ For; +/* handle = For_Eval(line); + * Evaluate for loop in line, and returns an opaque handle. + * Loop lines are parsed as + * for <variable1> ... in <values> + * assuming the dot has been parsed by previous modules. + * Returns NULL if this is not a for loop after all. */ +extern For *For_Eval(const char *); + +/* finished = For_Accumulate(handle, line); + * Accumulate lines in a loop, until we find the matching .endfor. */ +extern bool For_Accumulate(For *, const char *); + +/* For_Run(handle); + * Runs the complete for loop, pushing back expanded lines to reparse + * using Parse_FromString. */ +extern void For_Run(For *); + +#endif diff --git a/usr.bin/make/generate.c b/usr.bin/make/generate.c index c5287495ba1..80e4d4a1668 100644 --- a/usr.bin/make/generate.c +++ b/usr.bin/make/generate.c @@ -1,12 +1,39 @@ +/* $OpenPackages$ */ +/* $OpenBSD: generate.c,v 1.4 2001/05/23 12:34:43 espie Exp $ */ +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +#include <stddef.h> #include <stdio.h> #include <stdlib.h> -#include <stddef.h> -#include "make.h" #include "stats.h" #include "ohash.h" #include "cond_int.h" +#include "var_int.h" #define M(x) x, #x char *table_var[] = { @@ -71,9 +98,7 @@ main(int argc, char *argv[]) char **t; int tn; -#ifdef HAS_STATS Init_Stats(); -#endif if (argc != 3) exit(1); diff --git a/usr.bin/make/gnode.h b/usr.bin/make/gnode.h new file mode 100644 index 00000000000..7ba6e3c46c5 --- /dev/null +++ b/usr.bin/make/gnode.h @@ -0,0 +1,189 @@ +#ifndef GNODE_H +#define GNODE_H +/* $OpenPackages$ */ +/* $OpenBSD: gnode.h,v 1.1 2001/05/23 12:34:43 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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 TIMESTAMP_TYPE +#include "timestamp_t.h" +#endif +#ifndef LIST_TYPE +#include "lst_t.h" +#endif +#ifndef SYMTABLE_H +#include "symtable.h" +#endif + +struct Suff_; +/*- + * The structure for an individual graph node. Each node has several + * pieces of data associated with it. + * 1) the name of the target it describes + * 2) the location of the target file in the file system. + * 3) the type of operator used to define its sources (qv. parse.c) + * 4) whether it is involved in this invocation of make + * 5) whether the target has been remade + * 6) whether any of its children has been remade + * 7) the number of its children that are, as yet, unmade + * 8) its modification time + * 9) the modification time of its youngest child (qv. make.c) + * 10) a list of nodes for which this is a source + * 11) a list of nodes on which this depends + * 12) a list of nodes that depend on this, as gleaned from the + * transformation rules. + * 13) a list of nodes of the same name created by the :: operator + * 14) a list of nodes that must be made (if they're made) before + * this node can be, but that do no enter into the datedness of + * this node. + * 15) a list of nodes that must be made (if they're made) after + * this node is, but that do not depend on this node, in the + * normal sense. + * 16) a Lst of ``local'' variables that are specific to this target + * and this target only (qv. var.c [$@ $< $?, etc.]) + * 17) a Lst of strings that are commands to be given to a shell + * to create this target. + */ +struct GNode_ { + char *path; /* The full pathname of the file */ + int type; /* Its type (see the OP flags, below) */ + int order; /* Its wait weight */ + + bool make; /* true if this target needs to be remade */ + enum { + UNMADE, BEINGMADE, MADE, UPTODATE, ERROR, ABORTED, + CYCLE, ENDCYCLE + } made; /* Set to reflect the state of processing + * on this node: + * UNMADE - Not examined yet + * BEINGMADE - Target is already being made. + * Indicates a cycle in the graph. (compat + * mode only) + * MADE - Was out-of-date and has been made + * UPTODATE - Was already up-to-date + * ERROR - An error occured while it was being + * made (used only in compat mode) + * ABORTED - The target was aborted due to + * an error making an inferior (compat). + * CYCLE - Marked as potentially being part of + * a graph cycle. If we come back to a + * node marked this way, it is printed + * and 'made' is changed to ENDCYCLE. + * ENDCYCLE - the cycle has been completely + * printed. Go back and unmark all its + * members. + */ + bool childMade; /* true if one of this target's children was + * made */ + int unmade; /* The number of unmade children */ + + TIMESTAMP mtime; /* Its modification time */ + TIMESTAMP cmtime; /* The modification time of its youngest + * child */ + + LIST iParents; /* Links to parents for which this is an + * implied source, if any */ + LIST cohorts; /* Other nodes for the :: operator */ + LIST parents; /* Nodes that depend on this one */ + LIST children; /* Nodes on which this one depends */ + LIST successors; /* Nodes that must be made after this one */ + LIST preds; /* Nodes that must be made before this one */ + + SymTable context; /* The local variables */ + unsigned long lineno; /* First line number of commands. */ + const char * fname; /* File name of commands. */ + LIST commands; /* Creation commands */ + LstNode current; /* Current command, for job */ + + struct Suff_ *suffix; /* Suffix for the node (determined by + * Suff_FindDeps and opaque to everyone + * but the Suff module) */ + char name[1]; /* The target's name */ +}; + +/* + * The OP_ constants are used when parsing a dependency line as a way of + * communicating to other parts of the program the way in which a target + * should be made. These constants are bitwise-OR'ed together and + * placed in the 'type' field of each node. Any node that has + * a 'type' field which satisfies the OP_NOP function was never never on + * the lefthand side of an operator, though it may have been on the + * righthand side... + */ +#define OP_DEPENDS 0x00000001 /* Execution of commands depends on + * kids (:) */ +#define OP_FORCE 0x00000002 /* Always execute commands (!) */ +#define OP_DOUBLEDEP 0x00000004 /* Execution of commands depends on kids + * per line (::) */ +#define OP_OPMASK (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP) + +#define OP_OPTIONAL 0x00000008 /* Don't care if the target doesn't + * exist and can't be created */ +#define OP_USE 0x00000010 /* Use associated commands for parents */ +#define OP_EXEC 0x00000020 /* Target is never out of date, but always + * execute commands anyway. Its time + * doesn't matter, so it has none...sort + * of */ +#define OP_IGNORE 0x00000040 /* Ignore errors when creating the node */ +#define OP_PRECIOUS 0x00000080 /* Don't remove the target when + * interrupted */ +#define OP_SILENT 0x00000100 /* Don't echo commands when executed */ +#define OP_MAKE 0x00000200 /* Target is a recurrsive make so its + * commands should always be executed when + * it is out of date, regardless of the + * state of the -n or -t flags */ +#define OP_JOIN 0x00000400 /* Target is out-of-date only if any of its + * children was out-of-date */ +#define OP_MADE 0x00000800 /* Assume the node is already made; even if + * it really is out of date */ +#define OP_INVISIBLE 0x00004000 /* The node is invisible to its parents. + * I.e. it doesn't show up in the parents's + * local variables. */ +#define OP_NOTMAIN 0x00008000 /* The node is exempt from normal 'main + * target' processing in parse.c */ +#define OP_PHONY 0x00010000 /* Not a file target; run always */ +#define OP_NOPATH 0x00020000 /* Don't search for file in the path */ +/* Attributes applied by PMake */ +#define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */ +#define OP_MEMBER 0x40000000 /* Target is a member of an archive */ +#define OP_LIB 0x20000000 /* Target is a library */ +#define OP_ARCHV 0x10000000 /* Target is an archive construct */ +#define OP_HAS_COMMANDS 0x08000000 /* Target has all the commands it should. + * Used when parsing to catch multiple + * commands for a target */ +#define OP_SAVE_CMDS 0x04000000 /* Saving commands on .END (Compat) */ +#define OP_DEPS_FOUND 0x02000000 /* Already processed by Suff_FindDeps */ + +/* + * OP_NOP will return true if the node with the given type was not the + * object of a dependency operator + */ +#define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000) + +#define OP_NOTARGET (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM) + + +#endif diff --git a/usr.bin/make/init.c b/usr.bin/make/init.c new file mode 100644 index 00000000000..71afa520df5 --- /dev/null +++ b/usr.bin/make/init.c @@ -0,0 +1,68 @@ +/* $OpenPackages$ */ +/* $OpenBSD: init.c,v 1.1 2001/05/23 12:34:43 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ +#include <stdio.h> +#include "defines.h" +#include "config.h" +#include "init.h" +#include "timestamp.h" +#include "stats.h" +#include "dir.h" +#include "parse.h" +#include "var.h" +#include "arch.h" +#include "targ.h" +#include "suff.h" +#include "job.h" + +void +Init() +{ + Init_Timestamp(); + Init_Stats(); + Dir_Init(); /* Initialize directory structures so -I flags + * can be processed correctly */ + Parse_Init(); /* Need to initialize the paths of #include + * directories */ + Var_Init(); /* As well as the lists of variables for + * parsing arguments */ + Arch_Init(); + Targ_Init(); + Suff_Init(); +} + +void +End() +{ + Suff_End(); + Targ_End(); + Arch_End(); + Var_End(); + Parse_End(); + Dir_End(); + Job_End(); +} diff --git a/usr.bin/make/init.h b/usr.bin/make/init.h new file mode 100644 index 00000000000..90863570b11 --- /dev/null +++ b/usr.bin/make/init.h @@ -0,0 +1,38 @@ +#ifndef INIT_H +#define INIT_H +/* $OpenPackages$ */ +/* $OpenBSD: init.h,v 1.1 2001/05/23 12:34:44 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* General init/cleanup functions. Handles all modules init/cleanup in + * one single place. This also simplifies main's dependencies on other + * modules. + */ +extern void Init(void); +extern void End(void); + +#endif diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index 281e18fd326..17a7d9a90e6 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: job.c,v 1.40 2001/05/03 13:41:06 espie Exp $ */ +/* $OpenBSD: job.c,v 1.41 2001/05/23 12:34:44 espie Exp $ */ /* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */ /* @@ -52,7 +52,7 @@ * frequently to keep the whole make going at * a decent clip, since job table entries aren't * removed until their process is caught this way. - * Its single argument is TRUE if the function + * Its single argument is true if the function * should block waiting for a child to terminate. * * Job_CatchOutput Print any output our children have produced. @@ -70,14 +70,14 @@ * * Job_End Cleanup any memory used. * - * Job_Full Return TRUE if the job table is filled. + * Job_Full Return true if the job table is filled. * - * Job_Empty Return TRUE if the job table is completely + * Job_Empty Return true if the job table is completely * empty. * * Job_ParseShell Given the line following a .SHELL target, parse * the line as a shell specification. Returns - * FAILURE if the spec was incorrect. + * false if the spec was incorrect. * * Job_Finish Perform any final processing which needs doing. * This includes the execution of any commands @@ -99,22 +99,33 @@ */ #include <sys/types.h> -#include <sys/stat.h> -#include <sys/file.h> -#include <sys/time.h> #include <sys/wait.h> -#include <fcntl.h> +#include <ctype.h> #include <errno.h> -#include <utime.h> +#include <fcntl.h> +#include <signal.h> #include <stddef.h> #include <stdio.h> #include <string.h> -#include <signal.h> -#include "make.h" -#include "ohash.h" +#include <unistd.h> +#include "config.h" +#include "defines.h" #include "dir.h" #include "job.h" #include "pathnames.h" +#include "arch.h" +#include "var.h" +#include "targ.h" +#include "error.h" +#include "str.h" +#include "lst.h" +#include "extern.h" +#include "gnode.h" +#include "memory.h" +#include "make.h" +#include "timestamp.h" +#include "main.h" + #ifdef REMOTE #include "rmt.h" # define STATIC @@ -122,16 +133,6 @@ # define STATIC static #endif -#ifndef lint -#if 0 -static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: job.c,v 1.40 2001/05/03 13:41:06 espie Exp $"; -#endif -#endif /* not lint */ - - /* * error handling variables */ @@ -185,8 +186,8 @@ static Shell shells[] = { */ { "csh", - TRUE, "unset verbose", "set verbose", "unset verbose", 10, - FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", + true, "unset verbose", "set verbose", "unset verbose", 10, + false, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", "v", "e", }, /* @@ -195,10 +196,10 @@ static Shell shells[] = { */ { "sh", - TRUE, "set -", "set -v", "set -", 5, - TRUE, "set -e", "set +e", + true, "set -", "set -v", "set -", 5, + true, "set -e", "set +e", #ifdef OLDBOURNESHELL - FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", + false, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", #endif "v", "e", }, @@ -207,8 +208,8 @@ static Shell shells[] = { */ { (char *)0, - FALSE, (char *)0, (char *)0, (char *)0, 0, - FALSE, (char *)0, (char *)0, + false, (char *)0, (char *)0, (char *)0, 0, + false, (char *)0, (char *)0, (char *)0, (char *)0, } }; @@ -225,11 +226,11 @@ static char *shellPath = NULL, /* full pathname of static int maxJobs; /* The most children we can run at once */ static int maxLocal; /* The most local ones we can have */ -STATIC int nJobs; /* The number of children currently running */ +STATIC int nJobs = 0; /* The number of children currently running */ STATIC int nLocal; /* The number of local children */ STATIC LIST jobs; /* The structures that describe them */ -STATIC Boolean jobFull; /* Flag to tell when the job table is full. It - * is set TRUE when (1) the total number of +STATIC bool jobFull; /* Flag to tell when the job table is full. It + * is set true when (1) the total number of * running jobs equals the maximum allowed or * (2) a job can only be run locally, but * nLocal equals maxLocal */ @@ -315,7 +316,7 @@ static void JobMakeArgv(Job *, char **); static void JobRestart(Job *); static int JobStart(GNode *, int, Job *); static char *JobOutput(Job *, char *, char *, int); -static void JobDoOutput(Job *, Boolean); +static void JobDoOutput(Job *, bool); static Shell *JobMatchShell(char *); static void JobInterrupt(int, int); static void JobRestartJobs(void); @@ -387,9 +388,9 @@ JobPassSig(signo) * three termination signals are more of a "get out *now*" command. */ if (signo == SIGINT) { - JobInterrupt(TRUE, signo); + JobInterrupt(true, signo); } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { - JobInterrupt(FALSE, signo); + JobInterrupt(false, signo); } /* @@ -504,12 +505,12 @@ JobPrintCommand(cmdp, jobp) void *cmdp; /* command string to print */ void *jobp; /* job for which to print it */ { - Boolean noSpecials; /* true if we shouldn't worry about + bool noSpecials; /* true if we shouldn't worry about * inserting special commands into * the input stream. */ - Boolean shutUp = FALSE; /* true if we put a no echo command + bool shutUp = false; /* true if we put a no echo command * into the command file */ - Boolean errOff = FALSE; /* true if we turned error checking + bool errOff = false; /* true if we turned error checking * off before printing the command * and need to turn it back on */ char *cmdTemplate; /* Template to use when printing the @@ -542,7 +543,7 @@ JobPrintCommand(cmdp, jobp) /* For debugging, we replace each command with the result of expanding * the variables in the command. */ cmdNode = Lst_Member(&job->node->commands, cmd); - cmdStart = cmd = Var_Subst(cmd, &job->node->context, FALSE); + cmdStart = cmd = Var_Subst(cmd, &job->node->context, false); Lst_Replace(cmdNode, cmdStart); cmdTemplate = "%s\n"; @@ -552,9 +553,9 @@ JobPrintCommand(cmdp, jobp) */ for (;; cmd++) { if (*cmd == '@') - shutUp = DEBUG(LOUD) ? FALSE : TRUE; + shutUp = DEBUG(LOUD) ? false : true; else if (*cmd == '-') - errOff = TRUE; + errOff = true; else if (*cmd != '+') break; } @@ -567,7 +568,7 @@ JobPrintCommand(cmdp, jobp) commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); } else { - shutUp = FALSE; + shutUp = false; } } @@ -606,7 +607,7 @@ JobPrintCommand(cmdp, jobp) commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); DBPRINTF(commandShell->errCheck, cmd); - shutUp = TRUE; + shutUp = true; } cmdTemplate = commandShell->ignErr; /* @@ -614,12 +615,12 @@ JobPrintCommand(cmdp, jobp) * of by the ignErr template, so pretend error checking * is still on. */ - errOff = FALSE; + errOff = false; } else { - errOff = FALSE; + errOff = false; } } else { - errOff = FALSE; + errOff = false; } } @@ -633,7 +634,7 @@ JobPrintCommand(cmdp, jobp) */ if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ DBPRINTF("%s\n", commandShell->echoOff); - shutUp = TRUE; + shutUp = true; } DBPRINTF("%s\n", commandShell->errCheck); } @@ -661,7 +662,7 @@ JobSaveCommand(cmd, gn) GNode *g = (GNode *)gn; char *result; - result = Var_Subst((char *)cmd, &g->context, FALSE); + result = Var_Subst((char *)cmd, &g->context, false); Lst_AtEnd(&postCommands->commands, result); } @@ -688,11 +689,11 @@ JobClose(job) if (job->outPipe != job->inPipe) { (void)close(job->outPipe); } - JobDoOutput(job, TRUE); + JobDoOutput(job, true); (void)close(job->inPipe); } else { (void)close(job->outFd); - JobDoOutput(job, TRUE); + JobDoOutput(job, true); } } @@ -722,7 +723,7 @@ JobFinish(job, status) Job *job; /* job to finish */ int *status; /* sub-why job went away */ { - Boolean done; + bool done; if ((WIFEXITED(*status) && WEXITSTATUS(*status) != 0 && !(job->flags & JOB_IGNERR)) || @@ -743,7 +744,7 @@ JobFinish(job, status) if (job->cmdFILE != NULL && job->cmdFILE != stdout) { (void)fclose(job->cmdFILE); } - done = TRUE; + done = true; #ifdef REMOTE if (job->flags & JOB_REMOTE) Rmt_Done(job->rmtID, job->node); @@ -753,7 +754,7 @@ JobFinish(job, status) * Deal with ignored errors in -B mode. We need to print a message * telling of the ignored error as well as setting status.w_status * to 0 so the next command gets run. To do this, we set done to be - * TRUE if in -B mode and the job exited non-zero. + * true if in -B mode and the job exited non-zero. */ done = WEXITSTATUS(*status) != 0; /* @@ -772,7 +773,7 @@ JobFinish(job, status) /* * No need to close things down or anything. */ - done = FALSE; + done = false; } if (done || @@ -881,7 +882,7 @@ JobFinish(job, status) nLocal += 1; } if (nJobs == maxJobs) { - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Job queue is full.\n"); (void)fflush(stdout); @@ -908,10 +909,10 @@ JobFinish(job, status) if (compatMake && WIFEXITED(*status) && job->node->current != NULL) { switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { case JOB_RUNNING: - done = FALSE; + done = false; break; case JOB_ERROR: - done = TRUE; + done = true; W_SETEXITSTATUS(status, 1); break; case JOB_FINISHED: @@ -922,11 +923,11 @@ JobFinish(job, status) * JobStart needs to do the update so we can proceed up the * graph when given the -n flag.. */ - done = FALSE; + done = false; break; } } else - done = TRUE; + done = true; if (done && aborting != ABORT_ERROR && @@ -982,7 +983,7 @@ JobFinish(job, status) void Job_Touch(gn, silent) GNode *gn; /* the node of the file to touch */ - Boolean silent; /* TRUE if should not print messages */ + bool silent; /* true if should not print messages */ { int streamID; /* ID of stream opened to do the touch */ @@ -1041,14 +1042,14 @@ Job_Touch(gn, silent) * Make sure the given node has all the commands it needs. * * Results: - * TRUE if the commands list is/was ok. + * true if the commands list is/was ok. * * Side Effects: * The node will have commands from the .DEFAULT rule added to it * if it needs them. *----------------------------------------------------------------------- */ -Boolean +bool Job_CheckCommands(gn, abortProc) GNode *gn; /* The target whose commands need * verifying */ @@ -1089,15 +1090,15 @@ Job_CheckCommands(gn, abortProc) } else if (keepgoing) { (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); (void)fflush(stdout); - return FALSE; + return false; } else { (*abortProc)("%s %s. Stop in %s.", msg, gn->name, Var_Value(".CURDIR")); - return FALSE; + return false; } } } - return TRUE; + return true; } #ifdef RMT_WILL_WATCH /*- @@ -1115,7 +1116,7 @@ JobLocalInput(stream, job) int stream; /* Stream that's ready (ignored) */ Job *job; /* Job to which the stream belongs */ { - JobDoOutput(job, FALSE); + JobDoOutput(job, false); } #endif /* RMT_WILL_WATCH */ @@ -1223,7 +1224,7 @@ JobExec(job, argv) #ifdef REMOTE if (job->flags & JOB_REMOTE) { - Rmt_Exec(shellPath, argv, FALSE); + Rmt_Exec(shellPath, argv, false); } else #endif /* REMOTE */ (void)execv(shellPath, argv); @@ -1294,7 +1295,7 @@ jobExecFinish: nJobs += 1; Lst_AtEnd(&jobs, job); if (nJobs == maxJobs) { - jobFull = TRUE; + jobFull = true; } } @@ -1418,7 +1419,7 @@ JobRestart(job) (void)fflush(stdout); } Lst_AtFront(&stoppedJobs, job); - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Job queue is full.\n"); (void)fflush(stdout); @@ -1441,7 +1442,7 @@ JobRestart(job) Lst_AtEnd(&jobs, job); nJobs += 1; if (nJobs == maxJobs) { - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Job queue is full.\n"); (void)fflush(stdout); @@ -1484,7 +1485,7 @@ JobRestart(job) (void)fflush(stdout); } Lst_AtFront(&stoppedJobs, job); - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Job queue is full.\n"); (void)fflush(stdout); @@ -1542,7 +1543,7 @@ JobRestart(job) * job must be run locally and maxLocal is 0), it's also ok to * resume it. */ - Boolean error; + bool error; int status; #ifdef RMT_WANTS_SIGNALS @@ -1583,7 +1584,7 @@ JobRestart(job) (void)fflush(stdout); } Lst_AtFront(&stoppedJobs, job); - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Job queue is full.\n"); (void)fflush(stdout); @@ -1618,9 +1619,9 @@ JobStart(gn, flags, previous) { Job *job; /* new job descriptor */ char *argv[4]; /* Argument vector to shell */ - Boolean cmdsOK; /* true if the nodes commands were all right */ - Boolean local; /* Set true if the job was run locally */ - Boolean noExec; /* Set true if we decide not to run the job */ + bool cmdsOK; /* true if the nodes commands were all right */ + bool local; /* Set true if the job was run locally */ + bool noExec; /* Set true if we decide not to run the job */ if (previous != NULL) { previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE); @@ -1657,7 +1658,7 @@ JobStart(gn, flags, previous) if (!compatMake && job->flags & JOB_FIRST) { cmdsOK = Job_CheckCommands(gn, Error); } else { - cmdsOK = TRUE; + cmdsOK = true; } /* @@ -1684,7 +1685,7 @@ JobStart(gn, flags, previous) * Send the commands to the command file, flush all its buffers then * rewind and remove the thing. */ - noExec = FALSE; + noExec = false; /* * used to be backwards; replace when start doing multiple commands @@ -1706,7 +1707,7 @@ JobStart(gn, flags, previous) if (gn->current == NULL || !JobPrintCommand(Lst_Datum(gn->current), job)) { - noExec = TRUE; + noExec = true; gn->current = NULL; } if (noExec && !(job->flags & JOB_FIRST)) { @@ -1735,7 +1736,7 @@ JobStart(gn, flags, previous) * there's not much point in executing the shell, is there? */ if (numCommands == 0) { - noExec = TRUE; + noExec = true; } } } else if (noExecute) { @@ -1759,7 +1760,7 @@ JobStart(gn, flags, previous) /* * Don't execute the shell, thank you. */ - noExec = TRUE; + noExec = true; } else { /* * Just touch the target and note that no shell should be executed. @@ -1769,7 +1770,7 @@ JobStart(gn, flags, previous) */ job->cmdFILE = stdout; Job_Touch(gn, job->flags&JOB_SILENT); - noExec = TRUE; + noExec = true; } /* @@ -1849,7 +1850,7 @@ JobStart(gn, flags, previous) } } else #endif - local = TRUE; + local = true; if (local && nLocal >= maxLocal && !(job->flags & JOB_SPECIAL) && @@ -1869,7 +1870,7 @@ JobStart(gn, flags, previous) * all possible. In addition, any target marked with .NOEXPORT will * be run locally if maxLocal is 0. */ - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Can only run job locally.\n"); @@ -1883,7 +1884,7 @@ JobStart(gn, flags, previous) * If we're running this job locally as a special case (see above), * at least say the table is full. */ - jobFull = TRUE; + jobFull = true; if (DEBUG(JOB)) { (void)fprintf(stdout, "Local job queue is full.\n"); (void)fflush(stdout); @@ -1967,11 +1968,11 @@ JobOutput(job, cp, endp, msg) STATIC void JobDoOutput(job, finish) Job *job; /* the job whose output needs printing */ - Boolean finish; /* TRUE if this is the last time we'll be + bool finish; /* true if this is the last time we'll be * called for this job */ { - Boolean gotNL = FALSE; /* true if got a newline */ - Boolean fbuf; /* true if our buffer filled up */ + bool gotNL = false; /* true if got a newline */ + bool fbuf; /* true if our buffer filled up */ int nr; /* number of bytes read */ int i; /* auxiliary index into outBuf */ int max; /* limit for i (end of current data) */ @@ -1986,8 +1987,8 @@ JobDoOutput(job, finish) * Read as many bytes as will fit in the buffer. */ end_loop: - gotNL = FALSE; - fbuf = FALSE; + gotNL = false; + fbuf = false; nRead = read(job->inPipe, &job->outBuf[job->curPos], JOB_BUFSIZE - job->curPos); @@ -2009,20 +2010,20 @@ end_loop: if (nr == 0 && job->curPos != 0) { job->outBuf[job->curPos] = '\n'; nr = 1; - finish = FALSE; + finish = false; } else if (nr == 0) { - finish = FALSE; + finish = false; } /* * Look for the last newline in the bytes we just got. If there is * one, break out of the loop with 'i' as its index and gotNL set - * TRUE. + * true. */ max = job->curPos + nr; for (i = job->curPos + nr - 1; i >= job->curPos; i--) { if (job->outBuf[i] == '\n') { - gotNL = TRUE; + gotNL = true; break; } else if (job->outBuf[i] == '\0') { /* @@ -2039,7 +2040,7 @@ end_loop: * If we've run out of buffer space, we have no choice * but to print the stuff. sigh. */ - fbuf = TRUE; + fbuf = true; i = job->curPos; } } @@ -2058,7 +2059,7 @@ end_loop: if (i >= job->curPos) { char *cp; - cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE); + cp = JobOutput(job, job->outBuf, &job->outBuf[i], false); /* * There's still more in that thar buffer. This time, though, @@ -2093,7 +2094,7 @@ end_loop: * end-of-file on the pipe. This is guaranteed to happen * eventually since the other end of the pipe is now closed * (we closed it explicitly and the child has exited). When - * we do get an EOF, finish will be set FALSE and we'll fall + * we do get an EOF, finish will be set false and we'll fall * through and out. */ goto end_loop; @@ -2121,7 +2122,7 @@ end_loop: if (endp[-1] == '\n') { *--endp = '\0'; } - cp = JobOutput(job, inLine, endp, FALSE); + cp = JobOutput(job, inLine, endp, false); /* * There's still more in that thar buffer. This time, though, @@ -2158,7 +2159,7 @@ end_loop: */ void Job_CatchChildren(block) - Boolean block; /* TRUE if should block on the wait. */ + bool block; /* true if should block on the wait. */ { int pid; /* pid of dead child */ Job *job; /* job descriptor for dead child */ @@ -2204,7 +2205,7 @@ Job_CatchChildren(block) (void)fprintf(stdout, "Job queue is no longer full.\n"); (void)fflush(stdout); } - jobFull = FALSE; + jobFull = false; #ifdef REMOTE if (!(job->flags & JOB_REMOTE)) { if (DEBUG(JOB)) { @@ -2289,7 +2290,7 @@ Job_CatchOutput() for (ln = Lst_First(&jobs); nfds && ln != NULL; ln = Lst_Adv(ln)) { job = (Job *)Lst_Datum(ln); if (FD_ISSET(job->inPipe, readfdsp)) { - JobDoOutput(job, FALSE); + JobDoOutput(job, false); nfds -= 1; } } @@ -2347,7 +2348,7 @@ Job_Init(maxproc, maxlocal) maxLocal = maxlocal; nJobs = 0; nLocal = 0; - jobFull = FALSE; + jobFull = false; aborting = 0; errors = 0; @@ -2377,7 +2378,7 @@ Job_Init(maxproc, maxlocal) * All default shells are located in _PATH_DEFSHELLDIR. */ shellName = commandShell->name; - shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, '/'); + shellPath = Str_concat(_PATH_DEFSHELLDIR, shellName, '/'); } if (commandShell->exit == NULL) { @@ -2424,7 +2425,7 @@ Job_Init(maxproc, maxlocal) } #endif - begin = Targ_FindNode(".BEGIN", NULL, TARG_NOCREATE); + begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); if (begin != NULL) { JobStart(begin, JOB_SPECIAL, (Job *)0); @@ -2435,7 +2436,7 @@ Job_Init(maxproc, maxlocal) #endif /* RMT_WILL_WATCH */ } } - postCommands = Targ_FindNode(".END", NULL, TARG_CREATE); + postCommands = Targ_FindNode(".END", TARG_CREATE); } /*- @@ -2447,10 +2448,10 @@ Job_Init(maxproc, maxlocal) * from starting up. * * Results: - * TRUE if the job table is full, FALSE otherwise + * true if the job table is full, false otherwise *----------------------------------------------------------------------- */ -Boolean +bool Job_Full() { return aborting || jobFull; @@ -2465,10 +2466,10 @@ Job_Full() * we want to restart as many jobs as we can. * * Results: - * TRUE if it is. FALSE if it ain't. + * true if it is. false if it ain't. * ----------------------------------------------------------------------- */ -Boolean +bool Job_Empty() { if (nJobs == 0) { @@ -2477,14 +2478,14 @@ Job_Empty() * The job table is obviously not full if it has no jobs in * it...Try and restart the stopped jobs. */ - jobFull = FALSE; + jobFull = false; JobRestartJobs(); - return FALSE; + return false; } else { - return TRUE; + return true; } } else { - return FALSE; + return false; } } @@ -2533,7 +2534,7 @@ JobMatchShell(name) * and shellName appropriately. * * Results: - * FAILURE if the specification was incorrect. + * false if the specification was incorrect. * * Side Effects: * commandShell points to a Shell structure (either predefined or @@ -2559,16 +2560,16 @@ JobMatchShell(name) * errFlag Flag to turn error checking on at the start * hasErrCtl True if shell has error checking control * check Command to turn on error checking if hasErrCtl - * is TRUE or template of command to echo a command + * is true or template of command to echo a command * for which error checking is off if hasErrCtl is - * FALSE. + * false. * ignore Command to turn off error checking if hasErrCtl - * is TRUE or template of command to execute a + * is true or template of command to execute a * command so as to ignore any errors it returns if - * hasErrCtl is FALSE. + * hasErrCtl is false. *----------------------------------------------------------------------- */ -ReturnStatus +bool Job_ParseShell(line) char *line; /* The shell spec */ { @@ -2578,7 +2579,7 @@ Job_ParseShell(line) int argc; char *path; Shell newShell; - Boolean fullSpec = FALSE; + bool fullSpec = false; while (isspace(*line)) { line++; @@ -2624,9 +2625,9 @@ Job_ParseShell(line) Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", *argv); free(words); - return FAILURE; + return false; } - fullSpec = TRUE; + fullSpec = true; } } @@ -2639,7 +2640,7 @@ Job_ParseShell(line) */ if (newShell.name == NULL) { Parse_Error(PARSE_FATAL, "Neither path nor name specified"); - return FAILURE; + return false; } else { commandShell = JobMatchShell(newShell.name); shellName = newShell.name; @@ -2647,7 +2648,7 @@ Job_ParseShell(line) } else { /* * The user provided a path. If s/he gave nothing else (fullSpec is - * FALSE), try and find a matching shell in the ones we know of. + * false), try and find a matching shell in the ones we know of. * Else we just take the specification at its word and copy it * to a new location. In either case, we need to record the * path the user gave for the shell. @@ -2673,7 +2674,7 @@ Job_ParseShell(line) } if (commandShell->echoOn && commandShell->echoOff) { - commandShell->hasEchoCtl = TRUE; + commandShell->hasEchoCtl = true; } if (!commandShell->hasErrCtl) { @@ -2690,7 +2691,7 @@ Job_ParseShell(line) * shell specification... */ free(words); - return SUCCESS; + return true; } /*- @@ -2818,9 +2819,9 @@ JobInterrupt(runINTERRUPT, signo) #endif if (runINTERRUPT && !touchFlag) { - interrupt = Targ_FindNode(".INTERRUPT", NULL, TARG_NOCREATE); + interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); if (interrupt != NULL) { - ignoreErrors = FALSE; + ignoreErrors = false; JobStart(interrupt, JOB_IGNDOTS, (Job *)0); while (nJobs) { @@ -2879,13 +2880,13 @@ Job_Finish() * Memory is freed *----------------------------------------------------------------------- */ +#ifdef CLEANUP void Job_End() { -#ifdef CLEANUP efree(shellArgv); -#endif } +#endif /*- *----------------------------------------------------------------------- diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h index 6a03a50bf84..8885980a448 100644 --- a/usr.bin/make/job.h +++ b/usr.bin/make/job.h @@ -1,5 +1,8 @@ +#ifndef _JOB_H_ +#define _JOB_H_ + /* $OpenPackages$ */ -/* $OpenBSD: job.h,v 1.9 2001/05/03 13:41:06 espie Exp $ */ +/* $OpenBSD: job.h,v 1.10 2001/05/23 12:34:45 espie Exp $ */ /* $NetBSD: job.h,v 1.5 1996/11/06 17:59:10 christos Exp $ */ /* @@ -47,9 +50,6 @@ * Definitions pertaining to the running of jobs in parallel mode. * Exported from job.c for the use of remote-execution modules. */ -#ifndef _JOB_H_ -#define _JOB_H_ - #define TMPPAT "/tmp/makeXXXXXXXXXX" /* @@ -175,7 +175,7 @@ typedef struct Job_ { * a case, errCheck becomes a printf template for echoing the command, * should echoing be on and ignErr becomes another printf template for * executing the command while ignoring the return status. If either of these - * strings is empty when hasErrCtl is FALSE, the command will be executed + * strings is empty when hasErrCtl is false, the command will be executed * anyway as is and if it causes an error, so be it. */ typedef struct Shell_ { @@ -185,14 +185,14 @@ typedef struct Shell_ { * source of a .SHELL target. For user-defined * shells, this is the full path of the shell. */ - Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */ + bool hasEchoCtl; /* True if both echoOff and echoOn defined */ char *echoOff; /* command to turn off echo */ char *echoOn; /* command to turn it back on again */ char *noPrint; /* command to skip when printing output from * shell. This is usually the command which * was executed to turn off echoing */ int noPLen; /* length of noPrint command */ - Boolean hasErrCtl; /* set if can control error checking for + bool hasErrCtl; /* set if can control error checking for * individual commands */ char *errCheck; /* string to turn error checking on */ char *ignErr; /* string to turn off error checking */ @@ -216,24 +216,28 @@ extern GNode *lastNode; /* Last node for which a banner was printed. extern int nJobs; /* Number of jobs running (local and remote) */ extern int nLocal; /* Number of jobs running locally */ extern LIST jobs; /* List of active job descriptors */ -extern Boolean jobFull; /* Non-zero if no more jobs should/will start*/ +extern bool jobFull; /* Non-zero if no more jobs should/will start*/ extern LIST stoppedJobs; /* List of jobs that are stopped or didn't * quite get started */ #endif -extern void Job_Touch(GNode *, Boolean); -extern Boolean Job_CheckCommands(GNode *, +extern void Job_Touch(GNode *, bool); +extern bool Job_CheckCommands(GNode *, void (*abortProc )(char *, ...)); -extern void Job_CatchChildren(Boolean); +extern void Job_CatchChildren(bool); extern void Job_CatchOutput(void); extern void Job_Make(GNode *); extern void Job_Init(int, int); -extern Boolean Job_Full(void); -extern Boolean Job_Empty(void); -extern ReturnStatus Job_ParseShell(char *); +extern bool Job_Full(void); +extern bool Job_Empty(void); +extern bool Job_ParseShell(char *); extern int Job_Finish(void); +#ifdef CLEANUP extern void Job_End(void); +#else +#define Job_End() +#endif extern void Job_Wait(void); extern void Job_AbortAll(void); extern void JobFlagForMigration(int); diff --git a/usr.bin/make/lowparse.c b/usr.bin/make/lowparse.c index 40df479384a..a837fb179ad 100644 --- a/usr.bin/make/lowparse.c +++ b/usr.bin/make/lowparse.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lowparse.c,v 1.8 2001/05/14 12:55:48 espie Exp $ */ +/* $OpenBSD: lowparse.c,v 1.9 2001/05/23 12:34:45 espie Exp $ */ /* low-level parsing functions. */ @@ -30,114 +30,95 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <stdarg.h> -#include <stdio.h> #include <assert.h> -#include "make.h" +#include <stddef.h> +#include <stdio.h> +#include <unistd.h> +#include "config.h" +#include "defines.h" #include "buf.h" #include "lowparse.h" +#include "error.h" +#include "lst.h" +#include "memory.h" -#ifdef CLEANUP +/* XXX check whether we can free filenames at the end, for a proper + * definition of `end'. */ + +#if 0 static LIST fileNames; /* file names to free at end */ #endif -/* Definitions for handling #include specifications */ -typedef struct IFile_ { - char *fname; /* name of file */ - unsigned long lineno; /* line number */ - FILE *F; /* open stream */ - char *str; /* read from char area */ - char *ptr; /* where we are */ - char *end; /* don't overdo it */ +/* Input stream structure, file or string. */ +typedef struct { + const char *fname; /* Name of file */ + unsigned long lineno; /* Line number */ + FILE *F; /* Open stream, or NULL if pure string. */ + char *str; /* Input string, if F == NULL. */ + + /* Line buffer. */ + char *ptr; /* Where we are. */ + char *end; /* Don't overdo it. */ } IFile; -static IFile *current; +static IFile *current; /* IFile being parsed. */ -static LIST includes; /* stack of IFiles generated by - * #includes */ +static LIST input_stack; /* Stack of IFiles waiting to be parsed + * (includes and loop reparses) */ -static IFile *new_ifile(char *, FILE *); -static IFile *new_istring(char *, char *, unsigned long); +/* IFile ctors. + * + * obj = new_ifile(filename, filehandle); + * Create input object from filename, filehandle. */ +static IFile *new_ifile(const char *, FILE *); +/* obj = new_istring(str, filename, lineno); + * Create input object from str, filename, lineno. */ +static IFile *new_istring(char *, const char *, unsigned long); +/* free_ifile(obj); + * Discard consumed input object, closing streams, freeing memory. */ static void free_ifile(IFile *); -static void ParseVErrorInternal(char *, unsigned long, int, char *, va_list); + + +/* Handling basic character reading. + * c = ParseReadc(); + * New character c from current input stream, or EOF at end of stream. */ +#define ParseReadc() current->ptr < current->end ? *current->ptr++ : newline() +/* len = newline(); + * Guts for ParseReadc. Grabs a new line off fgetln when we have + * consumed the current line and returns its length. Or EOF at end of + * stream. */ static int newline(void); +/* c = skiptoendofline(); + * Skips to the end of the current line, returns either '\n' or EOF. */ static int skiptoendofline(void); -static void ParseFoldLF(Buffer, int); -static int ParseSkipEmptyLines(Buffer); -static int fatals = 0; -/*- - * ParseVErrorInternal -- - * Error message abort function for parsing. Prints out the context - * of the error (line number and file) as well as the message with - * two optional arguments. - * - * Side Effects: - * "fatals" is incremented if the level is PARSE_FATAL. - */ -/* VARARGS */ -static void -#ifdef __STDC__ -ParseVErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt, - va_list ap) -#else -ParseVErrorInternal(va_alist) - va_dcl -#endif -{ - (void)fprintf(stderr, "\"%s\", line %lu: ", cfname, clineno); - if (type == PARSE_WARNING) - (void)fprintf(stderr, "warning: "); - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - (void)fprintf(stderr, "\n"); - if (type == PARSE_FATAL) - fatals ++; -} -/*- - * Parse_Error -- - * External interface to ParseVErrorInternal; uses the default filename - * Line number. - */ -/* VARARGS */ -void -#ifdef __STDC__ -Parse_Error(int type, char *fmt, ...) -#else -Parse_Error(va_alist) - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ - char *fmt; - - va_start(ap); - type = va_arg(ap, int); - fmt = va_arg(ap, char *); -#endif +/* Helper functions to handle basic parsing. */ +/* ParseFoldLF(buffer, firstchar); + * Grabs logical line into buffer, the first character has already been + * read into firstchar. */ +static void ParseFoldLF(Buffer, int); - ParseVErrorInternal(current->fname, current->lineno, type, fmt, ap); -} +/* firstchar = ParseSkipEmptyLines(buffer); + * Scans lines, skipping empty lines. May put some characters into + * buffer, returns the first character useful to continue parsing + * (e.g., not a backslash or a space. */ +static int ParseSkipEmptyLines(Buffer); static IFile * new_ifile(name, stream) - char *name; + const char *name; FILE *stream; { IFile *ifile; -#ifdef CLEANUP +#if 0 Lst_AtEnd(&fileNames, name); #endif ifile = emalloc(sizeof(*ifile)); ifile->fname = name; ifile->str = NULL; - /* Naturally enough, we start reading at line 0 */ + /* Naturally enough, we start reading at line 0. */ ifile->lineno = 0; ifile->F = stream; ifile->ptr = ifile->end = NULL; @@ -159,7 +140,7 @@ free_ifile(ifile) static IFile * new_istring(str, name, lineno) char *str; - char *name; + const char *name; unsigned long lineno; { IFile *ifile; @@ -168,7 +149,8 @@ new_istring(str, name, lineno) /* No malloc, name is always taken from an already existing ifile */ ifile->fname = name; ifile->F = NULL; - /* Strings are used from for loops... */ + /* Strings are used in for loops, so we need to reset the line counter + * to an appropriate value. */ ifile->lineno = lineno; ifile->ptr = ifile->str = str; ifile->end = str + strlen(str); @@ -176,16 +158,6 @@ new_istring(str, name, lineno) } -/*- - *--------------------------------------------------------------------- - * Parse_FromString -- - * Start Parsing from the given string - * - * Side Effects: - * A structure is added to the includes Lst and readProc, lineno, - * fname and curFILE are altered for the new file - *--------------------------------------------------------------------- - */ void Parse_FromString(str, lineno) char *str; @@ -195,52 +167,30 @@ Parse_FromString(str, lineno) (void)fprintf(stderr, "%s\n----\n", str); if (current != NULL) - Lst_AtFront(&includes, current); + Lst_Push(&input_stack, current); current = new_istring(str, current->fname, lineno); } void Parse_FromFile(name, stream) - char *name; + const char *name; FILE *stream; { if (current != NULL) - Lst_AtFront(&includes, current); + Lst_Push(&input_stack, current); current = new_ifile(name, stream); } -/*- - *--------------------------------------------------------------------- - * Parse_NextFile -- - * Called when EOF is reached in the current file. If we were reading - * an include file, the includes stack is popped and things set up - * to go back to reading the previous file at the previous location. - * - * Results: - * CONTINUE if there's more to do. DONE if not. - * - * Side Effects: - * The old curFILE, is closed. The includes list is shortened. - * lineno, curFILE, and fname are changed if CONTINUE is returned. - *--------------------------------------------------------------------- - */ -Boolean +bool Parse_NextFile() { - IFile *next; - - next = (IFile *)Lst_DeQueue(&includes); - if (next != NULL) { - if (current != NULL) - free_ifile(current); - current = next; - return TRUE; - } else - return FALSE; + if (current != NULL) + free_ifile(current); + current = (IFile *)Lst_Pop(&input_stack); + return current != NULL; } -/* guts for ParseReadc. Grab a new line off fgetln when we hit "\n" */ static int newline() { @@ -258,10 +208,6 @@ newline() return EOF; } -#define ParseReadc() current->ptr < current->end ? *current->ptr++ : newline() - -/* Take advantage of fgetln: we don't have to scan a whole line to skip it. - */ static int skiptoendofline() { @@ -282,11 +228,8 @@ skiptoendofline() } -/* ParseSkipGetLine(): - * Return the first logical line that starts with '.' - */ char * -ParseSkipGetLine(linebuf) +Parse_ReadNextConditionalLine(linebuf) Buffer linebuf; { int c; @@ -308,11 +251,9 @@ ParseSkipGetLine(linebuf) } /* This is the line we need to copy */ - return ParseGetLine(linebuf, "conditional"); + return Parse_ReadUnparsedLine(linebuf, "conditional"); } -/* Grab logical line into linebuf. - * The first character is already in c. */ static void ParseFoldLF(linebuf, c) Buffer linebuf; @@ -347,11 +288,8 @@ ParseFoldLF(linebuf, c) } } -/* ParseGetLine: - * Simply get line, no parsing beyond \ - */ char * -ParseGetLine(linebuf, type) +Parse_ReadUnparsedLine(linebuf, type) Buffer linebuf; const char *type; { @@ -386,10 +324,8 @@ ParseGetLine(linebuf, type) return Buf_Retrieve(linebuf); } -/* Skip all empty lines, and return the first `useful' character. - * (This does skip blocks of comments at high speed, which justifies - * the complexity of the function.) - */ +/* This is a fairly complex function, but without it, we could not skip + * blocks of comments without reading them. */ static int ParseSkipEmptyLines(linebuf) Buffer linebuf; @@ -462,24 +398,18 @@ ParseSkipEmptyLines(linebuf) } } -/*- - *--------------------------------------------------------------------- - * ParseReadLine -- - * Read an entire line from the input file. +/* Parse_ReadNormalLine removes beginning and trailing blanks (but keeps + * the first tab), handles escaped newlinews, and skip over uninteresting + * lines. * - * Results: - * A line without a new line, or NULL at EOF. + * The line number is advanced, which implies that continuation + * lines are numbered with the last line no (we could do better, at a + * price). * - * Notes: - * Removes beginning and trailing blanks (but keeps first tab). - * Updates line numbers, handles escaped newlines, and skip over - * uninteresting lines. - * All but trivial comments can't be handled at this point, because we - * don't know yet which lines are shell commands or not. - *--------------------------------------------------------------------- - */ + * Trivial comments are also removed, but we can't do more, as + * we don't know which lines are shell commands or not. */ char * -ParseReadLine(linebuf) +Parse_ReadNormalLine(linebuf) Buffer linebuf; { int c; /* the current character */ @@ -511,27 +441,31 @@ Parse_Getfilename() void LowParse_Init() { - Lst_Init(&includes); + Lst_Init(&input_stack); current = NULL; } void LowParse_End() { - Lst_Destroy(&includes, NOFREE); /* Should be empty now */ + Lst_Destroy(&input_stack, NOFREE); /* Should be empty now */ +#ifdef 0 + Lst_Destroy(&fileNames, (SimpleProc)free); +#endif } #endif void -Finish_Errors() +Parse_ReportErrors() { - if (current != NULL) { - free_ifile(current); - current = NULL; - } - if (fatals) { + if (fatal_errors) { +#ifdef CLEANUP + while (Parse_NextFile()) + ; +#endif fprintf(stderr, "Fatal errors encountered -- cannot continue\n"); exit(1); - } + } else + assert(current == NULL); } diff --git a/usr.bin/make/lowparse.h b/usr.bin/make/lowparse.h index b39e70c2278..404d22b1c39 100644 --- a/usr.bin/make/lowparse.h +++ b/usr.bin/make/lowparse.h @@ -1,5 +1,8 @@ +#ifndef LOWPARSE_H +#define LOWPARSE_H + /* $OpenPackages$ */ -/* $OpenBSD: lowparse.h,v 1.3 2001/05/03 13:41:07 espie Exp $ */ +/* $OpenBSD: lowparse.h,v 1.4 2001/05/23 12:34:45 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -27,16 +30,78 @@ * (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 LOWPARSE_H -#define LOWPARSE_H -extern void Parse_FromFile(char *, FILE *); -extern Boolean Parse_NextFile(void); +/* low-level parsing module: + * select input stream to parse, and do high-speed processing of + * lines: skipping comments, handling continuation lines, or skipping + * over dead conditionals. + * + * Basic template: + * + * Parse_Fromxxx(source); + * do { + * while ((line = Parse_ReadNormalLine(&buf)) != NULL) { + * handle line, use Parse_Fromxxx to push includes, + * Parse_ReadNextConditional to get over non-conditional lines. + * or Parse_ReadUnparsedLine to handle special cases manually. + * } + * } while (Parse_NextFile()); + */ + +/* Initialization and cleanup */ #ifdef CLEANUP extern void LowParse_Init(void); extern void LowParse_End(void); +#else +#define LowParse_Init() +#define LowParse_End() #endif -extern char *ParseReadLine(Buffer); -extern char *ParseSkipGetLine(Buffer); -extern char *ParseGetLine(Buffer, const char *); -extern void Finish_Errors(void); + +/* Selection of input stream */ +/* Parse_FromFile(filename, filehandle); + * Push given filehandle on the input stack, using filename for diagnostic + * messages. The module assumes ownership of the filehandle and of + * the filename: provide copies if necessary. */ +extern void Parse_FromFile(const char *, FILE *); +/* Parse_FromString(str, lineno); + * Push expanded string str on the input stack, assuming it starts at + * lineno in the current file. This is used to reparse .for loops + * after the variable has been expanded, hence no need to respecify + * the filename. The module assumes ownership of the string: provide a + * copy if necessary. */ +extern void Parse_FromString(char *, unsigned long); + +/* Error reporting, and tagging of read structures. */ +/* lineno = Parse_Getlineno(); + * Returns the current lineno. */ +extern unsigned long Parse_Getlineno(void); +/* name = Parse_Getfilename(); + * Returns the current filename. Safe to keep without copying. */ +extern const char *Parse_Getfilename(void); + +/* continue = Parse_NextFile(); + * Advance parsing to the next file in the input stack. Returns true + * if there is parsing left to do. + */ +extern bool Parse_NextFile(void); + + +/* line = Parse_ReadNormalLine(buf); + * Reads next line into buffer and return its contents. Handles line + * continuation, remove extra blanks, and skip trivial comments. tabs at + * beginning of line are left alone, to be able to recognize target + * lines. */ +extern char *Parse_ReadNormalLine(Buffer); + +/* line = ParseReadNextConditionalLine(buf); + * Returns next conditional line, skipping over everything else. */ +extern char *Parse_ReadNextConditionalLine(Buffer); +/* line = ParseReadUnparsedLine(buf, type); + * Reads line without parsing anything beyond continuations. + * Handle special cases such as conditional lines, or lines that + * need a reparse (loops). */ +extern char *Parse_ReadUnparsedLine(Buffer, const char *); +/* Parse_ReportErrors(); + * At end of parsing, report on fatal errors. + */ +extern void Parse_ReportErrors(void); #endif diff --git a/usr.bin/make/lst.h b/usr.bin/make/lst.h index 53ff01ddb9f..d89aa85136b 100644 --- a/usr.bin/make/lst.h +++ b/usr.bin/make/lst.h @@ -1,5 +1,8 @@ +#ifndef _LST_H_ +#define _LST_H_ + /* $OpenPackages$ */ -/* $OpenBSD: lst.h,v 1.19 2001/05/03 13:41:07 espie Exp $ */ +/* $OpenBSD: lst.h,v 1.20 2001/05/23 12:34:45 espie Exp $ */ /* $NetBSD: lst.h,v 1.7 1996/11/06 17:59:12 christos Exp $ */ /* @@ -46,10 +49,6 @@ * lst.h -- * Header for using the list library */ -#ifndef _LST_H_ -#define _LST_H_ - -#include "sprite.h" #include <sys/param.h> #ifdef __STDC__ #include <stdlib.h> @@ -58,18 +57,15 @@ /* These data structures are PRIVATE !!! * Here for efficiency, so that some functions can be recoded as inlines, * and so that lst headers don't need dynamic allocation most of the time. */ -typedef struct ListNode_ { +struct ListNode_ { struct ListNode_ *prevPtr; /* previous element in list */ struct ListNode_ *nextPtr; /* next in list */ void *datum; /* datum associated with this element */ -} *LstNode; +}; -typedef struct { - LstNode firstPtr; /* first node in list */ - LstNode lastPtr; /* last node in list */ -} LIST; - -typedef LIST *Lst; +#ifndef LIST_TYPE +#include "lst_t.h" +#endif typedef void (*SimpleProc)(void *); typedef int (*FindProc)(void *, void *); @@ -137,7 +133,7 @@ extern LstNode Lst_Member(Lst, void *); extern void Lst_ForEachFrom(LstNode, ForEachProc, void *); extern void Lst_Every(Lst, SimpleProc); -extern ReturnStatus Lst_AddNew(Lst, void *); +extern bool Lst_AddNew(Lst, void *); /* * for using the list as a queue */ @@ -145,6 +141,12 @@ extern ReturnStatus Lst_AddNew(Lst, void *); #define Lst_EnQueue Lst_AtEnd #define Lst_QueueNew Lst_AddNew +/* + * for using the list as a stack + */ +#define Lst_Push Lst_AtFront +#define Lst_Pop Lst_DeQueue + /* Remove an element from head of queue */ extern void * Lst_DeQueue(Lst); @@ -157,6 +159,7 @@ extern void * Lst_DeQueue(Lst); #define Lst_Rev(ln) ((ln)->prevPtr) +/* Inlines are preferable to macros here because of the type checking. */ #ifdef HAS_INLINES static INLINE LstNode Lst_FindConst(Lst l, FindProcConst cProc, const void *d) diff --git a/usr.bin/make/lst.lib/lstAddNew.c b/usr.bin/make/lst.lib/lstAddNew.c index 2c74119b371..53334b775f3 100644 --- a/usr.bin/make/lst.lib/lstAddNew.c +++ b/usr.bin/make/lst.lib/lstAddNew.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstAddNew.c,v 1.1 2001/05/03 13:41:16 espie Exp $ */ +/* $OpenBSD: lstAddNew.c,v 1.2 2001/05/23 12:34:53 espie Exp $ */ /* ex:ts=8 sw=4: */ @@ -34,22 +34,22 @@ #ifndef lint UNUSED -static char rcsid[] = "$OpenBSD: lstAddNew.c,v 1.1 2001/05/03 13:41:16 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstAddNew.c,v 1.2 2001/05/23 12:34:53 espie Exp $"; #endif /* not lint */ /* Add datum to the end of a list only if it wasn't there already. - * Returns FAILURE if datum was already there. + * Returns false if datum was already there. */ -ReturnStatus +bool Lst_AddNew(l, d) Lst l; void *d; { if (Lst_Member(l, d) != NULL) - return FAILURE; + return false; else { Lst_AtEnd(l, d); - return SUCCESS; + return true; } } diff --git a/usr.bin/make/lst.lib/lstAppend.c b/usr.bin/make/lst.lib/lstAppend.c index 86316326bc3..aea38698b72 100644 --- a/usr.bin/make/lst.lib/lstAppend.c +++ b/usr.bin/make/lst.lib/lstAppend.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstAppend.c,v 1.12 2001/05/03 13:41:17 espie Exp $ */ +/* $OpenBSD: lstAppend.c,v 1.13 2001/05/23 12:34:53 espie Exp $ */ /* $NetBSD: lstAppend.c,v 1.5 1996/11/06 17:59:31 christos Exp $ */ /* @@ -43,14 +43,15 @@ * Add a new node with a new datum after an existing node */ -#include "lstInt.h" +#include "lstInt.h" +#include "memory.h" #ifndef lint #if 0 static char sccsid[] = "@(#)lstAppend.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstAppend.c,v 1.12 2001/05/03 13:41:17 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstAppend.c,v 1.13 2001/05/23 12:34:53 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstConcat.c b/usr.bin/make/lst.lib/lstConcat.c index c56ff3d0f2d..9bb55445c65 100644 --- a/usr.bin/make/lst.lib/lstConcat.c +++ b/usr.bin/make/lst.lib/lstConcat.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstConcat.c,v 1.12 2001/05/03 13:41:19 espie Exp $ */ +/* $OpenBSD: lstConcat.c,v 1.13 2001/05/23 12:34:54 espie Exp $ */ /* $NetBSD: lstConcat.c,v 1.6 1996/11/06 17:59:34 christos Exp $ */ /* @@ -43,14 +43,15 @@ * Function to copy a list and append it to another. */ -#include "lstInt.h" +#include "lstInt.h" +#include "memory.h" #ifndef lint #if 0 static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstConcat.c,v 1.12 2001/05/03 13:41:19 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstConcat.c,v 1.13 2001/05/23 12:34:54 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstConcatDestroy.c b/usr.bin/make/lst.lib/lstConcatDestroy.c index 83f95d278f4..f14d6dabd51 100644 --- a/usr.bin/make/lst.lib/lstConcatDestroy.c +++ b/usr.bin/make/lst.lib/lstConcatDestroy.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstConcatDestroy.c,v 1.3 2001/05/03 13:41:19 espie Exp $ */ +/* $OpenBSD: lstConcatDestroy.c,v 1.4 2001/05/23 12:34:54 espie Exp $ */ /* $NetBSD: lstConcat.c,v 1.6 1996/11/06 17:59:34 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstConcatDestroy.c,v 1.3 2001/05/03 13:41:19 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstConcatDestroy.c,v 1.4 2001/05/23 12:34:54 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstDeQueue.c b/usr.bin/make/lst.lib/lstDeQueue.c index 272e8a41ebe..c964d9ec464 100644 --- a/usr.bin/make/lst.lib/lstDeQueue.c +++ b/usr.bin/make/lst.lib/lstDeQueue.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstDeQueue.c,v 1.11 2001/05/03 13:41:19 espie Exp $ */ +/* $OpenBSD: lstDeQueue.c,v 1.12 2001/05/23 12:34:54 espie Exp $ */ /* $NetBSD: lstDeQueue.c,v 1.5 1996/11/06 17:59:36 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstDeQueue.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstDeQueue.c,v 1.11 2001/05/03 13:41:19 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstDeQueue.c,v 1.12 2001/05/23 12:34:54 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstDestroy.c b/usr.bin/make/lst.lib/lstDestroy.c index 73f8aa108ed..babefb7b779 100644 --- a/usr.bin/make/lst.lib/lstDestroy.c +++ b/usr.bin/make/lst.lib/lstDestroy.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstDestroy.c,v 1.12 2001/05/03 13:41:19 espie Exp $ */ +/* $OpenBSD: lstDestroy.c,v 1.13 2001/05/23 12:34:55 espie Exp $ */ /* $NetBSD: lstDestroy.c,v 1.6 1996/11/06 17:59:37 christos Exp $ */ /* @@ -51,7 +51,7 @@ static char sccsid[] = "@(#)lstDestroy.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstDestroy.c,v 1.12 2001/05/03 13:41:19 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstDestroy.c,v 1.13 2001/05/23 12:34:55 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstDupl.c b/usr.bin/make/lst.lib/lstDupl.c index 55abac5ad87..6f22b8d3460 100644 --- a/usr.bin/make/lst.lib/lstDupl.c +++ b/usr.bin/make/lst.lib/lstDupl.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstDupl.c,v 1.14 2001/05/03 13:41:20 espie Exp $ */ +/* $OpenBSD: lstDupl.c,v 1.15 2001/05/23 12:34:55 espie Exp $ */ /* $NetBSD: lstDupl.c,v 1.6 1996/11/06 17:59:37 christos Exp $ */ /* @@ -51,7 +51,7 @@ static char sccsid[] = "@(#)lstDupl.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstDupl.c,v 1.14 2001/05/03 13:41:20 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstDupl.c,v 1.15 2001/05/23 12:34:55 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstFindFrom.c b/usr.bin/make/lst.lib/lstFindFrom.c index 05e18146f76..aab0be03f4b 100644 --- a/usr.bin/make/lst.lib/lstFindFrom.c +++ b/usr.bin/make/lst.lib/lstFindFrom.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstFindFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $ */ +/* $OpenBSD: lstFindFrom.c,v 1.11 2001/05/23 12:34:56 espie Exp $ */ /* $NetBSD: lstFindFrom.c,v 1.6 1996/11/06 17:59:40 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstFindFrom.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char *rcsid = "$OpenBSD: lstFindFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $"; +static char *rcsid = "$OpenBSD: lstFindFrom.c,v 1.11 2001/05/23 12:34:56 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstForEachFrom.c b/usr.bin/make/lst.lib/lstForEachFrom.c index dfff0580f73..6c0ffe79250 100644 --- a/usr.bin/make/lst.lib/lstForEachFrom.c +++ b/usr.bin/make/lst.lib/lstForEachFrom.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstForEachFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $ */ +/* $OpenBSD: lstForEachFrom.c,v 1.11 2001/05/23 12:34:56 espie Exp $ */ /* $NetBSD: lstForEachFrom.c,v 1.5 1996/11/06 17:59:42 christos Exp $ */ /* @@ -51,7 +51,7 @@ static char sccsid[] = "@(#)lstForEachFrom.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstForEachFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstForEachFrom.c,v 1.11 2001/05/23 12:34:56 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstInit.c b/usr.bin/make/lst.lib/lstInit.c index fec822b7ec4..58fe86ff252 100644 --- a/usr.bin/make/lst.lib/lstInit.c +++ b/usr.bin/make/lst.lib/lstInit.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstInit.c,v 1.11 2001/05/03 13:41:21 espie Exp $ */ +/* $OpenBSD: lstInit.c,v 1.12 2001/05/23 12:34:56 espie Exp $ */ /* $NetBSD: lstInit.c,v 1.5 1996/11/06 17:59:43 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstInit.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstInit.c,v 1.11 2001/05/03 13:41:21 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstInit.c,v 1.12 2001/05/23 12:34:56 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstInsert.c b/usr.bin/make/lst.lib/lstInsert.c index 6337f4e17e2..854ae9a78c2 100644 --- a/usr.bin/make/lst.lib/lstInsert.c +++ b/usr.bin/make/lst.lib/lstInsert.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstInsert.c,v 1.12 2001/05/03 13:41:21 espie Exp $ */ +/* $OpenBSD: lstInsert.c,v 1.13 2001/05/23 12:34:56 espie Exp $ */ /* $NetBSD: lstInsert.c,v 1.5 1996/11/06 17:59:44 christos Exp $ */ /* @@ -43,14 +43,15 @@ * Insert a new datum before an old one */ -#include "lstInt.h" +#include "lstInt.h" +#include "memory.h" #ifndef lint #if 0 static char sccsid[] = "@(#)lstInsert.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstInsert.c,v 1.12 2001/05/03 13:41:21 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstInsert.c,v 1.13 2001/05/23 12:34:56 espie Exp $"; #endif #endif /* not lint */ @@ -60,9 +61,6 @@ static char rcsid[] = "$OpenBSD: lstInsert.c,v 1.12 2001/05/03 13:41:21 espie Ex * Insert a new node with the given piece of data before the given * node in the given list. * - * Results: - * SUCCESS or FAILURE. - * * Side Effects: * the firstPtr field will be changed if ln is the first node in the * list. diff --git a/usr.bin/make/lst.lib/lstInt.h b/usr.bin/make/lst.lib/lstInt.h index 3b616769489..85d061a64fc 100644 --- a/usr.bin/make/lst.lib/lstInt.h +++ b/usr.bin/make/lst.lib/lstInt.h @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstInt.h,v 1.12 2001/05/03 13:41:22 espie Exp $ */ +/* $OpenBSD: lstInt.h,v 1.13 2001/05/23 12:34:56 espie Exp $ */ /* $NetBSD: lstInt.h,v 1.7 1996/11/06 17:59:44 christos Exp $ */ /* @@ -47,8 +47,9 @@ #ifndef _LSTINT_H_ #define _LSTINT_H_ -#include "make.h" -#include "lst.h" +#include "config.h" +#include "defines.h" +#include "lst.h" /* * PAlloc(var, ptype) -- diff --git a/usr.bin/make/lst.lib/lstMember.c b/usr.bin/make/lst.lib/lstMember.c index 294aab46816..624be86943f 100644 --- a/usr.bin/make/lst.lib/lstMember.c +++ b/usr.bin/make/lst.lib/lstMember.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstMember.c,v 1.9 2001/05/03 13:41:23 espie Exp $ */ +/* $OpenBSD: lstMember.c,v 1.10 2001/05/23 12:34:57 espie Exp $ */ /* $NetBSD: lstMember.c,v 1.5 1996/11/06 17:59:48 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstMember.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstMember.c,v 1.9 2001/05/03 13:41:23 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstMember.c,v 1.10 2001/05/23 12:34:57 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstRemove.c b/usr.bin/make/lst.lib/lstRemove.c index f2be845d888..3624b26df07 100644 --- a/usr.bin/make/lst.lib/lstRemove.c +++ b/usr.bin/make/lst.lib/lstRemove.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstRemove.c,v 1.11 2001/05/03 13:41:25 espie Exp $ */ +/* $OpenBSD: lstRemove.c,v 1.12 2001/05/23 12:34:57 espie Exp $ */ /* $NetBSD: lstRemove.c,v 1.5 1996/11/06 17:59:50 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstRemove.c,v 1.11 2001/05/03 13:41:25 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstRemove.c,v 1.12 2001/05/23 12:34:57 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstReplace.c b/usr.bin/make/lst.lib/lstReplace.c index f5ec891de52..441782bd781 100644 --- a/usr.bin/make/lst.lib/lstReplace.c +++ b/usr.bin/make/lst.lib/lstReplace.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstReplace.c,v 1.10 2001/05/03 13:41:26 espie Exp $ */ +/* $OpenBSD: lstReplace.c,v 1.11 2001/05/23 12:34:57 espie Exp $ */ /* $NetBSD: lstReplace.c,v 1.5 1996/11/06 17:59:51 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstReplace.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstReplace.c,v 1.10 2001/05/03 13:41:26 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstReplace.c,v 1.11 2001/05/23 12:34:57 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst.lib/lstSucc.c b/usr.bin/make/lst.lib/lstSucc.c index d6acc4816b5..f425c3aa8ea 100644 --- a/usr.bin/make/lst.lib/lstSucc.c +++ b/usr.bin/make/lst.lib/lstSucc.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: lstSucc.c,v 1.8 2001/05/03 13:41:27 espie Exp $ */ +/* $OpenBSD: lstSucc.c,v 1.9 2001/05/23 12:34:57 espie Exp $ */ /* $NetBSD: lstSucc.c,v 1.5 1996/11/06 17:59:52 christos Exp $ */ /* @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)lstSucc.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstSucc.c,v 1.8 2001/05/03 13:41:27 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstSucc.c,v 1.9 2001/05/23 12:34:57 espie Exp $"; #endif #endif /* not lint */ diff --git a/usr.bin/make/lst_t.h b/usr.bin/make/lst_t.h new file mode 100644 index 00000000000..69a4a3246d7 --- /dev/null +++ b/usr.bin/make/lst_t.h @@ -0,0 +1,34 @@ +/* $OpenPackages$ */ +/* $OpenBSD: lst_t.h,v 1.1 2001/05/23 12:34:46 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +typedef struct List_ { + LstNode firstPtr; /* first node in list */ + LstNode lastPtr; /* last node in list */ +} LIST; + +#define LIST_TYPE diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 757cfbc4932..4107e4272fa 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: main.c,v 1.47 2001/05/07 22:57:19 espie Exp $ */ +/* $OpenBSD: main.c,v 1.48 2001/05/23 12:34:46 espie Exp $ */ /* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ /* @@ -40,77 +40,33 @@ * SUCH DAMAGE. */ -/*- - * main.c -- - * The main file for this entire program. Exit routines etc - * reside here. - * - * Utility functions defined in this file: - * Main_ParseArgLine Takes a line of arguments, breaks them and - * treats them as if they were given when first - * invoked. Used by the parse module to implement - * the .MFLAGS target. - * - * Error Print a tagged error message. The global - * MAKE variable must have been defined. This - * takes a format string and two optional - * arguments for it. - * - * Fatal Print an error message and exit. Also takes - * a format string and two arguments. - * - * Punt Aborts all jobs and exits with a message. Also - * takes a format string and two arguments. - * - * Finish Finish things up by printing the number of - * errors which occured, as passed to it, and - * exiting. - */ - #include <sys/types.h> -#include <sys/time.h> -#include <sys/param.h> -#include <sys/resource.h> -#include <sys/signal.h> #include <sys/stat.h> #ifndef MAKE_BOOTSTRAP #include <sys/utsname.h> #endif -#include <sys/wait.h> #include <errno.h> -#include <fcntl.h> -#include <stddef.h> #include <stdio.h> -#include <stdlib.h> -#include <time.h> -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif -#include "make.h" -#include "ohash.h" +#include <string.h> +#include <unistd.h> +#include "config.h" +#include "defines.h" +#include "var.h" +#include "parse.h" +#include "parsevar.h" #include "dir.h" -#include "job.h" +#include "error.h" #include "pathnames.h" -#include "stats.h" - -#ifndef lint -UNUSED -static char copyright[] = -"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: main.c,v 1.47 2001/05/07 22:57:19 espie Exp $"; -#endif -#endif /* not lint */ - +#include "init.h" +#include "job.h" +#include "compat.h" +#include "targ.h" +#include "suff.h" +#include "str.h" +#include "main.h" +#include "lst.h" +#include "memory.h" +#include "make.h" #ifndef DEFMAXLOCAL #define DEFMAXLOCAL DEFMAXJOBS @@ -118,29 +74,27 @@ static char rcsid[] = "$OpenBSD: main.c,v 1.47 2001/05/07 22:57:19 espie Exp $"; #define MAKEFLAGS ".MAKEFLAGS" -LIST create; /* Targets to be made */ -TIMESTAMP now; /* Time at start of make */ +static LIST to_create; /* Targets to be made */ +Lst create = &to_create; GNode *DEFAULT; /* .DEFAULT node */ -Boolean allPrecious; /* .PRECIOUS given on line by itself */ +bool allPrecious; /* .PRECIOUS given on line by itself */ -static Boolean noBuiltins; /* -r flag */ +static bool noBuiltins; /* -r flag */ static LIST makefiles; /* ordered list of makefiles to read */ -static Boolean printVars; /* print value of one or more vars */ -static LIST variables; /* list of variables to print */ +static LIST varstoprint; /* list of variables to print */ int maxJobs; /* -j argument */ static int maxLocal; /* -L argument */ -Boolean compatMake; /* -B argument */ -Boolean debug; /* -d flag */ -Boolean noExecute; /* -n flag */ -Boolean keepgoing; /* -k flag */ -Boolean queryFlag; /* -q flag */ -Boolean touchFlag; /* -t flag */ -Boolean usePipes; /* !-P flag */ -Boolean ignoreErrors; /* -i flag */ -Boolean beSilent; /* -s flag */ -Boolean oldVars; /* variable substitution style */ -Boolean checkEnvFirst; /* -e flag */ -static Boolean jobsRunning; /* TRUE if the jobs might be running */ +bool compatMake; /* -B argument */ +bool debug; /* -d flag */ +bool noExecute; /* -n flag */ +bool keepgoing; /* -k flag */ +bool queryFlag; /* -q flag */ +bool touchFlag; /* -t flag */ +bool usePipes; /* !-P flag */ +bool ignoreErrors; /* -i flag */ +bool beSilent; /* -s flag */ +bool oldVars; /* variable substitution style */ +bool checkEnvFirst; /* -e flag */ static void MainParseArgs(int, char **); static char * chdir_verify_path(char *, char *); @@ -148,64 +102,70 @@ static int ReadMakefile(void *, void *); static void add_dirpath(Lst, const char *); static void usage(void); static void posixParseOptLetter(int); +static void record_option(int, const char *); static char *curdir; /* startup directory */ static char *objdir; /* where we chdir'ed to */ +static void record_option(c, arg) + int c; + const char *arg; +{ + char opt[3]; + + opt[0] = '-'; + opt[1] = c; + opt[2] = '\0'; + Var_Append(MAKEFLAGS, opt, VAR_GLOBAL); + if (arg != NULL) + Var_Append(MAKEFLAGS, arg, VAR_GLOBAL); +} + static void posixParseOptLetter(c) int c; { switch(c) { case 'B': - compatMake = TRUE; - break; + compatMake = true; + return; /* XXX don't pass to submakes. */ case 'P': - usePipes = FALSE; - Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); + usePipes = false; break; case 'S': - keepgoing = FALSE; - Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); + keepgoing = false; break; case 'e': - checkEnvFirst = TRUE; - Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); + checkEnvFirst = true; break; case 'i': - ignoreErrors = TRUE; - Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); + ignoreErrors = true; break; case 'k': - keepgoing = TRUE; - Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); + keepgoing = true; break; case 'n': - noExecute = TRUE; - Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); + noExecute = true; break; case 'q': - queryFlag = TRUE; + queryFlag = true; /* Kind of nonsensical, wot? */ - Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); break; case 'r': - noBuiltins = TRUE; - Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); + noBuiltins = true; break; case 's': - beSilent = TRUE; - Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); + beSilent = true; break; case 't': - touchFlag = TRUE; - Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); + touchFlag = true; break; default: case '?': usage(); } + record_option(c, NULL); } /*- @@ -240,19 +200,15 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { switch (c) { case 'D': Var_Set(optarg, "1", VAR_GLOBAL); - Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + record_option(c, optarg); break; case 'I': Parse_AddIncludeDir(optarg); - Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + record_option(c, optarg); break; case 'V': - printVars = TRUE; - Lst_AtEnd(&variables, optarg); - Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + Lst_AtEnd(&varstoprint, optarg); + record_option(c, optarg); break; #ifdef REMOTE case 'L': { @@ -265,8 +221,7 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { optarg); usage(); } - Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + record_option(c, optend); break; } #endif @@ -324,8 +279,7 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { *modules); usage(); } - Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + record_option(c, optarg); break; } case 'f': @@ -334,7 +288,7 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { case 'j': { char *endptr; - forceJobs = TRUE; + forceJobs = true; maxJobs = strtol(optarg, &endptr, 0); if (endptr == optarg) { fprintf(stderr, @@ -346,14 +300,12 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { #ifndef REMOTE maxLocal = maxJobs; #endif - Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + record_option(c, optarg); break; } case 'm': - Dir_AddDir(&sysIncPath, optarg, NULL); - Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); - Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); + Dir_AddDir(sysIncPath, optarg); + record_option(c, optarg); break; default: posixParseOptLetter(c); @@ -362,12 +314,12 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { /* * Be compatible if user did not specify -j and did not explicitly - * turned compatibility on + * turn compatibility on */ if (!compatMake && !forceJobs) - compatMake = TRUE; + compatMake = true; - oldVars = TRUE; + oldVars = true; /* * See if the rest of the arguments are variable assignments and @@ -375,12 +327,7 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { * on the end of the "create" list. */ for (argv += optind, argc -= optind; *argv; ++argv, --argc) - if (Parse_IsVar(*argv)) { - char *var = estrdup(*argv); - - Parse_DoVar(var, VAR_CMD); - free(var); - } else { + if (!Parse_DoVar(*argv, VAR_CMD)) { if (!**argv) Punt("illegal (null) argument."); if (**argv == '-') { @@ -390,7 +337,7 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { optind = 1; /* - */ goto rearg; } - Lst_AtEnd(&create, estrdup(*argv)); + Lst_AtEnd(create, estrdup(*argv)); } } @@ -408,14 +355,14 @@ rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { */ void Main_ParseArgLine(line) - char *line; /* Line to fracture */ + const char *line; /* Line to fracture */ { char **argv; /* Manufactured argument vector */ int argc; /* Number of arguments in argv */ char *args; /* Space used by the args */ char *buf; char *argv0; - char *s; + const char *s; if (line == NULL) @@ -486,7 +433,7 @@ add_dirpath(l, n) for (start = n;;) { for (cp = start; *cp != '\0' && *cp != ':';) cp++; - Dir_AddDir(l, start, cp); + Dir_AddDiri(l, start, cp); if (*cp == '\0') break; else @@ -518,7 +465,7 @@ main(argc, argv) char **argv; { LIST targs; /* target nodes to create */ - Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ + bool outOfDate = true; /* false if all targets up to date */ struct stat sb, sa; char *p, *path, *pathp, *pwd; char mdpath[MAXPATHLEN + 1]; @@ -526,13 +473,7 @@ main(argc, argv) char cdpath[MAXPATHLEN + 1]; char *machine = getenv("MACHINE"); char *machine_arch = getenv("MACHINE_ARCH"); - /* avoid faults on read-only strings */ - static char syspath[] = _PATH_DEFSYSPATH; - - set_out_of_date(now); -#ifdef HAS_STATS - Init_Stats(); -#endif + const char *syspath = _PATH_DEFSYSPATH; #ifdef RLIMIT_NOFILE /* @@ -640,21 +581,19 @@ main(argc, argv) esetenv("PWD", objdir); unsetenv("CDPATH"); - Lst_Init(&create); + Lst_Init(create); Lst_Init(&makefiles); - printVars = FALSE; - Lst_Init(&variables); - beSilent = FALSE; /* Print commands as executed */ - ignoreErrors = FALSE; /* Pay attention to non-zero returns */ - noExecute = FALSE; /* Execute all commands */ - keepgoing = FALSE; /* Stop on error */ - allPrecious = FALSE; /* Remove targets when interrupted */ - queryFlag = FALSE; /* This is not just a check-run */ - noBuiltins = FALSE; /* Read the built-in rules */ - touchFlag = FALSE; /* Actually update targets */ - usePipes = TRUE; /* Catch child output in pipes */ + Lst_Init(&varstoprint); + beSilent = false; /* Print commands as executed */ + ignoreErrors = false; /* Pay attention to non-zero returns */ + noExecute = false; /* Execute all commands */ + keepgoing = false; /* Stop on error */ + allPrecious = false; /* Remove targets when interrupted */ + queryFlag = false; /* This is not just a check-run */ + noBuiltins = false; /* Read the built-in rules */ + touchFlag = false; /* Actually update targets */ + usePipes = true; /* Catch child output in pipes */ debug = 0; /* No debug verbosity, please. */ - jobsRunning = FALSE; maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ #ifdef REMOTE @@ -662,22 +601,16 @@ main(argc, argv) #else maxJobs = maxLocal; #endif - compatMake = FALSE; /* No compat mode */ + compatMake = false; /* No compat mode */ /* - * Initialize the parsing, directory and variable modules to prepare - * for the reading of inclusion paths and variable settings on the - * command line + * Initialize all external modules. */ - Dir_Init(); /* Initialize directory structures so -I flags - * can be processed correctly */ - Parse_Init(); /* Need to initialize the paths of #include - * directories */ - Var_Init(); /* As well as the lists of variables for - * parsing arguments */ + Init(); + if (objdir != curdir) - Dir_AddDir(&dirSearchPath, curdir, NULL); + Dir_AddDir(dirSearchPath, curdir); Var_Set(".CURDIR", curdir, VAR_GLOBAL); Var_Set(".OBJDIR", objdir, VAR_GLOBAL); @@ -705,26 +638,17 @@ main(argc, argv) Var_AddCmdline(MAKEFLAGS); - /* - * Initialize archive, target and suffix modules in preparation for - * parsing the makefile(s) - */ - Arch_Init(); - Targ_Init(); - Suff_Init(); - DEFAULT = NULL; - grab(now); /* * Set up the .TARGETS variable to contain the list of targets to be * created. If none specified, make the variable empty -- the parser * will fill the thing in with the default or .MAIN target. */ - if (!Lst_IsEmpty(&create)) { + if (!Lst_IsEmpty(create)) { LstNode ln; - for (ln = Lst_First(&create); ln != NULL; ln = Lst_Adv(ln)) { + for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) { char *name = (char *)Lst_Datum(ln); Var_Append(".TARGETS", name, VAR_GLOBAL); @@ -738,20 +662,20 @@ main(argc, argv) * add the directories from the DEFSYSPATH (more than one may be given * as dir1:...:dirn) to the system include path. */ - if (Lst_IsEmpty(&sysIncPath)) - add_dirpath(&sysIncPath, syspath); + if (Lst_IsEmpty(sysIncPath)) + add_dirpath(sysIncPath, syspath); /* * Read in the built-in rules first, followed by the specified - * makefile, if it was (makefile != (char *)NULL), or the default - * Makefile and makefile, in that order, if it wasn't. + * makefile(s), or the default BSDmakefile, Makefile or + * makefile, in that order. */ if (!noBuiltins) { LstNode ln; LIST sysMkPath; /* Path of sys.mk */ Lst_Init(&sysMkPath); - Dir_Expand(_PATH_DEFSYSMK, &sysIncPath, &sysMkPath); + Dir_Expand(_PATH_DEFSYSMK, sysIncPath, &sysMkPath); if (Lst_IsEmpty(&sysMkPath)) Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); ln = Lst_Find(&sysMkPath, ReadMakefile, NULL); @@ -772,6 +696,7 @@ main(argc, argv) if (!ReadMakefile("makefile", NULL)) (void)ReadMakefile("Makefile", NULL); + /* Always read a .depend file, if it exists. */ (void)ReadMakefile(".depend", NULL); Var_Append("MFLAGS", Var_Value(MAKEFLAGS), @@ -790,8 +715,8 @@ main(argc, argv) if (Var_Value("VPATH") != NULL) { char *vpath; - vpath = Var_Subst("${VPATH}", NULL, FALSE); - add_dirpath(&dirSearchPath, vpath); + vpath = Var_Subst("${VPATH}", NULL, false); + add_dirpath(dirSearchPath, vpath); (void)free(vpath); } @@ -804,26 +729,29 @@ main(argc, argv) Targ_PrintGraph(1); /* Print the values of any variables requested by the user. */ - if (printVars) { - LstNode ln; + if (!Lst_IsEmpty(&varstoprint)) { + LstNode ln; - for (ln = Lst_First(&variables); ln != NULL; ln = Lst_Adv(ln)) { - char *value = Var_Value((char *)Lst_Datum(ln)); + for (ln = Lst_First(&varstoprint); ln != NULL; ln = Lst_Adv(ln)) { + char *value = Var_Value((char *)Lst_Datum(ln)); - printf("%s\n", value ? value : ""); - } - } - - /* Have now read the entire graph and need to make a list of targets - * to create. If none was given on the command line, we consult the - * parsing module to find the main target(s) to create. */ - Lst_Init(&targs); - if (!Lst_IsEmpty(&create)) - Targ_FindList(&targs, &create); - else + printf("%s\n", value ? value : ""); + } + } else { + /* Have now read the entire graph and need to make a list of targets + * to create. If none was given on the command line, we consult the + * parsing module to find the main target(s) to create. */ + Lst_Init(&targs); + if (Lst_IsEmpty(create)) Parse_MainName(&targs); + else + Targ_FindList(&targs, create); - if (!compatMake && !printVars) { + if (compatMake) + /* Compat_Init will take care of creating all the targets as + * well as initializing the module. */ + Compat_Run(&targs); + else { /* Initialize job module before traversing the graph, now that * any .BEGIN and .END targets have been read. This is done * only if the -q flag wasn't given (to prevent the .BEGIN from @@ -832,34 +760,22 @@ main(argc, argv) if (maxLocal == -1) maxLocal = maxJobs; Job_Init(maxJobs, maxLocal); - jobsRunning = TRUE; } /* Traverse the graph, checking on all the targets. */ outOfDate = Make_Run(&targs); - } else if (!printVars) { - /* Compat_Init will take care of creating all the targets as - * well as initializing the module. */ - Compat_Run(&targs); + } } Lst_Destroy(&targs, NOFREE); - Lst_Destroy(&variables, NOFREE); + Lst_Destroy(&varstoprint, NOFREE); Lst_Destroy(&makefiles, NOFREE); - Lst_Destroy(&create, (SimpleProc)free); + Lst_Destroy(create, (SimpleProc)free); /* print the graph now it's been processed if the user requested it */ if (DEBUG(GRAPH2)) Targ_PrintGraph(2); - Suff_End(); - Targ_End(); - Arch_End(); - Var_End(); - Parse_End(); - Dir_End(); - Job_End(); - if (queryFlag && outOfDate) return 1; else @@ -871,18 +787,17 @@ main(argc, argv) * Open and parse the given makefile. * * Results: - * TRUE if ok. FALSE if couldn't open file. + * true if ok. false if couldn't open file. * * Side Effects: * lots */ -static Boolean +static bool ReadMakefile(p, q) void * p; void * q UNUSED; { char *fname = p; /* makefile to read */ - extern LIST parseIncPath; FILE *stream; char *name, path[MAXPATHLEN + 1]; @@ -901,11 +816,11 @@ ReadMakefile(p, q) } } /* look in -I and system include directories. */ - name = Dir_FindFile(fname, &parseIncPath); + name = Dir_FindFile(fname, parseIncPath); if (!name) - name = Dir_FindFile(fname, &sysIncPath); + name = Dir_FindFile(fname, sysIncPath); if (!name || !(stream = fopen(name, "r"))) - return FALSE; + return false; fname = name; /* * set the MAKEFILE variable desired by System V fans -- the @@ -915,269 +830,7 @@ ReadMakefile(p, q) found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); Parse_File(fname, stream); } - return TRUE; -} - -/*- - * Cmd_Exec -- - * Execute the command in cmd, and return the output of that command - * in a string. - * - * Results: - * A string containing the output of the command, or the empty string - * If err is not NULL, it contains the reason for the command failure - * - * Side Effects: - * The string must be freed by the caller. - */ -char * -Cmd_Exec(cmd, err) - const char *cmd; - char **err; -{ - char *args[4]; /* Args for invoking the shell */ - int fds[2]; /* Pipe streams */ - int cpid; /* Child PID */ - int pid; /* PID from wait() */ - char *res; /* result */ - int status; /* command exit status */ - BUFFER buf; /* buffer to store the result */ - char *cp; - ssize_t cc; - size_t length; - - - *err = NULL; - - /* - * Set up arguments for shell - */ - args[0] = "sh"; - args[1] = "-c"; - args[2] = (char *)cmd; - args[3] = NULL; - - /* - * Open a pipe for fetching its output - */ - if (pipe(fds) == -1) { - *err = "Couldn't create pipe for \"%s\""; - goto bad; - } - - /* - * Fork - */ - switch (cpid = vfork()) { - case 0: - /* - * Close input side of pipe - */ - (void)close(fds[0]); - - /* - * Duplicate the output stream to the shell's output, then - * shut the extra thing down. Note we don't fetch the error - * stream...why not? Why? - */ - (void)dup2(fds[1], 1); - if (fds[1] != 1) - (void)close(fds[1]); - - (void)execv("/bin/sh", args); - _exit(1); - /*NOTREACHED*/ - - case -1: - *err = "Couldn't exec \"%s\""; - goto bad; - - default: - /* - * No need for the writing half - */ - (void)close(fds[1]); - - Buf_Init(&buf, MAKE_BSIZE); - - do { - char result[BUFSIZ]; - cc = read(fds[0], result, sizeof(result)); - if (cc > 0) - Buf_AddChars(&buf, cc, result); - } - while (cc > 0 || (cc == -1 && errno == EINTR)); - - /* - * Close the input side of the pipe. - */ - (void)close(fds[0]); - - /* - * Wait for the process to exit. - */ - while ((pid = wait(&status)) != cpid && pid >= 0) - continue; - - if (cc == -1) - *err = "Couldn't read shell's output for \"%s\""; - - if (status) - *err = "\"%s\" returned non-zero status"; - - length = Buf_Size(&buf); - res = Buf_Retrieve(&buf); - - /* The result is null terminated, Convert newlines to spaces and - * install in the variable. */ - cp = res + length - 1; - - if (*cp == '\n') - /* A final newline is just stripped. */ - *cp-- = '\0'; - - while (cp >= res) { - if (*cp == '\n') - *cp = ' '; - cp--; - } - break; - } - return res; -bad: - return estrdup(""); -} - -/*- - * Error -- - * Print an error message given its format. - */ -/* VARARGS */ -void -#ifdef __STDC__ -Error(char *fmt, ...) -#else -Error(va_alist) - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - char *fmt; - - va_start(ap); - fmt = va_arg(ap, char *); -#endif - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - (void)fprintf(stderr, "\n"); -} - -/*- - * Fatal -- - * Produce a Fatal error message. If jobs are running, waits for them - * to finish. - * - * Side Effects: - * The program exits - */ -/* VARARGS */ -void -#ifdef __STDC__ -Fatal(char *fmt, ...) -#else -Fatal(va_alist) - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - char *fmt; - - va_start(ap); - fmt = va_arg(ap, char *); -#endif - if (jobsRunning) - Job_Wait(); - - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - (void)fprintf(stderr, "\n"); - - if (DEBUG(GRAPH2)) - Targ_PrintGraph(2); - exit(2); /* Not 1 so -q can distinguish error */ -} - -/* - * Punt -- - * Major exception once jobs are being created. Kills all jobs, prints - * a message and exits. - * - * Side Effects: - * All children are killed indiscriminately and the program Lib_Exits - */ -/* VARARGS */ -void -#ifdef __STDC__ -Punt(char *fmt, ...) -#else -Punt(va_alist) - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - char *fmt; - - va_start(ap); - fmt = va_arg(ap, char *); -#endif - - (void)fprintf(stderr, "make: "); - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - (void)fprintf(stderr, "\n"); - - DieHorribly(); -} - -/*- - * DieHorribly -- - * Exit without giving a message. - * - * Side Effects: - * A big one... - */ -void -DieHorribly() -{ - if (jobsRunning) - Job_AbortAll(); - if (DEBUG(GRAPH2)) - Targ_PrintGraph(2); - exit(2); /* Not 1, so -q can distinguish error */ -} - -/* - * Finish -- - * Called when aborting due to errors in child shell to signal - * abnormal exit. - * - * Side Effects: - * The program exits - */ -void -Finish(errors) - int errors; /* number of errors encountered in Make_Make */ -{ - Fatal("%d error%s", errors, errors == 1 ? "" : "s"); + return true; } @@ -1196,9 +849,3 @@ usage() } -void -PrintAddr(a) - void *a; -{ - printf("%lx ", (unsigned long)a); -} diff --git a/usr.bin/make/main.h b/usr.bin/make/main.h new file mode 100644 index 00000000000..a8e48fecab8 --- /dev/null +++ b/usr.bin/make/main.h @@ -0,0 +1,44 @@ +#ifndef MAIN_H +#define MAIN_H +/* $OpenPackages$ */ +/* $OpenBSD: main.h,v 1.1 2001/05/23 12:34:46 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ +/* main + * User interface to make. + */ +/* Main_ParseArgLine(string); + * Parse string as a line of arguments, and treats them as if they + * were given at make's invocation. Used to implement .MFLAGS. */ +extern void Main_ParseArgLine(const char *); + +/* List of target names given on the command line. Needed to resolve + * .if make(...) statements. */ +extern Lst create; + +extern GNode *DEFAULT; /* .DEFAULT rule */ + +#endif diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c index 809eab06a5a..87964cb82b0 100644 --- a/usr.bin/make/make.c +++ b/usr.bin/make/make.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: make.c,v 1.25 2001/05/03 13:41:08 espie Exp $ */ +/* $OpenBSD: make.c,v 1.26 2001/05/23 12:34:46 espie Exp $ */ /* $NetBSD: make.c,v 1.10 1996/11/06 17:59:15 christos Exp $ */ /* @@ -47,8 +47,9 @@ * * Interface: * Make_Run Initialize things for the module and recreate - * whatever needs recreating. Returns TRUE if - * work was (or would have been) done and FALSE + * whatever needs recreating. Returns true if + * work was (or would have been) done and + * false * otherwise. * * Make_Update Update all parents of a given child. Performs @@ -72,21 +73,21 @@ * and perform the .USE actions if so. */ -#include <stddef.h> -#include "make.h" -#include "ohash.h" -#include "dir.h" -#include "job.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: make.c,v 1.25 2001/05/03 13:41:08 espie Exp $"; -#endif -#endif /* not lint */ - +#include <stdio.h> +#include "config.h" +#include "defines.h" +#include "dir.h" +#include "job.h" +#include "arch.h" +#include "suff.h" +#include "var.h" +#include "targ.h" +#include "error.h" +#include "make.h" +#include "gnode.h" +#include "extern.h" +#include "timestamp.h" +#include "lst.h" static LIST toBeMade; /* The current fringe of the graph. These * are nodes which await examination by @@ -95,13 +96,13 @@ static LIST toBeMade; /* The current fringe of the graph. These * MakeStartJobs */ static int numNodes; /* Number of nodes to be processed. If this * is non-zero when Job_Empty() returns - * TRUE, there's a cycle in the graph */ + * true, there's a cycle in the graph */ static void MakeAddChild(void *, void *); static void MakeAddAllSrc(void *, void *); static void MakeTimeStamp(void *, void *); static void MakeHandleUse(void *, void *); -static Boolean MakeStartJobs(void); +static bool MakeStartJobs(void); static void MakePrintStatus(void *, void *); /*- *----------------------------------------------------------------------- @@ -119,7 +120,7 @@ Make_TimeStamp(pgn, cgn) GNode *pgn; /* the current parent */ GNode *cgn; /* the child we've just examined */ { - if (is_before(pgn->cmtime, cgn->mtime)) + if (is_strictly_before(pgn->cmtime, cgn->mtime)) pgn->cmtime = cgn->mtime; } @@ -143,18 +144,18 @@ MakeTimeStamp(pgn, cgn) * will have been recreated. * * Results: - * TRUE if the node is out of date. FALSE otherwise. + * true if the node is out of date. false otherwise. * * Side Effects: * The mtime field of the node and the cmtime field of its parents * will/may be changed. *----------------------------------------------------------------------- */ -Boolean +bool Make_OODate(gn) GNode *gn; /* the node to check */ { - Boolean oodate; + bool oodate; /* * Certain types of targets needn't even be sought as their datedness @@ -193,7 +194,7 @@ Make_OODate(gn) if (DEBUG(MAKE)) { printf(".USE node..."); } - oodate = FALSE; + oodate = false; } else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) { if (DEBUG(MAKE)) { printf("library..."); @@ -228,8 +229,8 @@ Make_OODate(gn) printf(".EXEC node..."); } } - oodate = TRUE; - } else if (is_before(gn->mtime, gn->cmtime) || + oodate = true; + } else if (is_strictly_before(gn->mtime, gn->cmtime) || (is_out_of_date(gn->cmtime) && (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) { @@ -241,7 +242,7 @@ Make_OODate(gn) * it. */ if (DEBUG(MAKE)) { - if (is_before(gn->mtime, gn->cmtime)) { + if (is_strictly_before(gn->mtime, gn->cmtime)) { printf("modified before source..."); } else if (is_out_of_date(gn->mtime)) { printf("non-existent and no sources..."); @@ -249,7 +250,7 @@ Make_OODate(gn) printf(":: operator and no sources..."); } } - oodate = TRUE; + oodate = true; } else { #if 0 /* WHY? */ @@ -258,7 +259,7 @@ Make_OODate(gn) } oodate = gn->childMade; #else - oodate = FALSE; + oodate = false; #endif /* 0 */ } @@ -279,7 +280,7 @@ Make_OODate(gn) *----------------------------------------------------------------------- * MakeAddChild -- * Function used by Make_Run to add a child to the list l. - * It will only add the child if its make field is FALSE. + * It will only add the child if its make field is false. * * Side Effects: * The given list is extended @@ -335,7 +336,7 @@ Make_HandleUse(cgn, pgn) for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) { gn = (GNode *)Lst_Datum(ln); - if (Lst_AddNew(&pgn->children, gn) == SUCCESS) { + if (Lst_AddNew(&pgn->children, gn)) { Lst_AtEnd(&gn->parents, pgn); pgn->unmade += 1; } @@ -473,8 +474,8 @@ Make_Update(cgn) if ( ! (cgn->type & (OP_EXEC|OP_USE))) { if (cgn->made == MADE) { - pgn->childMade = TRUE; - if (is_before(pgn->cmtime, cgn->mtime)) + pgn->childMade = true; + if (is_strictly_before(pgn->cmtime, cgn->mtime)) pgn->cmtime = cgn->mtime; } else { (void)Make_TimeStamp(pgn, cgn); @@ -558,8 +559,8 @@ MakeAddAllSrc(cgnp, pgnp) if (cgn->made == MADE) { Varq_Append(OODATE_INDEX, child, pgn); } - } else if (is_before(pgn->mtime, cgn->mtime) || - (!is_before(cgn->mtime, now) && cgn->made == MADE)) + } else if (is_strictly_before(pgn->mtime, cgn->mtime) || + (!is_strictly_before(cgn->mtime, now) && cgn->made == MADE)) { /* * It goes in the OODATE variable if the parent is younger than the @@ -624,14 +625,14 @@ Make_DoAllVar(gn) * Results: * If the query flag was given to pmake, no job will be started, * but as soon as an out-of-date target is found, this function - * returns TRUE. At all other times, this function returns FALSE. + * returns true. At all other times, this function returns false. * * Side Effects: * Nodes are removed from the toBeMade queue and job table slots * are filled. *----------------------------------------------------------------------- */ -static Boolean +static bool MakeStartJobs() { GNode *gn; @@ -674,7 +675,7 @@ MakeStartJobs() printf("out-of-date\n"); } if (queryFlag) { - return TRUE; + return true; } Make_DoAllVar(gn); Job_Make(gn); @@ -696,7 +697,7 @@ MakeStartJobs() Make_Update(gn); } } - return FALSE; + return false; } /*- @@ -718,12 +719,12 @@ MakePrintStatus(gnp, cyclep) * inferior */ { GNode *gn = (GNode *)gnp; - Boolean cycle = *(Boolean *)cyclep; + bool cycle = *(bool *)cyclep; if (gn->made == UPTODATE) { printf("`%s' is up to date.\n", gn->name); } else if (gn->unmade != 0) { if (cycle) { - Boolean t = TRUE; + bool t = true; /* * If printing cycles and came to one that has unmade children, * print out the cycle by recursing on its children. Note a @@ -763,7 +764,7 @@ MakePrintStatus(gnp, cyclep) * possible. * * Results: - * TRUE if work was done. FALSE otherwise. + * true if work was done. false otherwise. * * Side Effects: * The make field of all nodes involved in the creation of the given @@ -771,7 +772,7 @@ MakePrintStatus(gnp, cyclep) * 'leaves' of these subgraphs. *----------------------------------------------------------------------- */ -Boolean +bool Make_Run(targs) Lst targs; /* the initial list of targets */ { @@ -794,7 +795,7 @@ Make_Run(targs) */ while ((gn = (GNode *)Lst_DeQueue(&examine)) != NULL) { if (!gn->make) { - gn->make = TRUE; + gn->make = true; numNodes++; /* @@ -855,5 +856,5 @@ Make_Run(targs) errors = errors == 0 && numNodes != 0; Lst_ForEach(targs, MakePrintStatus, &errors); - return TRUE; + return true; } diff --git a/usr.bin/make/make.h b/usr.bin/make/make.h index d785d92e772..0d1d649a12f 100644 --- a/usr.bin/make/make.h +++ b/usr.bin/make/make.h @@ -1,5 +1,8 @@ +#ifndef _MAKE_H_ +#define _MAKE_H_ + /* $OpenPackages$ */ -/* $OpenBSD: make.h,v 1.31 2001/05/03 13:41:08 espie Exp $ */ +/* $OpenBSD: make.h,v 1.32 2001/05/23 12:34:46 espie Exp $ */ /* $NetBSD: make.h,v 1.15 1997/03/10 21:20:00 christos Exp $ */ /* @@ -42,418 +45,11 @@ * from: @(#)make.h 8.3 (Berkeley) 6/13/95 */ -/*- - * make.h -- - * The global definitions for pmake - */ - -#ifndef _MAKE_H_ -#define _MAKE_H_ - -#include <sys/types.h> -#include <sys/param.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#ifdef __GNUC__ -# define UNUSED __attribute__((__unused__)) -# define HAS_INLINES -# define INLINE __inline__ -#else -# define UNUSED -#endif - -#ifdef HAS_INLINES -# ifndef INLINE -# define INLINE inline -# endif -#endif - -#if !defined(MAKE_BOOTSTRAP) && defined(BSD4_4) -# include <sys/cdefs.h> -#endif - -#ifdef __STDC__ -#include <stdlib.h> -#include <unistd.h> -#endif -#include "sprite.h" -#include "lst.h" -#include "config.h" -#include "buf.h" - -#ifdef USE_TIMESPEC -#include <sys/time.h> -typedef struct timespec TIMESTAMP; -#define set_out_of_date(t) (t).tv_sec = INT_MIN, (t).tv_nsec = 0 -#define is_out_of_date(t) ((t).tv_sec == INT_MIN && (t).tv_nsec == 0) -#define grab_stat(s, t) \ -do { \ - (t).tv_sec = (s).st_mtime; \ - (t).tv_nsec = (s).st_mtimensec; \ - if (is_out_of_date(t)) \ - (t).tv_nsec++; \ -} while (0) -#define is_before(t1, t2) timespeccmp(&(t1), &(t2), <) -#define grab_date(d, t) \ -do { \ - (t).tv_sec = d; \ - (t).tv_nsec = 0; \ - if (is_out_of_date(t)) \ - (t).tv_nsec++; \ -} while (0) -#define grab(n) \ -do { \ - struct timeval tv; \ - gettimeofday(&tv, NULL); \ - TIMEVAL_TO_TIMESPEC(&(tv), &n); \ -} while (0) -#define timestamp2time_t(t) ((t).tv_sec) -#else -typedef time_t TIMESTAMP; -#define is_out_of_date(t) ((t) == INT_MIN) -#define set_out_of_date(t) (t) = INT_MIN -#define grab_stat(s, t) \ -do { \ - (t) = (s).st_mtime; \ - if (is_out_of_date(t)) \ - (t)++; \ -} while (0) -#define is_before(t1, t2) ((t1) < (t2)) -#define grab_date(d, t) \ -do { \ - (t) = d; \ - if (is_out_of_date(t)) \ - (t)++; \ -} while (0) -#define grab(n) time(&(n)) -#define timestamp2time_t(t) (t) -#endif - -/* local contexts are real small */ -#define TARGET_INDEX 0 -#define PREFIX_INDEX 1 -#define ARCHIVE_INDEX 2 -#define MEMBER_INDEX 3 -#define OODATE_INDEX 4 -#define ALLSRC_INDEX 5 -#define IMPSRC_INDEX 6 - -#define LOCAL_SIZE 7 - -/* extended indices for System V stuff */ -#define FTARGET_INDEX 7 -#define DTARGET_INDEX 8 -#define FPREFIX_INDEX 9 -#define DPREFIX_INDEX 10 -#define FARCHIVE_INDEX 11 -#define DARCHIVE_INDEX 12 -#define FMEMBER_INDEX 13 -#define DMEMBER_INDEX 14 - -#define EXTENDED2SIMPLE(i) (((i)-LOCAL_SIZE)/2) -#define IS_EXTENDED_F(i) ((i)%2 == 1) - -struct Var_; - -/* SymTable is private to var.c, but is declared here to allow for - local declaration of context tables - */ -typedef struct { - struct Var_ *locals[LOCAL_SIZE]; -} SymTable; - -typedef struct ohash GSymT; - -/*- - * The structure for an individual graph node. Each node has several - * pieces of data associated with it. - * 1) the name of the target it describes - * 2) the location of the target file in the file system. - * 3) the type of operator used to define its sources (qv. parse.c) - * 4) whether it is involved in this invocation of make - * 5) whether the target has been remade - * 6) whether any of its children has been remade - * 7) the number of its children that are, as yet, unmade - * 8) its modification time - * 9) the modification time of its youngest child (qv. make.c) - * 10) a list of nodes for which this is a source - * 11) a list of nodes on which this depends - * 12) a list of nodes that depend on this, as gleaned from the - * transformation rules. - * 13) a list of nodes of the same name created by the :: operator - * 14) a list of nodes that must be made (if they're made) before - * this node can be, but that do no enter into the datedness of - * this node. - * 15) a list of nodes that must be made (if they're made) after - * this node is, but that do not depend on this node, in the - * normal sense. - * 16) a Lst of ``local'' variables that are specific to this target - * and this target only (qv. var.c [$@ $< $?, etc.]) - * 17) a Lst of strings that are commands to be given to a shell - * to create this target. - */ -typedef struct GNode_ { - char *path; /* The full pathname of the file */ - int type; /* Its type (see the OP flags, below) */ - int order; /* Its wait weight */ - - Boolean make; /* TRUE if this target needs to be remade */ - enum { - UNMADE, BEINGMADE, MADE, UPTODATE, ERROR, ABORTED, - CYCLE, ENDCYCLE - } made; /* Set to reflect the state of processing - * on this node: - * UNMADE - Not examined yet - * BEINGMADE - Target is already being made. - * Indicates a cycle in the graph. (compat - * mode only) - * MADE - Was out-of-date and has been made - * UPTODATE - Was already up-to-date - * ERROR - An error occured while it was being - * made (used only in compat mode) - * ABORTED - The target was aborted due to - * an error making an inferior (compat). - * CYCLE - Marked as potentially being part of - * a graph cycle. If we come back to a - * node marked this way, it is printed - * and 'made' is changed to ENDCYCLE. - * ENDCYCLE - the cycle has been completely - * printed. Go back and unmark all its - * members. - */ - Boolean childMade; /* TRUE if one of this target's children was - * made */ - int unmade; /* The number of unmade children */ - - TIMESTAMP mtime; /* Its modification time */ - TIMESTAMP cmtime; /* The modification time of its youngest - * child */ - - LIST iParents; /* Links to parents for which this is an - * implied source, if any */ - LIST cohorts; /* Other nodes for the :: operator */ - LIST parents; /* Nodes that depend on this one */ - LIST children; /* Nodes on which this one depends */ - LIST successors; /* Nodes that must be made after this one */ - LIST preds; /* Nodes that must be made before this one */ - - SymTable context; /* The local variables */ - unsigned long lineno; /* First line number of commands. */ - const char * fname; /* File name of commands. */ - LIST commands; /* Creation commands */ - LstNode current; /* Current command, for job */ - - struct Suff_ *suffix; /* Suffix for the node (determined by - * Suff_FindDeps and opaque to everyone - * but the Suff module) */ - char name[1]; /* The target's name */ -} GNode; - -/* - * The OP_ constants are used when parsing a dependency line as a way of - * communicating to other parts of the program the way in which a target - * should be made. These constants are bitwise-OR'ed together and - * placed in the 'type' field of each node. Any node that has - * a 'type' field which satisfies the OP_NOP function was never never on - * the lefthand side of an operator, though it may have been on the - * righthand side... - */ -#define OP_DEPENDS 0x00000001 /* Execution of commands depends on - * kids (:) */ -#define OP_FORCE 0x00000002 /* Always execute commands (!) */ -#define OP_DOUBLEDEP 0x00000004 /* Execution of commands depends on kids - * per line (::) */ -#define OP_OPMASK (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP) - -#define OP_OPTIONAL 0x00000008 /* Don't care if the target doesn't - * exist and can't be created */ -#define OP_USE 0x00000010 /* Use associated commands for parents */ -#define OP_EXEC 0x00000020 /* Target is never out of date, but always - * execute commands anyway. Its time - * doesn't matter, so it has none...sort - * of */ -#define OP_IGNORE 0x00000040 /* Ignore errors when creating the node */ -#define OP_PRECIOUS 0x00000080 /* Don't remove the target when - * interrupted */ -#define OP_SILENT 0x00000100 /* Don't echo commands when executed */ -#define OP_MAKE 0x00000200 /* Target is a recurrsive make so its - * commands should always be executed when - * it is out of date, regardless of the - * state of the -n or -t flags */ -#define OP_JOIN 0x00000400 /* Target is out-of-date only if any of its - * children was out-of-date */ -#define OP_MADE 0x00000800 /* Assume the node is already made; even if - * it really is out of date */ -#define OP_INVISIBLE 0x00004000 /* The node is invisible to its parents. - * I.e. it doesn't show up in the parents's - * local variables. */ -#define OP_NOTMAIN 0x00008000 /* The node is exempt from normal 'main - * target' processing in parse.c */ -#define OP_PHONY 0x00010000 /* Not a file target; run always */ -#define OP_NOPATH 0x00020000 /* Don't search for file in the path */ -/* Attributes applied by PMake */ -#define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */ -#define OP_MEMBER 0x40000000 /* Target is a member of an archive */ -#define OP_LIB 0x20000000 /* Target is a library */ -#define OP_ARCHV 0x10000000 /* Target is an archive construct */ -#define OP_HAS_COMMANDS 0x08000000 /* Target has all the commands it should. - * Used when parsing to catch multiple - * commands for a target */ -#define OP_SAVE_CMDS 0x04000000 /* Saving commands on .END (Compat) */ -#define OP_DEPS_FOUND 0x02000000 /* Already processed by Suff_FindDeps */ - -/* - * OP_NOP will return TRUE if the node with the given type was not the - * object of a dependency operator - */ -#define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000) - -#define OP_NOTARGET (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM) - -/* - * The TARG_ constants are used when calling the Targ_FindNode functions targ.c. - * They simply tell the function what to do if the desired node is not found. - * If the TARG_CREATE constant is given, a new, empty node will be created - * for the target, placed in the table of all targets and its address returned. - * If TARG_NOCREATE is given, a NULL pointer will be returned. - */ -#define TARG_CREATE 0x01 /* create node if not found */ -#define TARG_NOCREATE 0x00 /* don't create it */ - -/* - * There are several places where expandable buffers are used (parse.c and - * var.c). This constant is merely the starting point for those buffers. If - * lines tend to be much shorter than this, it would be best to reduce BSIZE. - * If longer, it should be increased. Reducing it will cause more copying to - * be done for longer lines, but will save space for shorter ones. In any - * case, it ought to be a power of two simply because most storage allocation - * schemes allocate in powers of two. - */ -#define MAKE_BSIZE 256 /* starting size for expandable buffers */ - -/* - * Error levels for parsing. PARSE_FATAL means the process cannot continue - * once the makefile has been parsed. PARSE_WARNING means it can. Passed - * as the first argument to Parse_Error. - */ -#define PARSE_WARNING 2 -#define PARSE_FATAL 1 - -/* - * Values returned by Cond_Eval. - */ -#define COND_PARSE 0 /* Parse the next lines */ -#define COND_SKIP 1 /* Skip the next lines */ -#define COND_INVALID 2 /* Not a conditional statement */ - -/* - * Definitions for the "local" variables. Used only for clarity. - */ -#define TARGET "@" /* Target of dependency */ -#define OODATE "?" /* All out-of-date sources */ -#define ALLSRC ">" /* All sources */ -#define IMPSRC "<" /* Source implied by transformation */ -#define PREFIX "*" /* Common prefix */ -#define ARCHIVE "!" /* Archive in "archive(member)" syntax */ -#define MEMBER "%" /* Member in "archive(member)" syntax */ -#define LONGTARGET ".TARGET" -#define LONGOODATE ".OODATE" -#define LONGALLSRC ".ALLSRC" -#define LONGIMPSRC ".IMPSRC" -#define LONGPREFIX ".PREFIX" -#define LONGARCHIVE ".ARCHIVE" -#define LONGMEMBER ".MEMBER" - -/* System V extended variables (get directory/file part) */ -#define FTARGET "@F" -#define DTARGET "@D" -#define FIMPSRC "<F" -#define DIMPSRC "<D" -#define FPREFIX "*F" -#define DPREFIX "*D" -#define FARCHIVE "!F" -#define DARCHIVE "!D" -#define FMEMBER "%F" -#define DMEMBER "%D" - -/* - * Global Variables - */ -extern LIST create; /* The list of target names specified on the - * command line. used to resolve #if - * make(...) statements */ -extern LIST dirSearchPath; /* The list of directories to search when - * looking for targets */ - -extern Boolean compatMake; /* True if we are make compatible */ -extern Boolean ignoreErrors; /* True if should ignore all errors */ -extern Boolean beSilent; /* True if should print no commands */ -extern Boolean noExecute; /* True if should execute nothing */ -extern Boolean allPrecious; /* True if every target is precious */ -extern Boolean keepgoing; /* True if should continue on unaffected - * portions of the graph when have an error - * in one portion */ -extern Boolean touchFlag; /* TRUE if targets should just be 'touched' - * if out of date. Set by the -t flag */ -extern Boolean usePipes; /* TRUE if should capture the output of - * subshells by means of pipes. Otherwise it - * is routed to temporary files from which it - * is retrieved when the shell exits */ -extern Boolean queryFlag; /* TRUE if we aren't supposed to really make - * anything, just see if the targets are out- - * of-date */ - -extern Boolean checkEnvFirst; /* TRUE if environment should be searched for - * variables before the global context */ - -extern GNode *DEFAULT; /* .DEFAULT rule */ - -extern GSymT *VAR_GLOBAL; /* Variables defined in a global context, e.g - * in the Makefile itself */ -extern GSymT *VAR_CMD; /* Variables defined on the command line */ - -extern char var_Error[]; /* Value returned by Var_Parse when an error - * is encountered. It actually points to - * an empty string, so naive callers needn't - * worry about it. */ - -extern TIMESTAMP now; /* The time at the start of this whole - * process */ - -extern Boolean oldVars; /* Do old-style variable substitution */ - -extern LIST sysIncPath; /* The system include path. */ - -/* - * debug control: - * There is one bit per module. It is up to the module what debug - * information to print. - */ -extern int debug; -#define DEBUG_ARCH 0x0001 -#define DEBUG_COND 0x0002 -#define DEBUG_DIR 0x0004 -#define DEBUG_GRAPH1 0x0008 -#define DEBUG_GRAPH2 0x0010 -#define DEBUG_JOB 0x0020 -#define DEBUG_MAKE 0x0040 -#define DEBUG_SUFF 0x0080 -#define DEBUG_TARG 0x0100 -#define DEBUG_VAR 0x0200 -#define DEBUG_FOR 0x0400 -#define DEBUG_LOUD 0x0800 - -#ifdef __STDC__ -#define CONCAT(a,b) a##b -#else -#define I(a) a -#define CONCAT(a,b) I(a)b -#endif /* __STDC__ */ - -#define DEBUG(module) (debug & CONCAT(DEBUG_,module)) - -#include "extern.h" +extern void Make_TimeStamp(GNode *, GNode *); +extern bool Make_OODate(GNode *); +extern void Make_HandleUse(GNode *, GNode *); +extern void Make_Update(GNode *); +extern void Make_DoAllVar(GNode *); +extern bool Make_Run(Lst); #endif /* _MAKE_H_ */ diff --git a/usr.bin/make/memory.c b/usr.bin/make/memory.c new file mode 100644 index 00000000000..3abd1513a32 --- /dev/null +++ b/usr.bin/make/memory.c @@ -0,0 +1,189 @@ +/* $OpenPackages$ */ +/* $OpenBSD: memory.c,v 1.1 2001/05/23 12:34:47 espie Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * 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. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "defines.h" +#include "memory.h" + +static void enomem(size_t); + +/* + * emalloc -- + * malloc, but die on error. + */ +void * +emalloc(len) + size_t len; +{ + void *p; + + if ((p = malloc(len)) == NULL) + enomem(len); + return p; +} + +/* + * estrdup -- + * strdup, but die on error. + */ +char * +estrdup(str) + const char *str; +{ + char *p; + size_t size; + + size = strlen(str) + 1; + + p = emalloc(size); + memcpy(p, str, size); + return p; +} + +/* + * erealloc -- + * realloc, but die on error. + */ +void * +erealloc(ptr, size) + void *ptr; + size_t size; +{ + if ((ptr = realloc(ptr, size)) == NULL) + enomem(size); + return ptr; +} + +void * +ecalloc(s1, s2) + size_t s1; + size_t s2; +{ + void *p; + + if ((p = calloc(s1, s2)) == NULL) + enomem(s1 * s2); + return p; +} + +/* Support routines for hash tables. */ +void * +hash_alloc(s, u) + size_t s; + void *u UNUSED; +{ + return ecalloc(s, 1); +} + +void +hash_free(p, s, u) + void *p; + size_t s UNUSED; + void *u UNUSED; +{ + free(p); +} + +void * +element_alloc(s, u) + size_t s; + void *u UNUSED; +{ + return emalloc(s); +} + + + +/* + * enomem -- + * die when out of memory. + */ +void +enomem(size) + size_t size; +{ + fprintf(stderr, "make: %s (%lu)\n", strerror(errno), (u_long)size); + exit(2); +} + +/* + * esetenv -- + * change environment, die on error. + */ +void +esetenv(name, value) + const char *name; + const char *value; +{ + if (setenv(name, value, 1) == 0) + return; + + fprintf(stderr, "make: setenv failed (%s)\n", strerror(errno)); + exit(2); +} + + +/* + * enunlink -- + * Remove a file carefully, avoiding directories. + */ +int +eunlink(file) + const char *file; +{ + struct stat st; + + if (lstat(file, &st) == -1) + return -1; + + if (S_ISDIR(st.st_mode)) { + errno = EISDIR; + return -1; + } + return unlink(file); +} + diff --git a/usr.bin/make/sprite.h b/usr.bin/make/memory.h index c64799acec2..5d1e29fab74 100644 --- a/usr.bin/make/sprite.h +++ b/usr.bin/make/memory.h @@ -1,8 +1,10 @@ -/* $OpenPackages$ */ -/* $OpenBSD: sprite.h,v 1.10 2001/05/03 13:41:10 espie Exp $ */ -/* $NetBSD: sprite.h,v 1.6 1996/11/06 17:59:22 christos Exp $ */ +#ifndef MEMORY_H +#define MEMORY_H -/* +/* $OpenPackages$ */ +/* $OpenBSD: memory.h,v 1.1 2001/05/23 12:34:47 espie Exp $ */ + +/*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks @@ -39,24 +41,21 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)sprite.h 8.1 (Berkeley) 6/6/93 + * from: @(#)nonints.h 8.3 (Berkeley) 3/19/94 */ +extern void *emalloc(size_t); +extern char *estrdup(const char *); +extern void *erealloc(void *, size_t); +extern void *ecalloc(size_t, size_t); +extern int eunlink(const char *); +extern void esetenv(const char *, const char *); -#ifndef _SPRITE -#define _SPRITE - -/* Some basic types and definitions, originally from Sprite */ - -typedef int Boolean; -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif +/* efree(x) works when x==NULL. STDC behavior, may need some different + * definition for cross-builds on deficient systems */ +#define efree free -typedef int ReturnStatus; -#define SUCCESS 0 -#define FAILURE 1 +extern void *hash_alloc(size_t, void *); +extern void hash_free(void *, size_t, void *); +extern void *element_alloc(size_t, void *); -#endif /* _SPRITE */ +#endif /* MEMORY_H */ diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index 1f7e0b548ee..e71eac27ec2 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: parse.c,v 1.60 2001/05/15 12:52:15 espie Exp $ */ +/* $OpenBSD: parse.c,v 1.61 2001/05/23 12:34:47 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* @@ -66,82 +66,40 @@ * SUCH DAMAGE. */ -/*- - * parse.c -- - * Functions to parse a makefile. - * - * One function, Parse_Init, must be called before any functions - * in this module are used. After that, the function Parse_File is the - * main entry point and controls most of the other functions in this - * module. - * - * Most important structures are kept in Lsts. Directories for - * the #include "..." function are kept in the 'parseIncPath' Lst, while - * those for the #include <...> are kept in the 'sysIncPath' Lst. The - * targets currently being defined are kept in the 'targets' Lst. - * - * The variables 'fname' and 'lineno' are used to track the name - * of the current file and the line number in that file so that error - * messages can be more meaningful. - * - * Interface: - * Parse_Init Initialization function which must be - * called before anything else in this module - * is used. - * - * Parse_End Cleanup the module - * - * Parse_File Function used to parse a makefile. It must - * be given the name of the file, which should - * already have been opened, and a function - * to call to read a character from the file. - * - * Parse_IsVar Returns TRUE if the given line is a - * variable assignment. Used by MainParseArgs - * to determine if an argument is a target - * or a variable assignment. Used internally - * for pretty much the same thing... - * - * Parse_Error Function called when an error occurs in - * parsing. Used by the variable and - * conditional modules. - * Parse_MainName Returns a Lst of the main target to create. - */ - -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif #include <assert.h> -#include <stddef.h> -#include <stdio.h> #include <ctype.h> -#include <errno.h> -#include "make.h" -#include "ohash.h" +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "defines.h" #include "dir.h" #include "job.h" #include "buf.h" -#include "pathnames.h" +#include "for.h" #include "lowparse.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: parse.c,v 1.60 2001/05/15 12:52:15 espie Exp $"; -#endif -#endif /* not lint */ - -LIST parseIncPath; /* list of directories for "..." includes */ -LIST sysIncPath; /* list of directories for <...> includes */ +#include "arch.h" +#include "cond.h" +#include "suff.h" +#include "parse.h" +#include "var.h" +#include "targ.h" +#include "error.h" +#include "str.h" +#include "main.h" +#include "gnode.h" +#include "memory.h" +#include "extern.h" +#include "lst.h" +#include "parsevar.h" + +static LIST theParseIncPath;/* list of directories for "..." includes */ +static LIST theSysIncPath; /* list of directories for <...> includes */ +Lst sysIncPath = &theSysIncPath; +Lst parseIncPath = &theParseIncPath; static LIST targets; /* targets we're working on */ #ifdef CLEANUP static LIST targCmds; /* command lines for targets */ -static LIST fileNames; #endif static GNode *mainNode; /* The main target to create. This is the @@ -254,15 +212,13 @@ static void ParseHasCommands(void *); static void ParseDoInclude(char *); static void ParseTraditionalInclude(char *); static void ParseConditionalInclude(char *); -static void ParseLookupIncludeFile(char *, char *, Boolean, Boolean); -#define ParseGetLoopLine(linebuf) ParseGetLine(linebuf, "for loop") +static void ParseLookupIncludeFile(char *, char *, bool, bool); +#define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop") static void ParseFinishDependency(void); -static Boolean ParseIsCond(Buffer, Buffer, char *); +static bool ParseIsCond(Buffer, Buffer, char *); static char *strip_comments(Buffer, const char *); static void ParseDoCommands(const char *); -static const char *find_op1(const char *); -static const char *find_op2(const char *); /*- *---------------------------------------------------------------------- @@ -317,7 +273,7 @@ ParseLinkSrc(pgn, cgn) GNode *pgn; /* The parent node */ GNode *cgn; /* The child node */ { - if (Lst_AddNew(&pgn->children, cgn) == SUCCESS) { + if (Lst_AddNew(&pgn->children, cgn)) { if (specType == Not) Lst_AtEnd(&cgn->parents, pgn); pgn->unmade++; @@ -366,7 +322,7 @@ ParseDoOp(gnp, opp) GNode *cohort; LstNode ln; - cohort = Targ_NewGN(gn->name, NULL); + cohort = Targ_NewGN(gn->name); /* Duplicate links to parents so graph traversal is simple. Perhaps * some type bits should be duplicated? * @@ -470,14 +426,14 @@ ParseDoSrc(tOp, src, allsrc) /* * If we have noted the existence of a .MAIN, it means we need * to add the sources of said target to the list of things - * to create. The string 'src' is likely to be free, so we + * to create. The string 'src' is likely to be freed, so we * must make a new copy of it. Note that this will only be * invoked if the user didn't specify a target on the command * line. This is to allow #ifmake's to succeed, or something... */ - Lst_AtEnd(&create, estrdup(src)); + Lst_AtEnd(create, estrdup(src)); /* - * Add the name to the .TARGETS variable as well, so the user cna + * Add the name to the .TARGETS variable as well, so the user can * employ that, if desired. */ Var_Append(".TARGETS", src, VAR_GLOBAL); @@ -488,7 +444,7 @@ ParseDoSrc(tOp, src, allsrc) * Create proper predecessor/successor links between the previous * source and the current one. */ - gn = Targ_FindNode(src, NULL, TARG_CREATE); + gn = Targ_FindNode(src, TARG_CREATE); if (predecessor != NULL) { Lst_AtEnd(&predecessor->successors, gn); Lst_AtEnd(&gn->preds, predecessor); @@ -511,7 +467,7 @@ ParseDoSrc(tOp, src, allsrc) * the 'cohorts' list of the node) or all the cohorts are linked * to all the targets. */ - gn = Targ_FindNode(src, NULL, TARG_CREATE); + gn = Targ_FindNode(src, TARG_CREATE); if (tOp) { gn->type |= tOp; } else { @@ -589,7 +545,7 @@ ParseAddDir(path, name) void *path; void *name; { - Dir_AddDir((Lst)path, (char *)name, NULL); + Dir_AddDir((Lst)path, (char *)name); } /*- @@ -712,10 +668,10 @@ ParseDoDependency(line) * things like "archive(file1.o file2.o file3.o)" are permissible. * Arch_ParseArchive will set 'line' to be the first non-blank * after the archive-spec. It creates/finds nodes for the members - * and places them on the given list, returning SUCCESS if all - * went well and FAILURE if there was an error in the + * and places them on the given list, returning true if all + * went well and false if there was an error in the * specification. On error, line should remain untouched. */ - if (Arch_ParseArchive(&line, &targets, NULL) != SUCCESS) { + if (!Arch_ParseArchive(&line, &targets, NULL)) { Parse_Error(PARSE_FATAL, "Error in archive specification: \"%s\"", line); return; @@ -777,22 +733,22 @@ ParseDoDependency(line) */ switch (specType) { case ExPath: - Lst_AtEnd(&paths, &dirSearchPath); + Lst_AtEnd(&paths, dirSearchPath); break; case Main: - if (!Lst_IsEmpty(&create)) { + if (!Lst_IsEmpty(create)) { specType = Not; } break; case Begin: case End: case Interrupt: - gn = Targ_FindNode(line, NULL, TARG_CREATE); + gn = Targ_FindNode(line, TARG_CREATE); gn->type |= OP_NOTMAIN; Lst_AtEnd(&targets, gn); break; case Default: - gn = Targ_NewGN(".DEFAULT", NULL); + gn = Targ_NewGN(".DEFAULT"); gn->type |= OP_NOTMAIN|OP_TRANSFORM; Lst_AtEnd(&targets, gn); DEFAULT = gn; @@ -863,7 +819,7 @@ ParseDoDependency(line) while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) { if (!Suff_IsTransform(targName)) { - gn = Targ_FindNode(targName, NULL, TARG_CREATE); + gn = Targ_FindNode(targName, TARG_CREATE); } else { gn = Suff_AddTransform(targName); } @@ -881,11 +837,11 @@ ParseDoDependency(line) * allow on this line... */ if (specType != Not && specType != ExPath) { - Boolean warn = FALSE; + bool warn = false; while (*cp != '!' && *cp != ':' && *cp) { if (*cp != ' ' && *cp != '\t') { - warn = TRUE; + warn = true; } cp++; } @@ -965,13 +921,13 @@ ParseDoDependency(line) Suff_ClearSuffixes(); break; case Precious: - allPrecious = TRUE; + allPrecious = true; break; case Ignore: - ignoreErrors = TRUE; + ignoreErrors = true; break; case Silent: - beSilent = TRUE; + beSilent = true; break; case ExPath: Lst_Every(&paths, ParseClearPath); @@ -988,7 +944,7 @@ ParseDoDependency(line) Main_ParseArgLine(line); *line = '\0'; } else if (specType == ExShell) { - if (Job_ParseShell(line) != SUCCESS) { + if (!Job_ParseShell(line)) { Parse_Error(PARSE_FATAL, "improper shell specification"); return; } @@ -1090,7 +1046,7 @@ ParseDoDependency(line) * expansion */ Lst_Init(&sources); - if (Arch_ParseArchive(&line, &sources, NULL) != SUCCESS) { + if (!Arch_ParseArchive(&line, &sources, NULL)) { Parse_Error(PARSE_FATAL, "Error in source archive spec \"%s\"", line); return; @@ -1127,241 +1083,6 @@ ParseDoDependency(line) } /*- - *--------------------------------------------------------------------- - * Parse_IsVar -- - * Return TRUE if the passed line is a variable assignment. A variable - * assignment consists of a single word followed by optional whitespace - * followed by either a += or an = operator. - * This function is used both by the Parse_File function and main when - * parsing the command-line arguments. - * - * Results: - * TRUE if it is. FALSE if it ain't - *--------------------------------------------------------------------- - */ -Boolean -Parse_IsVar(line) - char *line; /* the line to check */ -{ - Boolean wasSpace = FALSE; /* set TRUE if found a space */ - Boolean haveName = FALSE; /* Set TRUE if have a variable name */ - int level = 0; -#define ISEQOPERATOR(c) \ - ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') - - for (; *line != '=' || level != 0; line++) - switch (*line) { - case '\0': - /* end-of-line -- can't be a variable assignment. */ - return FALSE; - - case ' ': - case '\t': - /* - * there can be as much white space as desired so long as there is - * only one word before the operator - */ - wasSpace = TRUE; - break; - - case '(': - case '{': - level++; - break; - - case '}': - case ')': - level--; - break; - - default: - if (wasSpace && haveName) { - if (ISEQOPERATOR(*line)) { - /* We must have a finished word. */ - if (level != 0) - return FALSE; - - /* When an = operator [+?!:] is found, the next - * character must be an = or it ain't a valid - * assignment. */ - if (line[1] == '=') - return haveName; - /* This is a shell command. */ - if (FEATURES(FEATURE_SUNSHCMD) && - strncmp(line, ":sh", 3) == 0) - return haveName; - } - /* This is the start of another word, so not assignment. */ - return FALSE; - } - else { - haveName = TRUE; - wasSpace = FALSE; - } - break; - } - - return haveName; -} - -static const char * -find_op1(p) - const char *p; -{ - for(;; p++) { - if (*p == '=' || isspace(*p) || *p == '$') - break; - if (p[1] == '=' && (*p == '?' || *p == ':' || *p == '!' || *p == '+')) - break; - if (p[0] == ':' && p[1] == 's' && p[2] == 'h') - break; - } - return p; -} - -static const char * -find_op2(p) - const char *p; -{ - for(;; p++) { - if (*p == '=' || isspace(*p) || *p == '$') - break; - if (p[1] == '=' && (*p == '?' || *p == ':' || *p == '!' || *p == '+')) - break; - } - return p; -} - -/*- - *--------------------------------------------------------------------- - * Parse_DoVar -- - * Take the variable assignment in the passed line and do it in the - * global context. - * - * Note: There is a lexical ambiguity with assignment modifier characters - * in variable names. This routine interprets the character before the = - * as a modifier. Therefore, an assignment like - * C++=/usr/bin/CC - * is interpreted as "C+ +=" instead of "C++ =". - * - * Side Effects: - * the variable structure of the given variable name is altered in the - * global context. - *--------------------------------------------------------------------- - */ -void -Parse_DoVar(line, ctxt) - const char *line; /* a line guaranteed to be a variable - * assignment. This reduces error checks */ - GSymT *ctxt; /* Context in which to do the assignment */ -{ - const char *end; - const char *arg; - enum { - VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL - } type; /* Type of assignment */ - struct Name name; - - end = Var_Name_Get(line, &name, (SymTable *)ctxt, TRUE, - FEATURES(FEATURE_SUNSHCMD) ? find_op1 : find_op2); - - while (isspace(*end)) - end++; - - /* Check operator type. */ - switch (*end) { - case '+': - type = VAR_APPEND; - break; - - case '?': - /* If the variable already has a value, we don't do anything. */ - if (Var_Value_interval(name.s, name.e) != NULL) { - Var_Name_Free(&name); - return; - } - type = VAR_NORMAL; - break; - - case ':': - if (FEATURES(FEATURE_SUNSHCMD) && strncmp(end, ":sh", 3) == 0) - type = VAR_SHELL; - else - type = VAR_SUBST; - break; - - case '!': - type = VAR_SHELL; - break; - - default: - type = VAR_NORMAL; - break; - } - - /* Find operator itself and go over it. */ - arg = end; - while (*arg != '=') - arg++; - arg++; - while (isspace(*arg)) - arg++; - - if (type == VAR_APPEND) - Var_Append_interval(name.s, name.e, arg, ctxt); - else if (type == VAR_SUBST) { - char *sub; - /* - * Allow variables in the old value to be undefined, but leave their - * invocation alone -- this is done by forcing oldVars to be false. - * XXX: This can cause recursive variables, but that's not hard to do, - * and this allows someone to do something like - * - * CFLAGS = $(.INCLUDES) - * CFLAGS := -I.. $(CFLAGS) - * - * And not get an error. - */ - Boolean oldOldVars = oldVars; - - oldVars = FALSE; - /* ensure the variable is set to something to avoid `variable - * is recursive' errors. */ - if (Var_Value_interval(name.s, name.e) == NULL) - Var_Set_interval(name.s, name.e, "", ctxt); - - sub = Var_Subst(arg, (SymTable *)ctxt, FALSE); - oldVars = oldOldVars; - - Var_Set_interval(name.s, name.e, sub, ctxt); - free(sub); - } else if (type == VAR_SHELL) { - char *res, *err; - - if (strchr(arg, '$') != NULL) { - char *sub; - /* There's a dollar sign in the command, so perform variable - * expansion on the whole thing. */ - sub = Var_Subst(arg, NULL, TRUE); - res = Cmd_Exec(sub, &err); - free(sub); - } else - res = Cmd_Exec(arg, &err); - - Var_Set_interval(name.s, name.e, res, ctxt); - free(res); - - if (err) - Parse_Error(PARSE_WARNING, err, arg); - - } else - /* Normal assignment -- just do it. */ - Var_Set_interval(name.s, name.e, arg, ctxt); - Var_Name_Free(&name); -} - - -/*- * ParseAddCmd -- * Lst_ForEach function to add a command line to all targets * @@ -1417,7 +1138,7 @@ void Parse_AddIncludeDir(dir) const char *dir; /* The name of the directory to add */ { - Dir_AddDir(&parseIncPath, dir, NULL); + Dir_AddDir(parseIncPath, dir); } /*- @@ -1441,7 +1162,7 @@ ParseDoInclude(file) { char endc; /* the character which ends the file spec */ char *cp; /* current position in file spec */ - Boolean isSystem; /* TRUE if makefile is a system makefile */ + bool isSystem; /* true if makefile is a system makefile */ /* Skip to delimiter character so we know where to look. */ while (*file == ' ' || *file == '\t') @@ -1457,10 +1178,10 @@ ParseDoInclude(file) * characters which bracket its name. Angle-brackets imply it's * a system Makefile while double-quotes imply it's a user makefile */ if (*file == '<') { - isSystem = TRUE; + isSystem = true; endc = '>'; } else { - isSystem = FALSE; + isSystem = false; endc = '"'; } @@ -1473,7 +1194,7 @@ ParseDoInclude(file) return; } } - ParseLookupIncludeFile(file, cp, isSystem, TRUE); + ParseLookupIncludeFile(file, cp, isSystem, true); } /*- @@ -1509,7 +1230,7 @@ ParseTraditionalInclude(file) for (cp = file; *cp != '\0' && !isspace(*cp);) cp++; - ParseLookupIncludeFile(file, cp, TRUE, TRUE); + ParseLookupIncludeFile(file, cp, true, true); } /*- @@ -1539,7 +1260,7 @@ ParseConditionalInclude(file) for (cp = file; *cp != '\0' && !isspace(*cp);) cp++; - ParseLookupIncludeFile(file, cp, TRUE, FALSE); + ParseLookupIncludeFile(file, cp, true, false); } /* Common part to lookup and read an include file. */ @@ -1547,8 +1268,8 @@ static void ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound) char *spec; char *endSpec; - Boolean isSystem; - Boolean errIfNotFound; + bool isSystem; + bool errIfNotFound; { char *file; char *fullname; @@ -1558,7 +1279,7 @@ ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound) * find the thing. */ endc = *endSpec; *endSpec = '\0'; - file = Var_Subst(spec, NULL, FALSE); + file = Var_Subst(spec, NULL, false); *endSpec = endc; /* Now that we know the file name and its search path, we attempt to @@ -1572,18 +1293,19 @@ ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound) * location. We don't want to cd there, of course, so we * just tack on the old file's leading path components * and call Dir_FindFile to see if we can locate the beast. */ - char *slash; + char *slash; + const char *fname; - slash = strrchr(Parse_Getfilename(), '/'); + fname = Parse_Getfilename(); + + slash = strrchr(fname, '/'); if (slash != NULL) { - char *base, *newName; + char *newName; - base = interval_dup(Parse_Getfilename(), slash); - newName = str_concat(base, file, '/'); - free(base); - fullname = Dir_FindFile(newName, &parseIncPath); + newName = Str_concati(fname, slash, file, strchr(file, '\0'), '/'); + fullname = Dir_FindFile(newName, parseIncPath); if (fullname == NULL) - fullname = Dir_FindFile(newName, &dirSearchPath); + fullname = Dir_FindFile(newName, dirSearchPath); free(newName); } } @@ -1592,14 +1314,14 @@ ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound) * search path, if not found in a -I directory. * XXX: Suffix specific? */ if (fullname == NULL) - fullname = Dir_FindFile(file, &parseIncPath); + fullname = Dir_FindFile(file, parseIncPath); if (fullname == NULL) - fullname = Dir_FindFile(file, &dirSearchPath); + fullname = Dir_FindFile(file, dirSearchPath); /* Still haven't found the makefile. Look for it on the system * path as a last resort. */ if (fullname == NULL) - fullname = Dir_FindFile(file, &sysIncPath); + fullname = Dir_FindFile(file, sysIncPath); if (fullname == NULL && errIfNotFound) Parse_Error(PARSE_FATAL, "Could not find %s", file); @@ -1646,7 +1368,7 @@ strip_comments(copy, line) for (p = line; *p != '\0'; p++) { if (*p == '\\') { if (p[1] == '#') { - Buf_AddInterval(copy, line, p); + Buf_Addi(copy, line, p); Buf_AddChar(copy, '#'); line = p+2; } @@ -1655,13 +1377,13 @@ strip_comments(copy, line) } else if (*p == '#') break; } - Buf_AddInterval(copy, line, p); + Buf_Addi(copy, line, p); Buf_KillTrailingSpaces(copy); return Buf_Retrieve(copy); } } -static Boolean +static bool ParseIsCond(linebuf, copy, line) Buffer linebuf; Buffer copy; @@ -1679,7 +1401,7 @@ ParseIsCond(linebuf, copy, line) case COND_SKIP: /* Skip to next conditional that evaluates to COND_PARSE. */ do { - line = ParseSkipGetLine(linebuf); + line = Parse_ReadNextConditionalLine(linebuf); if (line != NULL) { while (*line != '\0' && isspace(*line)) line++; @@ -1688,7 +1410,7 @@ ParseIsCond(linebuf, copy, line) } while (line != NULL && Cond_Eval(stripped) != COND_PARSE); /* FALLTHROUGH */ case COND_PARSE: - return TRUE; + return true; default: break; } @@ -1698,25 +1420,25 @@ ParseIsCond(linebuf, copy, line) loop = For_Eval(line); if (loop != NULL) { - Boolean ok; + bool ok; do { /* Find the matching endfor. */ - line = ParseGetLoopLine(linebuf); + line = ParseReadLoopLine(linebuf); if (line == NULL) { Parse_Error(PARSE_FATAL, "Unexpected end of file in for loop.\n"); - return FALSE; + return false; } ok = For_Accumulate(loop, line); } while (ok); For_Run(loop); - return TRUE; + return true; } } if (strncmp(line, "include", 7) == 0) { ParseDoInclude(line + 7); - return TRUE; + return true; } else if (strncmp(line, "undef", 5) == 0) { char *cp; @@ -1727,9 +1449,9 @@ ParseIsCond(linebuf, copy, line) cp++; *cp = '\0'; Var_Delete(line); - return TRUE; + return true; } - return FALSE; + return false; } /*- @@ -1763,26 +1485,14 @@ ParseDoCommands(line) #endif } -/*- - *--------------------------------------------------------------------- - * Parse_File -- - * Parse a file into its component parts, incorporating it into the - * current dependency graph. This is the main function and controls - * almost every other function in this module - * - * Side Effects: - * Loads. Nodes are added to the list of all targets, nodes and links - * are added to the dependency graph. etc. etc. etc. - *--------------------------------------------------------------------- - */ void Parse_File(name, stream) - char *name; /* the name of the file being read */ + const char *name; /* the name of the file being read */ FILE *stream; /* Stream open to makefile to parse */ { char *cp, /* pointer into the line */ *line; /* the line we're working on */ - Boolean inDependency; /* true if currently in a dependency + bool inDependency; /* true if currently in a dependency * line or its commands */ BUFFER buf; @@ -1790,11 +1500,11 @@ Parse_File(name, stream) Buf_Init(&buf, MAKE_BSIZE); Buf_Init(©, MAKE_BSIZE); - inDependency = FALSE; + inDependency = false; Parse_FromFile(name, stream); do { - while ((line = ParseReadLine(&buf)) != NULL) { + while ((line = Parse_ReadNormalLine(&buf)) != NULL) { if (*line == '\t') { if (inDependency) ParseDoCommands(line+1); @@ -1824,16 +1534,15 @@ Parse_File(name, stream) if (inDependency) ParseFinishDependency(); - if (Parse_IsVar(stripped)) { - inDependency = FALSE; - Parse_DoVar(stripped, VAR_GLOBAL); - } else { + if (Parse_DoVar(stripped, VAR_GLOBAL)) + inDependency = false; + else { size_t pos; char *end; /* Need a new list for the target nodes. */ Lst_Init(&targets); - inDependency = TRUE; + inDependency = true; dep = NULL; /* First we need to find eventual dependencies */ @@ -1854,7 +1563,7 @@ Parse_File(name, stream) * have all variables expanded before being parsed. * Tell the variable module to complain if some * variable is undefined... */ - cp = Var_Subst(stripped, NULL, TRUE); + cp = Var_Subst(stripped, NULL, true); ParseDoDependency(cp); free(cp); @@ -1877,58 +1586,37 @@ Parse_File(name, stream) /* Make sure conditionals are clean. */ Cond_End(); - Finish_Errors(); + Parse_ReportErrors(); Buf_Destroy(&buf); Buf_Destroy(©); } -/*- - *--------------------------------------------------------------------- - * Parse_Init -- - * initialize the parsing module - * - * Side Effects: - * the parseIncPath list is initialized... - *--------------------------------------------------------------------- - */ void Parse_Init() { mainNode = NULL; - Lst_Init(&parseIncPath); - Lst_Init(&sysIncPath); + Lst_Init(parseIncPath); + Lst_Init(sysIncPath); Lst_Init(&targets); -#ifdef CLEANUP LowParse_Init(); +#ifdef CLEANUP Lst_Init(&targCmds); - Lst_Init(&fileNames); #endif } +#ifdef CLEANUP void Parse_End() { -#ifdef CLEANUP Lst_Destroy(&targCmds, (SimpleProc)free); - Lst_Destroy(&fileNames, (SimpleProc)free); Lst_Destroy(&targets, NOFREE); - Lst_Destroy(&sysIncPath, Dir_Destroy); - Lst_Destroy(&parseIncPath, Dir_Destroy); + Lst_Destroy(sysIncPath, Dir_Destroy); + Lst_Destroy(parseIncPath, Dir_Destroy); LowParse_End(); -#endif } +#endif -/*- - *----------------------------------------------------------------------- - * Parse_MainName -- - * Return a Lst of the main target to create for main()'s sake. If - * no such target exists, we Punt with an obnoxious error message. - * - * Side effect: - * Add the node to create to the list. - *----------------------------------------------------------------------- - */ void Parse_MainName(listmain) Lst listmain; /* result list */ diff --git a/usr.bin/make/parse.h b/usr.bin/make/parse.h new file mode 100644 index 00000000000..95d5802c5a0 --- /dev/null +++ b/usr.bin/make/parse.h @@ -0,0 +1,60 @@ +#ifndef PARSE_H +#define PARSE_H +/* $OpenPackages$ */ +/* $OpenBSD: parse.h,v 1.1 2001/05/23 12:34:47 espie Exp $ */ +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* parse + * Functions to parse Makefiles and fragments. + */ + +extern void Parse_Init(void); +#ifdef CLEANUP +extern void Parse_End(void); +#else +#define Parse_End() +#endif + +extern Lst sysIncPath; /* The system include<> path. */ +extern Lst parseIncPath; /* The user include"" path. */ + +/* Parse_File(filename, filehandle); + * Parses stream filehandle, use filename when reporting error + * messages. Builds a graph of GNode and Suffixes. This modules + * acquires ownership of the filename and filehandle, and will + * close/free them when it sees fit. */ +extern void Parse_File(const char *, FILE *); + +/* Parse_AddIncludeDir(dir); + * Adds directory dir to user include"" path (copy the string). */ +extern void Parse_AddIncludeDir(const char *); + +/* Parse_MainName(lst); + * Adds set of main targets to create to list lst. Errors out if no + * target exists. */ +extern void Parse_MainName(Lst); + +#endif diff --git a/usr.bin/make/parsevar.c b/usr.bin/make/parsevar.c new file mode 100644 index 00000000000..a6dba3803de --- /dev/null +++ b/usr.bin/make/parsevar.c @@ -0,0 +1,210 @@ +/* $OpenPackages$ */ +/* $OpenBSD: parsevar.c,v 1.1 2001/05/23 12:34:48 espie Exp $ */ +/* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +#include <ctype.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "var.h" +#include "varname.h" +#include "error.h" +#include "cmd_exec.h" +#include "parsevar.h" + +static const char *find_op1(const char *); +static const char *find_op2(const char *); + +static const char * +find_op1(p) + const char *p; +{ + for(;; p++) { + if (isspace(*p) || *p == '$' || *p == '\0') + break; + if (p[strspn(p, "?:!+")] == '=') + break; + if (p[0] == ':' && p[1] == 's' && p[2] == 'h') + break; + } + return p; +} + +static const char * +find_op2(p) + const char *p; +{ + for(;; p++) { + if (isspace(*p) || *p == '$' || *p == '\0') + break; + if (p[strspn(p, "?:!+")] == '=') + break; + } + return p; +} + +bool +Parse_DoVar(line, ctxt) + const char *line; + GSymT *ctxt; /* Context in which to do the assignment */ +{ + const char *arg; + char *res1 = NULL, *res2 = NULL; +#define VAR_NORMAL 0 +#define VAR_SUBST 1 +#define VAR_APPEND 2 +#define VAR_SHELL 4 +#define VAR_OPT 8 + int type; /* Type of assignment */ + struct Name name; + + arg = VarName_Get(line, &name, (SymTable *)ctxt, true, + FEATURES(FEATURE_SUNSHCMD) ? find_op1 : find_op2); + + while (isspace(*arg)) + arg++; + + type = VAR_NORMAL; + + while (*arg != '=' && !isspace(*arg)) { + /* Check operator type. */ + switch (*arg++) { + case '+': + if (type & (VAR_OPT|VAR_APPEND)) { + VarName_Free(&name); + return false; + } + type |= VAR_APPEND; + break; + + case '?': + if (type & (VAR_OPT|VAR_APPEND)) { + VarName_Free(&name); + return false; + } + type |= VAR_OPT; + break; + + case ':': + if (FEATURES(FEATURE_SUNSHCMD) && strncmp(arg, "sh", 2) == 0) { + type = VAR_SHELL; + arg += 2; + while (*arg != '=' && *arg != '\0') + arg++; + } else { + if (type & VAR_SUBST) { + VarName_Free(&name); + return false; + } + type |= VAR_SUBST; + } + break; + + case '!': + if (type & VAR_SHELL) { + VarName_Free(&name); + return false; + } + type |= VAR_SHELL; + break; + + default: + VarName_Free(&name); + return false; + } + } + + /* Check validity of operator */ + if (*arg++ != '=') { + VarName_Free(&name); + return false; + } + + while (isspace(*arg)) + arg++; + /* If the variable already has a value, we don't do anything. */ + if ((type & VAR_OPT) && Var_Valuei(name.s, name.e) != NULL) { + VarName_Free(&name); + return true; + } + if (type & VAR_SHELL) { + char *err; + + if (strchr(arg, '$') != NULL) { + char *sub; + /* There's a dollar sign in the command, so perform variable + * expansion on the whole thing. */ + sub = Var_Subst(arg, NULL, true); + res1 = Cmd_Exec(sub, &err); + free(sub); + } else + res1 = Cmd_Exec(arg, &err); + + if (err) + Parse_Error(PARSE_WARNING, err, arg); + arg = res1; + } + if (type & VAR_SUBST) { + /* + * Allow variables in the old value to be undefined, but leave their + * invocation alone -- this is done by forcing oldVars to be false. + * XXX: This can cause recursive variables, but that's not hard to do, + * and this allows someone to do something like + * + * CFLAGS = $(.INCLUDES) + * CFLAGS := -I.. $(CFLAGS) + * + * And not get an error. + */ + bool oldOldVars = oldVars; + + oldVars = false; + /* ensure the variable is set to something to avoid `variable + * is recursive' errors. */ + if (Var_Valuei(name.s, name.e) == NULL) + Var_Seti(name.s, name.e, "", ctxt); + + res2 = Var_Subst(arg, (SymTable *)ctxt, false); + oldVars = oldOldVars; + + arg = res2; + } + + if (type & VAR_APPEND) + Var_Appendi(name.s, name.e, arg, ctxt); + else + Var_Seti(name.s, name.e, arg, ctxt); + + VarName_Free(&name); + free(res2); + free(res1); + return true; +} + diff --git a/usr.bin/make/parsevar.h b/usr.bin/make/parsevar.h new file mode 100644 index 00000000000..95df3ff2d30 --- /dev/null +++ b/usr.bin/make/parsevar.h @@ -0,0 +1,39 @@ +#ifndef PARSEVAR_H +#define PARSEVAR_H +/* $OpenPackages$ */ +/* $OpenBSD: parsevar.h,v 1.1 2001/05/23 12:34:48 espie Exp $ */ +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* parsevar + * Functions to parse variable assignments + */ + +/* wasvar = Parse_DoVar(str, ctxt); + * Parses variable assignment str and adds it to context ctxt. + * Returns false if this is something else. */ +extern bool Parse_DoVar(const char *, GSymT *); + +#endif diff --git a/usr.bin/make/pathnames.h b/usr.bin/make/pathnames.h index 2649cac31fc..30786672f49 100644 --- a/usr.bin/make/pathnames.h +++ b/usr.bin/make/pathnames.h @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: pathnames.h,v 1.8 2001/05/03 13:41:09 espie Exp $ */ +/* $OpenBSD: pathnames.h,v 1.9 2001/05/23 12:34:48 espie Exp $ */ /* $NetBSD: pathnames.h,v 1.6 1996/11/06 17:59:21 christos Exp $ */ /* @@ -37,6 +37,12 @@ * from: @(#)pathnames.h 5.2 (Berkeley) 6/1/90 */ +#ifdef HAS_PATH_H +# include <paths.h> +#endif +#ifndef _PATH_BSHELL +# define _PATH_BSHELL "/bin/sh" +#endif #ifndef _PATH_OBJDIR #define _PATH_OBJDIR "obj" #endif /* !_PATH_OBJDIR */ diff --git a/usr.bin/make/regress.c b/usr.bin/make/regress.c index 0a12f90f2f9..cfd5502aef6 100644 --- a/usr.bin/make/regress.c +++ b/usr.bin/make/regress.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: regress.c,v 1.3 2001/05/03 13:41:10 espie Exp $ */ +/* $OpenBSD: regress.c,v 1.4 2001/05/23 12:34:48 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -29,8 +29,10 @@ */ /* regression tests */ -#include "make.h" #include <stdio.h> +#include <string.h> +#include "defines.h" +#include "str.h" int main(void); #define CHECK(s) \ @@ -49,25 +51,25 @@ main() { unsigned int errors = 0; - CHECK(Str_Match("string", "string") == TRUE); - CHECK(Str_Match("string", "string2") == FALSE); - CHECK(Str_Match("string", "string*") == TRUE); - CHECK(Str_Match("Long string", "Lo*ng") == TRUE); - CHECK(Str_Match("Long string", "Lo*ng ") == FALSE); - CHECK(Str_Match("Long string", "Lo*ng *") == TRUE); - CHECK(Str_Match("string", "stri?g") == TRUE); - CHECK(Str_Match("str?ng", "str\\?ng") == TRUE); - CHECK(Str_Match("striiiing", "str?*ng") == TRUE); - CHECK(Str_Match("Very long string just to see", "******a****") == FALSE); - CHECK(Str_Match("d[abc?", "d\\[abc\\?") == TRUE); - CHECK(Str_Match("d[abc!", "d\\[abc\\?") == FALSE); - CHECK(Str_Match("dwabc?", "d\\[abc\\?") == FALSE); - CHECK(Str_Match("da0", "d[bcda]0") == TRUE); - CHECK(Str_Match("da0", "d[z-a]0") == TRUE); - CHECK(Str_Match("d-0", "d[-a-z]0") == TRUE); - CHECK(Str_Match("dy0", "d[a\\-z]0") == FALSE); - CHECK(Str_Match("d-0", "d[a\\-z]0") == TRUE); - CHECK(Str_Match("dz0", "d[a\\]z]0") == TRUE); + CHECK(Str_Match("string", "string") == true); + CHECK(Str_Match("string", "string2") == false); + CHECK(Str_Match("string", "string*") == true); + CHECK(Str_Match("Long string", "Lo*ng") == true); + CHECK(Str_Match("Long string", "Lo*ng ") == false); + CHECK(Str_Match("Long string", "Lo*ng *") == true); + CHECK(Str_Match("string", "stri?g") == true); + CHECK(Str_Match("str?ng", "str\\?ng") == true); + CHECK(Str_Match("striiiing", "str?*ng") == true); + CHECK(Str_Match("Very long string just to see", "******a****") == false); + CHECK(Str_Match("d[abc?", "d\\[abc\\?") == true); + CHECK(Str_Match("d[abc!", "d\\[abc\\?") == false); + CHECK(Str_Match("dwabc?", "d\\[abc\\?") == false); + CHECK(Str_Match("da0", "d[bcda]0") == true); + CHECK(Str_Match("da0", "d[z-a]0") == true); + CHECK(Str_Match("d-0", "d[-a-z]0") == true); + CHECK(Str_Match("dy0", "d[a\\-z]0") == false); + CHECK(Str_Match("d-0", "d[a\\-z]0") == true); + CHECK(Str_Match("dz0", "d[a\\]z]0") == true); if (errors != 0) printf("Errors: %d\n", errors); diff --git a/usr.bin/make/stats.c b/usr.bin/make/stats.c index 6a97d807d55..25b2f1a6731 100644 --- a/usr.bin/make/stats.c +++ b/usr.bin/make/stats.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: stats.c,v 1.1 2001/05/03 13:41:10 espie Exp $ */ +/* $OpenBSD: stats.c,v 1.2 2001/05/23 12:34:49 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -35,7 +35,8 @@ to allow for concurrent adjustment to variables. */ -#include "make.h" +#include "config.h" +#include "defines.h" #include "stats.h" #ifdef HAS_STATS @@ -50,7 +51,7 @@ void Init_Stats(void); static float average_runs(unsigned long val); unsigned long *statarray; -static Boolean mmapped = FALSE; +static bool mmapped = false; static float average_runs(val) @@ -154,7 +155,7 @@ Init_Stats() PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (statarray == MAP_FAILED) exit(1); - mmapped = TRUE; + mmapped = true; } } else /* or we don't -> simple stats gathering */ diff --git a/usr.bin/make/stats.h b/usr.bin/make/stats.h index 546e68fad77..8de9a120d7e 100644 --- a/usr.bin/make/stats.h +++ b/usr.bin/make/stats.h @@ -1,5 +1,7 @@ +#ifndef STAT_H +#define STAT_H /* $OpenPackages$ */ -/* $OpenBSD: stats.h,v 1.1 2001/05/03 13:41:11 espie Exp $ */ +/* $OpenBSD: stats.h,v 1.2 2001/05/23 12:34:49 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -38,6 +40,8 @@ #endif #ifdef HAS_STATS +extern void Init_Stats(void); + extern unsigned long *statarray; #define STAT_INVOCATIONS statarray[0] #define STAT_VAR_SEARCHES statarray[1] @@ -70,5 +74,8 @@ extern unsigned long *statarray; #define STAT_NUMBER 30 +#else +#define Init_Stats() #endif +#endif diff --git a/usr.bin/make/str.c b/usr.bin/make/str.c index bd01d0c4466..c1f2abec2e0 100644 --- a/usr.bin/make/str.c +++ b/usr.bin/make/str.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: str.c,v 1.18 2001/05/07 22:54:53 espie Exp $ */ +/* $OpenBSD: str.c,v 1.19 2001/05/23 12:34:49 espie Exp $ */ /* $NetBSD: str.c,v 1.13 1996/11/06 17:59:23 christos Exp $ */ /*- @@ -40,34 +40,24 @@ * SUCH DAMAGE. */ -#include "make.h" +#include <ctype.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "str.h" +#include "memory.h" +#include "buf.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: str.c,v 1.18 2001/05/07 22:54:53 espie Exp $"; -#endif -#endif /* not lint */ - -/*- - * str_concati -- - * concatenate the two strings, possibly inserting a separator - * - * returns -- - * the resulting string in allocated space. - */ char * -str_concati(s1, s2, e2, sep) - const char *s1, *s2, *e2; +Str_concati(s1, e1, s2, e2, sep) + const char *s1, *e1, *s2, *e2; int sep; { size_t len1, len2; char *result; /* get the length of both strings */ - len1 = strlen(s1); + len1 = e1 - s1; len2 = e2 - s2; /* space for separator */ @@ -208,15 +198,7 @@ done: return argv; } -/* Iterate through a string word by word, - * without needing to copy anything. - * More light-weight than brk_string, handles \ ' " as well. - * - * position = s; - * while ((begin = iterate_words(&position)) != NULL) { - * do_something_with_word_interval(begin, position); - * } - */ + const char * iterate_words(end) const char **end; @@ -256,18 +238,10 @@ iterate_words(end) } } -/* - * Str_Matchi -- - * - * See if a particular string matches a particular pattern. - * - * Results: TRUE is returned if string matches pattern, FALSE otherwise. The - * matching operation permits the following special characters in the - * pattern: *?\[] (see the man page for details on what these mean). - */ -Boolean -Str_Matchi(string, pattern, end) +bool +Str_Matchi(string, estring, pattern, end) const char *string; /* String */ + const char *estring; /* End of string */ const char *pattern; /* Pattern */ const char *end; /* End of Pattern */ { @@ -282,52 +256,52 @@ Str_Matchi(string, pattern, end) * calls only occur on `real' characters. */ while (pattern != end && (*pattern == '?' || *pattern == '*')) { if (*pattern == '?') { - if (*string == '\0') - return FALSE; + if (string == estring) + return false; else string++; } pattern++; } if (pattern == end) - return TRUE; - for (; *string != '\0'; string++) - if (Str_Matchi(string, pattern, end)) - return TRUE; - return FALSE; - } else if (*string == '\0') - return FALSE; + return true; + for (; string != estring; string++) + if (Str_Matchi(string, estring, pattern, end)) + return true; + return false; + } else if (string == estring) + return false; /* Check for a "[" as the next pattern character. It is * followed by a list of characters that are acceptable, or * by a range (two characters separated by "-"). */ else if (*pattern == '[') { pattern++; if (pattern == end) - return FALSE; + return false; if (*pattern == '!' || *pattern == '^') { pattern++; if (pattern == end) - return FALSE; + return false; /* Negative match */ for (;;) { if (*pattern == '\\') { if (++pattern == end) - return FALSE; + return false; } if (*pattern == *string) - return FALSE; + return false; if (pattern[1] == '-') { if (pattern + 2 == end) - return FALSE; + return false; if (*pattern < *string && *string <= pattern[2]) - return FALSE; + return false; if (pattern[2] <= *string && *string < *pattern) - return FALSE; + return false; pattern += 3; } else pattern++; if (pattern == end) - return FALSE; + return false; /* The test for ']' is done at the end so that ']' * can be used at the start of the range without '\' */ if (*pattern == ']') @@ -337,13 +311,13 @@ Str_Matchi(string, pattern, end) for (;;) { if (*pattern == '\\') { if (++pattern == end) - return FALSE; + return false; } if (*pattern == *string) break; if (pattern[1] == '-') { if (pattern + 2 == end) - return FALSE; + return false; if (*pattern < *string && *string <= pattern[2]) break; if (pattern[2] <= *string && *string < *pattern) @@ -354,7 +328,7 @@ Str_Matchi(string, pattern, end) /* The test for ']' is done at the end so that ']' * can be used at the start of the range without '\' */ if (pattern == end || *pattern == ']') - return FALSE; + return false; } /* Found matching character, skip over rest of class. */ while (*pattern != ']') { @@ -373,20 +347,20 @@ Str_Matchi(string, pattern, end) * '\' so we do exact matching on the character that follows. */ if (*pattern == '\\') { if (++pattern == end) - return FALSE; + return false; } /* There's no special character. Just make sure that * the next characters of each string match. */ if (*pattern != *string) - return FALSE; + return false; } pattern++; string++; } - if (*string == '\0') - return TRUE; + if (string == estring) + return true; else - return FALSE; + return false; } @@ -468,7 +442,7 @@ Str_SYSVSubst(buf, pat, src, len) if ((m = strchr(pat, '%')) != NULL) { /* Copy the prefix. */ - Buf_AddInterval(buf, pat, m); + Buf_Addi(buf, pat, m); /* Skip the %. */ pat = m + 1; } @@ -481,7 +455,7 @@ Str_SYSVSubst(buf, pat, src, len) } char * -interval_dup(begin, end) +Str_dupi(begin, end) const char *begin; const char *end; { @@ -493,9 +467,8 @@ interval_dup(begin, end) return s; } -/* copy interval, skipping characters in the set. */ char * -escape_dup(begin, end, set) +escape_dupi(begin, end, set) const char *begin; const char *end; const char *set; @@ -520,7 +493,7 @@ escape_dup(begin, end, set) } char * -lastchar(s, e, c) +Str_rchri(s, e, c) const char *s; const char *e; int c; diff --git a/usr.bin/make/str.h b/usr.bin/make/str.h new file mode 100644 index 00000000000..a0bb8471840 --- /dev/null +++ b/usr.bin/make/str.h @@ -0,0 +1,69 @@ +#ifndef STR_H +#define STR_H +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* pos = Str_rchri(str, end, c); + * strrchr on intervals. */ +extern char *Str_rchri(const char *, const char *, int); + +/* copy = Str_concati(s1, e1, s2, e2, sep); + * Concatenate strings s1/e1 and s2/e2, wedging separator sep if != 0. */ +extern char *Str_concati(const char *, const char *, const char *, const char *, int); +#define Str_concat(s1, s2, sep) Str_concati(s1, strchr(s1, '\0'), s2, strchr(s2, '\0'), sep) + +/* copy = Str_dupi(str, end); + * strdup on intervals. */ +extern char *Str_dupi(const char *, const char *); + +/* copy = escape_dupi(str, end, set); + * copy string str/end. All escape sequences such as \c with c in set + * are handled as well. */ +extern char *escape_dupi(const char *, const char *, const char *); + + +extern char **brk_string(const char *, int *, char **); + + +/* Iterate through a string word by word, + * without copying anything. + * More light-weight than brk_string, handles \ ' " as well. + * + * position = s; + * while ((begin = iterate_words(&position)) != NULL) { + * do_something_with_word_interval(begin, position); + * } + */ +extern const char *iterate_words(const char **); + +/* match = Str_Matchi(str, estr, pat, end); + * Checks if string str/estr matches pattern pat/end */ +extern bool Str_Matchi(const char *, const char *, const char *, const char *); +#define Str_Match(string, pattern) \ + Str_Matchi(string, strchr(string, '\0'), pattern, strchr(pattern, '\0')) + +extern const char *Str_SYSVMatch(const char *, const char *, size_t *); +extern void Str_SYSVSubst(Buffer, const char *, const char *, size_t); +#endif diff --git a/usr.bin/make/suff.c b/usr.bin/make/suff.c index 42f0acf6a98..921a4dea6c1 100644 --- a/usr.bin/make/suff.c +++ b/usr.bin/make/suff.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: suff.c,v 1.41 2001/05/03 13:41:11 espie Exp $ */ +/* $OpenBSD: suff.c,v 1.42 2001/05/23 12:34:49 espie Exp $ */ /* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */ /* @@ -66,7 +66,7 @@ * Suff_ClearSuffixes Clear out all the suffixes and defined * transformations. * - * Suff_IsTransform Return TRUE if the passed string is the lhs + * Suff_IsTransform Return true if the passed string is the lhs * of a transformation rule. * * Suff_AddSuffix Add the passed string as another known suffix. @@ -91,20 +91,22 @@ * if the target had no implicit sources. */ -#include <stddef.h> -#include <stdio.h> -#include "make.h" -#include "ohash.h" -#include "dir.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: suff.c,v 1.41 2001/05/03 13:41:11 espie Exp $"; -#endif -#endif /* not lint */ +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "dir.h" +#include "arch.h" +#include "suff.h" +#include "var.h" +#include "targ.h" +#include "error.h" +#include "str.h" +#include "lst.h" +#include "memory.h" +#include "gnode.h" +#include "make.h" static LIST sufflist; /* Lst of suffixes */ #ifdef CLEANUP @@ -174,7 +176,7 @@ static void SuffUnRef(Lst, Suff *); static void SuffFree(void *); #endif static void SuffInsert(Lst, Suff *); -static Boolean SuffParseTransform(const char *, Suff **, Suff **); +static bool SuffParseTransform(const char *, Suff **, Suff **); static void SuffRebuildGraph(void *, void *); static void SuffAddSrc(void *, void *); static int SuffRemoveSrc(Lst); @@ -184,7 +186,7 @@ static Src *SuffFindCmds(Src *, Lst); static void SuffExpandChildren(void *, void *); static void SuffExpandVarChildren(LstNode, GNode *, GNode *); static void SuffExpandWildChildren(LstNode, GNode *, GNode *); -static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); +static bool SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); static void SuffFindDeps(GNode *, Lst); static void SuffFindArchiveDeps(GNode *, Lst); static void SuffFindNormalDeps(GNode *, Lst); @@ -192,6 +194,9 @@ static void SuffPrintName(void *); static void SuffPrintSuff(void *); static void SuffPrintTrans(void *); +#ifdef DEBUG_SRC +static void PrintAddr(void *); +#endif /*************** Lst Predicates ****************/ /*- *----------------------------------------------------------------------- @@ -440,13 +445,13 @@ Suff_ClearSuffixes() * Parse a transformation string to find its two component suffixes. * * Results: - * TRUE if the string is a valid transformation and FALSE otherwise. + * true if the string is a valid transformation and false otherwise. * * Side Effects: * The passed pointers are overwritten. *----------------------------------------------------------------------- */ -static Boolean +static bool SuffParseTransform(str, srcPtr, targPtr) const char *str; /* String being parsed */ Suff **srcPtr; /* Place to store source of trans. */ @@ -491,9 +496,9 @@ SuffParseTransform(str, srcPtr, targPtr) */ *srcPtr = single; *targPtr = suffNull; - return TRUE; + return true; } - return FALSE; + return false; } src = (Suff *)Lst_Datum(srcLn); str2 = str + src->nameLen; @@ -505,7 +510,7 @@ SuffParseTransform(str, srcPtr, targPtr) if (targLn != NULL) { *srcPtr = src; *targPtr = (Suff *)Lst_Datum(targLn); - return TRUE; + return true; } } } @@ -514,14 +519,14 @@ SuffParseTransform(str, srcPtr, targPtr) /*- *----------------------------------------------------------------------- * Suff_IsTransform -- - * Return TRUE if the given string is a transformation rule + * Return true if the given string is a transformation rule * * Results: - * TRUE if the string is a concatenation of two known suffixes. - * FALSE otherwise + * true if the string is a concatenation of two known suffixes. + * false otherwise *----------------------------------------------------------------------- */ -Boolean +bool Suff_IsTransform(str) const char *str; /* string to check */ { @@ -559,7 +564,7 @@ Suff_AddTransform(line) * Make a new graph node for the transformation. It will be filled in * by the Parse module. */ - gn = Targ_NewGN(line, NULL); + gn = Targ_NewGN(line); Lst_AtEnd(&transforms, gn); } else { /* @@ -804,11 +809,9 @@ Suff_DoPaths() Dir_Concat(&inLibs, &s->searchPath); } #endif /* LIBRARIES */ - Dir_Concat(&s->searchPath, &dirSearchPath); - } else { - Lst_Destroy(&s->searchPath, Dir_Destroy); - Lst_Clone(&s->searchPath, &dirSearchPath, Dir_CopyDir); - } + Dir_Concat(&s->searchPath, dirSearchPath); + } else + Lst_Clone(&s->searchPath, dirSearchPath, Dir_CopyDir); } Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", &inIncludes), VAR_GLOBAL); @@ -920,7 +923,7 @@ SuffAddSrc(sp, lsp) #endif } s2 = emalloc(sizeof(Src)); - s2->file = str_concat(targ->pref, s->name, 0); + s2->file = Str_concat(targ->pref, s->name, 0); s2->pref = targ->pref; s2->parent = targ; s2->node = NULL; @@ -1008,7 +1011,7 @@ SuffRemoveSrc(l) Lst_Remove(l, ln); free(s); t |= 1; - return TRUE; + return true; } #ifdef DEBUG_SRC else { @@ -1051,7 +1054,7 @@ SuffFindThem(srcs, slst) * A file is considered to exist if either a node exists in the * graph for it or the file actually exists. */ - if (Targ_FindNode(s->file, NULL, TARG_NOCREATE) != NULL) { + if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) { #ifdef DEBUG_SRC printf("remove %x from %x\n", s, srcs); #endif @@ -1181,7 +1184,7 @@ SuffExpandVarChildren(after, cgn, pgn) if (DEBUG(SUFF)) printf("Expanding \"%s\"...", cgn->name); - cp = Var_Subst(cgn->name, &pgn->context, TRUE); + cp = Var_Subst(cgn->name, &pgn->context, true); if (cp == NULL) { printf("Problem substituting in %s", cgn->name); printf("\n"); @@ -1213,7 +1216,7 @@ SuffExpandVarChildren(after, cgn, pgn) if (isspace(*cp2)) { /* White-space -- terminate element, find the node, * add it, skip any further spaces. */ - gn = Targ_FindNode(start, cp2, TARG_CREATE); + gn = Targ_FindNodei(start, cp2, TARG_CREATE); cp2++; Lst_AtEnd(&members, gn); while (isspace(*cp2)) @@ -1232,7 +1235,7 @@ SuffExpandVarChildren(after, cgn, pgn) if (cp2 != start) { /* Stuff left over -- add it to the list too. */ - gn = Targ_FindNode(start, cp2, TARG_CREATE); + gn = Targ_FindNodei(start, cp2, TARG_CREATE); Lst_AtEnd(&members, gn); } } @@ -1285,7 +1288,7 @@ SuffExpandWildChildren(after, cgn, pgn) path = &s->searchPath; } else /* Use default search path. */ - path = &dirSearchPath; + path = dirSearchPath; /* Expand the word along the chosen path. */ Lst_Init(&exp); @@ -1296,7 +1299,7 @@ SuffExpandWildChildren(after, cgn, pgn) GNode *gn; /* New source 8) */ if (DEBUG(SUFF)) printf("%s...", cp); - gn = Targ_FindNode(cp, NULL, TARG_CREATE); + gn = Targ_FindNode(cp, TARG_CREATE); /* If gn isn't already a child of the parent, make it so and * up the parent's count of unmade children. */ @@ -1361,7 +1364,7 @@ SuffExpandChildren(cgnp, pgnp) * and suffixes. * * Results: - * TRUE if successful, FALSE if not. + * true if successful, false if not. * * Side Effects: * The source and target are linked and the commands from the @@ -1371,7 +1374,7 @@ SuffExpandChildren(cgnp, pgnp) * the transformation rule. *----------------------------------------------------------------------- */ -static Boolean +static bool SuffApplyTransform(tGn, sGn, t, s) GNode *tGn; /* Target node */ GNode *sGn; /* Source node */ @@ -1383,7 +1386,7 @@ SuffApplyTransform(tGn, sGn, t, s) char *tname; /* Name of transformation rule */ GNode *gn; /* Node for same */ - if (Lst_AddNew(&tGn->children, sGn) == SUCCESS) { + if (Lst_AddNew(&tGn->children, sGn)) { /* Not already linked, so form the proper links between the * target and source. */ Lst_AtEnd(&sGn->parents, tGn); @@ -1398,7 +1401,7 @@ SuffApplyTransform(tGn, sGn, t, s) for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) { gn = (GNode *)Lst_Datum(ln); - if (Lst_AddNew(&tGn->children, gn) == SUCCESS) { + if (Lst_AddNew(&tGn->children, gn)) { /* Not already linked, so form the proper links between the * target and source. */ Lst_AtEnd(&gn->parents, tGn); @@ -1407,7 +1410,7 @@ SuffApplyTransform(tGn, sGn, t, s) } } /* Locate the transformation rule itself. */ - tname = str_concat(s->name, t->name, 0); + tname = Str_concat(s->name, t->name, 0); ln = Lst_FindConst(&transforms, SuffGNHasNameP, tname); free(tname); @@ -1415,9 +1418,9 @@ SuffApplyTransform(tGn, sGn, t, s) /* * Not really such a transformation rule (can happen when we're * called to link an OP_MEMBER and OP_ARCHV node), so return - * FALSE. + * false. */ - return FALSE; + return false; gn = (GNode *)Lst_Datum(ln); @@ -1440,7 +1443,7 @@ SuffApplyTransform(tGn, sGn, t, s) * the .IMPSRC variable can be set correctly for the parent. */ Lst_AtEnd(&sGn->iParents, tGn); - return TRUE; + return true; } @@ -1481,11 +1484,11 @@ SuffFindArchiveDeps(gn, slst) * to locate its suffix. This allows us to figure out the suffix to * use for the archive without having to do a quadratic search over the * suffix list, backtracking for each one... */ - mem = Targ_FindNode(name, eoname, TARG_CREATE); + mem = Targ_FindNodei(name, eoname, TARG_CREATE); SuffFindDeps(mem, slst); /* Create the link between the two nodes right off. */ - if (Lst_AddNew(&gn->children, mem) == SUCCESS) { + if (Lst_AddNew(&gn->children, mem)) { Lst_AtEnd(&mem->parents, gn); gn->unmade++; } @@ -1708,7 +1711,7 @@ sfnd_abort: (Lst_IsEmpty(&gn->children) && Lst_IsEmpty(&gn->commands))) { gn->path = Dir_FindFile(gn->name, - (targ == NULL ? &dirSearchPath : + (targ == NULL ? dirSearchPath : &targ->suff->searchPath)); if (gn->path != NULL) { char *ptr; @@ -1795,7 +1798,7 @@ sfnd_abort: * transformation rule. Also, the unmade field of gn is incremented. * Etc. */ if (bottom->node == NULL) { - bottom->node = Targ_FindNode(bottom->file, NULL, TARG_CREATE); + bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); } for (src = bottom; src->parent != NULL; src = src->parent) { @@ -1804,7 +1807,7 @@ sfnd_abort: src->node->suffix = src->suff; if (targ->node == NULL) { - targ->node = Targ_FindNode(targ->file, NULL, TARG_CREATE); + targ->node = Targ_FindNode(targ->file, TARG_CREATE); } SuffApplyTransform(targ->node, src->node, @@ -1998,7 +2001,7 @@ Suff_Init() suffNull->name = estrdup(""); suffNull->nameLen = 0; Lst_Init(&suffNull->searchPath); - Dir_Concat(&suffNull->searchPath, &dirSearchPath); + Dir_Concat(&suffNull->searchPath, dirSearchPath); Lst_Init(&suffNull->children); Lst_Init(&suffNull->parents); Lst_Init(&suffNull->ref); @@ -2018,18 +2021,18 @@ Suff_Init() *---------------------------------------------------------------------- */ +#ifdef CLEANUP void Suff_End() { -#ifdef CLEANUP Lst_Destroy(&sufflist, SuffFree); Lst_Destroy(&suffClean, SuffFree); if (suffNull) SuffFree(suffNull); Lst_Destroy(&srclist, NOFREE); Lst_Destroy(&transforms, NOFREE); -#endif } +#endif /********************* DEBUGGING FUNCTIONS **********************/ @@ -2104,3 +2107,12 @@ Suff_PrintAll() printf("#*** Transformations:\n"); Lst_Every(&transforms, SuffPrintTrans); } + +#ifdef DEBUG_SRC +static void +PrintAddr(a) + void *a; +{ + printf("%lx ", (unsigned long)a); +} +#endif diff --git a/usr.bin/make/suff.h b/usr.bin/make/suff.h new file mode 100644 index 00000000000..d15b3f37bc4 --- /dev/null +++ b/usr.bin/make/suff.h @@ -0,0 +1,50 @@ +#ifndef SUFF_H +#define SUFF_H +/* $OpenPackages$ */ +/* $OpenBSD: suff.h,v 1.1 2001/05/23 12:34:50 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +extern void Suff_ClearSuffixes(void); +extern bool Suff_IsTransform(const char *); +extern GNode *Suff_AddTransform(const char *); +extern void Suff_EndTransform(void *); +extern void Suff_AddSuffix(char *); +extern Lst Suff_GetPath(char *); +extern void Suff_DoPaths(void); +extern void Suff_AddInclude(char *); +extern void Suff_AddLib(char *); +extern void Suff_FindDeps(GNode *); +extern void Suff_SetNull(char *); +extern void Suff_Init(void); +#ifdef CLEANUP +extern void Suff_End(void); +#else +#define Suff_End() +#endif +extern void Suff_PrintAll(void); + +#endif diff --git a/usr.bin/make/symtable.h b/usr.bin/make/symtable.h new file mode 100644 index 00000000000..8b109160d94 --- /dev/null +++ b/usr.bin/make/symtable.h @@ -0,0 +1,42 @@ +#ifndef SYMTABLE_H +#define SYMTABLE_H +/* $OpenPackages$ */ +/* $OpenBSD: symtable.h,v 1.1 2001/05/23 12:34:50 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +struct Var_; + +#define LOCAL_SIZE 7 + +/* SymTable is private to var.c, but is declared here to allow for + local declaration of context tables + */ +struct SymTable_ { + struct Var_ *locals[LOCAL_SIZE]; +}; + +#endif diff --git a/usr.bin/make/targ.c b/usr.bin/make/targ.c index aec09a27c01..292e01c2c36 100644 --- a/usr.bin/make/targ.c +++ b/usr.bin/make/targ.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: targ.c,v 1.31 2001/05/03 13:41:12 espie Exp $ */ +/* $OpenBSD: targ.c,v 1.32 2001/05/23 12:34:50 espie Exp $ */ /* $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $ */ /* @@ -87,13 +87,13 @@ * Targ_FindList Given a list of names, find nodes for all * of them, creating nodes if needed. * - * Targ_Ignore Return TRUE if errors should be ignored when + * Targ_Ignore Return true if errors should be ignored when * creating the given target. * - * Targ_Silent Return TRUE if we should be silent when + * Targ_Silent Return true if we should be silent when * creating the given target. * - * Targ_Precious Return TRUE if the target is precious and + * Targ_Precious Return true if the target is precious and * should not be removed if we are interrupted. * * Debugging: @@ -102,23 +102,21 @@ * print something for suffixes, too, but... */ -#include <stddef.h> -#include <stdio.h> -#include <time.h> -#include "make.h" -#include "ohash.h" -#include "dir.h" -#include "stats.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94"; -#else -UNUSED -static char *rcsid = "$OpenBSD: targ.c,v 1.31 2001/05/03 13:41:12 espie Exp $"; -#endif -#endif /* not lint */ - +#include <sys/types.h> +#include <stddef.h> +#include <stdio.h> +#include "config.h" +#include "defines.h" +#include "ohash.h" +#include "stats.h" +#include "suff.h" +#include "var.h" +#include "targ.h" +#include "memory.h" +#include "gnode.h" +#include "extern.h" +#include "timestamp.h" +#include "lst.h" static struct ohash targets; /* a hash table of same */ static struct ohash_info gnode_info = { @@ -157,10 +155,10 @@ Targ_Init() * All lists and gnodes are cleared *----------------------------------------------------------------------- */ +#ifdef CLEANUP void Targ_End() { -#ifdef CLEANUP unsigned int i; GNode *n; @@ -168,12 +166,12 @@ Targ_End() TargFreeGN(n); ohash_delete(&targets); -#endif } +#endif /*- *----------------------------------------------------------------------- - * Targ_NewGN -- + * Targ_NewGNi -- * Create and initialize a new graph node * * Results: @@ -185,7 +183,7 @@ Targ_End() *----------------------------------------------------------------------- */ GNode * -Targ_NewGN(name, end) +Targ_NewGNi(name, end) const char *name; /* the name to stick in the new node */ const char *end; { @@ -199,12 +197,12 @@ Targ_NewGN(name, end) gn->type = 0; } gn->unmade = 0; - gn->make = FALSE; + gn->make = false; gn->made = UNMADE; - gn->childMade = FALSE; + gn->childMade = false; gn->order = 0; - set_out_of_date(gn->mtime); - set_out_of_date(gn->cmtime); + ts_set_out_of_date(gn->mtime); + ts_set_out_of_date(gn->cmtime); Lst_Init(&gn->iParents); Lst_Init(&gn->cohorts); Lst_Init(&gn->parents); @@ -253,7 +251,7 @@ TargFreeGN(gnp) /*- *----------------------------------------------------------------------- - * Targ_FindNode -- + * Targ_FindNodei -- * Find a node in the list using the given name for matching * * Results: @@ -266,7 +264,7 @@ TargFreeGN(gnp) *----------------------------------------------------------------------- */ GNode * -Targ_FindNode(name, end, flags) +Targ_FindNodei(name, end, flags) const char *name; /* the name to find */ const char *end; int flags; /* flags governing events when target not @@ -280,7 +278,7 @@ Targ_FindNode(name, end, flags) gn = ohash_find(&targets, slot); if (gn == NULL && (flags & TARG_CREATE)) { - gn = Targ_NewGN(name, end); + gn = Targ_NewGNi(name, end); ohash_insert(&targets, slot, gn); } @@ -311,7 +309,7 @@ Targ_FindList(nodes, names) for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) { name = (char *)Lst_Datum(ln); - gn = Targ_FindNode(name, NULL, TARG_CREATE); + gn = Targ_FindNode(name, TARG_CREATE); /* Note: Lst_AtEnd must come before the Lst_Concat so the nodes * are added to the list in the order in which they were * encountered in the makefile. */ @@ -327,14 +325,14 @@ Targ_FindList(nodes, names) * Return true if should ignore errors when creating gn *----------------------------------------------------------------------- */ -Boolean +bool Targ_Ignore(gn) GNode *gn; /* node to check for */ { if (ignoreErrors || gn->type & OP_IGNORE) - return TRUE; + return true; else - return FALSE; + return false; } /*- @@ -343,14 +341,14 @@ Targ_Ignore(gn) * Return true if be silent when creating gn *----------------------------------------------------------------------- */ -Boolean +bool Targ_Silent(gn) GNode *gn; /* node to check for */ { if (beSilent || gn->type & OP_SILENT) - return TRUE; + return true; else - return FALSE; + return false; } /*- @@ -359,14 +357,14 @@ Targ_Silent(gn) * See if the given target is precious *----------------------------------------------------------------------- */ -Boolean +bool Targ_Precious(gn) GNode *gn; /* the node to check */ { if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) - return TRUE; + return true; else - return FALSE; + return false; } /******************* DEBUG INFO PRINTING ****************/ @@ -595,7 +593,9 @@ Targ_PrintGraph(pass) TargPrintOnlySrc(gn); Var_Dump(); printf("\n"); +#ifdef DEBUG_DIRECTORY_CACHE Dir_PrintDirectories(); printf("\n"); +#endif Suff_PrintAll(); } diff --git a/usr.bin/make/targ.h b/usr.bin/make/targ.h new file mode 100644 index 00000000000..01078b74bdd --- /dev/null +++ b/usr.bin/make/targ.h @@ -0,0 +1,65 @@ +#ifndef TARG_H +#define TARG_H +/* $OpenPackages$ */ +/* $OpenBSD: targ.h,v 1.1 2001/05/23 12:34:50 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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 TIMESTAMP_TYPE +#include "timestamp_t.h" +#endif +/* + * The TARG_ constants are used when calling the Targ_FindNode functions. + * They simply tell the function what to do if the desired node is not found. + * If the TARG_CREATE constant is given, a new, empty node will be created + * for the target, placed in the table of all targets and its address returned. + * If TARG_NOCREATE is given, a NULL pointer will be returned. + */ +#define TARG_CREATE 0x01 /* create node if not found */ +#define TARG_NOCREATE 0x00 /* don't create it */ + +extern void Targ_Init(void); +#ifdef CLEANUP +extern void Targ_End(void); +#else +#define Targ_End() +#endif +extern GNode *Targ_NewGNi(const char *, const char *); +#define Targ_NewGN(n) Targ_NewGNi(n, NULL); +extern GNode *Targ_FindNodei(const char *, const char *, int); +#define Targ_FindNode(n, i) Targ_FindNodei(n, NULL, i) +extern void Targ_FindList(Lst, Lst); +extern bool Targ_Ignore(GNode *); +extern bool Targ_Silent(GNode *); +extern bool Targ_Precious(GNode *); +extern void Targ_SetMain(GNode *); +extern void Targ_PrintCmd(void *); +extern char *Targ_FmtTime(TIMESTAMP); +extern void Targ_PrintType(int); +extern void Targ_PrintGraph(int); + + +#endif diff --git a/usr.bin/make/timestamp.c b/usr.bin/make/timestamp.c new file mode 100644 index 00000000000..9f518f81b6b --- /dev/null +++ b/usr.bin/make/timestamp.c @@ -0,0 +1,56 @@ +/* $OpenPackages$ */ +/* $OpenBSD: timestamp.c,v 1.1 2001/05/23 12:34:50 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ +#include "config.h" +#include "defines.h" +#include "timestamp.h" + +#ifndef USE_TIMESPEC +#include <sys/types.h> +#include <utime.h> +#endif + +TIMESTAMP now; /* The time at the start of this whole + * process */ + +int +set_times(f) + const char *f; +{ +#ifdef USE_TIMESPEC + struct timeval tv[2]; + + TIMESPEC_TO_TIMEVAL(&tv[0], &now); + TIMESPEC_TO_TIMEVAL(&tv[1], &now); + return utimes(f, tv); +#else + struct utimbuf times; + + times.actime = times.modtime = now; + return utime(f, ×); +#endif +} diff --git a/usr.bin/make/timestamp.h b/usr.bin/make/timestamp.h new file mode 100644 index 00000000000..28572fb6866 --- /dev/null +++ b/usr.bin/make/timestamp.h @@ -0,0 +1,105 @@ +#ifndef TIMESTAMP_H +#define TIMESTAMP_H + +/* $OpenPackages$ */ +/* $OpenBSD: timestamp.h,v 1.1 2001/05/23 12:34:51 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* This module handles time stamps on files in a relatively high-level way. + * Most of the interface is achieved through inlineable code. + * + * TIMESTAMP: opaque data type to store a date. + * ts_set_out_of_date(t): set up t so that it is out-of-date. + * b = is_out_of_date(t): check whether t is out-of-date. + * ts_set_from_stat(s, t): grab date out of stat(2) buffer. + * b = is_strictly_before(t1, t2): + * check whether t1 is before t2. + * stamp = timestamp2time_t(t): extract time_t from timestamp. + * ts_set_from_time_t(d, t): create timestamp from time_t. + * ts_set_from_now(n): grab current date. + */ + +/* sysresult = set_times(name): set modification times on a file. + * system call results. + */ + +#define Init_Timestamp() ts_set_from_now(now) + +#ifndef TIMESTAMP_TYPE +#include "timestamp_t.h" +#endif +#ifdef USE_TIMESPEC +#define ts_set_out_of_date(t) (t).tv_sec = INT_MIN, (t).tv_nsec = 0 +#define is_out_of_date(t) ((t).tv_sec == INT_MIN && (t).tv_nsec == 0) +#define ts_set_from_stat(s, t) \ +do { \ + (t).tv_sec = (s).st_mtime; \ + (t).tv_nsec = (s).st_mtimensec; \ + if (is_out_of_date(t)) \ + (t).tv_nsec++; \ +} while (0) +#define is_strictly_before(t1, t2) timespeccmp(&(t1), &(t2), <) +#define ts_set_from_time_t(d, t) \ +do { \ + (t).tv_sec = d; \ + (t).tv_nsec = 0; \ + if (is_out_of_date(t)) \ + (t).tv_nsec++; \ +} while (0) +#define ts_set_from_now(n) \ +do { \ + struct timeval tv; \ + gettimeofday(&tv, NULL); \ + TIMEVAL_TO_TIMESPEC(&(tv), &n); \ +} while (0) +#define timestamp2time_t(t) ((t).tv_sec) +#else +#define is_out_of_date(t) ((t) == INT_MIN) +#define ts_set_out_of_date(t) (t) = INT_MIN +#define ts_set_from_stat(s, t) \ +do { \ + (t) = (s).st_mtime; \ + if (is_out_of_date(t)) \ + (t)++; \ +} while (0) +#define is_strictly_before(t1, t2) ((t1) < (t2)) +#define ts_set_from_time_t(d, t) \ +do { \ + (t) = d; \ + if (is_out_of_date(t)) \ + (t)++; \ +} while (0) +#define ts_set_from_now(n) time(&(n)) +#define timestamp2time_t(t) (t) +#endif + +extern int set_times(const char *); + +extern TIMESTAMP now; /* The time at the start of this whole + * process */ + +#endif diff --git a/usr.bin/make/timestamp_t.h b/usr.bin/make/timestamp_t.h new file mode 100644 index 00000000000..5eb98aaa524 --- /dev/null +++ b/usr.bin/make/timestamp_t.h @@ -0,0 +1,37 @@ +/* $OpenPackages$ */ +/* $OpenBSD: timestamp_t.h,v 1.1 2001/05/23 12:34:51 espie Exp $ */ + +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +#ifdef USE_TIMESPEC +#include <sys/time.h> +typedef struct timespec TIMESTAMP; +#else +#include <time.h> +typedef time_t TIMESTAMP; +#endif + +#define TIMESTAMP_TYPE diff --git a/usr.bin/make/util.c b/usr.bin/make/util.c index 98f0eb18c3d..5de54011808 100644 --- a/usr.bin/make/util.c +++ b/usr.bin/make/util.c @@ -1,18 +1,39 @@ /* $OpenPackages$ */ -/* $OpenBSD: util.c,v 1.15 2001/05/03 14:06:20 espie Exp $ */ +/* $OpenBSD: util.c,v 1.16 2001/05/23 12:34:51 espie Exp $ */ /* $NetBSD: util.c,v 1.10 1996/12/31 17:56:04 christos Exp $ */ /* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ +/* * Missing stuff from OS's */ -#ifndef lint -static char rcsid[] = "$OpenBSD: util.c,v 1.15 2001/05/03 14:06:20 espie Exp $"; -#endif - -#include <stdio.h> -#include "make.h" #include <sys/param.h> +#include <stdio.h> +#include "config.h" +#include "defines.h" #ifndef __STDC__ # ifndef const @@ -353,7 +374,7 @@ signal(s, a))() #endif -#if !defined(BSD4_4) && !defined(linux) +#ifndef BSD4_4 #ifdef __STDC__ #include <stdarg.h> #else diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c index 11c3be411ed..7ba2dee486f 100644 --- a/usr.bin/make/var.c +++ b/usr.bin/make/var.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: var.c,v 1.54 2001/05/15 13:31:03 espie Exp $ */ +/* $OpenBSD: var.c,v 1.55 2001/05/23 12:34:51 espie Exp $ */ /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */ /* @@ -66,72 +66,40 @@ * SUCH DAMAGE. */ -/*- - * var.c -- - * Variable-handling functions - * - * Basic interface: - * Var_Set Set the value of a variable in the given - * context. The variable is created if it doesn't - * yet exist. The value and variable name need not - * be preserved. - * - * Var_Append Append more characters to an existing variable - * in the given context. The variable needn't - * exist already -- it will be created if it doesn't. - * A space is placed between the old value and the - * new one. - * - * Var_Value Return the value of a variable in a context or - * NULL if the variable is undefined. - * - * Var_Delete Delete a variable in a context. - * - * Var_Init Initialize this module. - * - * Fast interface: - * Varq_Set, Varq_Append, Varq_Value: - * Use index form of local variables - * - * Higher level functions: - * Var_Subst Substitute variables in a string using - * the given context as the top-most one. If the - * third argument is non-zero, Parse_Error is - * called if any variables are undefined. - * - * Var_SubstVar Substitute a named variable in a string using - * the given context as the top-most one, - * accumulating the result into a user-supplied - * buffer. - * - * Var_Parse Parse a variable expansion from a string and - * return the result and the number of characters - * consumed. - * - * Debugging: - * Var_Dump Print out all global variables. - */ - -#include <assert.h> -#include <ctype.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include "make.h" -#include "buf.h" -#include "stats.h" -#include "ohash.h" -#include "varmodifiers.h" - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: var.c,v 1.54 2001/05/15 13:31:03 espie Exp $"; -#endif -#endif /* not lint */ - +#include <sys/types.h> +#include <assert.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "defines.h" +#include "buf.h" +#include "stats.h" +#include "ohash.h" +#include "varmodifiers.h" +#include "var.h" +#include "varname.h" +#include "error.h" +#include "str.h" +#include "var_int.h" +#include "memory.h" +#include "symtable.h" +#include "gnode.h" + +/* extended indices for System V stuff */ +#define FTARGET_INDEX 7 +#define DTARGET_INDEX 8 +#define FPREFIX_INDEX 9 +#define DPREFIX_INDEX 10 +#define FARCHIVE_INDEX 11 +#define DARCHIVE_INDEX 12 +#define FMEMBER_INDEX 13 +#define DMEMBER_INDEX 14 + +#define EXTENDED2SIMPLE(i) (((i)-LOCAL_SIZE)/2) +#define IS_EXTENDED_F(i) ((i)%2 == 1) /* * This is a harmless return value for Var_Parse that can be used by Var_Subst @@ -210,7 +178,7 @@ static struct ohash_info var_info = { static int quick_lookup(const char *, const char **, u_int32_t *); #define VarValue(v) Buf_Retrieve(&((v)->val)) static Var *varfind(const char *, const char *, SymTable *, int, int, u_int32_t); -static Var *VarFind_interval(const char *, const char *, SymTable *, int); +static Var *VarFindi(const char *, const char *, SymTable *, int); static Var *VarAdd(const char *, const char *, u_int32_t, const char *, GSymT *); static void VarDelete(void *); static void VarPrintVar(Var *); @@ -230,57 +198,6 @@ static find_t find_pos(int); /* retrieve the hashed values for well-known variables. */ #include "varhashconsts.h" -/* Parse a variable name for embedded $, to handle recursive variables */ -const char * -Var_Name_Get(start, name, ctxt, err, cont) - const char *start; /* start of variable spec */ - struct Name *name; /* result, might be a copy or not */ - SymTable *ctxt; /* context in which to expand */ - Boolean err; /* whether to error out for undefined sub */ - const char *(*cont)(const char *); - /* hook: find the next interesting character */ -{ - const char *p; - size_t len; - - p = cont(start); - /* If we don't want recursive variables, we skip over '$' */ - if (!FEATURES(FEATURE_RECVARS)) { - while (*p == '$') - p = cont(p); - } - if (*p != '$') { - name->s = start; - name->e = p; - name->tofree = FALSE; - return p; - } else { - BUFFER buf; - Buf_Init(&buf, MAKE_BSIZE); - for (;;) { - Buf_AddInterval(&buf, start, p); - if (*p != '$') { - name->s = (const char *)Buf_Retrieve(&buf); - name->e = name->s + Buf_Size(&buf); - name->tofree = TRUE; - return p; - } - start = p; - Var_ParseBuffer(&buf, start, ctxt, err, &len); - start += len; - p = cont(start); - } - } -} - -void -Var_Name_Free(name) - struct Name *name; -{ - if (name->tofree) - free((char *)name->s); -} - void SymTable_Init(ctxt) SymTable *ctxt; @@ -573,7 +490,7 @@ getvar(ctxt, name, end, k) /*- *----------------------------------------------------------------------- - * VarFind_interval -- + * VarFindi -- * Find the given variable in the given context and any other contexts * indicated. if end is NULL, name is a string, otherwise, only * the interval name - end is concerned. @@ -584,7 +501,7 @@ getvar(ctxt, name, end, k) *----------------------------------------------------------------------- */ static Var * -VarFind_interval(name, end, ctxt, flags) +VarFindi(name, end, ctxt, flags) const char *name; /* name to find */ const char *end; /* end of name */ SymTable *ctxt; /* context in which to find it */ @@ -725,15 +642,6 @@ VarDelete(vp) -/*- - *----------------------------------------------------------------------- - * Var_Delete -- - * Remove a global variable. - * - * Side Effects: - * The Var structure is removed and freed. - *----------------------------------------------------------------------- - */ void Var_Delete(name) const char *name; @@ -759,24 +667,13 @@ Var_Delete(name) } } -/*- - *----------------------------------------------------------------------- - * Var_Set -- - * Set the variable name to the value val in the given context. - * - * Side Effects: - * If the variable doesn't yet exist, a new record is created for it. - * Else the old value is freed and the new one stuck in its place - * - * Notes: - * The variable is searched for only in its context before being +/* The variable is searched for only in its context before being * created in that context. I.e. if the context is CTXT_GLOBAL, * only CTXT_GLOBAL is searched. Likewise if it is CTXT_CMD, only * CTXT_CMD is searched. - *----------------------------------------------------------------------- */ void -Var_Set_interval(name, end, val, ctxt) +Var_Seti(name, end, val, ctxt) const char *name; /* name of variable to set */ const char *end; const char *val; /* value to give to the variable */ @@ -817,20 +714,8 @@ Var_Set_interval(name, end, val, ctxt) esetenv(v->name, val); } -/*- - *----------------------------------------------------------------------- - * Var_Append -- - * The variable of the given name has the given value appended to it in - * the given context. - * - * Side Effects: - * If the variable doesn't exist, it is created. Else the strings - * are concatenated (with a space in between). - * - *----------------------------------------------------------------------- - */ void -Var_Append_interval(name, end, val, ctxt) +Var_Appendi(name, end, val, ctxt) const char *name; /* Name of variable to modify */ const char *end; const char *val; /* String to append to it */ @@ -863,23 +748,14 @@ Var_Append_interval(name, end, val, ctxt) printf("%s:%s = %s\n", context_name(ctxt), v->name, VarValue(v)); } -/*- - *----------------------------------------------------------------------- - * Var_Value -- - * Return the value of a global named variable - * - * Results: - * The value if the variable exists, NULL if it doesn't - *----------------------------------------------------------------------- - */ char * -Var_Value_interval(name, end) +Var_Valuei(name, end) const char *name; /* name to find */ const char *end; { Var *v; - v = VarFind_interval(name, end, NULL, FIND_ENV | FIND_MINE); + v = VarFindi(name, end, NULL, FIND_ENV | FIND_MINE); if (v != NULL && (v->flags & VAR_DUMMY) == 0) return VarValue(v); else @@ -929,20 +805,11 @@ find_pos(c) } } -/*- - *----------------------------------------------------------------------- - * Var_ParseSkip -- - * Do whatever is needed to skip over a var specification. Since the - * result is not needed at this point, some shortcuts may be taken. - * - * Return value: the amount to skip - *----------------------------------------------------------------------- - */ size_t Var_ParseSkip(str, ctxt, result) const char *str; SymTable *ctxt; - ReturnStatus *result; + bool *result; { const char *tstr; /* Pointer into str */ Var *v; /* Variable in invocation */ @@ -957,7 +824,7 @@ Var_ParseSkip(str, ctxt, result) str++; if (*str != '(' && *str != '{') { - name.tofree = FALSE; + name.tofree = false; tstr = str + 1; length = 2; endc = '\0'; @@ -966,82 +833,53 @@ Var_ParseSkip(str, ctxt, result) str++; /* Find eventual modifiers in the variable */ - tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc)); - Var_Name_Free(&name); + tstr = VarName_Get(str, &name, ctxt, false, find_pos(endc)); + VarName_Free(&name); length = tstr - start; - /* Terminated correctly */ - if (*tstr != '\0') - length++; + if (*tstr != 0) + length++; } if (result != NULL) - *result = SUCCESS; + *result = true; if (*tstr == ':' && endc != '\0') - if (VarModifiers_Apply(NULL, NULL, ctxt, TRUE, NULL, tstr, endc, + if (VarModifiers_Apply(NULL, NULL, ctxt, true, NULL, tstr, endc, &length) == var_Error) - *result = FAILURE; + *result = false; return length; } -/*- - *----------------------------------------------------------------------- - * Var_ParseBuffer -- - * Given the start of a variable invocation, extract the variable - * name and find its value, then modify it according to the - * specification, and add the result to the buffer. - * - * Results: - * FAILURE for invalid specifications. - * - * Side-effects: - * The length of the specification is placed in *lengthPtr - * (for invalid specifications, this is just 2...?). - *----------------------------------------------------------------------- - */ -ReturnStatus +/* As of now, Var_ParseBuffer is just a wrapper around Var_Parse. For + * speed, it may be better to revisit the implementation to do things + * directly. */ +bool Var_ParseBuffer(buf, str, ctxt, err, lengthPtr) Buffer buf; const char *str; SymTable *ctxt; - Boolean err; + bool err; size_t *lengthPtr; { char *result; - Boolean freeIt; + bool freeIt; result = Var_Parse(str, ctxt, err, lengthPtr, &freeIt); if (result == var_Error) - return FAILURE; + return false; Buf_AddString(buf, result); if (freeIt) free(result); - return SUCCESS; + return true; } -/*- - *----------------------------------------------------------------------- - * Var_Parse -- - * Given the start of a variable invocation, extract the variable - * name and find its value, then modify it according to the - * specification. - * - * Results: - * The (possibly-modified) value of the variable or var_Error if the - * specification is invalid. The length of the specification is - * placed in *lengthPtr (for invalid specifications, this is just - * 2...?). - * A Boolean in *freePtr telling whether the returned string should - * be freed by the caller. - *----------------------------------------------------------------------- - */ char * Var_Parse(str, ctxt, err, lengthPtr, freePtr) const char *str; /* The string to parse */ SymTable *ctxt; /* The context for the variable */ - Boolean err; /* TRUE if undefined variables are an error */ + bool err; /* true if undefined variables are an error */ size_t *lengthPtr; /* OUT: The length of the specification */ - Boolean *freePtr; /* OUT: TRUE if caller should free result */ + bool *freePtr; /* OUT: true if caller should free result */ { const char *tstr; /* Pointer into str */ Var *v; /* Variable in invocation */ @@ -1053,7 +891,7 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) u_int32_t k; int idx; - *freePtr = FALSE; + *freePtr = false; start = str++; val = NULL; @@ -1063,7 +901,7 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) if (*str != '(' && *str != '{') { name.s = str; name.e = str+1; - name.tofree = FALSE; + name.tofree = false; tstr = str + 1; *lengthPtr = 2; endc = '\0'; @@ -1072,7 +910,7 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) str++; /* Find eventual modifiers in the variable */ - tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc)); + tstr = VarName_Get(str, &name, ctxt, false, find_pos(endc)); *lengthPtr = tstr - start; if (*tstr != '\0') (*lengthPtr)++; @@ -1098,14 +936,14 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) if (idx == -1) { if (strchr(val, '$') != NULL) { val = Var_Subst(val, ctxt, err); - *freePtr = TRUE; + *freePtr = true; } } else if (idx >= LOCAL_SIZE) { if (IS_EXTENDED_F(idx)) val = Var_GetTail(val); else val = Var_GetHead(val); - *freePtr = TRUE; + *freePtr = true; } v->flags &= ~VAR_IN_USE; } @@ -1118,8 +956,8 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) if (idx != -1) { /* can't be expanded for now: copy the var spec instead. */ if (ctxt == NULL || ctxt == CTXT_GLOBAL || ctxt == CTXT_CMD) { - *freePtr = TRUE; - val = interval_dup(start, start+ *lengthPtr); + *freePtr = true; + val = Str_dupi(start, start+ *lengthPtr); } else { /* somehow, this should have been expanded already. */ GNode *n; @@ -1139,48 +977,34 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) } } } - Var_Name_Free(&name); + VarName_Free(&name); return val; } -/*- - *----------------------------------------------------------------------- - * Var_Subst -- - * Substitute for all variables in a string in a context - * If undefErr is TRUE, Parse_Error will be called when an undefined - * variable is encountered. - * - * Results: - * The resulting string. - * - * Side Effects: - * The new string must be freed by the caller - *----------------------------------------------------------------------- - */ char * Var_Subst(str, ctxt, undefErr) const char *str; /* the string in which to substitute */ SymTable *ctxt; /* the context wherein to find variables */ - Boolean undefErr; /* TRUE if undefineds are an error */ + bool undefErr; /* true if undefineds are an error */ { BUFFER buf; /* Buffer for forming things */ - static Boolean errorReported; /* Set true if an error has already + static bool errorReported; /* Set true if an error has already * been reported to prevent a plethora * of messages when recursing */ Buf_Init(&buf, MAKE_BSIZE); - errorReported = FALSE; + errorReported = false; for (;;) { char *val; /* Value to substitute for a variable */ size_t length; /* Length of the variable invocation */ - Boolean doFree; /* Set true if val should be freed */ + bool doFree; /* Set true if val should be freed */ const char *cp; /* copy uninteresting stuff */ for (cp = str; *str != '\0' && *str != '$'; str++) ; - Buf_AddInterval(&buf, cp, str); + Buf_Addi(&buf, cp, str); if (*str == '\0') break; if (str[1] == '$') { @@ -1209,7 +1033,7 @@ Var_Subst(str, ctxt, undefErr) Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",length,str); str += length; - errorReported = TRUE; + errorReported = true; } else { Buf_AddChar(&buf, *str); str++; @@ -1229,14 +1053,6 @@ Var_Subst(str, ctxt, undefErr) return Buf_Retrieve(&buf); } -/*- - *----------------------------------------------------------------------- - * Var_SubstVar -- - * Substitute for one variable in the given string in the given context - * If undefErr is TRUE, Parse_Error will be called when an undefined - * variable is encountered. Add the substituted string to buffer. - *----------------------------------------------------------------------- - */ void Var_SubstVar(buf, str, var, val) Buffer buf; @@ -1252,7 +1068,7 @@ Var_SubstVar(buf, str, var, val) /* Copy uninteresting stuff */ for (start = str; *str != '\0' && *str != '$'; str++) ; - Buf_AddInterval(buf, start, str); + Buf_Addi(buf, start, str); start = str; if (*str++ == '\0') @@ -1260,7 +1076,7 @@ Var_SubstVar(buf, str, var, val) str++; /* and escaped dollars */ if (start[1] == '$') { - Buf_AddInterval(buf, start, start+2); + Buf_Addi(buf, start, start+2); continue; } /* Simple variable, if it's not us, copy. */ @@ -1286,7 +1102,7 @@ Var_SubstVar(buf, str, var, val) * expand the external variable at this point, so we try * again with the nested variable. */ if (*p == '$') { - Buf_AddInterval(buf, start, p); + Buf_Addi(buf, start, p); str = p; continue; } @@ -1294,24 +1110,24 @@ Var_SubstVar(buf, str, var, val) if (strncmp(var, str, p - str) != 0 || var[p - str] != '\0') { /* Not the variable we want to expand. */ - Buf_AddInterval(buf, start, p); + Buf_Addi(buf, start, p); str = p; continue; } if (*p == ':') { size_t length; /* Length of the variable invocation */ - Boolean doFree; /* Set true if val should be freed */ + bool doFree; /* Set true if val should be freed */ char *newval; /* Value substituted for a variable */ struct Name name; length = p - str + 1; - doFree = FALSE; + doFree = false; name.s = var; name.e = var + (p-str); - /* val won't be freed since doFree == FALSE, but + /* val won't be freed since doFree == false, but * VarModifiers_Apply doesn't know that, hence the cast. */ - newval = VarModifiers_Apply((char *)val, &name, NULL, FALSE, + newval = VarModifiers_Apply((char *)val, &name, NULL, false, &doFree, p, endc, &length); Buf_AddString(buf, newval); if (doFree) @@ -1350,10 +1166,10 @@ Var_Init() } +#ifdef CLEANUP void Var_End() { -#ifdef CLEANUP Var *v; unsigned int i; @@ -1363,8 +1179,8 @@ Var_End() for (v = ohash_first(VAR_CMD, &i); v != NULL; v = ohash_next(VAR_CMD, &i)) VarDelete(v); -#endif } +#endif static const char *interpret(int); @@ -1387,12 +1203,6 @@ VarPrintVar(v) (v->flags & VAR_DUMMY) == 0 ? VarValue(v) : "(none)"); } -/*- - *----------------------------------------------------------------------- - * Var_Dump -- - * print all variables - *----------------------------------------------------------------------- - */ void Var_Dump() { diff --git a/usr.bin/make/var.h b/usr.bin/make/var.h new file mode 100644 index 00000000000..8f411ec5a64 --- /dev/null +++ b/usr.bin/make/var.h @@ -0,0 +1,139 @@ +#ifndef VAR_H +#define VAR_H +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +extern void Var_Init(void); +#ifdef CLEANUP +extern void Var_End(void); +#else +#define Var_End() +#endif + +extern GSymT *VAR_GLOBAL; /* Variables defined in a global context, e.g + * in the Makefile itself */ +extern GSymT *VAR_CMD; /* Variables defined on the command line */ + +/* Global contexts handling. */ +/* value = Var_Valuei(name, end); + * Returns value of global variable name/end, or NULL if inexistent. */ +extern char *Var_Valuei(const char *, const char *); +#define Var_Value(n) Var_Valuei(n, NULL) + +/* Var_Seti(name, end, val, ctxt); + * Sets value val of variable name/end in context ctxt. Copies val. */ +extern void Var_Seti(const char *, const char *, const char *, + GSymT *); +#define Var_Set(n, v, ctxt) Var_Seti(n, NULL, v, ctxt) +/* Var_Appendi(name, end, val, cxt); + * Appends value val to variable name/end in context ctxt, defining it + * if it does not already exist, and inserting one space otherwise. */ +extern void Var_Appendi(const char *, const char *, + const char *, GSymT *); +#define Var_Append(n, v, ctxt) Var_Appendi(n, NULL, v, ctxt) + +/* Var_Delete(name); + * Deletes a variable from the global context. */ +extern void Var_Delete(const char *); + +/* Local context handling */ +#define TARGET_INDEX 0 +#define PREFIX_INDEX 1 +#define ARCHIVE_INDEX 2 +#define MEMBER_INDEX 3 +#define OODATE_INDEX 4 +#define ALLSRC_INDEX 5 +#define IMPSRC_INDEX 6 +extern char *Varq_Value(int, GNode *); +extern void Varq_Set(int, const char *, GNode *); +extern void Varq_Append(int, const char *, GNode *); + +/* SymTable_Init(t); + * Inits the local symtable in a GNode. */ +extern void SymTable_Init(SymTable *); +/* SymTable_destroy(t); + * Destroys the local symtable in a GNode. */ +extern void SymTable_Destroy(SymTable *); + +/* Several ways to parse a variable specification. */ +/* value = Var_Parse(varspec, ctxt, undef_is_bad, &length, &freeit); + * Parses a variable specification varspec and evaluates it in context + * ctxt. Returns the resulting value, freeit indicates whether it's + * a copy that should be freed when no longer needed. If it's not a + * copy, it's only valid until the next time variables are set. + * The length of the spec is returned in length, e.g., varspec begins + * at the $ and ends at the closing } or ). Returns special value + * var_Error if a problem occurred. */ +extern char *Var_Parse(const char *, SymTable *, bool, size_t *, + bool *); +/* Note that var_Error is an instance of the empty string "", so that + * callers who don't care don't need to. */ +extern char var_Error[]; + +/* length = Var_ParseSkip(varspec, ctxt, &ok); + * Parses a variable specification and returns the specification + * length. Fills ok if the varspec is correct, that pointer can be + * NULL if this information is not needed. */ +extern size_t Var_ParseSkip(const char *, SymTable *, bool *); + +/* ok = Var_ParseBuffer(buf, varspec, ctxt, undef_is_bad, &length); + * Similar to Var_Parse, except the value is directly appended to + * buffer buf. */ +extern bool Var_ParseBuffer(Buffer, const char *, SymTable *, + bool, size_t *); + + +/* The substitution itself */ +/* subst = Var_Subst(str, ctxt, undef_is_bad); + * Substitutes all variable values in string str under context ctxt. + * Emit a PARSE_FATAL error if undef_is_bad and an undef variable is + * encountered. The result is always a copy that should be free. */ +extern char *Var_Subst(const char *, SymTable *, bool); + +/* Var_SubstVar(buf, str, varname, val); + * Substitutes variable varname with value val in string str, adding + * the result to buffer buf. undefs are never error. */ +extern void Var_SubstVar(Buffer, const char *, const char *, const char *); + +/* Note that substituting to a buffer in Var_Subst is not useful. On the + * other hand, handling intervals in Var_Subst and Var_Parse would be + * useful, but this is hard. */ + +/* Var_Dump(); + * Print out all global variables. */ +extern void Var_Dump(void); + +/* Var_AddCmdline(name); + * Add all variable values from VAR_CMD to variable name. + * Used to propagate variable values to submakes through MAKEFLAGS. */ +extern void Var_AddCmdline(const char *); + + +extern bool oldVars; /* Do old-style variable substitution */ + +extern bool checkEnvFirst; /* true if environment should be searched for + * variables before the global context */ + +#endif diff --git a/usr.bin/make/var_int.h b/usr.bin/make/var_int.h new file mode 100644 index 00000000000..5b3489e4b4e --- /dev/null +++ b/usr.bin/make/var_int.h @@ -0,0 +1,56 @@ +#ifndef VAR_INT_H +#define VAR_INT_H +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* Special variable names for hashing */ +#define TARGET "@" /* Target of dependency */ +#define OODATE "?" /* All out-of-date sources */ +#define ALLSRC ">" /* All sources */ +#define IMPSRC "<" /* Source implied by transformation */ +#define PREFIX "*" /* Common prefix */ +#define ARCHIVE "!" /* Archive in "archive(member)" syntax */ +#define MEMBER "%" /* Member in "archive(member)" syntax */ +#define LONGTARGET ".TARGET" +#define LONGOODATE ".OODATE" +#define LONGALLSRC ".ALLSRC" +#define LONGIMPSRC ".IMPSRC" +#define LONGPREFIX ".PREFIX" +#define LONGARCHIVE ".ARCHIVE" +#define LONGMEMBER ".MEMBER" + +/* System V extended variables (get directory/file part) */ +#define FTARGET "@F" +#define DTARGET "@D" +#define FIMPSRC "<F" +#define DIMPSRC "<D" +#define FPREFIX "*F" +#define DPREFIX "*D" +#define FARCHIVE "!F" +#define DARCHIVE "!D" +#define FMEMBER "%F" +#define DMEMBER "%D" + +#endif diff --git a/usr.bin/make/varmodifiers.c b/usr.bin/make/varmodifiers.c index 90d3fa70362..6ab61637c49 100644 --- a/usr.bin/make/varmodifiers.c +++ b/usr.bin/make/varmodifiers.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: varmodifiers.c,v 1.8 2001/05/07 22:59:33 espie Exp $ */ +/* $OpenBSD: varmodifiers.c,v 1.9 2001/05/23 12:34:52 espie Exp $ */ /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */ /* @@ -70,14 +70,28 @@ * is also called directly by Var_SubstVar. */ -#include <ctype.h> +#include <ctype.h> +#include <sys/types.h> #ifndef MAKE_BOOTSTRAP -#include <sys/types.h> -#include <regex.h> +#include <regex.h> #endif -#include "make.h" +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "defines.h" #include "buf.h" +#include "var.h" #include "varmodifiers.h" +#include "varname.h" +#include "targ.h" +#include "error.h" +#include "str.h" +#include "cmd_exec.h" +#include "memory.h" +#include "gnode.h" + /* Var*Pattern flags */ #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */ @@ -105,23 +119,23 @@ struct LoopStuff { char *var; char *expand; SymTable *ctxt; - Boolean err; + bool err; }; -static Boolean VarHead(struct Name *, Boolean, Buffer, void *); -static Boolean VarTail(struct Name *, Boolean, Buffer, void *); -static Boolean VarSuffix(struct Name *, Boolean, Buffer, void *); -static Boolean VarRoot(struct Name *, Boolean, Buffer, void *); -static Boolean VarMatch(struct Name *, Boolean, Buffer, void *); -static Boolean VarSYSVMatch(struct Name *, Boolean, Buffer, void *); -static Boolean VarNoMatch(struct Name *, Boolean, Buffer, void *); -static Boolean VarUniq(struct Name *, Boolean, Buffer, void *); -static Boolean VarLoop(struct Name *, Boolean, Buffer, void *); +static bool VarHead(struct Name *, bool, Buffer, void *); +static bool VarTail(struct Name *, bool, Buffer, void *); +static bool VarSuffix(struct Name *, bool, Buffer, void *); +static bool VarRoot(struct Name *, bool, Buffer, void *); +static bool VarMatch(struct Name *, bool, Buffer, void *); +static bool VarSYSVMatch(struct Name *, bool, Buffer, void *); +static bool VarNoMatch(struct Name *, bool, Buffer, void *); +static bool VarUniq(struct Name *, bool, Buffer, void *); +static bool VarLoop(struct Name *, bool, Buffer, void *); #ifndef MAKE_BOOTSTRAP static void VarREError(int, regex_t *, const char *); -static Boolean VarRESubstitute(struct Name *, Boolean, Buffer, void *); +static bool VarRESubstitute(struct Name *, bool, Buffer, void *); static char *do_regex(const char *, const struct Name *, void *); typedef struct { @@ -133,16 +147,16 @@ typedef struct { } VarREPattern; #endif -static Boolean VarSubstitute(struct Name *, Boolean, Buffer, void *); +static bool VarSubstitute(struct Name *, bool, Buffer, void *); static char *VarGetPattern(SymTable *, int, const char **, int, int, size_t *, VarPattern *); static char *VarQuote(const char *, const struct Name *, void *); -static char *VarModify(char *, Boolean (*)(struct Name *, Boolean, Buffer, void *), void *); +static char *VarModify(char *, bool (*)(struct Name *, bool, Buffer, void *), void *); -static void *check_empty(const char **, SymTable *, Boolean, int); +static void *check_empty(const char **, SymTable *, bool, int); static char *do_upper(const char *, const struct Name *, void *); static char *do_lower(const char *, const struct Name *, void *); -static void *check_shcmd(const char **, SymTable *, Boolean, int); +static void *check_shcmd(const char **, SymTable *, bool, int); static char *do_shcmd(const char *, const struct Name *, void *); static char *do_sort(const char *, const struct Name *, void *); static char *finish_loop(const char *, const struct Name *, void *); @@ -154,53 +168,53 @@ static char *do_undef(const char *, const struct Name *, void *); static char *do_assign(const char *, const struct Name *, void *); static char *do_exec(const char *, const struct Name *, void *); -static void *assign_get_value(const char **, SymTable *, Boolean, int); -static void *get_cmd(const char **, SymTable *, Boolean, int); -static void *get_value(const char **, SymTable *, Boolean, int); -static void *get_stringarg(const char **, SymTable *, Boolean, int); +static void *assign_get_value(const char **, SymTable *, bool, int); +static void *get_cmd(const char **, SymTable *, bool, int); +static void *get_value(const char **, SymTable *, bool, int); +static void *get_stringarg(const char **, SymTable *, bool, int); static void free_stringarg(void *); -static void *get_patternarg(const char **, SymTable *, Boolean, int); -static void *get_spatternarg(const char **, SymTable *, Boolean, int); +static void *get_patternarg(const char **, SymTable *, bool, int); +static void *get_spatternarg(const char **, SymTable *, bool, int); static void free_patternarg(void *); static void free_looparg(void *); -static void *get_sysvpattern(const char **, SymTable *, Boolean, int); -static void *get_loop(const char **, SymTable *, Boolean, int); +static void *get_sysvpattern(const char **, SymTable *, bool, int); +static void *get_loop(const char **, SymTable *, bool, int); static char *LoopGrab(const char **); static struct Name dummy; static struct Name *dummy_arg = &dummy; static struct modifier { - Boolean atstart; - void * (*getarg)(const char **, SymTable *, Boolean, int); + bool atstart; + void * (*getarg)(const char **, SymTable *, bool, int); char * (*apply)(const char *, const struct Name *, void *); - Boolean (*word_apply)(struct Name *, Boolean, Buffer, void *); + bool (*word_apply)(struct Name *, bool, Buffer, void *); void (*freearg)(void *); } *choose_mod[256], - match_mod = {FALSE, get_stringarg, NULL, VarMatch, free_stringarg}, - nomatch_mod = {FALSE, get_stringarg, NULL, VarNoMatch, free_stringarg}, - subst_mod = {FALSE, get_spatternarg, NULL, VarSubstitute, free_patternarg}, + match_mod = {false, get_stringarg, NULL, VarMatch, free_stringarg}, + nomatch_mod = {false, get_stringarg, NULL, VarNoMatch, free_stringarg}, + subst_mod = {false, get_spatternarg, NULL, VarSubstitute, free_patternarg}, #ifndef MAKE_BOOTSTRAP - resubst_mod = {FALSE, get_patternarg, do_regex, NULL, free_patternarg}, + resubst_mod = {false, get_patternarg, do_regex, NULL, free_patternarg}, #endif - quote_mod = {FALSE, check_empty, VarQuote, NULL , NULL}, - tail_mod = {FALSE, check_empty, NULL, VarTail, NULL}, - head_mod = {FALSE, check_empty, NULL, VarHead, NULL}, - suffix_mod = {FALSE, check_empty, NULL, VarSuffix, NULL}, - root_mod = {FALSE, check_empty, NULL, VarRoot, NULL}, - upper_mod = {FALSE, check_empty, do_upper, NULL, NULL}, - lower_mod = {FALSE, check_empty, do_lower, NULL, NULL}, - shcmd_mod = {FALSE, check_shcmd, do_shcmd, NULL, NULL}, - sysv_mod = {FALSE, get_sysvpattern, NULL, VarSYSVMatch, free_patternarg}, - uniq_mod = {FALSE, check_empty, NULL, VarUniq, NULL}, - sort_mod = {FALSE, check_empty, do_sort, NULL, NULL}, - loop_mod = {FALSE, get_loop, finish_loop, VarLoop, free_looparg}, - undef_mod = {TRUE, get_value, do_undef, NULL, NULL}, - def_mod = {TRUE, get_value, do_def, NULL, NULL}, - label_mod = {TRUE, check_empty, do_label, NULL, NULL}, - path_mod = {TRUE, check_empty, do_path, NULL, NULL}, - assign_mod = {TRUE, assign_get_value, do_assign, NULL, free_patternarg}, - exec_mod = {TRUE, get_cmd, do_exec, NULL, free_patternarg} + quote_mod = {false, check_empty, VarQuote, NULL , NULL}, + tail_mod = {false, check_empty, NULL, VarTail, NULL}, + head_mod = {false, check_empty, NULL, VarHead, NULL}, + suffix_mod = {false, check_empty, NULL, VarSuffix, NULL}, + root_mod = {false, check_empty, NULL, VarRoot, NULL}, + upper_mod = {false, check_empty, do_upper, NULL, NULL}, + lower_mod = {false, check_empty, do_lower, NULL, NULL}, + shcmd_mod = {false, check_shcmd, do_shcmd, NULL, NULL}, + sysv_mod = {false, get_sysvpattern, NULL, VarSYSVMatch, free_patternarg}, + uniq_mod = {false, check_empty, NULL, VarUniq, NULL}, + sort_mod = {false, check_empty, do_sort, NULL, NULL}, + loop_mod = {false, get_loop, finish_loop, VarLoop, free_looparg}, + undef_mod = {true, get_value, do_undef, NULL, NULL}, + def_mod = {true, get_value, do_def, NULL, NULL}, + label_mod = {true, check_empty, do_label, NULL, NULL}, + path_mod = {true, check_empty, do_path, NULL, NULL}, + assign_mod = {true, assign_get_value, do_assign, NULL, free_patternarg}, + exec_mod = {true, get_cmd, do_exec, NULL, free_patternarg} ; void @@ -251,20 +265,20 @@ VarModifiers_Init() * buffer. *----------------------------------------------------------------------- */ -static Boolean +static bool VarHead(word, addSpace, buf, dummy) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *dummy UNUSED; { const char *slash; - slash = lastchar(word->s, word->e, '/'); + slash = Str_rchri(word->s, word->e, '/'); if (slash != NULL) { if (addSpace) Buf_AddSpace(buf); - Buf_AddInterval(buf, word->s, slash); + Buf_Addi(buf, word->s, slash); } else { /* If no directory part, give . (q.v. the POSIX standard). */ if (addSpace) @@ -272,7 +286,7 @@ VarHead(word, addSpace, buf, dummy) else Buf_AddChar(buf, '.'); } - return TRUE; + return true; } /*- @@ -282,10 +296,10 @@ VarHead(word, addSpace, buf, dummy) * buffer. *----------------------------------------------------------------------- */ -static Boolean +static bool VarTail(word, addSpace, buf, dummy) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *dummy UNUSED; { @@ -293,12 +307,12 @@ VarTail(word, addSpace, buf, dummy) if (addSpace) Buf_AddSpace(buf); - slash = lastchar(word->s, word->e, '/'); + slash = Str_rchri(word->s, word->e, '/'); if (slash != NULL) - Buf_AddInterval(buf, slash+1, word->e); + Buf_Addi(buf, slash+1, word->e); else - Buf_AddInterval(buf, word->s, word->e); - return TRUE; + Buf_Addi(buf, word->s, word->e); + return true; } /*- @@ -307,21 +321,21 @@ VarTail(word, addSpace, buf, dummy) * Add the suffix of the given word to the given buffer. *----------------------------------------------------------------------- */ -static Boolean +static bool VarSuffix(word, addSpace, buf, dummy) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *dummy UNUSED; { const char *dot; - dot = lastchar(word->s, word->e, '.'); + dot = Str_rchri(word->s, word->e, '.'); if (dot != NULL) { if (addSpace) Buf_AddSpace(buf); - Buf_AddInterval(buf, dot+1, word->e); - addSpace = TRUE; + Buf_Addi(buf, dot+1, word->e); + addSpace = true; } return addSpace; } @@ -333,10 +347,10 @@ VarSuffix(word, addSpace, buf, dummy) * buffer. *----------------------------------------------------------------------- */ -static Boolean +static bool VarRoot(word, addSpace, buf, dummy) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *dummy UNUSED; { @@ -344,12 +358,12 @@ VarRoot(word, addSpace, buf, dummy) if (addSpace) Buf_AddSpace(buf); - dot = lastchar(word->s, word->e, '.'); + dot = Str_rchri(word->s, word->e, '.'); if (dot != NULL) - Buf_AddInterval(buf, word->s, dot); + Buf_Addi(buf, word->s, dot); else - Buf_AddInterval(buf, word->s, word->e); - return TRUE; + Buf_Addi(buf, word->s, word->e); + return true; } /*- @@ -358,18 +372,20 @@ VarRoot(word, addSpace, buf, dummy) * Add the word to the buffer if it matches the given pattern. *----------------------------------------------------------------------- */ -static Boolean +static bool VarMatch(word, addSpace, buf, pattern) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *pattern; /* Pattern the word must match */ { - if (Str_Match(word->s, (const char *)pattern)) { + const char *pat = (const char *)pattern; + + if (Str_Matchi(word->s, word->e, pat, strchr(pat, '\0'))) { if (addSpace) Buf_AddSpace(buf); - Buf_AddInterval(buf, word->s, word->e); - return TRUE; + Buf_Addi(buf, word->s, word->e); + return true; } else return addSpace; } @@ -380,26 +396,28 @@ VarMatch(word, addSpace, buf, pattern) * Add the word to the buffer if it doesn't match the given pattern. *----------------------------------------------------------------------- */ -static Boolean +static bool VarNoMatch(word, addSpace, buf, pattern) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *pattern; /* Pattern the word must not match */ { - if (!Str_Match(word->s, (const char *)pattern)) { + const char *pat = (const char *)pattern; + + if (!Str_Matchi(word->s, word->e, pat, strchr(pat, '\0'))) { if (addSpace) Buf_AddSpace(buf); - Buf_AddInterval(buf, word->s, word->e); - return TRUE; + Buf_Addi(buf, word->s, word->e); + return true; } else return addSpace; } -static Boolean +static bool VarUniq(word, addSpace, buf, lastp) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *lastp; { @@ -410,18 +428,18 @@ VarUniq(word, addSpace, buf, lastp) strncmp(word->s, last->s, word->e - word->s) != 0) { if (addSpace) Buf_AddSpace(buf); - Buf_AddInterval(buf, word->s, word->e); - addSpace = TRUE; + Buf_Addi(buf, word->s, word->e); + addSpace = true; } last->s = word->s; last->e = word->e; return addSpace; } -static Boolean +static bool VarLoop(word, addSpace, buf, vp) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *vp; { @@ -430,7 +448,7 @@ VarLoop(word, addSpace, buf, vp) if (addSpace) Buf_AddSpace(buf); Var_SubstVar(buf, v->expand, v->var, word->s); - return TRUE; + return true; } static char * @@ -504,10 +522,10 @@ do_sort(s, dummy, arg) Buf_Init(&buf, end - s); qsort(t, i, sizeof(struct Name), NameCompare); - Buf_AddInterval(&buf, t[0].s, t[0].e); + Buf_Addi(&buf, t[0].s, t[0].e); for (j = 1; j < i; j++) { Buf_AddSpace(&buf); - Buf_AddInterval(&buf, t[j].s, t[j].e); + Buf_Addi(&buf, t[j].s, t[j].e); } free(t); return Buf_Retrieve(&buf); @@ -523,7 +541,7 @@ do_label(s, n, arg) const struct Name *n; void *arg UNUSED; { - return interval_dup(n->s, n->e); + return Str_dupi(n->s, n->e); } static char * @@ -534,9 +552,9 @@ do_path(s, n, arg) { GNode *gn; - gn = Targ_FindNode(n->s, n->e, TARG_NOCREATE); + gn = Targ_FindNodei(n->s, n->e, TARG_NOCREATE); if (gn == NULL) - return interval_dup(n->s, n->e); + return Str_dupi(n->s, n->e); else return strdup(gn->path); } @@ -581,22 +599,22 @@ do_assign(s, n, arg) switch (v->flags) { case VAR_EQUAL: - Var_Set_interval(n->s, n->e, v->lbuffer, VAR_GLOBAL); + Var_Seti(n->s, n->e, v->lbuffer, VAR_GLOBAL); break; case VAR_MAY_EQUAL: if (s == NULL) - Var_Set_interval(n->s, n->e, v->lbuffer, VAR_GLOBAL); + Var_Seti(n->s, n->e, v->lbuffer, VAR_GLOBAL); break; case VAR_ADD_EQUAL: if (s == NULL) - Var_Set_interval(n->s, n->e, v->lbuffer, VAR_GLOBAL); + Var_Seti(n->s, n->e, v->lbuffer, VAR_GLOBAL); else - Var_Append_interval(n->s, n->e, v->lbuffer, VAR_GLOBAL); + Var_Appendi(n->s, n->e, v->lbuffer, VAR_GLOBAL); break; case VAR_BANG_EQUAL: result = Cmd_Exec(v->lbuffer, &msg); if (result != NULL) { - Var_Set_interval(n->s, n->e, result, VAR_GLOBAL); + Var_Seti(n->s, n->e, result, VAR_GLOBAL); free(result); } else Error(msg, v->lbuffer); @@ -629,10 +647,10 @@ do_exec(s, n, arg) * Used to implement the System V % modifiers. *----------------------------------------------------------------------- */ -static Boolean +static bool VarSYSVMatch(word, addSpace, buf, patp) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *patp; /* Pattern the word must match */ { @@ -646,8 +664,8 @@ VarSYSVMatch(word, addSpace, buf, patp) if ((ptr = Str_SYSVMatch(word->s, pat->lhs, &len)) != NULL) Str_SYSVSubst(buf, pat->rhs, ptr, len); else - Buf_AddInterval(buf, word->s, word->e); - return TRUE; + Buf_Addi(buf, word->s, word->e); + return true; } else return addSpace; } @@ -656,7 +674,7 @@ void * get_sysvpattern(p, ctxt, err, endc) const char **p; SymTable *ctxt UNUSED; - Boolean err UNUSED; + bool err UNUSED; int endc; { VarPattern *pattern; @@ -690,9 +708,9 @@ get_sysvpattern(p, ctxt, err, endc) } pattern = (VarPattern *)emalloc(sizeof(VarPattern)); - pattern->lbuffer = pattern->lhs = interval_dup(*p, cp); + pattern->lbuffer = pattern->lhs = Str_dupi(*p, cp); pattern->leftLen = cp - *p; - pattern->rhs = interval_dup(cp+1, cp2); + pattern->rhs = Str_dupi(cp+1, cp2); pattern->rightLen = cp2 - (cp+1); pattern->flags = 0; *p = cp2; @@ -707,10 +725,10 @@ get_sysvpattern(p, ctxt, err, endc) * result to the given buffer. *----------------------------------------------------------------------- */ -static Boolean +static bool VarSubstitute(word, addSpace, buf, patternp) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *patternp; /* Pattern for substitution */ { @@ -734,7 +752,7 @@ VarSubstitute(word, addSpace, buf, patternp) if (pattern->rightLen != 0) { if (addSpace) Buf_AddSpace(buf); - addSpace = TRUE; + addSpace = true; Buf_AddChars(buf, pattern->rightLen, pattern->rhs); } @@ -748,7 +766,7 @@ VarSubstitute(word, addSpace, buf, patternp) if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){ if (addSpace) Buf_AddSpace(buf); - addSpace = TRUE; + addSpace = true; } Buf_AddChars(buf, pattern->rightLen, pattern->rhs); Buf_AddChars(buf, wordLen - pattern->leftLen, @@ -773,9 +791,9 @@ VarSubstitute(word, addSpace, buf, patternp) if (((cp - word->s) + pattern->rightLen) != 0) { if (addSpace) Buf_AddSpace(buf); - addSpace = TRUE; + addSpace = true; } - Buf_AddInterval(buf, word->s, cp); + Buf_Addi(buf, word->s, cp); Buf_AddChars(buf, pattern->rightLen, pattern->rhs); pattern->flags |= VAR_SUB_MATCHED; } else { @@ -790,29 +808,29 @@ VarSubstitute(word, addSpace, buf, patternp) * remaining part of the word (word and wordLen are adjusted * accordingly through the loop) is copied straight into the * buffer. - * addSpace is set to FALSE as soon as a space is added to the + * addSpace is set to false as soon as a space is added to the * buffer. */ - Boolean done; + bool done; size_t origSize; - done = FALSE; + done = false; origSize = Buf_Size(buf); while (!done) { cp = strstr(word->s, pattern->lhs); if (cp != NULL) { if (addSpace && (cp - word->s) + pattern->rightLen != 0){ Buf_AddSpace(buf); - addSpace = FALSE; + addSpace = false; } - Buf_AddInterval(buf, word->s, cp); + Buf_Addi(buf, word->s, cp); Buf_AddChars(buf, pattern->rightLen, pattern->rhs); wordLen -= (cp - word->s) + pattern->leftLen; word->s = cp + pattern->leftLen; if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0) - done = TRUE; + done = true; pattern->flags |= VAR_SUB_MATCHED; } else - done = TRUE; + done = true; } if (wordLen != 0) { if (addSpace) @@ -830,7 +848,7 @@ VarSubstitute(word, addSpace, buf, patternp) if (addSpace) Buf_AddSpace(buf); Buf_AddChars(buf, wordLen, word->s); - return TRUE; + return true; } #ifndef MAKE_BOOTSTRAP @@ -863,10 +881,10 @@ VarREError(err, pat, str) * result in the passed buffer. *----------------------------------------------------------------------- */ -static Boolean +static bool VarRESubstitute(word, addSpace, buf, patternp) struct Name *word; - Boolean addSpace; + bool addSpace; Buffer buf; void *patternp; { @@ -984,17 +1002,17 @@ static char * VarModify(str, modProc, datum) char *str; /* String whose words should be trimmed */ /* Function to use to modify them */ - Boolean (*modProc)(struct Name *, Boolean, Buffer, void *); + bool (*modProc)(struct Name *, bool, Buffer, void *); void *datum; /* Datum to pass it */ { BUFFER buf; /* Buffer for the new string */ - Boolean addSpace; /* TRUE if need to add a space to the + bool addSpace; /* true if need to add a space to the * buffer before adding the trimmed * word */ struct Name word; Buf_Init(&buf, 0); - addSpace = FALSE; + addSpace = false; word.e = str; @@ -1124,7 +1142,7 @@ static void * check_empty(p, ctxt, b, endc) const char **p; SymTable *ctxt UNUSED; - Boolean b UNUSED; + bool b UNUSED; int endc; { dummy_arg->s = NULL; @@ -1139,7 +1157,7 @@ static void * check_shcmd(p, ctxt, b, endc) const char **p; SymTable *ctxt UNUSED; - Boolean b UNUSED; + bool b UNUSED; int endc; { if ((*p)[1] == 'h' && ((*p)[2] == endc || (*p)[2] == ':')) { @@ -1169,7 +1187,7 @@ static void * get_stringarg(p, ctxt, b, endc) const char **p; SymTable *ctxt UNUSED; - Boolean b UNUSED; + bool b UNUSED; int endc; { const char *cp; @@ -1182,7 +1200,7 @@ get_stringarg(p, ctxt, b, endc) } else if (*cp == '\0') return NULL; } - s = escape_dup(*p+1, cp, ":)}"); + s = escape_dupi(*p+1, cp, ":)}"); *p = cp; return s; } @@ -1233,7 +1251,7 @@ static void * get_spatternarg(p, ctxt, err, endc) const char **p; SymTable *ctxt; - Boolean err; + bool err; int endc; { VarPattern *pattern; @@ -1277,14 +1295,14 @@ LoopGrab(s) return NULL; } *s = p+1; - return escape_dup(start, p, "@\\"); + return escape_dupi(start, p, "@\\"); } static void * get_loop(p, ctxt, err, endc) const char **p; SymTable *ctxt; - Boolean err; + bool err; int endc; { static struct LoopStuff loop; @@ -1312,7 +1330,7 @@ static void * get_patternarg(p, ctxt, err, endc) const char **p; SymTable *ctxt; - Boolean err; + bool err; int endc; { VarPattern *pattern; @@ -1364,7 +1382,7 @@ static void * assign_get_value(p, ctxt, err, endc) const char **p; SymTable *ctxt; - Boolean err; + bool err; int endc; { const char *s; @@ -1395,7 +1413,7 @@ static void * get_value(p, ctxt, err, endc) const char **p; SymTable *ctxt; - Boolean err; + bool err; int endc; { VarPattern *pattern; @@ -1418,7 +1436,7 @@ static void * get_cmd(p, ctxt, err, endc) const char **p; SymTable *ctxt; - Boolean err; + bool err; int endc UNUSED; { VarPattern *pattern; @@ -1485,14 +1503,14 @@ VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) char *str; const struct Name *name; SymTable *ctxt; - Boolean err; - Boolean *freePtr; + bool err; + bool *freePtr; const char *start; int endc; size_t *lengthPtr; { const char *tstr; - Boolean atstart; /* Some ODE modifiers only make sense at start */ + bool atstart; /* Some ODE modifiers only make sense at start */ tstr = start; /* @@ -1515,7 +1533,7 @@ VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) * the invocation. */ - atstart = TRUE; + atstart = true; while (*tstr != endc && *tstr != '\0') { struct modifier *mod; void *arg; @@ -1534,7 +1552,7 @@ VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) mod = &sysv_mod; arg = mod->getarg(&tstr, ctxt, err, endc); } - atstart = FALSE; + atstart = false; if (arg != NULL) { if (str != NULL || (mod->atstart && name != NULL)) { if (mod->word_apply != NULL) { @@ -1552,9 +1570,9 @@ VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) free(str); str = newStr; if (str != var_Error) - *freePtr = TRUE; + *freePtr = true; else - *freePtr = FALSE; + *freePtr = false; } if (mod->freearg != NULL) mod->freearg(arg); @@ -1566,7 +1584,7 @@ VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) if (str != NULL && *freePtr) free(str); str = var_Error; - freePtr = FALSE; + freePtr = false; break; } if (DEBUG(VAR)) @@ -1579,14 +1597,6 @@ VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) return str; } -/*- - *----------------------------------------------------------------------- - * Var_GetHead -- - * Find the leading components of a (list of) filename(s). - * XXX: VarHead does not replace foo by ., as (sun) System V make - * does. - *----------------------------------------------------------------------- - */ char * Var_GetHead(s) char *s; @@ -1594,13 +1604,6 @@ Var_GetHead(s) return VarModify(s, VarHead, NULL); } -/*- - *----------------------------------------------------------------------- - * Var_GetTail -- - * Return the tail from each of a list of words. Used to set the - * System V local variables. - *----------------------------------------------------------------------- - */ char * Var_GetTail(s) char *s; diff --git a/usr.bin/make/varmodifiers.h b/usr.bin/make/varmodifiers.h index 227459ca6e8..590e86fa612 100644 --- a/usr.bin/make/varmodifiers.h +++ b/usr.bin/make/varmodifiers.h @@ -1,5 +1,8 @@ +#ifndef VARMODIFIERS_H +#define VARMODIFIERS_H + /* $OpenPackages$ */ -/* $OpenBSD: varmodifiers.h,v 1.2 2001/05/03 13:41:15 espie Exp $ */ +/* $OpenBSD: varmodifiers.h,v 1.3 2001/05/23 12:34:52 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -27,11 +30,35 @@ * (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 VARMODIFIERS_H -#define VARMODIFIERS_H + +/* VarModifiers_Init(); + * Set up varmodifiers internal table according to selected features. + * This can be called several times without harm. */ +extern void VarModifiers_Init(void); + + +/* result = VarModifiers_Apply(val, name, ctxt, undef_is_bad, + * &should_free, modstart, endc, &length); + * Applies variable modifiers starting at modstart (including :), + * ending with character endc, to value val. + * Variables in spec are taken from context ctxt. + * If undef_is_bad, error occurs if undefined variables are mentioned. + * length is filled with the total length of the modifier spec. + * name holds the name of the corresponding variable, as some ODE + * modifiers need it. + * + * If both val and name are NULL, VarModifiers_Apply just parses the + * modifiers specification, as it can't apply it to anything. */ extern char *VarModifiers_Apply(char *, const struct Name *, SymTable *, - Boolean, Boolean *, const char *, int, size_t *); + bool, bool *, const char *, int, size_t *); + +/* Direct interface to specific modifiers used under special circumstances. */ +/* tails = Var_GetTail(string); + * Returns the tail of list of words in string (needed for SysV locals). */ extern char *Var_GetTail(char *); +/* heads = Var_GetHead(string); + * Returns the head of list of words in string. */ +/* XXX this does not replace foo with ., as (sun) System V make does. + * Should it ? */ extern char *Var_GetHead(char *); -extern void VarModifiers_Init(void); #endif diff --git a/usr.bin/make/varname.c b/usr.bin/make/varname.c new file mode 100644 index 00000000000..51a30aa277e --- /dev/null +++ b/usr.bin/make/varname.c @@ -0,0 +1,83 @@ +/* $OpenPackages$ */ +/* $OpenBSD: varname.c,v 1.1 2001/05/23 12:34:52 espie Exp $ */ +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +#include <stdlib.h> +#include "config.h" +#include "defines.h" +#include "var.h" +#include "buf.h" +#include "varname.h" + +const char * +VarName_Get(start, name, ctxt, err, cont) + const char *start; + struct Name *name; + SymTable *ctxt; + bool err; + const char *(*cont)(const char *); +{ + const char *p; + size_t len; + + p = cont(start); + /* If we don't want recursive variables, we skip over '$' */ + if (!FEATURES(FEATURE_RECVARS)) { + while (*p == '$') + p = cont(p); + } + if (*p != '$') { + name->s = start; + name->e = p; + name->tofree = false; + return p; + } else { + BUFFER buf; + Buf_Init(&buf, MAKE_BSIZE); + for (;;) { + Buf_Addi(&buf, start, p); + if (*p != '$') { + name->s = (const char *)Buf_Retrieve(&buf); + name->e = name->s + Buf_Size(&buf); + name->tofree = true; + return p; + } + start = p; + Var_ParseBuffer(&buf, start, ctxt, err, &len); + start += len; + p = cont(start); + } + } +} + +void +VarName_Free(name) + struct Name *name; +{ + if (name->tofree) + free((char *)name->s); +} + diff --git a/usr.bin/make/varname.h b/usr.bin/make/varname.h new file mode 100644 index 00000000000..8394eb644eb --- /dev/null +++ b/usr.bin/make/varname.h @@ -0,0 +1,56 @@ +#ifndef VARNAME_H +#define VARNAME_H +/* + * Copyright (c) 2001 Marc Espie. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT 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 OPENBSD + * PROJECT 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. + */ + +/* varname - + * Handles variable names in recursive situations, e.g., + * to expand ${A${BC}}. + */ + +/* Used to store temporary names, e.g., after $ expansion. */ +struct Name { + const char *s; /* Start of name. */ + const char *e; /* End of name. */ + bool tofree; /* Needs freeing after use ? */ +}; + +/* endpos = VarName_Get(startpos, &name, ctxt, undef_is_bad, cont_function); + * Gets a variable name from startpos, storing the result into name. + * Recursive names are expanded from context ctxt. Boolean + * undef_is_bad governs whether undefined variables should trigger a + * parse error. To parse its argument efficiently, VarName_Get + * uses cont_function(pos), which should return the position of the + * next $ in string, or the position where the variable spec ends (as + * differing modules have different requirements wrt variable spec + * endings). Returns the position where the variable spec finally + * ends. Name result might be a copy, or not. */ +extern const char *VarName_Get(const char *, struct Name *, SymTable *, + bool, const char *(*)(const char *)); +/* VarName_Free(name); + * Frees a variable name filled by VarName_Get(). */ +extern void VarName_Free(struct Name *); + +#endif |