diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2001-05-03 13:41:28 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2001-05-03 13:41:28 +0000 |
commit | 32d5cfe8f4f4bd9647d36fc0f609479f02311103 (patch) | |
tree | 06bd5d3e7a2a46bf77a1da707955bfdc16acf068 /usr.bin/make | |
parent | a50fea6f0032902e640160d4c42a8c9ce003fc2d (diff) |
Synch with my current work.
Numerous changes:
- generate can build several tables
- style cleanup
- statistics code
- use variable names throughout (struct Name)
- recursive variables everywhere
- faster parser (pass buffer along instead of allocating multiple copies)
- correct parser. Handles comments everywhere, and ; correctly
- more string intervals
- simplified dir.c, less recursion.
- extended for loops
- sinclude()
- finished removing extra junk from Lst_*
- handles ${@D} and friends in a simpler way
- cleaned up and modular VarModifiers handling.
- recognizes some gnu Makefile usages and errors out about them.
Additionally, some extra functionality is defined by FEATURES. The set of
functionalities is currently hardcoded to OpenBSD defaults, but this may
include support for some NetBSD extensions, like ODE modifiers.
Backed by miod@ and millert@, who finally got sick of my endless patches...
Diffstat (limited to 'usr.bin/make')
61 files changed, 7123 insertions, 7612 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile index 107a0893eb6..9eee31f2b98 100644 --- a/usr.bin/make/Makefile +++ b/usr.bin/make/Makefile @@ -1,7 +1,8 @@ -# $OpenBSD: Makefile,v 1.25 2001/03/02 16:57:26 espie Exp $ +# $OpenBSD: Makefile,v 1.26 2001/05/03 13:40:59 espie Exp $ PROG= make -CFLAGS+= -I${.OBJDIR} -I${.CURDIR} -Wall -Wno-char-subscripts -Wstrict-prototypes +CFLAGS+= -I${.OBJDIR} -I${.CURDIR} ${WARNINGS} +WARNINGS=-Wall -W -Wno-char-subscripts -Wstrict-prototypes -pedantic #-Wmissing-prototypes CFLAGS+=-DUSE_TIMESPEC .if (${MACHINE_ARCH} == "m88k") @@ -9,28 +10,30 @@ 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 suff.c targ.c var.c varmodifiers.c #util.c -SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \ - lstConcatDestroy.c lstDeQueue.c lstDestroy.c lstDupl.c lstEnQueue.c \ - lstFindFrom.c lstForEachFrom.c \ - lstInit.c lstInsert.c lstIsAtEnd.c lstIsEmpty.c \ - lstMember.c lstNext.c lstOpen.c lstRemove.c lstReplace.c lstSucc.c + main.c make.c parse.c str.c stats.c suff.c targ.c var.c varmodifiers.c #util.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 .PATH: ${.CURDIR}/lst.lib CLEANFILES+=generate hashconsts.h generate.o regress.o check CLEANFILES+=${LIBOBJS} libohash.a -CLEANFILES+= hashconsts.h generate.o generate +CLEANFILES+= varhashconsts.h condhashconsts.h generate.o generate -beforedepend: hashconsts.h +beforedepend: varhashconsts.h condhashconsts.h # may need tweaking if you add variable synonyms or change the hash function -MAGICSLOTS=34 +MAGICVARSLOTS=77 +MAGICCONDSLOTS=43 -hashconsts.h: generate - ${.OBJDIR}/generate ${MAGICSLOTS} >${.TARGET} +varhashconsts.h: generate + ${.OBJDIR}/generate 1 ${MAGICVARSLOTS} >${.TARGET} -generate: generate.o error.o +condhashconsts.h: generate + ${.OBJDIR}/generate 2 ${MAGICCONDSLOTS} >${.TARGET} + +generate: generate.o stats.o error.o ${CC} -o ${.TARGET} ${CFLAGS} ${.ALLSRC} ${LDADD} check: regress.o str.o error.o buf.o @@ -40,10 +43,12 @@ regress: check ${.OBJDIR}/check # kludge for people who forget to make depend -var.o: hashconsts.h +var.o: varhashconsts.h .if make(install) SUBDIR+= PSD.doc .endif +.PHONY: regress + .include <bsd.prog.mk> diff --git a/usr.bin/make/arch.c b/usr.bin/make/arch.c index b191fe4b089..0412720e2d9 100644 --- a/usr.bin/make/arch.c +++ b/usr.bin/make/arch.c @@ -1,8 +1,9 @@ -/* $OpenBSD: arch.c,v 1.43 2001/03/02 16:57:26 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: arch.c,v 1.44 2001/05/03 13:41:00 espie Exp $ */ /* $NetBSD: arch.c,v 1.17 1996/11/06 17:58:59 christos Exp $ */ /* - * Copyright (c) 2000 Marc Espie. + * Copyright (c) 1999,2000 Marc Espie. * * Extensive code changes for the OpenBSD project. * @@ -76,53 +77,53 @@ * 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_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_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_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*, return TRUE if - * exists. The time is placed in the member's - * GNode. Returns the modification time. + * 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_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_FindLib Search for a library along a path. The + * library name in the GNode should be in + * -l<name> format. * - * Arch_LibOODate Special function to decide if a library node - * is out-of-date. + * Arch_LibOODate Special function to decide if a library node + * is out-of-date. * - * Arch_Init Initialize this module. + * Arch_Init Initialize this module. * - * Arch_End Cleanup this module. + * Arch_End Cleanup this module. */ #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/param.h> -#include <stddef.h> +#include <assert.h> #include <ctype.h> #include <ar.h> -#include <assert.h> #include <utime.h> #include <stdio.h> +#include <stddef.h> #include <stdlib.h> #include <fcntl.h> #include "make.h" @@ -135,10 +136,11 @@ static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: arch.c,v 1.43 2001/03/02 16:57:26 espie Exp $"; +static char rcsid[] = "$OpenBSD: arch.c,v 1.44 2001/05/03 13:41:00 espie Exp $"; #endif #endif /* not lint */ + #ifdef TARGET_MACHINE #undef MACHINE #define MACHINE TARGET_MACHINE @@ -148,48 +150,50 @@ static char rcsid[] = "$OpenBSD: arch.c,v 1.43 2001/03/02 16:57:26 espie Exp $"; #define MACHINE_ARCH TARGET_MACHINE_ARCH #endif -static struct ohash archives; /* Archives we've already examined */ +static struct ohash archives; /* Archives we've already examined. */ typedef struct Arch_ { - struct ohash members; /* All the members of this archive, as - * struct arch_member entries. */ - char name[1]; /* Archive name */ + struct ohash members; /* All the members of this archive, as + * struct arch_member entries. */ + char name[1]; /* Archive name. */ } Arch; /* Used to get to ar's field sizes. */ static struct ar_hdr *dummy; -#define AR_NAME_SIZE (sizeof(dummy->ar_name)) +#define AR_NAME_SIZE (sizeof(dummy->ar_name)) #define AR_DATE_SIZE (sizeof(dummy->ar_date)) -/* Each archive member is tied to an arch_member structure, +/* Each archive member is tied to an arch_member structure, * suitable for hashing. */ struct arch_member { TIMESTAMP mtime; /* Member modification date. */ - char date[AR_DATE_SIZE+1]; - /* Same, before conversion to numeric value. */ + char date[AR_DATE_SIZE+1]; + /* Same, before conversion to numeric value. */ char name[1]; /* Member name. */ }; static struct ohash_info members_info = { - offsetof(struct arch_member, name), NULL, - hash_alloc, hash_free, element_alloc + offsetof(struct arch_member, name), NULL, + hash_alloc, hash_free, element_alloc }; static struct ohash_info arch_info = { - offsetof(Arch, name), NULL, hash_alloc, hash_free, element_alloc + offsetof(Arch, name), NULL, hash_alloc, hash_free, element_alloc }; -static struct arch_member *new_arch_member __P((struct ar_hdr *, const char *)); -static TIMESTAMP mtime_of_member __P((struct arch_member *)); -static long field2long __P((const char *, size_t)); -static Arch *read_archive __P((const char *, const char *)); + + +static struct arch_member *new_arch_member(struct ar_hdr *, const char *); +static TIMESTAMP mtime_of_member(struct arch_member *); +static long field2long(const char *, size_t); +static Arch *read_archive(const char *, const char *); #ifdef CLEANUP -static void ArchFree __P((Arch *)); +static void ArchFree(Arch *); #endif -static TIMESTAMP ArchMTimeMember __P((const char *, const char *, Boolean)); -static FILE *ArchFindMember __P((const char *, const char *, struct ar_hdr *, const char *)); -static void ArchTouch __P((const char *, const char *)); +static TIMESTAMP ArchMTimeMember(const char *, const char *, Boolean); +static FILE *ArchFindMember(const char *, const char *, struct ar_hdr *, const char *); +static void ArchTouch(const char *, const char *); #if defined(__svr4__) || defined(__SVR4) || \ (defined(__OpenBSD__) && defined(__mips__)) || \ (defined(__OpenBSD__) && defined(__powerpc)) @@ -204,7 +208,7 @@ struct SVR4namelist { static const char *svr4list = "Archive list"; -static char *ArchSVR4Entry __P((struct SVR4namelist *, char *, size_t, FILE *)); +static char *ArchSVR4Entry(struct SVR4namelist *, char *, size_t, FILE *); #endif static struct arch_member * @@ -216,7 +220,7 @@ new_arch_member(hdr, name) struct arch_member *n; n = ohash_create_entry(&members_info, name, &end); - /* XXX ar entries are NOT null terminated. */ + /* XXX ar entries are NOT null terminated. */ memcpy(n->date, &(hdr->ar_date), AR_DATE_SIZE); n->date[AR_DATE_SIZE] = '\0'; /* Don't compute mtime before it is needed. */ @@ -229,7 +233,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); + grab_date((time_t) strtol(m->date, NULL, 10), m->mtime); return m->mtime; } @@ -241,15 +245,15 @@ mtime_of_member(m) *----------------------------------------------------------------------- */ static void -ArchFree(ap) - Arch *a; +ArchFree(a) + Arch *a; { struct arch_member *mem; unsigned int i; /* Free memory from hash entries */ for (mem = ohash_first(&a->members, &i); mem != NULL; - mem = ohash_next(&a->members, &i)) + mem = ohash_next(&a->members, &i)) free(mem); ohash_delete(&a->members); @@ -273,128 +277,88 @@ ArchFree(ap) * * Side Effects: * Some nodes may be created. The given list is extended. - * *----------------------------------------------------------------------- */ ReturnStatus Arch_ParseArchive(linePtr, nodeLst, ctxt) - char **linePtr; /* Pointer to start of specification */ - Lst nodeLst; /* Lst on which to place the nodes */ - SymTable *ctxt; /* Context in which to expand variables */ + char **linePtr; /* Pointer to start of specification */ + Lst nodeLst; /* Lst on which to place the nodes */ + SymTable *ctxt; /* Context in which to expand variables */ { - register char *cp; /* Pointer into line */ - GNode *gn; /* New node */ - char *libName; /* Library-part of specification */ - char *memName; /* Member-part of specification */ + char *cp; /* Pointer into line */ + GNode *gn; /* New node */ + char *libName; /* Library-part of specification */ + 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 + char saveChar; /* Ending delimiter of member-name */ + Boolean subLibName; /* TRUE if libName should have/had * variable substitution performed on it */ libName = *linePtr; subLibName = FALSE; - for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { + for (cp = libName; *cp != '(' && *cp != '\0';) { if (*cp == '$') { - /* - * Variable spec, so call the Var module to parse the puppy - * so we can safely advance beyond it... - */ - size_t length; - Boolean freeIt; - char *result; - - result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt); - if (result == var_Error) { - return(FAILURE); - } else { - subLibName = TRUE; - } + ReturnStatus result; - if (freeIt) { - free(result); - } - cp += length-1; - } + cp += Var_ParseSkip(cp, ctxt, &result); + if (result == FAILURE) + return FAILURE; + subLibName = TRUE; + } else + cp++; } *cp++ = '\0'; - if (subLibName) { + if (subLibName) libName = Var_Subst(libName, ctxt, TRUE); - } - for (;;) { - /* - * First skip to the start of the member's name, mark that + /* First skip to the start of the member's name, mark that * place and skip to the end of it (either white-space or - * a close paren). - */ - Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ + * a close paren). */ + Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ - while (*cp != '\0' && *cp != ')' && isspace (*cp)) { + while (*cp != '\0' && *cp != ')' && isspace(*cp)) cp++; - } memName = cp; - while (*cp != '\0' && *cp != ')' && !isspace (*cp)) { + while (*cp != '\0' && *cp != ')' && !isspace(*cp)) { if (*cp == '$') { - /* - * Variable spec, so call the Var module to parse the puppy - * so we can safely advance beyond it... - */ - size_t length; - Boolean freeIt; - char *result; - - result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt); - if (result == var_Error) { - return(FAILURE); - } else { - doSubst = TRUE; - } - - if (freeIt) { - free(result); - } - cp += length; - } else { + ReturnStatus result; + cp += Var_ParseSkip(cp, ctxt, &result); + if (result == FAILURE) + return FAILURE; + doSubst = TRUE; + } else cp++; - } } - /* - * If the specification ends without a closing parenthesis, + /* If the specification ends without a closing parenthesis, * chances are there's something wrong (like a missing backslash), - * so it's better to return failure than allow such things to happen - */ + * so it's better to return failure than allow such things to + * happen. */ if (*cp == '\0') { printf("No closing parenthesis in archive specification\n"); - return (FAILURE); + return FAILURE; } - /* - * If we didn't move anywhere, we must be done - */ - if (cp == memName) { + /* If we didn't move anywhere, we must be done. */ + if (cp == memName) break; - } saveChar = *cp; *cp = '\0'; - /* - * XXX: This should be taken care of intelligently by - * SuffExpandChildren, both for the archive and the member portions. - */ - /* - * If member contains variables, try and substitute for them. + /* XXX: This should be taken care of intelligently by + * SuffExpandChildren, both for the archive and the member portions. */ + + /* If member contains variables, try and substitute for them. * This will slow down archive specs with dynamic sources, of course, * since we'll be (non-)substituting them three times, but them's * the breaks -- we need to do this since SuffExpandChildren calls * us, otherwise we could assume the thing would be taken care of - * later. - */ + * later. */ if (doSubst) { char *buf; char *sacrifice; @@ -402,113 +366,86 @@ Arch_ParseArchive(linePtr, nodeLst, ctxt) memName = Var_Subst(memName, ctxt, TRUE); - /* - * Now form an archive spec and recurse to deal with nested + /* Now form an archive spec and recurse to deal with nested * variables and multi-word variable values.... The results - * are just placed at the end of the nodeLst we're returning. - */ + * are just placed at the end of the nodeLst we're returning. */ buf = sacrifice = emalloc(strlen(memName)+strlen(libName)+3); sprintf(buf, "%s(%s)", libName, memName); if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { - /* - * Must contain dynamic sources, so we can't deal with it now. + /* Must contain dynamic sources, so we can't deal with it now. * Just create an ARCHV node for the thing and let - * SuffExpandChildren handle it... - */ - gn = Targ_FindNode(buf, TARG_CREATE); + * SuffExpandChildren handle it... */ + gn = Targ_FindNode(buf, NULL, TARG_CREATE); if (gn == NULL) { free(buf); - return(FAILURE); + return FAILURE; } else { gn->type |= OP_ARCHV; Lst_AtEnd(nodeLst, gn); } } else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) { - /* - * Error in nested call -- free buffer and return FAILURE - * ourselves. - */ + /* Error in nested call -- free buffer and return FAILURE + * ourselves. */ free(buf); - return(FAILURE); + return FAILURE; } - /* - * Free buffer and continue with our work. - */ + /* Free buffer and continue with our work. */ free(buf); } else if (Dir_HasWildcards(memName)) { - LIST members; + LIST members; char *member; Lst_Init(&members); + Dir_Expand(memName, &dirSearchPath, &members); while ((member = (char *)Lst_DeQueue(&members)) != NULL) { - - sprintf(nameBuf, "%s(%s)", libName, member); + snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, member); free(member); - gn = Targ_FindNode(nameBuf, TARG_CREATE); - if (gn == NULL) - return (FAILURE); - else { - /* - * 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 the OP_ARCHV bit before we place it on the - * end of the provided list. - */ - gn->type |= OP_ARCHV; - Lst_AtEnd(nodeLst, gn); - } - } - Lst_Destroy(&members, NOFREE); - } else { - sprintf(nameBuf, "%s(%s)", libName, memName); - gn = Targ_FindNode (nameBuf, TARG_CREATE); - if (gn == NULL) { - return (FAILURE); - } else { - /* - * 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 - * the OP_ARCHV bit before we place it on the end of the - * provided list. - */ + gn = Targ_FindNode(nameBuf, NULL, TARG_CREATE); + /* We've found the node, but have to make sure the rest of + * the world knows it's an archive member, without having + * to constantly check for parentheses, so we type the + * thing with the OP_ARCHV bit before we place it on the + * end of the provided list. */ gn->type |= OP_ARCHV; Lst_AtEnd(nodeLst, gn); } + } else { + snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, memName); + gn = Targ_FindNode(nameBuf, NULL, TARG_CREATE); + /* We've found the node, but have to make sure the rest of the + * world knows it's an archive member, without having to + * constantly check for parentheses, so we type the thing with + * the OP_ARCHV bit before we place it on the end of the + * provided list. */ + gn->type |= OP_ARCHV; + Lst_AtEnd(nodeLst, gn); } - if (doSubst) { + if (doSubst) free(memName); - } *cp = saveChar; } - /* - * If substituted libName, free it now, since we need it no longer. - */ - if (subLibName) { + /* If substituted libName, free it now, since we need it no longer. */ + if (subLibName) free(libName); - } - /* - * We promised the pointer would be set up at the next non-space, so + /* We promised the pointer would be set up at the next non-space, so * we must advance cp there before setting *linePtr... (note that on - * entrance to the loop, cp is guaranteed to point at a ')') - */ + * entrance to the loop, cp is guaranteed to point at a ')') */ do { cp++; - } while (*cp != '\0' && isspace (*cp)); + } while (*cp != '\0' && isspace(*cp)); *linePtr = cp; - return (SUCCESS); + return SUCCESS; } -/* Helper function: ar fields are not null terminated. */ +/* Helper function: ar fields are not null terminated. */ static long field2long(field, len) const char *field; @@ -527,10 +464,9 @@ read_archive(archive, end) const char *archive; const char *end; { - FILE *arch; /* Stream to archive */ - char magic[SARMAG]; - Arch *ar; - + FILE * arch; /* Stream to archive */ + char magic[SARMAG]; + Arch *ar; #ifdef SVR4ARCHIVES struct SVR4namelist list; @@ -554,16 +490,16 @@ read_archive(archive, end) ohash_init(&ar->members, 8, &members_info); for (;;) { - size_t n; - struct ar_hdr arh; /* Archive-member header for reading archive */ + size_t n; + struct ar_hdr arh; /* Archive-member header for reading archive */ off_t size; /* Size of archive member */ char buffer[MAXPATHLEN+1]; - char *memName; + char *memName; /* Current member name while hashing. */ - char *cp; /* Useful character pointer */ + char *cp; /* Useful character pointer */ memName = buffer; - n = fread(&arh, 1, sizeof(struct ar_hdr), arch); + n = fread(&arh, 1, sizeof(struct ar_hdr), arch); /* Whole archive read ok. */ if (n == 0 && feof(arch)) { @@ -582,13 +518,13 @@ read_archive(archive, end) } else { /* We need to advance the stream's pointer to the start of the * next header. Records are padded with newlines to an even-byte - * boundary, so we need to extract the size of the record and + * boundary, so we need to extract the size of the record and * round it up during the seek. */ size = (off_t) field2long(arh.ar_size, sizeof(arh.ar_size)); (void)memcpy(memName, arh.ar_name, AR_NAME_SIZE); /* Find real end of name (strip extranous ' ') */ - for (cp = memName + AR_NAME_SIZE - 1; *cp == ' ';) + for (cp = memName + AR_NAME_SIZE - 1; *cp == ' ';) cp--; cp[1] = '\0'; @@ -598,9 +534,9 @@ read_archive(archive, end) if (memName[0] == '/') { /* SVR4 magic mode. */ memName = ArchSVR4Entry(&list, memName, size, arch); - if (memName == NULL) /* Invalid data */ + if (memName == NULL) /* Invalid data */ break; - else if (memName == svr4list) /* List of files entry */ + else if (memName == svr4list) /* List of files entry */ continue; /* Got the entry. */ /* XXX this assumes further processing, such as AR_EFMT1, @@ -619,7 +555,7 @@ read_archive(archive, end) isdigit(memName[sizeof(AR_EFMT1) - 1])) { int elen = atoi(memName + sizeof(AR_EFMT1)-1); - + if (elen <= 0 || elen > MAXPATHLEN) break; memName = buffer; @@ -657,14 +593,12 @@ read_archive(archive, end) * path to the archive and the path to the desired member. * * Results: - * The archive member's modification time, or OUT_OF_DATE if member - * was not found (convenient, so that missing members are always + * The archive member's modification time, or OUT_OF_DATE if member + * was not found (convenient, so that missing members are always * out of date). * * Side Effects: * Cache the whole archive contents if hash is TRUE. - * Locate a member of an archive, given the path of the archive and - * the path of the desired member. *----------------------------------------------------------------------- */ static TIMESTAMP @@ -672,14 +606,13 @@ 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 - * already so. */ + Boolean hash; /* TRUE if archive should be hashed if not + * already so. */ { -#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) - FILE * arch; /* Stream to archive */ + FILE * arch; /* Stream to archive */ Arch *ar; /* Archive descriptor */ - unsigned int slot; /* Place of archive in the archives hash */ - const char *end = NULL; + unsigned int slot; /* Place of archive in the archives hash */ + const char *end = NULL; const char *cp; TIMESTAMP result; @@ -716,9 +649,10 @@ ArchMTimeMember(archive, member, hash) if (ar != NULL) ohash_insert(&archives, slot, ar); } + /* If archive was found, get entry we seek. */ if (ar != NULL) { - struct arch_member *he; + struct arch_member *he; end = NULL; he = ohash_find(&ar->members, ohash_qlookupi(&ar->members, member, &end)); @@ -726,8 +660,8 @@ ArchMTimeMember(archive, member, hash) return mtime_of_member(he); else { if (end - member > AR_NAME_SIZE) { - /* Try truncated name */ - end = member + AR_NAME_SIZE; + /* Try truncated name. */ + end = member + AR_NAME_SIZE; he = ohash_find(&ar->members, ohash_qlookupi(&ar->members, member, &end)); if (he != NULL) @@ -738,7 +672,6 @@ ArchMTimeMember(archive, member, hash) return result; } - #ifdef SVR4ARCHIVES /*- *----------------------------------------------------------------------- @@ -750,13 +683,14 @@ ArchMTimeMember(archive, member, hash) * * Results: * svr4list: just read a list of names - * NULL: error occured + * NULL: error occured * extended name * * Side-effect: * For a list of names, store the list in l. *----------------------------------------------------------------------- */ + static char * ArchSVR4Entry(l, name, size, arch) struct SVR4namelist *l; @@ -771,7 +705,6 @@ ArchSVR4Entry(l, name, size, arch) assert(name[0] == '/'); name++; - /* First comes a table of archive names, to be used by subsequent calls. */ if (memcmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || memcmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { @@ -790,6 +723,7 @@ ArchSVR4Entry(l, name, size, arch) printf("Reading an SVR4 name table failed\n"); return NULL; } + eptr = l->fnametab + size; for (entry = 0, ptr = l->fnametab; ptr < eptr; ptr++) switch (*ptr) { @@ -805,11 +739,10 @@ ArchSVR4Entry(l, name, size, arch) break; } if (DEBUG(ARCH)) - printf("Found svr4 archive name table with %lu entries\n", - (u_long)entry); + printf("Found svr4 archive name table with %lu entries\n", + (u_long)entry); return (char *)svr4list; } - /* Then the names themselves are given as offsets in this table. */ if (*name == ' ' || *name == '\0') return NULL; @@ -817,18 +750,18 @@ ArchSVR4Entry(l, name, size, arch) entry = (size_t) strtol(name, &eptr, 0); if ((*eptr != ' ' && *eptr != '\0') || eptr == name) { if (DEBUG(ARCH)) - printf("Could not parse SVR4 name %s\n", name); + printf("Could not parse SVR4 name /%s\n", name); return NULL; } if (entry >= l->fnamesize) { if (DEBUG(ARCH)) - printf("SVR4 entry offset %s is greater than %lu\n", + printf("SVR4 entry offset /%s is greater than %lu\n", name, (u_long)l->fnamesize); return NULL; } if (DEBUG(ARCH)) - printf("Replaced %s with %s\n", name, l->fnametab + entry); + printf("Replaced /%s with %s\n", name, l->fnametab + entry); return l->fnametab + entry; } @@ -844,11 +777,10 @@ ArchSVR4Entry(l, name, size, arch) * * Results: * A FILE *, opened for reading and writing, positioned right after - * the member's header, or NULL if the member was nonexistent. + * the member's header, or NULL if the member was nonexistent. * * Side Effects: * Fill the struct ar_hdr pointed by arhPtr. - * *----------------------------------------------------------------------- */ static FILE * @@ -859,11 +791,10 @@ ArchFindMember(archive, member, arhPtr, mode) struct ar_hdr *arhPtr; /* Pointer to header structure to be filled in */ const char *mode; /* The mode for opening the stream */ { - FILE * arch; /* Stream to archive */ + FILE * arch; /* Stream to archive */ char *cp; /* Useful character pointer */ char magic[SARMAG]; size_t len; - #ifdef SVR4ARCHIVES struct SVR4namelist list; @@ -879,7 +810,7 @@ ArchFindMember(archive, member, arhPtr, mode) strncmp(magic, ARMAG, SARMAG) != 0) { fclose(arch); return NULL; - } + } /* Because of space constraints and similar things, files are archived * using their final path components, not the entire thing, so we need @@ -888,32 +819,34 @@ ArchFindMember(archive, member, arhPtr, mode) cp = strrchr(member, '/'); if (cp != NULL) member = cp + 1; + len = strlen(member); if (len >= AR_NAME_SIZE) len = AR_NAME_SIZE; - /* Error handling is simpler than for read_archive, since we just + /* Error handling is simpler than for read_archive, since we just * look for a given member. */ while (fread(arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) { - off_t size; /* Size of archive member */ - char *memName; + off_t size; /* Size of archive member */ + char *memName; - if (memcmp(arhPtr->ar_fmag, ARFMAG, sizeof(arhPtr->ar_fmag) ) != 0) + if (memcmp(arhPtr->ar_fmag, ARFMAG, sizeof(arhPtr->ar_fmag) ) != 0) /* The header is bogus, so the archive is bad. */ break; + memName = arhPtr->ar_name; if (memcmp(member, memName, len) == 0) { /* If the member's name doesn't take up the entire 'name' field, - * we have to be careful of matching prefixes. Names are space- - * padded to the right, so if the character in 'name' at the end - * of the matched string is anything but a space, this isn't the + * we have to be careful of matching prefixes. Names are space- + * padded to the right, so if the character in 'name' at the end + * of the matched string is anything but a space, this isn't the * member we sought. */ #ifdef SVR4ARCHIVES if (len < sizeof(arhPtr->ar_name) && memName[len] == '/') - len++; + len++; #endif - if (len == sizeof(arhPtr->ar_name) || - memName[len] == ' ') { + if (len == sizeof(arhPtr->ar_name) || + memName[len] == ' ') { #ifdef SVR4ARCHIVES efree(list.fnametab); #endif @@ -925,11 +858,11 @@ ArchFindMember(archive, member, arhPtr, mode) #ifdef SVR4ARCHIVES /* svr4 names are slash terminated. Also svr4 extended AR format. - */ + */ if (memName[0] == '/') { /* svr4 magic mode. */ memName = ArchSVR4Entry(&list, arhPtr->ar_name, size, arch); - if (memName == NULL) /* Invalid data */ + if (memName == NULL) /* Invalid data */ break; else if (memName == svr4list) /* List of files entry */ continue; @@ -950,16 +883,16 @@ ArchFindMember(archive, member, arhPtr, mode) int elen = atoi(memName + sizeof(AR_EFMT1)-1); - if (elen <= 0 || elen > MAXPATHLEN) - break; - if (fread(ename, elen, 1, arch) != 1) - break; + if (elen <= 0 || elen > MAXPATHLEN) + break; + if (fread(ename, elen, 1, arch) != 1) + break; if (fseek(arch, -elen, SEEK_CUR) != 0) - break; + break; ename[elen] = '\0'; - if (DEBUG(ARCH) || DEBUG(MAKE)) + if (DEBUG(ARCH) || DEBUG(MAKE)) printf("ArchFind: Extended format entry for %s\n", ename); - /* Found as extended name. */ + /* Found as extended name. */ if (strcmp(ename, member) == 0) { #ifdef SVR4ARCHIVES efree(list.fnametab); @@ -1011,7 +944,6 @@ ArchTouch(archive, member) * 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 @@ -1030,16 +962,15 @@ Arch_Touch(gn) * 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 */ + GNode *gn; /* The node of the library to touch */ { #ifdef RANLIBMAG if (gn->path != NULL) { - ArchTouch(gn->path, RANLIBMAG); + ArchTouch(gn->path, RANLIBMAG); set_times(gn->path); } #endif @@ -1063,8 +994,8 @@ Arch_MTime(gn) GNode *gn; /* Node describing archive member */ { gn->mtime = ArchMTimeMember(Varq_Value(ARCHIVE_INDEX, gn), - Varq_Value(MEMBER_INDEX, gn), - TRUE); + Varq_Value(MEMBER_INDEX, gn), + TRUE); return gn->mtime; } @@ -1075,13 +1006,18 @@ Arch_MTime(gn) * 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; +Arch_MemMTime(gn) + GNode *gn; { - LstNode ln; + LstNode ln; for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln)) { GNode *pgn; @@ -1097,10 +1033,10 @@ Arch_MemMTime (gn) * child. We keep searching its parents in case some other * parent requires this child to exist... */ if ((nameStart = strchr(pgn->name, '(') ) != NULL) { - nameStart++; - nameEnd = strchr(nameStart, ')'); + nameStart++; + nameEnd = strchr(nameStart, ')'); } else - nameEnd = NULL; + nameEnd = NULL; if (pgn->make && nameEnd != NULL && strncmp(nameStart, gn->name, nameEnd - nameStart) == 0 && @@ -1109,7 +1045,7 @@ 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); + set_out_of_date(gn->mtime); break; } } @@ -1121,9 +1057,6 @@ Arch_MemMTime (gn) * Arch_FindLib -- * Search for a library along the given search path. * - * Results: - * None. - * * 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 @@ -1133,22 +1066,21 @@ Arch_MemMTime (gn) * 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) - GNode *gn; /* Node of library to find */ - Lst path; /* Search path */ +Arch_FindLib(gn, path) + GNode *gn; /* Node of library to find */ + Lst path; /* Search path */ { - char *libName; /* file name for archive */ + char *libName; /* file name for archive */ - libName = (char *)emalloc (strlen (gn->name) + 6 - 2); + libName = emalloc(strlen(gn->name) + 6 - 2); sprintf(libName, "lib%s.a", &gn->name[2]); - gn->path = Dir_FindFile (libName, path); + gn->path = Dir_FindFile(libName, path); - free (libName); + free(libName); #ifdef LIBRARIES Varq_Set(TARGET_INDEX, gn->name, gn); @@ -1172,13 +1104,13 @@ Arch_FindLib (gn, path) * A library will be considered out-of-date for any of these reasons, * given that it is a target on a dependency line somewhere: * Its modification time is less than that of one of its - * sources (gn->mtime < gn->cmtime). + * sources (gn->mtime < gn->cmtime). * Its modification time is greater than the time at which the - * make began (i.e. it's been modified in the course - * of the make, probably by archiving). + * make began (i.e. it's been modified in the course + * of the make, probably by archiving). * The modification time of one of its sources is greater than * the one of its RANLIBMAG member (i.e. its table of contents - * is out-of-date). We don't compare of the archive time + * is out-of-date). We don't compare of the archive time * vs. TOC time because they can be too close. In my * opinion we should not bother with the TOC at all since * this is used by 'ar' rules that affect the data contents @@ -1190,25 +1122,23 @@ Arch_FindLib (gn, path) * * Side Effects: * The library will be hashed if it hasn't been already. - * *----------------------------------------------------------------------- */ Boolean -Arch_LibOODate (gn) - GNode *gn; /* The library's graph node */ +Arch_LibOODate(gn) + GNode *gn; /* The library's graph node */ { - TIMESTAMP modTimeTOC; /* mod time of __.SYMDEF */ + TIMESTAMP modTimeTOC; /* mod time of __.SYMDEF */ - if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) + if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) return FALSE; if (is_before(now, gn->mtime) || is_before(gn->mtime, gn->cmtime) || - is_out_of_date(gn->mtime)) + is_out_of_date(gn->mtime)) return TRUE; #ifdef RANLIBMAG /* non existent libraries are always out-of-date. */ if (gn->path == NULL) - return TRUE; - + return TRUE; modTimeTOC = ArchMTimeMember(gn->path, RANLIBMAG, FALSE); if (!is_out_of_date(modTimeTOC)) { @@ -1216,7 +1146,7 @@ Arch_LibOODate (gn) printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); return is_before(modTimeTOC, gn->cmtime); } - /* A library w/o a table of contents is out-of-date */ + /* A library w/o a table of contents is out-of-date. */ if (DEBUG(ARCH) || DEBUG(MAKE)) printf("No t.o.c...."); return TRUE; @@ -1252,14 +1182,14 @@ Arch_Init() *----------------------------------------------------------------------- */ void -Arch_End () +Arch_End() { #ifdef CLEANUP Arch *e; unsigned int i; - for (e = ohash_first(&archives, &i); e != NULL; - e = ohash_next(&archives, &i)) + for (e = ohash_first(&archives, &i); e != NULL; + e = ohash_next(&archives, &i)) ArchFree(e); ohash_delete(&archives); #endif @@ -1272,29 +1202,24 @@ Arch_End () * * Results: * True or False. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ -int +Boolean Arch_IsLib(gn) GNode *gn; { - static const char armag[] = "!<arch>\n"; - char buf[sizeof(armag)-1]; + char buf[SARMAG]; int fd; - if ((fd = open(gn->path, O_RDONLY)) == -1) + if (gn->path == NULL || (fd = open(gn->path, O_RDONLY)) == -1) return FALSE; - if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { - (void) close(fd); + if (read(fd, buf, SARMAG) != SARMAG) { + (void)close(fd); return FALSE; } - (void) close(fd); + (void)close(fd); - return memcmp(buf, armag, sizeof(buf)) == 0; + return memcmp(buf, ARMAG, SARMAG) == 0; } diff --git a/usr.bin/make/buf.c b/usr.bin/make/buf.c index 54cc9994486..90a59933a43 100644 --- a/usr.bin/make/buf.c +++ b/usr.bin/make/buf.c @@ -1,10 +1,11 @@ -/* $OpenBSD: buf.c,v 1.14 2000/11/24 14:27:19 espie Exp $ */ -/* $NetBSD: buf.c,v 1.9 1996/12/31 17:53:21 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: buf.c,v 1.15 2001/05/03 13:41:01 espie Exp $ */ +/* $NetBSD: buf.c,v 1.9 1996/12/31 17:53:21 christos Exp $ */ /* * Copyright (c) 1999 Marc Espie. * - * Extensive code modifications for the OpenBSD project. + * Extensive code changes for the OpenBSD project. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,7 +28,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. * Copyright (c) 1988, 1989 by Adam de Boor @@ -74,38 +74,50 @@ #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.14 2000/11/24 14:27:19 espie Exp $"; +static char rcsid[] = "$OpenBSD: buf.c,v 1.15 2001/05/03 13:41:01 espie Exp $"; #endif #endif /* not lint */ + +#ifdef STATS_BUF +#define DO_STAT_BUF(bp, nb) \ + STAT_BUFS_EXPANSION++; \ + if ((bp)->endPtr - (bp)->buffer == 1) \ + STAT_WEIRD_INEFFICIENT++; +#else +#define DO_STAT_BUF(a, b) +#endif + /* BufExpand -- - * Expand the given buffer to hold the given number of 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) \ + * Expand the given buffer to hold the given number of 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) \ do { \ size_t occupied = (bp)->inPtr - (bp)->buffer; \ size_t size = (bp)->endPtr - (bp)->buffer; \ + DO_STAT_BUF(bp, nb); \ \ - do { \ - size *= 2 ; \ + do { \ + size *= 2 ; \ } while (size - occupied < (nb)+1+BUF_MARGIN); \ (bp)->buffer = (bp)->inPtr = (bp)->endPtr = \ - erealloc((bp)->buffer, size); \ + erealloc((bp)->buffer, size); \ (bp)->inPtr += occupied; \ (bp)->endPtr += size; \ } while (0); -#define BUF_DEF_SIZE 256 /* Default buffer size */ +#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 +/* Buf_AddChar hard case: buffer must be expanded to accommodate * one more char. */ void BufOverflow(bp) @@ -114,11 +126,12 @@ BufOverflow(bp) BufExpand(bp, 1); } + void Buf_AddChars(bp, numBytes, bytesPtr) - Buffer bp; + Buffer bp; size_t numBytes; - const char *bytesPtr; + const char *bytesPtr; { if (bp->endPtr - bp->inPtr < numBytes+1) @@ -128,11 +141,19 @@ Buf_AddChars(bp, numBytes, bytesPtr) bp->inPtr += numBytes; } + void Buf_Init(bp, size) - Buffer bp; /* New Buffer */ - size_t size; /* Initial size for the buffer */ + Buffer bp; /* New Buffer to initialize */ + size_t size; /* Initial size for the buffer */ { +#ifdef STATS_BUF + STAT_TOTAL_BUFS++; + if (size == 0) + STAT_DEFAULT_BUFS++; + if (size == 1) + STAT_WEIRD_BUFS++; +#endif if (size == 0) size = BUF_DEF_SIZE; bp->inPtr = bp->endPtr = bp->buffer = emalloc(size); @@ -140,12 +161,12 @@ Buf_Init(bp, size) } void -Buf_ReplaceLastChar(buf, byte) - Buffer buf; /* buffer to augment */ - char byte; /* byte to be written */ +Buf_KillTrailingSpaces(bp) + Buffer bp; { - if (buf->inPtr == buf->buffer) - Buf_AddChar(buf, byte); - else - *(buf->inPtr - 1) = byte; + while (bp->inPtr > bp->buffer + 1 && isspace(bp->inPtr[-1])) { + if (bp->inPtr[-2] == '\\') + break; + bp->inPtr--; + } } diff --git a/usr.bin/make/buf.h b/usr.bin/make/buf.h index 3cdeaca6091..5940435768c 100644 --- a/usr.bin/make/buf.h +++ b/usr.bin/make/buf.h @@ -1,5 +1,33 @@ -/* $OpenBSD: buf.h,v 1.13 2000/11/24 14:27:19 espie Exp $ */ -/* $NetBSD: buf.h,v 1.7 1996/12/31 17:53:22 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: buf.h,v 1.14 2001/05/03 13:41:01 espie Exp $ */ +/* $NetBSD: buf.h,v 1.7 1996/12/31 17:53:22 christos Exp $ */ + +/* + * Copyright (c) 1999 Marc Espie. + * + * Extensive code changes for the OpenBSD project. + * + * 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. + */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -38,7 +66,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)buf.h 8.1 (Berkeley) 6/6/93 + * from: @(#)buf.h 8.1 (Berkeley) 6/6/93 */ /*- @@ -62,40 +90,39 @@ typedef struct Buffer_ { typedef struct Buffer_ *Buffer; /* Internal support for Buf_AddChar. */ -extern void BufOverflow __P((Buffer)); +extern void BufOverflow(Buffer); /* User interface */ /* Buf_AddChars -- Add a number of chars to the buffer. */ -extern void Buf_AddChars __P((Buffer, size_t, const char *)); +extern void Buf_AddChars(Buffer, size_t, const char *); /* Buf_Reset -- Remove all chars from a buffer. */ #define Buf_Reset(bp) ((void)((bp)->inPtr = (bp)->buffer)) -/* Buf_Size -- Return the number of chars in the given buffer. +/* Buf_Size -- Return the number of chars in the given buffer. * 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 (0), +/* Buf_Init -- Initialize a buffer. If no initial size is given, * a reasonable default is used. */ -extern void Buf_Init __P((Buffer, size_t)); -/* Buf_Destroy -- Nuke a buffer and all its resources. */ -#define Buf_Destroy(bp) (free((bp)->buffer)) +extern void Buf_Init(Buffer, size_t); +/* Buf_Destroy -- Nuke 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. */ #define Buf_Retrieve(bp) (*(bp)->inPtr = '\0', (bp)->buffer) -/* Buf_AddChar -- Add a single char to buffer. */ -#define Buf_AddChar(bp, byte) \ -do { \ +/* Buf_AddChar -- Add a single char to buffer. */ +#define Buf_AddChar(bp, byte) \ +do { \ if ((bp)->endPtr - (bp)->inPtr <= 1) \ BufOverflow(bp); \ *(bp)->inPtr++ = (byte); \ -} while (0) +} while (0) /* Buf_AddSpace -- Add a space to buffer. */ -#define Buf_AddSpace(b) Buf_AddChar((b), ' ') +#define Buf_AddSpace(b) Buf_AddChar((b), ' ') /* Buf_AddString -- Add 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)) +#define Buf_AddInterval(b, s, e) Buf_AddChars((b), (e) - (s), (s)) -/* Buf_ReplaceLastChar -- Replace the last char in a buffer. */ -extern void Buf_ReplaceLastChar __P((Buffer, char)); +extern void Buf_KillTrailingSpaces(Buffer); #endif /* _BUF_H */ diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c index 18671d4a0f0..ce761a4ef64 100644 --- a/usr.bin/make/compat.c +++ b/usr.bin/make/compat.c @@ -1,4 +1,5 @@ -/* $OpenBSD: compat.c,v 1.35 2000/09/14 13:52:41 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: compat.c,v 1.36 2001/05/03 13:41:02 espie Exp $ */ /* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */ /* @@ -49,17 +50,17 @@ * * Interface: * Compat_Run Initialize things for this module and recreate - * thems as need creatin' + * thems as need creatin' */ -#include <stddef.h> -#include <stdio.h> #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" @@ -70,25 +71,23 @@ static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: compat.c,v 1.35 2000/09/14 13:52:41 espie Exp $"; +static char rcsid[] = "$OpenBSD: compat.c,v 1.36 2001/05/03 13:41:02 espie Exp $"; #endif #endif /* not lint */ -/* - * The following array is used to make a fast determination of which +/* The following array is used to make a fast determination of which * characters are interpreted specially by the shell. If a command * contains any of these characters, it is executed by the shell, not - * directly by us. - */ + * directly by us. */ -static char meta[256]; +static char meta[256]; static GNode *curTarg = NULL; static GNode *ENDNode; -static void CompatInterrupt __P((int)); -static int CompatRunCommand __P((void *, void *)); -static void CompatMake __P((void *, void *)); -static int shellneed __P((char **av)); +static void CompatInterrupt(int); +static int CompatRunCommand(void *, void *); +static void CompatMake(void *, void *); +static int shellneed(char **); /*- *----------------------------------------------------------------------- @@ -96,64 +95,55 @@ static int shellneed __P((char **av)); * Interrupt the creation of the current target and remove it if * it ain't precious. * - * Results: - * None. - * * Side Effects: * The target is removed and the process exits. If .INTERRUPT exists, * its commands are run first WITH INTERRUPTS IGNORED.. - * *----------------------------------------------------------------------- */ static void -CompatInterrupt (signo) - int signo; +CompatInterrupt(signo) + int signo; { GNode *gn; - if ((curTarg != NULL) && !Targ_Precious (curTarg)) { - char *file = Varq_Value(TARGET_INDEX, curTarg); + if (curTarg != NULL && !Targ_Precious(curTarg)) { + char *file = Varq_Value(TARGET_INDEX, curTarg); - if (!noExecute && eunlink(file) != -1) { + if (!noExecute && eunlink(file) != -1) Error("*** %s removed\n", file); - } - /* - * Run .INTERRUPT only if hit with interrupt signal - */ + /* Run .INTERRUPT only if hit with interrupt signal. */ if (signo == SIGINT) { - gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); - if (gn != NULL) { + gn = Targ_FindNode(".INTERRUPT", NULL, TARG_NOCREATE); + if (gn != NULL) Lst_Find(&gn->commands, CompatRunCommand, gn); - } } } - exit (signo); + exit(signo); } - + /*- *----------------------------------------------------------------------- * shellneed -- - * + * * Results: - * Returns 1 if a specified set of arguments - * must be executed by the shell, + * Returns 1 if a specified set of arguments + * must be executed by the shell, * 0 if it can be run via execve, and -1 if the command can be - * handled internally + * handled internally * * Side Effects: * May modify the process umask - * *----------------------------------------------------------------------- */ static int -shellneed (av) +shellneed(av) char **av; { - char *runsh[] = { + char *runsh[] = { "alias", "cd", "eval", "exec", "exit", "read", "set", "ulimit", - "unalias", "unset", "wait", + "unalias", "unset", "wait", NULL }; @@ -162,7 +152,7 @@ shellneed (av) /* FIXME most of these ARE actual no-ops */ for (p = runsh; *p; p++) if (strcmp(av[0], *p) == 0) - return (1); + return 1; if (strcmp(av[0], "umask") == 0) { long umi; @@ -172,20 +162,20 @@ shellneed (av) if (av[1] != NULL) { umi = strtol(av[1], &ep, 8); if (ep == NULL) - return (1); + return 1; um = umi; } else { um = umask(0); printf("%o\n", um); } - (void) umask(um); - return (-1); + (void)umask(um); + return -1; } - return (0); + return 0; } - + /*- *----------------------------------------------------------------------- * CompatRunCommand -- @@ -193,44 +183,41 @@ shellneed (av) * error, the node's made field is set to ERROR and creation stops. * * Results: - * 1 if the command succeeded, 0 if an error occurred. + * 0 in case of error, 1 if ok. * * Side Effects: * The node's 'made' field may be set to ERROR. - * *----------------------------------------------------------------------- */ static int -CompatRunCommand (cmdp, gnp) - void *cmdp; /* Command to execute */ - void *gnp; /* Node from which the command came */ +CompatRunCommand(cmdp, gnp) + void * cmdp; /* Command to execute */ + void * gnp; /* Node from which the command came */ { - char *cmdStart; /* Start of expanded command */ + char *cmdStart; /* Start of expanded command */ char *cp, *bp = NULL; - Boolean silent, /* Don't print command */ - errCheck, /* Check errors */ + Boolean 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 */ - 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 + int reason; /* Reason for child's death */ + int status; /* Description of child's death */ + int cpid; /* Child actually found */ + ReturnStatus 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 + Boolean local; /* TRUE if command should be executed * locally */ - char *cmd = (char *) cmdp; - GNode *gn = (GNode *) gnp; - static char *shargv[4] = { "/bin/sh" }; - - /* - * Avoid clobbered variable warnings by forcing the compiler - * to ``unregister'' variables - */ + char *cmd = (char *)cmdp; + GNode *gn = (GNode *)gnp; + static char *shargv[4] = { "/bin/sh" }; + + /* Avoid clobbered variable warnings by forcing the compiler + * to ``unregister'' variables. */ #if __GNUC__ - (void) &av; - (void) &errCheck; + (void)&av; + (void)&errCheck; #endif silent = gn->type & OP_SILENT; errCheck = !(gn->type & OP_IGNORE); @@ -239,20 +226,17 @@ CompatRunCommand (cmdp, gnp) cmdNode = Lst_Member(&gn->commands, cmd); cmdStart = Var_Subst(cmd, &gn->context, FALSE); - /* - * brk_string will return an argv with a NULL in av[0], thus causing + /* 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 * command? In any case, we warn the user that the command expanded to - * nothing (is this the right thing to do?). - */ + * nothing (is this the right thing to do?). */ if (*cmdStart == '\0') { free(cmdStart); Error("%s expands to empty string", cmd); return 1; - } else { + } else cmd = cmdStart; - } Lst_Replace(cmdNode, cmdStart); if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { @@ -264,8 +248,8 @@ CompatRunCommand (cmdp, gnp) } for (;; cmd++) { - if (*cmd == '@') - silent = TRUE; + if (*cmd == '@') + silent = DEBUG(LOUD) ? FALSE : TRUE; else if (*cmd == '-') errCheck = FALSE; else if (*cmd == '+') @@ -274,65 +258,55 @@ CompatRunCommand (cmdp, gnp) break; } - while (isspace((unsigned char)*cmd)) + while (isspace(*cmd)) cmd++; - /* - * Search for meta characters in the command. If there are no meta + /* Search for meta characters in the command. If there are no meta * characters, there's no need to execute a shell to execute the - * command. - */ + * command. */ for (cp = cmd; !meta[(unsigned char)*cp]; cp++) { continue; } - /* - * Print the command before echoing if we're not supposed to be quiet for - * this one. We also print the command if -n given. - */ + /* Print the command before echoing if we're not supposed to be quiet for + * this one. We also print the command if -n given. */ if (!silent || noExecute) { - printf ("%s\n", cmd); + printf("%s\n", cmd); fflush(stdout); } - /* - * If we're not supposed to execute any commands, this is as far as - * we go... - */ + /* If we're not supposed to execute any commands, this is as far as + * we go... */ if (!doExecute) return 1; if (*cp != '\0') { - /* - * If *cp isn't the null character, we hit a "meta" character and + /* If *cp isn't the null character, we hit a "meta" character and * need to pass the command off to the shell. We give the shell the * -e flag as well as -c if it's supposed to exit when it hits an - * error. - */ + * error. */ - shargv[1] = (errCheck ? "-ec" : "-c"); + shargv[1] = errCheck ? "-ec" : "-c"; shargv[2] = cmd; - shargv[3] = (char *)NULL; + shargv[3] = NULL; av = shargv; argc = 0; } else { - /* - * No meta-characters, so probably no need to exec a shell. - * Break the command into words to form an argument vector - * we can execute. - */ - av = brk_string(cmd, &argc, TRUE, &bp); - switch(shellneed(av)) { + /* No meta-characters, so probably no need to exec a shell. + * Break the command into words to form an argument vector + * we can execute. */ + av = brk_string(cmd, &argc, &bp); + switch (shellneed(av)) { case -1: /* handled internally */ free(bp); free(av); return 1; case 1: - shargv[1] = (errCheck ? "-ec" : "-c"); + shargv[1] = errCheck ? "-ec" : "-c"; shargv[2] = cmd; - shargv[3] = (char *)NULL; - free(bp); + shargv[3] = NULL; free(av); + free(bp); bp = NULL; av = shargv; argc = 0; @@ -344,86 +318,72 @@ CompatRunCommand (cmdp, gnp) local = TRUE; - /* - * Fork and execute the single command. If the fork fails, we abort. - */ + /* Fork and execute the single command. If the fork fails, we abort. */ cpid = vfork(); - if (cpid < 0) { + if (cpid == -1) Fatal("Could not fork"); - } if (cpid == 0) { if (local) { execvp(av[0], av); if (errno == ENOENT) - fprintf(stderr, "%s: not found\n", av[0]); + fprintf(stderr, "%s: not found\n", av[0]); else perror(av[0]); - } else { + } else (void)execv(av[0], av); - } _exit(1); } if (bp) { - free(av); + free(av); free(bp); } free(cmdStart); Lst_Replace(cmdNode, NULL); - /* - * The child is off and running. Now all we can do is wait... - */ + /* The child is off and running. Now all we can do is wait... */ while (1) { while ((stat = wait(&reason)) != cpid) { - if (stat == -1 && errno != EINTR) { + if (stat == -1 && errno != EINTR) break; - } } - if (stat > -1) { - if (WIFSTOPPED(reason)) { + if (stat != -1) { + if (WIFSTOPPED(reason)) status = WSTOPSIG(reason); /* stopped */ - } else if (WIFEXITED(reason)) { + else if (WIFEXITED(reason)) { status = WEXITSTATUS(reason); /* exited */ - if (status != 0) { - printf ("*** Error code %d", status); - } + if (status != 0) + printf("*** Error code %d", status); } else { status = WTERMSIG(reason); /* signaled */ - printf ("*** Signal %d", status); + printf("*** Signal %d", status); } - if (!WIFEXITED(reason) || (status != 0)) { + if (!WIFEXITED(reason) || status != 0) { if (errCheck) { gn->made = ERROR; - if (keepgoing) { - /* - * Abort the current target, but let others - * continue. - */ - printf (" (continuing)\n"); - } + if (keepgoing) + /* Abort the current target, but let others + * continue. */ + printf(" (continuing)\n"); } else { - /* - * Continue executing commands for this target. - * If we return 0, this will happen... - */ - printf (" (ignored)\n"); + /* Continue executing commands for this target. + * If we return 0, this will happen... */ + printf(" (ignored)\n"); status = 0; } } break; - } else { - Fatal ("error in wait: %d", stat); + } else + Fatal("error in wait: %d", stat); /*NOTREACHED*/ - } } return !status; } - + /*- *----------------------------------------------------------------------- * CompatMake -- @@ -431,16 +391,15 @@ CompatRunCommand (cmdp, gnp) * * Side Effects: * If an error is detected and not being ignored, the process exits. - * *----------------------------------------------------------------------- */ static void CompatMake(gnp, pgnp) - void *gnp; /* The node to make */ - void *pgnp; /* Parent to abort if necessary */ + void * gnp; /* The node to make */ + void * pgnp; /* Parent to abort if necessary */ { - GNode *gn = (GNode *) gnp; - GNode *pgn = (GNode *) pgnp; + GNode *gn = (GNode *)gnp; + GNode *pgn = (GNode *)pgnp; if (pgn->type & OP_MADE) { (void)Dir_MTime(gn); @@ -450,17 +409,15 @@ CompatMake(gnp, pgnp) if (gn->type & OP_USE) { Make_HandleUse(gn, pgn); } else if (gn->made == UNMADE) { - /* - * First mark ourselves to be made, then apply whatever transformations + /* 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. * This is our signal to not attempt to do anything but abort our - * parent as well. - */ + * parent as well. */ gn->make = TRUE; gn->made = BEINGMADE; - Suff_FindDeps (gn); + Suff_FindDeps(gn); Lst_ForEach(&gn->children, CompatMake, gn); if (!gn->make) { gn->made = ABORTED; @@ -468,91 +425,71 @@ CompatMake(gnp, pgnp) return; } - if (Lst_Member(&gn->iParents, pgn) != NULL) + if (Lst_Member(&gn->iParents, pgn) != NULL) { Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn); + } - /* - * All the children were made ok. Now cmtime contains the modification + /* All the children were made ok. Now cmtime contains the modification * time of the newest child, we need to find out if we exist and when * we were modified last. The criteria for datedness are defined by the - * Make_OODate function. - */ - if (DEBUG(MAKE)) { + * Make_OODate function. */ + if (DEBUG(MAKE)) printf("Examining %s...", gn->name); - } if (! Make_OODate(gn)) { gn->made = UPTODATE; - if (DEBUG(MAKE)) { + if (DEBUG(MAKE)) printf("up-to-date.\n"); - } return; - } else if (DEBUG(MAKE)) { + } else if (DEBUG(MAKE)) printf("out-of-date.\n"); - } - /* - * If the user is just seeing if something is out-of-date, exit now - * to tell him/her "yes". - */ - if (queryFlag) { - exit (-1); - } + /* If the user is just seeing if something is out-of-date, exit now + * to tell him/her "yes". */ + if (queryFlag) + exit(-1); - /* - * We need to be re-made. We also have to make sure we've got a $? + /* We need to be re-made. We also have to make sure we've got a $? * variable. To be nice, we also define the $> variable using - * Make_DoAllVar(). - */ + * Make_DoAllVar(). */ Make_DoAllVar(gn); - /* - * Alter our type to tell if errors should be ignored or things - * should not be printed so CompatRunCommand knows what to do. - */ - if (Targ_Ignore (gn)) { + /* Alter our type to tell if errors should be ignored or things + * should not be printed so CompatRunCommand knows what to do. */ + if (Targ_Ignore(gn)) gn->type |= OP_IGNORE; - } - if (Targ_Silent (gn)) { + if (Targ_Silent(gn)) gn->type |= OP_SILENT; - } - if (Job_CheckCommands (gn, Fatal)) { - /* - * Our commands are ok, but we still have to worry about the -t - * flag... - */ + if (Job_CheckCommands(gn, Fatal)) { + /* Our commands are ok, but we still have to worry about the -t + * flag... */ if (!touchFlag) { curTarg = gn; Lst_Find(&gn->commands, CompatRunCommand, gn); curTarg = NULL; - } else { - Job_Touch (gn, gn->type & OP_SILENT); - } - } else { + } else + Job_Touch(gn, gn->type & OP_SILENT); + } else gn->made = ERROR; - } if (gn->made != ERROR) { - /* - * If the node was made successfully, mark it so, update + /* If the node was made successfully, mark it so, update * its modification time and timestamp all its parents. Note * that for .ZEROTIME targets, the timestamping isn't done. - * This is to keep its state from affecting that of its parent. - */ + * This is to keep its state from affecting that of its parent. */ gn->made = MADE; #ifndef RECHECK - /* - * We can't re-stat the thing, but we can at least take care of + /* We can't re-stat the thing, but we can at least take care of * rules where a target depends on a source that actually creates * the target, but only if it has changed, e.g. * * parse.h : parse.o * * parse.o : parse.y - * yacc -d parse.y - * cc -c y.tab.c - * mv y.tab.o parse.o - * cmp -s y.tab.h parse.h || mv y.tab.h parse.h + * yacc -d parse.y + * cc -c y.tab.c + * mv y.tab.o parse.o + * cmp -s y.tab.h parse.h || mv y.tab.h parse.h * * In this case, if the definitions produced by yacc haven't * changed from before, parse.h won't have been updated and @@ -565,14 +502,11 @@ CompatMake(gnp, pgnp) * FRC: * * To force things that depend on FRC to be made, so we have to - * check for gn->children being empty as well... - */ - if (!Lst_IsEmpty(&gn->commands) || Lst_IsEmpty(&gn->children)) { + * check for gn->children being empty as well... */ + if (!Lst_IsEmpty(&gn->commands) || Lst_IsEmpty(&gn->children)) gn->mtime = now; - } #else - /* - * This is what Make does and it's actually a good thing, as it + /* This is what Make does and it's actually a good thing, as it * allows rules like * * cmp -s y.tab.h parse.h || cp y.tab.h parse.h @@ -593,36 +527,35 @@ CompatMake(gnp, pgnp) gn->mtime = now; if (is_before(gn->mtime, gn->cmtime)) gn->mtime = gn->cmtime; - if (DEBUG(MAKE)) { + if (DEBUG(MAKE)) printf("update time: %s\n", Targ_FmtTime(gn->mtime)); - } #endif if (!(gn->type & OP_EXEC)) { pgn->childMade = TRUE; Make_TimeStamp(pgn, gn); } - } else if (keepgoing) { + } else if (keepgoing) pgn->make = FALSE; - } else { + else { + if (gn->lineno) - printf("\n\nStop in %s (line %lu of %s).\n", - Var_Value(".CURDIR", VAR_GLOBAL), + printf("\n\nStop in %s (line %lu of %s).\n", + Var_Value(".CURDIR"), (unsigned long)gn->lineno, gn->fname); else - printf("\n\nStop in %s.\n", Var_Value(".CURDIR", VAR_GLOBAL)); - exit (1); + printf("\n\nStop in %s.\n", Var_Value(".CURDIR")); + exit(1); } - } else if (gn->made == ERROR) { - /* - * Already had an error when making this beastie. Tell the parent - * to abort. - */ + } else if (gn->made == ERROR) + /* Already had an error when making this beastie. Tell the parent + * to abort. */ pgn->make = FALSE; - } else { - if (Lst_Member(&gn->iParents, pgn) != NULL) + else { + if (Lst_Member(&gn->iParents, pgn) != NULL) { Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn); - switch(gn->made) { + } + switch (gn->made) { case BEINGMADE: Error("Graph cycles through %s\n", gn->name); gn->made = ERROR; @@ -635,100 +568,81 @@ CompatMake(gnp, pgnp) } break; case UPTODATE: - if ((gn->type & OP_EXEC) == 0) { + if ((gn->type & OP_EXEC) == 0) Make_TimeStamp(pgn, gn); - } break; default: break; } } } - + /*- *----------------------------------------------------------------------- * Compat_Run -- * Initialize this mode and start making. * - * Results: - * None. - * * Side Effects: * Guess what? - * *----------------------------------------------------------------------- */ void Compat_Run(targs) - Lst targs; /* List of target nodes to re-create */ + Lst targs; /* List of target nodes to re-create */ { - char *cp; /* Pointer to string of shell meta-characters */ - GNode *gn = NULL;/* Current root target */ - int errors; /* Number of targets not remade due to errors */ + char *cp; /* Pointer to string of shell meta-characters */ + GNode *gn = NULL;/* Current root target */ + int errors; /* Number of targets not remade due to errors */ - if (signal(SIGINT, SIG_IGN) != SIG_IGN) { + if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, CompatInterrupt); - } - if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, CompatInterrupt); - } - if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, CompatInterrupt); - } - if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { + if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, CompatInterrupt); - } - for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) { + for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) meta[(unsigned char) *cp] = 1; - } - /* - * The null character serves as a sentinel in the string. - */ + /* The null character serves as a sentinel in the string. */ meta[0] = 1; - ENDNode = Targ_FindNode(".END", TARG_CREATE); - /* - * If the user has defined a .BEGIN target, execute the commands attached - * to it. - */ + ENDNode = Targ_FindNode(".END", NULL, TARG_CREATE); + /* If the user has defined a .BEGIN target, execute the commands attached + * to it. */ if (!queryFlag) { - gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); + gn = Targ_FindNode(".BEGIN", NULL, TARG_NOCREATE); if (gn != NULL) { Lst_Find(&gn->commands, CompatRunCommand, gn); - if (gn->made == ERROR) { - printf("\n\nStop.\n"); - exit(1); - } + if (gn->made == ERROR) { + printf("\n\nStop.\n"); + exit(1); + } } } - /* - * For each entry in the list of targets to create, call CompatMake on + /* For each entry in the list of targets to create, call CompatMake on * it to create the thing. CompatMake will leave the 'made' field of gn * in one of several states: * UPTODATE gn was already up-to-date - * MADE gn was recreated successfully - * ERROR An error occurred while gn was being created + * MADE gn was recreated successfully + * ERROR An error occurred while gn was being created * ABORTED gn was not remade because one of its inferiors - * could not be made due to errors. - */ + * could not be made due to errors. */ errors = 0; while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) { CompatMake(gn, gn); - if (gn->made == UPTODATE) { - printf ("`%s' is up to date.\n", gn->name); - } else if (gn->made == ABORTED) { - printf ("`%s' not remade because of errors.\n", gn->name); + if (gn->made == UPTODATE) + printf("`%s' is up to date.\n", gn->name); + else if (gn->made == ABORTED) { + printf("`%s' not remade because of errors.\n", gn->name); errors += 1; } } - /* - * If the user has defined a .END target, run its commands. - */ - if (errors == 0) { + /* If the user has defined a .END target, run its commands. */ + if (errors == 0) Lst_Find(&ENDNode->commands, CompatRunCommand, gn); - } } diff --git a/usr.bin/make/cond.c b/usr.bin/make/cond.c index 45ae0af6c3c..93ad02834d5 100644 --- a/usr.bin/make/cond.c +++ b/usr.bin/make/cond.c @@ -1,4 +1,5 @@ -/* $OpenBSD: cond.c,v 1.23 2001/02/17 14:39:07 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: cond.c,v 1.24 2001/05/03 13:41:02 espie Exp $ */ /* $NetBSD: cond.c,v 1.7 1996/11/06 17:59:02 christos Exp $ */ /* @@ -44,13 +45,13 @@ * Functions to handle conditionals in a makefile. * * Interface: - * Cond_Eval Evaluate the conditional in the passed line. + * Cond_Eval Evaluate the conditional in the passed line. * */ -#include <stddef.h> #include <ctype.h> #include <math.h> +#include <stddef.h> #include "make.h" #include "ohash.h" #include "dir.h" @@ -61,12 +62,12 @@ static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: cond.c,v 1.23 2001/02/17 14:39:07 espie Exp $"; +static char rcsid[] = "$OpenBSD: cond.c,v 1.24 2001/05/03 13:41:02 espie Exp $"; #endif #endif /* not lint */ -/* - * The parsing of conditional expressions is based on this grammar: + +/* The parsing of conditional expressions is based on this grammar: * E -> F || E * E -> F * F -> T && F @@ -93,83 +94,76 @@ static char rcsid[] = "$OpenBSD: cond.c,v 1.23 2001/02/17 14:39:07 espie Exp $"; * symbols, using either the default function or the function given in the * terminal, and return the result as either True or False. * - * All Non-Terminal functions (CondE, CondF and CondT) return Err on error. - */ + * All Non-Terminal functions (CondE, CondF and CondT) return Err on error. */ typedef enum { - And, Or, Not, True, False, LParen, RParen, EndOfFile, None, Err + False = 0, True = 1, And, Or, Not, LParen, RParen, EndOfFile, None, Err } Token; /*- * Structures to handle elegantly the different forms of #if's. The * last two fields are stored in condInvert and condDefProc, respectively. */ -static void CondPushBack __P((Token)); -static Boolean CondGetArg __P((char **, char **, size_t *, char *, Boolean)); -static Boolean CondDoDefined __P((size_t, char *)); -static int CondStrMatch __P((void *, void *)); -static Boolean CondDoMake __P((size_t, char *)); -static Boolean CondDoExists __P((size_t, char *)); -static Boolean CondDoTarget __P((size_t, char *)); -static Boolean CondCvtArg __P((char *, double *)); -static Token CondToken __P((Boolean)); -static Token CondT __P((Boolean)); -static Token CondF __P((Boolean)); -static Token CondE __P((Boolean)); +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 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) __P((size_t, char *)); /* Default function to apply */ + char *form; /* Form of if */ + int formlen; /* Length of form */ + Boolean doNot; /* TRUE if default function should be negated */ + Boolean (*defProc)(struct Name *); + /* Default function to apply */ } ifs[] = { { "ifdef", 5, FALSE, CondDoDefined }, - { "ifndef", 6, TRUE, CondDoDefined }, - { "ifmake", 6, FALSE, CondDoMake }, - { "ifnmake", 7, TRUE, CondDoMake }, + { "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 condInvert; /* Invert the default function */ static Boolean (*condDefProc) /* Default function to apply */ - __P((size_t, char *)); -static char *condExpr; /* The expression to parse */ + (struct Name *); +static const char *condExpr; /* The expression to parse */ static Token condPushBack=None; /* Single push-back token used in * parsing */ -#define MAXIF 30 /* greatest depth of #if'ing */ +#define MAXIF 30 /* greatest depth of #if'ing */ static struct { Boolean 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 + 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 * lines */ -/*- - *----------------------------------------------------------------------- - * CondPushBack -- - * Push back the most recent token read. We only need one level of - * this, so the thing is just stored in 'condPushback'. - * - * Results: - * None. - * - * Side Effects: - * condPushback is overwritten. - * - *----------------------------------------------------------------------- - */ -static void -CondPushBack (t) - Token t; /* Token to push back into the "stream" */ +static const char * +find_cond(p) + const char *p; { - condPushBack = t; + for (;;p++) { + if (strchr(" \t)&|$", *p) != NULL) + return p; + } } - + + /*- *----------------------------------------------------------------------- * CondGetArg -- @@ -180,97 +174,57 @@ CondPushBack (t) * * Side Effects: * The line pointer is set to point to the closing parenthesis of the - * function call. The argument and argument length are filled. + * function call. The argument is filled. *----------------------------------------------------------------------- */ static Boolean -CondGetArg(linePtr, argPtr, argLen, func, parens) - char **linePtr; - char **argPtr; - size_t *argLen; - char *func; - Boolean parens; /* TRUE if arg should be bounded by parens */ +CondGetArg(linePtr, arg, func, parens) + const char **linePtr; + struct Name *arg; + const char *func; + Boolean parens; /* TRUE if arg should be bounded by parens */ { - register char *cp; - BUFFER buf; + const char *cp; cp = *linePtr; if (parens) { - while (*cp != '(' && *cp != '\0') { + while (*cp != '(' && *cp != '\0') cp++; - } - if (*cp == '(') { + if (*cp == '(') cp++; - } } if (*cp == '\0') { - /* - * No arguments whatsoever. Because 'make' and 'defined' aren't really + /* No arguments whatsoever. Because 'make' and 'defined' aren't really * "reserved words", we don't print a message. I think this is better * than hitting the user with a warning message every time s/he uses - * the word 'make' or 'defined' at the beginning of a symbol... - */ - *argPtr = cp; + * the word 'make' or 'defined' at the beginning of a symbol... */ + arg->s = cp; + arg->e = cp; + arg->tofree = FALSE; return FALSE; } - while (*cp == ' ' || *cp == '\t') { + while (*cp == ' ' || *cp == '\t') cp++; - } - /* - * Create a buffer for the argument and start it out at 16 characters - * long. Why 16? Why not? - */ - Buf_Init(&buf, 16); - - while ((strchr(" \t)&|", *cp) == (char *)NULL) && (*cp != '\0')) { - if (*cp == '$') { - /* - * Parse the variable spec and install it as part of the argument - * if it's valid. We tell Var_Parse to complain on an undefined - * variable, so we don't do it too. Nor do we return an error, - * though perhaps we should... - */ - char *cp2; - size_t len; - Boolean doFree; - cp2 = Var_Parse(cp, NULL, TRUE, &len, &doFree); + cp = Var_Name_Get(cp, arg, NULL, TRUE, find_cond); - Buf_AddString(&buf, cp2); - if (doFree) { - free(cp2); - } - cp += len; - } else { - Buf_AddChar(&buf, *cp); - cp++; - } - } - - *argPtr = Buf_Retrieve(&buf); - *argLen = Buf_Size(&buf); - - while (*cp == ' ' || *cp == '\t') { + while (*cp == ' ' || *cp == '\t') cp++; - } if (parens && *cp != ')') { - Parse_Error (PARSE_WARNING, "Missing closing parenthesis for %s()", + Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()", func); return FALSE; - } else if (parens) { - /* - * Advance pointer past close parenthesis. - */ + } else if (parens) + /* Advance pointer past close parenthesis. */ cp++; - } *linePtr = cp; return TRUE; } - + /*- *----------------------------------------------------------------------- * CondDoDefined -- @@ -278,50 +232,18 @@ CondGetArg(linePtr, argPtr, argLen, func, parens) * * Results: * TRUE if the given variable is defined. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static Boolean -CondDoDefined(argLen, arg) - size_t argLen; - char *arg; +CondDoDefined(arg) + struct Name *arg; { - char savec = arg[argLen]; - Boolean result; - - if (argLen == 0) - return FALSE; - - arg[argLen] = '\0'; - if (Var_Value(arg, NULL) != NULL) - result = TRUE; + if (Var_Value_interval(arg->s, arg->e) != NULL) + return TRUE; else - result = FALSE; - arg[argLen] = savec; - return (result); -} - -/*- - *----------------------------------------------------------------------- - * CondStrMatch -- - * Front-end for Str_Match so it returns 0 on match and non-zero - * on mismatch. Callback function for CondDoMake via Lst_Find - * - * Results: - * 0 if string matches pattern - *----------------------------------------------------------------------- - */ -static int -CondStrMatch(string, pattern) - void *string; - void *pattern; -{ - return !Str_Match((char *)string,(char *)pattern); + return FALSE; } - + /*- *----------------------------------------------------------------------- * CondDoMake -- @@ -329,30 +251,22 @@ CondStrMatch(string, pattern) * * Results: * TRUE if the given target is being made. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static Boolean -CondDoMake (argLen, arg) - size_t argLen; - char *arg; +CondDoMake(arg) + struct Name *arg; { - char savec = arg[argLen]; - Boolean result; + LstNode ln; - arg[argLen] = '\0'; - if (Lst_Find(&create, CondStrMatch, arg) == NULL) { - result = FALSE; - } else { - result = TRUE; + for (ln = Lst_First(&create); ln != NULL; ln = Lst_Adv(ln)) { + if (Str_Matchi((char *)Lst_Datum(ln), arg->s, arg->e)) + return TRUE; } - arg[argLen] = savec; - return (result); + + return FALSE; } - + /*- *----------------------------------------------------------------------- * CondDoExists -- @@ -360,33 +274,25 @@ CondDoMake (argLen, arg) * * Results: * TRUE if the file exists and FALSE if it does not. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static Boolean -CondDoExists (argLen, arg) - size_t argLen; - char *arg; +CondDoExists(arg) + struct Name *arg; { - char savec = arg[argLen]; Boolean result; char *path; - arg[argLen] = '\0'; - path = Dir_FindFile(arg, &dirSearchPath); - if (path != (char *)NULL) { + path = Dir_FindFilei(arg->s, arg->e, &dirSearchPath); + if (path != NULL) { result = TRUE; free(path); } else { result = FALSE; } - arg[argLen] = savec; - return (result); + return result; } - + /*- *----------------------------------------------------------------------- * CondDoTarget -- @@ -394,33 +300,22 @@ CondDoExists (argLen, arg) * * Results: * TRUE if the node exists as a target and FALSE if it does not. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static Boolean -CondDoTarget(argLen, arg) - size_t argLen; - char *arg; +CondDoTarget(arg) + struct Name *arg; { - char savec = arg[argLen]; - Boolean result; GNode *gn; - arg[argLen] = '\0'; - gn = Targ_FindNode(arg, TARG_NOCREATE); - if ((gn != NULL) && !OP_NOP(gn->type)) { - result = TRUE; - } else { - result = FALSE; - } - arg[argLen] = savec; - return (result); + gn = Targ_FindNode(arg->s, arg->e, TARG_NOCREATE); + if (gn != NULL && !OP_NOP(gn->type)) + return TRUE; + else + return FALSE; } - + /*- *----------------------------------------------------------------------- * CondCvtArg -- @@ -435,24 +330,22 @@ CondDoTarget(argLen, arg) * * Side Effects: * Can change 'value' even if string is not a valid number. - * - * *----------------------------------------------------------------------- */ static Boolean CondCvtArg(str, value) - register char *str; + const char *str; double *value; { - if ((*str == '0') && (str[1] == 'x')) { - register long i; + if (*str == '0' && str[1] == 'x') { + long i; for (str += 2, i = 0; *str; str++) { int x; - if (isdigit((unsigned char) *str)) + if (isdigit(*str)) x = *str - '0'; - else if (isxdigit((unsigned char) *str)) - x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a'; + else if (isxdigit(*str)) + x = 10 + *str - isupper(*str) ? 'A' : 'a'; else return FALSE; i = (i << 4) + x; @@ -466,436 +359,364 @@ CondCvtArg(str, value) return *eptr == '\0'; } } - -/*- - *----------------------------------------------------------------------- - * CondToken -- - * Return the next token from the input. - * - * Results: - * A Token for the next lexical token in the stream. - * - * Side Effects: - * condPushback will be set back to None if it is used. - * - *----------------------------------------------------------------------- - */ + + static Token -CondToken(doEval) +CondHandleVarSpec(doEval) Boolean doEval; { - Token t; + Token t; + char *lhs; + const char *rhs; + const char *op; + size_t varSpecLen; + Boolean doFree; - if (condPushBack == None) { - while (*condExpr == ' ' || *condExpr == '\t') { - condExpr++; - } - switch (*condExpr) { - case '(': - t = LParen; - condExpr++; - break; - case ')': - t = RParen; - condExpr++; - break; - case '|': - if (condExpr[1] == '|') { - condExpr++; - } - condExpr++; - t = Or; - break; - case '&': - if (condExpr[1] == '&') { - condExpr++; - } - condExpr++; - t = And; - break; - case '!': - t = Not; - condExpr++; - break; - case '\n': - case '\0': - t = EndOfFile; - break; - case '$': { - char *lhs; - char *rhs; - char *op; - size_t varSpecLen; - Boolean doFree; - - /* - * Parse the variable spec and skip over it, saving its - * value in lhs. - */ - t = Err; - lhs = Var_Parse(condExpr, NULL, doEval,&varSpecLen,&doFree); - if (lhs == var_Error) { - /* - * Even if !doEval, we still report syntax errors, which - * is what getting var_Error back with !doEval means. - */ - return(Err); - } - condExpr += varSpecLen; + /* Parse the variable spec and skip over it, saving its + * value in lhs. */ + t = Err; + lhs = Var_Parse(condExpr, NULL, doEval,&varSpecLen,&doFree); + if (lhs == var_Error) + /* Even if !doEval, we still report syntax errors, which + * is what getting var_Error back with !doEval means. */ + return Err; + condExpr += varSpecLen; - if (!isspace((unsigned char) *condExpr) && - strchr("!=><", *condExpr) == NULL) { - BUFFER buf; + if (!isspace(*condExpr) && + strchr("!=><", *condExpr) == NULL) { + BUFFER buf; - Buf_Init(&buf, 0); + Buf_Init(&buf, 0); - Buf_AddString(&buf, lhs); + Buf_AddString(&buf, lhs); - if (doFree) - free(lhs); + if (doFree) + free(lhs); - for (;*condExpr && !isspace((unsigned char) *condExpr); - condExpr++) - Buf_AddChar(&buf, *condExpr); + for (;*condExpr && !isspace(*condExpr); condExpr++) + Buf_AddChar(&buf, *condExpr); - lhs = Buf_Retrieve(&buf); + lhs = Buf_Retrieve(&buf); - doFree = TRUE; - } + doFree = TRUE; + } - /* - * Skip whitespace to get to the operator - */ - while (isspace((unsigned char) *condExpr)) - condExpr++; + /* Skip whitespace to get to the operator. */ + while (isspace(*condExpr)) + condExpr++; + + /* Make sure the operator is a valid one. If it isn't a + * known relational operator, pretend we got a + * != 0 comparison. */ + op = condExpr; + switch (*condExpr) { + case '!': + case '=': + case '<': + case '>': + if (condExpr[1] == '=') + condExpr += 2; + else + condExpr += 1; + break; + default: + op = "!="; + rhs = "0"; - /* - * Make sure the operator is a valid one. If it isn't a - * known relational operator, pretend we got a - * != 0 comparison. - */ - op = condExpr; - switch (*condExpr) { - case '!': - case '=': - case '<': - case '>': - if (condExpr[1] == '=') { - condExpr += 2; - } else { - condExpr += 1; - } - break; - default: - op = "!="; - rhs = "0"; - - goto do_compare; - } - while (isspace((unsigned char) *condExpr)) { - condExpr++; - } - if (*condExpr == '\0') { - Parse_Error(PARSE_WARNING, - "Missing right-hand-side of operator"); - goto error; - } - rhs = condExpr; + goto do_compare; + } + while (isspace(*condExpr)) + condExpr++; + if (*condExpr == '\0') { + Parse_Error(PARSE_WARNING, + "Missing right-hand-side of operator"); + goto error; + } + rhs = condExpr; do_compare: - if (*rhs == '"') { - /* - * Doing a string comparison. Only allow == and != for - * operators. - */ - char *string; - char *cp, *cp2; - int qt; - BUFFER buf; + if (*rhs == '"') { + /* Doing a string comparison. Only allow == and != for + * operators. */ + char *string; + const char *cp; + int qt; + BUFFER buf; do_string_compare: - if (((*op != '!') && (*op != '=')) || (op[1] != '=')) { - Parse_Error(PARSE_WARNING, - "String comparison operator should be either == or !="); - goto error; - } - - Buf_Init(&buf, 0); - qt = *rhs == '"' ? 1 : 0; - - for (cp = &rhs[qt]; - ((qt && (*cp != '"')) || - (!qt && strchr(" \t)", *cp) == NULL)) && - (*cp != '\0'); cp++) { - if ((*cp == '\\') && (cp[1] != '\0')) { - /* - * Backslash escapes things -- skip over next - * character, if it exists. - */ - cp++; - Buf_AddChar(&buf, *cp); - } else if (*cp == '$') { - size_t len; - Boolean freeIt; - - cp2 = Var_Parse(cp, NULL, doEval,&len, &freeIt); - if (cp2 != var_Error) { - Buf_AddString(&buf, cp2); - if (freeIt) { - free(cp2); - } - cp += len - 1; - } else { - Buf_AddChar(&buf, *cp); - } - } else { - Buf_AddChar(&buf, *cp); - } - } - - string = Buf_Retrieve(&buf); - - if (DEBUG(COND)) { - printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n", - lhs, string, op); - } - /* - * Null-terminate rhs and perform the comparison. - * t is set to the result. - */ - if (*op == '=') { - t = strcmp(lhs, string) ? False : True; - } else { - t = strcmp(lhs, string) ? True : False; - } - free(string); - if (rhs == condExpr) { - if (!qt && *cp == ')') - condExpr = cp; - else if (*cp == '\0') - condExpr = cp; - else - condExpr = cp + 1; - } - } else { - /* - * rhs is either a float or an integer. Convert both the - * lhs and the rhs to a double and compare the two. - */ - double left, right; - char *string; - - if (!CondCvtArg(lhs, &left)) - goto do_string_compare; - if (*rhs == '$') { - size_t len; - Boolean freeIt; - - string = Var_Parse(rhs, NULL, doEval,&len,&freeIt); - if (string == var_Error) { - right = 0.0; - } else { - if (!CondCvtArg(string, &right)) { - if (freeIt) - free(string); - goto do_string_compare; - } - if (freeIt) - free(string); - if (rhs == condExpr) - condExpr += len; - } - } else { - if (!CondCvtArg(rhs, &right)) - goto do_string_compare; - if (rhs == condExpr) { - /* - * Skip over the right-hand side - */ - while(!isspace((unsigned char) *condExpr) && - (*condExpr != '\0')) { - condExpr++; - } - } - } - - if (DEBUG(COND)) { - printf("left = %f, right = %f, op = %.2s\n", left, - right, op); - } - switch(op[0]) { - case '!': - if (op[1] != '=') { - Parse_Error(PARSE_WARNING, - "Unknown operator"); - goto error; - } - t = (left != right ? True : False); - break; - case '=': - if (op[1] != '=') { - Parse_Error(PARSE_WARNING, - "Unknown operator"); - goto error; - } - t = (left == right ? True : False); - break; - case '<': - if (op[1] == '=') { - t = (left <= right ? True : False); - } else { - t = (left < right ? True : False); - } - break; - case '>': - if (op[1] == '=') { - t = (left >= right ? True : False); - } else { - t = (left > right ? True : False); - } - break; - } + if ((*op != '!' && *op != '=') || op[1] != '=') { + Parse_Error(PARSE_WARNING, + "String comparison operator should be either == or !="); + goto error; + } + + Buf_Init(&buf, 0); + qt = *rhs == '"' ? 1 : 0; + + for (cp = &rhs[qt]; + ((qt && *cp != '"') || + (!qt && strchr(" \t)", *cp) == NULL)) && + *cp != '\0';) { + if (*cp == '$') { + size_t len; + + if (Var_ParseBuffer(&buf, cp, NULL, doEval, &len) + == SUCCESS) { + cp += len; + continue; } -error: - if (doFree) - free(lhs); - break; - } - default: { - Boolean (*evalProc) __P((size_t, char *)); - Boolean invert = FALSE; - char *arg; - size_t arglen; - - if (strncmp (condExpr, "defined", 7) == 0) { - /* - * Use CondDoDefined to evaluate the argument and - * CondGetArg to extract the argument from the 'function - * call'. - */ - evalProc = CondDoDefined; - condExpr += 7; - if (!CondGetArg(&condExpr, &arg, &arglen, - "defined", TRUE)) { - condExpr -= 7; - goto use_default; - } - } else if (strncmp (condExpr, "make", 4) == 0) { - /* - * Use CondDoMake to evaluate the argument and - * CondGetArg to extract the argument from the 'function - * call'. - */ - evalProc = CondDoMake; - condExpr += 4; - if (!CondGetArg(&condExpr, &arg, &arglen, - "make", TRUE)) { - condExpr -= 4; - goto use_default; - } - } else if (strncmp (condExpr, "exists", 6) == 0) { - /* - * Use CondDoExists to evaluate the argument and - * CondGetArg to extract the argument from the - * 'function call'. - */ - evalProc = CondDoExists; - condExpr += 6; - if (!CondGetArg(&condExpr, &arg, &arglen, - "exists", TRUE)) { - condExpr -= 6; - goto use_default; - } - } else if (strncmp(condExpr, "empty", 5) == 0) { - /* - * Use Var_Parse to parse the spec in parens and return - * True if the resulting string is empty. - */ - size_t length; - Boolean doFree; - char *val; - - condExpr += 5; - - for (arglen = 0; - condExpr[arglen] != '(' && condExpr[arglen] != '\0'; - arglen += 1) - continue; - - if (condExpr[arglen] != '\0') { - val = Var_Parse(&condExpr[arglen - 1], NULL, - doEval, &length, &doFree); - if (val == var_Error) { - t = Err; - } else { - /* - * A variable is empty when it just contains - * spaces... 4/15/92, christos - */ - char *p; - for (p = val; *p && isspace((unsigned char)*p); p++) - continue; - t = (*p == '\0') ? True : False; - } - if (doFree) { - free(val); - } - /* - * Advance condExpr to beyond the closing ). Note that - * we subtract one from arglen + length b/c length - * is calculated from condExpr[arglen - 1]. - */ - condExpr += arglen + length - 1; - } else { - condExpr -= 5; - goto use_default; - } - break; - } else if (strncmp (condExpr, "target", 6) == 0) { - /* - * Use CondDoTarget to evaluate the argument and - * CondGetArg to extract the argument from the - * 'function call'. - */ - evalProc = CondDoTarget; - condExpr += 6; - if (!CondGetArg(&condExpr, &arg, &arglen, - "target", TRUE)) { - condExpr -= 6; - goto use_default; - } - } else { - /* - * The symbol is itself the argument to the default - * 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. - */ - use_default: - invert = condInvert; - evalProc = condDefProc; - /* XXX should we ignore problems now ? */ - CondGetArg(&condExpr, &arg, &arglen, "", FALSE); + } else if (*cp == '\\' && cp[1] != '\0') + /* Backslash escapes things -- skip over next + * character, if it exists. */ + cp++; + Buf_AddChar(&buf, *cp++); + } + + string = Buf_Retrieve(&buf); + + if (DEBUG(COND)) + printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n", + lhs, string, op); + /* Null-terminate rhs and perform the comparison. + * t is set to the result. */ + if (*op == '=') + t = strcmp(lhs, string) ? False : True; + else + t = strcmp(lhs, string) ? True : False; + free(string); + if (rhs == condExpr) { + if (!qt && *cp == ')') + condExpr = cp; + else if (*cp == '\0') + condExpr = cp; + else + condExpr = cp + 1; + } + } else { + /* rhs is either a float or an integer. Convert both the + * lhs and the rhs to a double and compare the two. */ + double left, right; + char *string; + + if (!CondCvtArg(lhs, &left)) + goto do_string_compare; + if (*rhs == '$') { + size_t len; + Boolean freeIt; + + string = Var_Parse(rhs, NULL, doEval,&len,&freeIt); + if (string == var_Error) + right = 0.0; + else { + if (!CondCvtArg(string, &right)) { + if (freeIt) + free(string); + goto do_string_compare; } + if (freeIt) + free(string); + if (rhs == condExpr) + condExpr += len; + } + } else { + if (!CondCvtArg(rhs, &right)) + goto do_string_compare; + if (rhs == condExpr) { + /* Skip over the right-hand side. */ + while (!isspace(*condExpr) && + *condExpr != '\0') + condExpr++; - /* - * Evaluate the argument using the set function. If invert - * is TRUE, we invert the sense of the function. - */ - t = (!doEval || (* evalProc) (arglen, arg) ? - (invert ? False : True) : - (invert ? True : False)); - free(arg); - break; } } + + if (DEBUG(COND)) + printf("left = %f, right = %f, op = %.2s\n", left, + right, op); + switch (op[0]) { + case '!': + if (op[1] != '=') { + Parse_Error(PARSE_WARNING, + "Unknown operator"); + goto error; + } + t = left != right ? True : False; + break; + case '=': + if (op[1] != '=') { + Parse_Error(PARSE_WARNING, + "Unknown operator"); + goto error; + } + t = left == right ? True : False; + break; + case '<': + if (op[1] == '=') + t = left <= right ? True : False; + else + t = left < right ? True : False; + break; + case '>': + if (op[1] == '=') + t = left >= right ? True : False; + else + t = left > right ? True : False; + break; + } + } +error: + if (doFree) + free(lhs); + return t; +} + +#define S(s) s, sizeof(s)-1 +static struct operator { + const char *s; + size_t len; + Boolean (*proc)(struct Name *); +} ops[] = { + {S("defined"), CondDoDefined}, + {S("make"), CondDoMake}, + {S("exists"), CondDoExists}, + {S("target"), CondDoTarget}, + {NULL, 0, NULL} +}; +static Token +CondHandleDefault(doEval) + Boolean doEval; +{ + Boolean t; + Boolean (*evalProc)(struct Name *); + Boolean invert = FALSE; + struct Name arg; + size_t arglen; + + evalProc = NULL; + if (strncmp(condExpr, "empty", 5) == 0) { + /* Use Var_Parse to parse the spec in parens and return + * True if the resulting string is empty. */ + size_t length; + Boolean doFree; + char *val; + + condExpr += 5; + + for (arglen = 0; condExpr[arglen] != '(' && condExpr[arglen] != '\0';) + arglen++; + + if (condExpr[arglen] != '\0') { + val = Var_Parse(&condExpr[arglen - 1], NULL, + doEval, &length, &doFree); + if (val == var_Error) + t = Err; + else { + /* A variable is empty when it just contains + * spaces... 4/15/92, christos */ + char *p; + for (p = val; *p && isspace(*p); p++) + continue; + t = *p == '\0' ? True : False; + } + if (doFree) + free(val); + /* Advance condExpr to beyond the closing ). Note that + * we subtract one from arglen + length b/c length + * is calculated from condExpr[arglen - 1]. */ + condExpr += arglen + length - 1; + return t; + } else + condExpr -= 5; } else { + struct operator *op; + + for (op = ops; op != NULL; op++) + if (strncmp(condExpr, op->s, op->len) == 0) { + condExpr += op->len; + if (CondGetArg(&condExpr, &arg, op->s, TRUE)) + evalProc = op->proc; + else + condExpr -= op->len; + break; + } + } + if (evalProc == NULL) { + /* The symbol is itself the argument to the default + * 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. */ + invert = condInvert; + evalProc = condDefProc; + /* XXX should we ignore problems now ? */ + CondGetArg(&condExpr, &arg, "", FALSE); + } + + /* Evaluate the argument using the set function. If invert + * is TRUE, we invert the sense of the function. */ + t = (!doEval || (*evalProc)(&arg) ? + (invert ? False : True) : + (invert ? True : False)); + Var_Name_Free(&arg); + return t; +} + +/*- + *----------------------------------------------------------------------- + * CondToken -- + * Return the next token from the input. + * + * Results: + * A Token for the next lexical token in the stream. + * + * Side Effects: + * condPushback will be set back to None if it is used. + *----------------------------------------------------------------------- + */ +static Token +CondToken(doEval) + Boolean doEval; +{ + + if (condPushBack != None) { + Token t; + t = condPushBack; condPushBack = None; + return t; + } + + while (*condExpr == ' ' || *condExpr == '\t') + condExpr++; + switch (*condExpr) { + case '(': + condExpr++; + return LParen; + case ')': + condExpr++; + return RParen; + case '|': + if (condExpr[1] == '|') + condExpr++; + condExpr++; + return Or; + case '&': + if (condExpr[1] == '&') + condExpr++; + condExpr++; + return And; + case '!': + condExpr++; + return Not; + case '\n': + case '\0': + return EndOfFile; + case '$': + return CondHandleVarSpec(doEval); + default: + return CondHandleDefault(doEval); } - return (t); } - + /*- *----------------------------------------------------------------------- * CondT -- @@ -910,7 +731,6 @@ error: * * Side Effects: * Tokens are consumed. - * *----------------------------------------------------------------------- */ static Token @@ -921,33 +741,26 @@ CondT(doEval) t = CondToken(doEval); - if (t == EndOfFile) { - /* - * If we reached the end of the expression, the expression - * is malformed... - */ + if (t == EndOfFile) + /* If we reached the end of the expression, the expression + * is malformed... */ t = Err; - } else if (t == LParen) { - /* - * T -> ( E ) - */ + else if (t == LParen) { + /* T -> ( E ). */ t = CondE(doEval); - if (t != Err) { - if (CondToken(doEval) != RParen) { + if (t != Err) + if (CondToken(doEval) != RParen) t = Err; - } - } } else if (t == Not) { t = CondT(doEval); - if (t == True) { + if (t == True) t = False; - } else if (t == False) { + else if (t == False) t = True; - } } - return (t); + return t; } - + /*- *----------------------------------------------------------------------- * CondF -- @@ -959,7 +772,6 @@ CondT(doEval) * * Side Effects: * Tokens are consumed. - * *----------------------------------------------------------------------- */ static Token @@ -973,28 +785,22 @@ CondF(doEval) o = CondToken(doEval); if (o == And) { - /* - * F -> T && F + /* F -> T && F * * If T is False, the whole thing will be False, but we have to * parse the r.h.s. anyway (to throw it away). - * If T is True, the result is the r.h.s., be it an Err or no. - */ - if (l == True) { + * If T is True, the result is the r.h.s., be it an Err or no. */ + if (l == True) l = CondF(doEval); - } else { - (void) CondF(FALSE); - } - } else { - /* - * F -> T - */ - CondPushBack (o); - } + else + (void)CondF(FALSE); + } else + /* F -> T. */ + condPushBack = o; } - return (l); + return l; } - + /*- *----------------------------------------------------------------------- * CondE -- @@ -1006,7 +812,6 @@ CondF(doEval) * * Side Effects: * Tokens are, of course, consumed. - * *----------------------------------------------------------------------- */ static Token @@ -1020,35 +825,29 @@ CondE(doEval) o = CondToken(doEval); if (o == Or) { - /* - * E -> F || E + /* E -> F || E * * A similar thing occurs for ||, except that here we make sure * the l.h.s. is False before we bother to evaluate the r.h.s. * Once again, if l is False, the result is the r.h.s. and once - * again if l is True, we parse the r.h.s. to throw it away. - */ - if (l == False) { + * again if l is True, we parse the r.h.s. to throw it away. */ + if (l == False) l = CondE(doEval); - } else { - (void) CondE(FALSE); - } - } else { - /* - * E -> F - */ - CondPushBack (o); - } + else + (void)CondE(FALSE); + } else + /* E -> F. */ + condPushBack = o; } - return (l); + return l; } - + /*- *----------------------------------------------------------------------- * Cond_Eval -- - * Evaluate the conditional in the passed line. The line + * Evaluate the conditional in the passed fragment. The fragment * looks like this: - * #<cond-type> <expr> + * <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) @@ -1057,126 +856,100 @@ CondE(doEval) * 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. - * - * Side Effects: - * None. - * + * COND_INVALID if not a valid conditional. *----------------------------------------------------------------------- */ int -Cond_Eval (line) - char *line; /* Line to parse */ +Cond_Eval(line) + char *line; /* Line to parse */ { struct If *ifp; - Boolean isElse; - Boolean value = FALSE; - int level; /* Level at which to report errors. */ + Boolean isElse; + Boolean value = FALSE; + int level; /* Level at which to report errors. */ level = PARSE_FATAL; - for (line++; *line == ' ' || *line == '\t'; line++) { - continue; - } + /* Stuff we are looking for can be if*, elif*, else, or endif. + * 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. - */ + /* 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. */ if (line[0] == 'e' && line[1] == 'l') { line += 2; isElse = TRUE; - } else if (strncmp (line, "endif", 5) == 0) { - /* - * End of a conditional section. If skipIfLevel is non-zero, that + } 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 * skipped. Hence, we return COND_SKIP. Otherwise, the conditional * was read so succeeding lines should be parsed (think about it...) * so we return COND_PARSE, unless this endif isn't paired with - * a decent if. - */ + * a decent if. */ if (skipIfLevel != 0) { skipIfLevel -= 1; - return (COND_SKIP); + return COND_SKIP; } else { if (condTop == MAXIF) { - Parse_Error (level, "if-less endif"); - return (COND_INVALID); + Parse_Error(level, "if-less endif"); + return COND_INVALID; } else { skipLine = FALSE; condTop += 1; - return (COND_PARSE); + return COND_PARSE; } } - } else { + } else isElse = FALSE; - } - /* - * Figure out what sort of conditional it is -- what its default - * function is, etc. -- by looking in the table of valid "ifs" - */ - for (ifp = ifs; ifp->form != (char *)0; ifp++) { - if (strncmp (ifp->form, line, ifp->formlen) == 0) { + /* Figure out what sort of conditional it is -- what its default + * function is, etc. -- by looking in the table of valid "ifs" */ + for (ifp = ifs; ifp->form != NULL; ifp++) { + if (strncmp(ifp->form, line, ifp->formlen) == 0) break; - } } - if (ifp->form == (char *) 0) { - /* - * Nothing fit. If the first word on the line is actually + if (ifp->form == NULL) { + /* Nothing fits. If the first word on the line is actually * "else", it's a valid conditional whose value is the inverse - * of the previous if we parsed. - */ - if (isElse && (line[0] == 's') && (line[1] == 'e')) { + * of the previous if we parsed. */ + if (isElse && line[0] == 's' && line[1] == 'e') { if (condTop == MAXIF) { - Parse_Error (level, "if-less else"); - return (COND_INVALID); - } else if (skipIfLevel == 0) { + Parse_Error(level, "if-less else"); + return COND_INVALID; + } else if (skipIfLevel == 0) value = !condStack[condTop].value; - } else { - return (COND_SKIP); - } - } else { - /* - * Not a valid conditional type. No error... - */ - return (COND_INVALID); - } + else + return COND_SKIP; + } else + /* Not a valid conditional type. No error... */ + return COND_INVALID; } else { if (isElse) { if (condTop == MAXIF) { - Parse_Error (level, "if-less elif"); - return (COND_INVALID); + Parse_Error(level, "if-less elif"); + return COND_INVALID; } else if (skipIfLevel != 0) { - /* - * If skipping this conditional, just ignore the whole thing. + /* If skipping this conditional, just ignore the whole thing. * If we don't, the user might be employing a variable that's * undefined, for which there's an enclosing ifdef that - * we're skipping... - */ - return(COND_SKIP); + * we're skipping... */ + return COND_SKIP; } } else if (skipLine) { - /* - * Don't even try to evaluate a conditional that's not an else if - * we're skipping things... - */ + /* Don't even try to evaluate a conditional that's not an else if + * we're skipping things... */ skipIfLevel += 1; - return(COND_SKIP); + return COND_SKIP; } - /* - * Initialize file-global variables for parsing - */ + /* Initialize file-global variables for parsing. */ condDefProc = ifp->defProc; condInvert = ifp->doNot; line += ifp->formlen; - while (*line == ' ' || *line == '\t') { + while (*line == ' ' || *line == '\t') line++; - } condExpr = line; condPushBack = None; @@ -1197,54 +970,45 @@ Cond_Eval (line) /* FALLTHROUGH */ case Err: err: - Parse_Error (level, "Malformed conditional (%s)", - line); - return (COND_INVALID); + Parse_Error(level, "Malformed conditional (%s)", line); + return COND_INVALID; default: break; } } - if (!isElse) { + if (!isElse) condTop -= 1; - } else if ((skipIfLevel != 0) || condStack[condTop].value) { - /* - * If this is an else-type conditional, it should only take effect + 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 * we weren't already), leaving the stack unmolested so later elif's - * don't screw up... - */ + * don't screw up... */ skipLine = TRUE; - return (COND_SKIP); + return COND_SKIP; } if (condTop < 0) { - /* - * This is the one case where we can definitely proclaim a fatal - * error. If we don't, we're hosed. - */ - Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF); - return (COND_INVALID); + /* This is the one case where we can definitely proclaim a fatal + * error. If we don't, we're hosed. */ + Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.", MAXIF); + return COND_INVALID; } else { condStack[condTop].value = value; condStack[condTop].lineno = Parse_Getlineno(); condStack[condTop].filename = Parse_Getfilename(); skipLine = !value; - return (value ? COND_PARSE : COND_SKIP); + return value ? COND_PARSE : COND_SKIP; } } - + /*- *----------------------------------------------------------------------- * Cond_End -- * Make sure everything's clean at the end of a makefile. * - * Results: - * None. - * * Side Effects: * Parse_Error will be called if open conditionals are around. - * *----------------------------------------------------------------------- */ void diff --git a/usr.bin/make/cond_int.h b/usr.bin/make/cond_int.h new file mode 100644 index 00000000000..14fc951cc17 --- /dev/null +++ b/usr.bin/make/cond_int.h @@ -0,0 +1,18 @@ +/* $OpenPackages$ */ +/* $OpenBSD: cond_int.h,v 1.1 2001/05/03 13:41:02 espie Exp $ */ + +/* List of all keywords recognized by the make parser */ +#define COND_IF "if" +#define COND_IFDEF "ifdef" +#define COND_IFNDEF "ifndef" +#define COND_IFMAKE "ifmake" +#define COND_IFNMAKE "ifnmake" +#define COND_ELSE "else" +#define COND_ELIFDEF "elifdef" +#define COND_ELIFNDEF "elifndef" +#define COND_ELIFMAKE "elifmake" +#define COND_ELIFNMAKE "elifnmake" +#define COND_ENDIF "endif" +#define COND_FOR "for" +#define COND_INCLUDE "include" +#define COND_UNDEF "undef" diff --git a/usr.bin/make/config.h b/usr.bin/make/config.h index 71c83fd7153..1b027104fe1 100644 --- a/usr.bin/make/config.h +++ b/usr.bin/make/config.h @@ -1,4 +1,5 @@ -/* $OpenBSD: config.h,v 1.9 1998/12/05 00:06:27 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: config.h,v 1.10 2001/05/03 13:41:03 espie Exp $ */ /* $NetBSD: config.h,v 1.7 1996/11/06 17:59:03 christos Exp $ */ /* @@ -41,7 +42,7 @@ * from: @(#)config.h 8.1 (Berkeley) 6/6/93 */ -#define DEFSHELL 1 /* Bourne shell */ +#define DEFSHELL 1 /* Bourne shell */ /* * DEFMAXJOBS @@ -82,17 +83,8 @@ * that don't have this problem, you should defined this. Under * NFS you probably should not, unless you aren't exporting jobs. */ -#define LIBSUFF ".a" -#define RECHECK - -/* - * POSIX - * Adhere to the POSIX 1003.2 draft for the make(1) program. - * - Use MAKEFLAGS instead of MAKE to pick arguments from the - * environment. - * - Allow empty command lines if starting with tab. - */ -#define POSIX +#define LIBSUFF ".a" +#define RECHECK /* * SYSVINCLUDE @@ -118,3 +110,36 @@ # define RANLIBMAG "__.SYMDEF" # endif #endif + +#ifdef SYSVINCLUDE +#define DOFEATURE_SYSVINCLUDE FEATURE_SYSVINCLUDE +#else +#define DOFEATURE_SYSVINCLUDE 0 +#endif +#ifdef SYSVVARSUB +#define DOFEATURE_SYSVVARSUB FEATURE_SYSVVARSUB +#else +#define DOFEATURE_SYSVVARSUB 0 +#endif +#ifdef SUNSHCMD +#define DOFEATURE_SUNSHCMD FEATURE_SUNSHCMD +#else +#define DOFEATURE_SUNSHCMD 0 +#endif + +#ifndef DEFAULT_FEATURES +#define DEFAULT_FEATURES (FEATURE_UPPERLOWER | DOFEATURE_SYSVVARSUB | DOFEATURE_SYSVINCLUDE | DOFEATURE_SUNSHCMD | FEATURE_RECVARS) +#endif + +#define FEATURES(x) ((DEFAULT_FEATURES & (x)) != 0) +#define FEATURE_ODE 1 +#define FEATURE_UNIQ 2 +#define FEATURE_SORT 4 +#define FEATURE_UPPERLOWER 8 +#define FEATURE_SYSVVARSUB 16 +#define FEATURE_SYSVINCLUDE 32 +#define FEATURE_SUNSHCMD 64 +#define FEATURE_RECVARS 128 +#define FEATURE_CONDINCLUDE 256 +#define FEATURE_ASSIGN 512 +#define FEATURE_EXECMOD 1024 diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c index 8007c14ae3e..63b801818a2 100644 --- a/usr.bin/make/dir.c +++ b/usr.bin/make/dir.c @@ -1,7 +1,34 @@ -/* $OpenBSD: dir.c,v 1.30 2001/03/02 16:57:26 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: dir.c,v 1.31 2001/05/03 13:41:03 espie Exp $ */ /* $NetBSD: dir.c,v 1.14 1997/03/29 16:51:26 christos Exp $ */ /* + * Copyright (c) 1999 Marc Espie. + * + * Extensive code changes for the OpenBSD project. + * + * 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. + */ +/* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks @@ -46,37 +73,36 @@ * implicit sources. * * The interface for this module is: - * Dir_Init Initialize the module. + * Dir_Init Initialize the module. * - * Dir_End Cleanup the module. + * Dir_End Cleanup the module. * * Dir_HasWildcards Returns TRUE if the name given it needs to - * be wildcard-expanded. + * be wildcard-expanded. * * Dir_Expand Given a pattern and a path, return a Lst of names - * which match the pattern on the search path. + * 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. + * If it exists, the entire path is returned. + * Otherwise NULL is returned. * - * Dir_MTime Return TRUE if node exists. The file - * is searched for along the default search path. - * The path and mtime fields of the node are filled - * in. + * 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. + * 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. - * Dir_ClearPath Resets a search path to the empty list. + * 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. @@ -96,12 +122,11 @@ static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: dir.c,v 1.30 2001/03/02 16:57:26 espie Exp $"; +static char rcsid[] = "$OpenBSD: dir.c,v 1.31 2001/05/03 13:41:03 espie Exp $"; #endif #endif /* not lint */ -/* - * A search path consists of a Lst of Path structures. A Path structure +/* 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 * in the directory. This is used to cut down on the number of system * calls necessary to find implicit dependents and their like. Since @@ -166,29 +191,26 @@ static char rcsid[] = "$OpenBSD: dir.c,v 1.30 2001/03/02 16:57:26 espie Exp $"; * essentially a stat() without the copyout() call, and that the same * filesystem overhead would have to be incurred in Dir_MTime, it made * sense to replace the access() with a stat() and record the mtime - * in a cache for when Dir_MTime was actually called. - */ + * in a cache for when Dir_MTime was actually called. */ -LIST dirSearchPath; /* main search path */ +LIST dirSearchPath; /* main search path */ -static struct ohash openDirectories; /* cache all open directories */ +/* 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 */ -/* - * 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 */ - -static Path *dot; /* contents of current directory */ +static Path *dot; /* contents of current directory */ struct file_stamp { TIMESTAMP mtime; /* time stamp... */ char name[1]; /* ...for that file. */ }; +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 @@ -199,6 +221,7 @@ static struct ohash mtimes; /* Results of doing a last-resort stat in * be two rules to update a single file, so this * should be ok, but... */ + /* There are three distinct hash structures: * - to collate files's last modification times (global mtimes) * - to collate file names (in each Path structure) @@ -206,33 +229,36 @@ static struct ohash mtimes; /* Results of doing a last-resort stat in static struct ohash_info stamp_info = { offsetof(struct file_stamp, name), NULL, hash_alloc, hash_free, element_alloc }; -static struct ohash_info file_info = { 0, +static struct ohash_info file_info = { 0, NULL, hash_alloc, hash_free, element_alloc }; -static struct ohash_info dir_info = { offsetof(Path, name), +static struct ohash_info dir_info = { offsetof(Path, name), NULL, hash_alloc, hash_free, element_alloc }; -static void record_stamp __P((const char *, TIMESTAMP)); -static void add_file __P((Path *, const char *)); -static char *find_file_hash __P((Path *, const char *, const char *, u_int32_t)); -static struct file_stamp *find_stamp __P((const char *)); -static void free_hash __P((struct ohash *)); +static void record_stamp(const char *, TIMESTAMP); +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 *); -static Path *DirReaddir __P((const char *, const char *)); -static void DirMatchFiles __P((char *, Path *, Lst)); -static void DirExpandCurly __P((char *, char *, Lst, Lst)); -static void DirExpandInt __P((char *, Lst, Lst)); -static void DirPrintWord __P((void *)); -static void DirPrintDir __P((void *)); + + +static Path *DirReaddir(const char *, const char *); +static void DirMatchFiles(const char *, Path *, Lst); +static void PathMatchFiles(const char *, Lst, Lst); +static void DirPrintWord(void *); +static void DirPrintDir(void *); +static void DirExpandWild(const char *, Lst, Lst); +static void DirExpandCurly(const char *, Lst, Lst); static void record_stamp(file, t) - const char *file; - TIMESTAMP t; + const char *file; + TIMESTAMP t; { - unsigned slot; - const char *end = NULL; - struct file_stamp *n; + unsigned slot; + const char *end = NULL; + struct file_stamp *n; slot = ohash_qlookupi(&mtimes, file, &end); n = ohash_find(&mtimes, slot); @@ -244,23 +270,24 @@ record_stamp(file, t) ohash_insert(&mtimes, slot, n); } } - + static struct file_stamp * -find_stamp(file) - const char *file; +find_stampi(file, end) + const char *file; + const char *end; { - return ohash_find(&mtimes, ohash_qlookup(&mtimes, file)); + return ohash_find(&mtimes, ohash_qlookupi(&mtimes, file, &end)); } static void add_file(p, file) - Path *p; - const char *file; + Path *p; + const char *file; { - unsigned slot; - const char *end = NULL; - char *n; - struct ohash *h = &p->files; + unsigned slot; + const char *end = NULL; + char *n; + struct ohash *h = &p->files; slot = ohash_qlookupi(h, file, &end); n = ohash_find(h, slot); @@ -269,12 +296,12 @@ add_file(p, file) ohash_insert(h, slot, n); } } - + static char * find_file_hash(p, file, e, hv) Path *p; - const char *file; - const char *e; + const char *file; + const char *e; u_int32_t hv; { struct ohash *h = &p->files; @@ -286,8 +313,8 @@ static void free_hash(h) struct ohash *h; { - void *e; - unsigned i; + void *e; + unsigned i; for (e = ohash_first(h, &i); e != NULL; e = ohash_next(h, &i)) free(e); @@ -299,11 +326,8 @@ free_hash(h) * Dir_Init -- * initialize things for this module * - * Results: - * none - * * Side Effects: - * some directories may be opened. + * cache the current directory *----------------------------------------------------------------------- */ void @@ -315,8 +339,11 @@ Dir_Init() dot = DirReaddir(".", NULL); + if (!dot) + Error("Can't access current directory"); + /* We always need to have dot around, so we increment its reference count - * to make sure it's not destroyed. */ + * to make sure it won't be destroyed. */ dot->refCount++; } @@ -324,12 +351,6 @@ Dir_Init() *----------------------------------------------------------------------- * Dir_End -- * cleanup things for this module - * - * Results: - * none - * - * Side Effects: - * none *----------------------------------------------------------------------- */ void @@ -343,7 +364,7 @@ Dir_End() Dir_Destroy(dot); Lst_Destroy(&dirSearchPath, Dir_Destroy); for (p = ohash_first(&openDirectories, &i); p != NULL; - p = ohash_next(&openDirectories, &i)) + p = ohash_next(&openDirectories, &i)) Dir_Destroy(p); ohash_delete(&openDirectories); free_hash(&mtimes); @@ -359,14 +380,14 @@ Dir_End() *----------------------------------------------------------------------- */ Boolean -Dir_HasWildcards (name) - const char *name; /* name to check */ +Dir_HasWildcards(name) + const char *name; /* name to check */ { - const char *cp; - Boolean wild = FALSE; + const char *cp; + Boolean wild = FALSE; unsigned long brace = 0, bracket = 0; - for (cp = name; *cp != '\0' ; cp++) { + for (cp = name; *cp != '\0'; cp++) { switch (*cp) { case '{': brace++; @@ -374,7 +395,7 @@ Dir_HasWildcards (name) break; case '}': if (brace == 0) - return FALSE; + return FALSE; brace--; break; case '[': @@ -383,7 +404,7 @@ Dir_HasWildcards (name) break; case ']': if (bracket == 0) - return FALSE; + return FALSE; bracket--; break; case '?': @@ -400,197 +421,234 @@ Dir_HasWildcards (name) /*- *----------------------------------------------------------------------- * DirMatchFiles -- - * Given a pattern and a Path structure, see if any files + * 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: - * File names are added to the expansions lst. The directory will be - * fully hashed when this is done. + * The directory will be fully hashed when this is done. *----------------------------------------------------------------------- */ static void -DirMatchFiles (pattern, p, expansions) - char *pattern; /* Pattern to look for */ - Path *p; /* Directory to search */ - Lst expansions; /* Place to store the results */ +DirMatchFiles(pattern, p, expansions) + const char *pattern; /* Pattern to look for */ + Path *p; /* Directory to search */ + Lst expansions; /* Place to store the results */ { - unsigned int search; /* Index into the directory's table */ - char *entry; /* Current entry in the table */ - Boolean isDot; /* TRUE if the directory being searched is . */ + unsigned int search; /* Index into the directory's table */ + const char *entry; /* Current entry in the table */ + Boolean isDot; /* Is the directory "." ? */ - isDot = (*p->name == '.' && p->name[1] == '\0'); + isDot = p->name[0] == '.' && p->name[1] == '\0'; for (entry = ohash_first(&p->files, &search); entry != NULL; entry = ohash_next(&p->files, &search)) { - /* See if the file matches the given pattern. Note we follow the UNIX + /* See if the file matches the given pattern. We follow the UNIX * convention that dot files will only be found if the pattern - * begins with a dot (note also that as a side effect of the hashing - * scheme, .* won't match . or .. since they aren't hashed). */ - if (*pattern != '.' && * entry == '.') - continue; + * begins with a dot (the hashing scheme doesn't hash . or .., + * so they won't match `.*'. */ + if (*pattern != '.' && *entry == '.') + continue; if (Str_Match(entry, pattern)) Lst_AtEnd(expansions, - (isDot ? estrdup(entry) : - str_concat(p->name, entry, '/'))); + isDot ? estrdup(entry) : str_concat(p->name, entry, '/')); } } /*- *----------------------------------------------------------------------- - * DirExpandCurly -- - * Expand curly braces like the C shell. Does this recursively. - * Note the special case: if after the piece of the curly brace is - * done there are no wildcard characters in the result, the result is - * placed on the list WITHOUT CHECKING FOR ITS EXISTENCE. - * - * Results: - * None. - * - * Side Effects: - * The given list is filled with the expansions... - * + * PathMatchFiles -- + * Traverse directories in the path, calling DirMatchFiles for each. + * NOTE: This doesn't handle patterns in directories. *----------------------------------------------------------------------- */ static void -DirExpandCurly(word, brace, path, expansions) - char *word; /* Entire word to expand */ - char *brace; /* First curly brace in it */ - Lst path; /* Search path to use */ - Lst expansions; /* Place to store the expansions */ +PathMatchFiles(word, path, expansions) + const char *word; /* Word to expand */ + Lst path; /* Path on which to look */ + Lst expansions; /* Place to store the result */ { - char *end; /* Character after the closing brace */ - char *cp; /* Current position in brace clause */ - char *start; /* Start of current piece of brace clause */ - int bracelevel; /* Number of braces we've seen. If we see a - * right brace when this is 0, we've hit the - * end of the clause. */ - char *file; /* Current expansion */ - int otherLen; /* The length of the other pieces of the - * expansion (chars before and after the - * clause in 'word') */ - char *cp2; /* Pointer for checking for wildcards in - * expansion before calling Dir_Expand */ - - start = brace+1; + LstNode ln; /* Current node */ - /* - * Find the end of the brace clause first, being wary of nested brace - * clauses. - */ - for (end = start, bracelevel = 0; *end != '\0'; end++) { - if (*end == '{') { - bracelevel++; - } else if ((*end == '}') && (bracelevel-- == 0)) { - break; - } - } - if (*end == '\0') { - Error("Unterminated {} clause \"%s\"", start); - return; - } else { - end++; - } - otherLen = brace - word + strlen(end); - - for (cp = start; cp < end; cp++) { - /* - * Find the end of this piece of the clause. - */ - bracelevel = 0; - while (*cp != ',') { - if (*cp == '{') { - bracelevel++; - } else if ((*cp == '}') && (bracelevel-- <= 0)) { - break; - } - cp++; - } - /* - * Allocate room for the combination and install the three pieces. - */ - file = emalloc(otherLen + cp - start + 1); - if (brace != word) { - strncpy(file, word, brace-word); - } - if (cp != start) { - strncpy(&file[brace-word], start, cp-start); - } - strcpy(&file[(brace-word)+(cp-start)], end); - - /* - * See if the result has any wildcards in it. If we find one, call - * Dir_Expand right away, telling it to place the result on our list - * of expansions. - */ - for (cp2 = file; *cp2 != '\0'; cp2++) { - switch(*cp2) { - case '*': - case '?': - case '{': - case '[': - Dir_Expand(file, path, expansions); - goto next; - } - } - if (*cp2 == '\0') { - /* - * Hit the end w/o finding any wildcards, so stick the expansion - * on the end of the list. - */ - Lst_AtEnd(expansions, file); - } else { - next: - free(file); - } - start = cp+1; - } + for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) + DirMatchFiles(word, (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; +{ + printf("%s ", (char *)word); +} /*- *----------------------------------------------------------------------- - * DirExpandInt -- - * Internal expand routine. Passes through the directories in the - * path one by one, calling DirMatchFiles for each. NOTE: This still - * doesn't handle patterns in directories... - * - * Side Effects: - * Things are added to the expansions list. - * + * DirExpandWild: + * Expand all wild cards in a fully qualified name, except for + * curly braces. *----------------------------------------------------------------------- */ static void -DirExpandInt(word, path, expansions) - char *word; /* Word to expand */ - Lst path; /* Path on which to look */ - Lst expansions; /* Place to store the result */ +DirExpandWild(word, path, expansions) + const char *word; /* the word to expand */ + Lst path; /* the list of directories in which to find + * the resulting files */ + Lst expansions; /* the list on which to place the results */ { - LstNode ln; /* Current node */ - Path *p; /* Directory in the node */ + const char *cp; + const char *slash; /* keep track of first slash before wildcard */ - Lst_Open(path); - while ((ln = Lst_Next(path)) != NULL) { - p = (Path *)Lst_Datum(ln); - DirMatchFiles(word, p, expansions); + slash = strchr(word, '/'); + if (slash == NULL) { + /* First the files in dot. */ + DirMatchFiles(word, dot, expansions); + + /* Then the files in every other directory on the path. */ + PathMatchFiles(word, path, expansions); + return; + } + /* The thing has a directory component -- find the first wildcard + * in the string. */ + slash = word; + for (cp = word; *cp; cp++) { + if (*cp == '/') + slash = cp; + if (*cp == '?' || *cp == '[' || *cp == '*') { + + if (slash != word) { + char *dirpath; + + /* If the glob isn't in the first component, try and find + * all the components up to the one with a wildcard. */ + dirpath = Dir_FindFilei(word, slash+1, path); + /* dirpath is null if we can't find the leading component + * XXX: Dir_FindFile won't find internal components. + * 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]; + LIST temp; + + if (*dp == '/') + *dp = '\0'; + Lst_Init(&temp); + Dir_AddDir(&temp, dirpath, NULL); + PathMatchFiles(slash+1, &temp, expansions); + Lst_Destroy(&temp, NOFREE); + } + } else + /* Start the search from the local directory. */ + PathMatchFiles(word, path, expansions); + return; + } } - Lst_Close(path); + /* Return the file -- this should never happen. */ + PathMatchFiles(word, path, expansions); } /*- *----------------------------------------------------------------------- - * DirPrintWord -- - * Print a word in the list of expansions, followed by a space. - * Callback for Dir_Expand when DEBUG(DIR), via Lst_ForEach. + * 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 + * no wildcards, the result is placed on the list WITHOUT CHECKING + * FOR ITS EXISTENCE. *----------------------------------------------------------------------- */ static void -DirPrintWord(word) - void *word; +DirExpandCurly(word, path, expansions) + const char *word; /* Entire word to expand */ + Lst path; /* Search path to use */ + Lst expansions; /* Place to store the expansions */ { - printf("%s ", (char *)word); + const char *cp2; /* Pointer for checking for wildcards in + * expansion before calling Dir_Expand */ + LIST curled; /* Queue of words to expand */ + char *toexpand; /* Current word to expand */ + Boolean 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++) + if (*cp2 == '*' || *cp2 == '?' || *cp2 == '[') { + dowild = TRUE; + break; + } + + /* Prime queue with copy of initial word */ + Lst_Init(&curled); + Lst_EnQueue(&curled, estrdup(word)); + while ((toexpand = (char *)Lst_DeQueue(&curled)) != NULL) { + const char *brace; + const char *start; /* Start of current chunk of brace clause */ + const char *end; /* Character after the closing brace */ + int bracelevel; + /* Keep track of nested braces. If we hit + * the right brace with bracelevel == 0, + * this is the end of the clause. */ + const char *cp; /* Current position in brace clause */ + size_t otherLen; + /* The length of the non-curlied part of + * the current expansion */ + + /* End case: no curly left to expand */ + brace = strchr(toexpand, '{'); + if (brace == NULL) { + if (dowild) { + DirExpandWild(toexpand, path, expansions); + free(toexpand); + } else + Lst_AtEnd(expansions, toexpand); + } + + start = brace+1; + + /* Find the end of the brace clause first, being wary of nested brace + * clauses. */ + for (end = start, bracelevel = 0;; end++) { + if (*end == '{') + bracelevel++; + else if (*end == '\0') { + Error("Unterminated {} clause \"%s\"", start); + return; + } else if (*end == '}' && bracelevel-- == 0) + break; + } + end++; + otherLen = brace - toexpand + strlen(end); + + for (cp = start; cp < end; cp++) { + char *file; /* To hold current expansion */ + + /* Find the end of the current expansion */ + bracelevel = 0; + while (*cp != ',') { + if (*cp == '{') + bracelevel++; + else if (*cp == '}' && bracelevel-- <= 0) + break; + cp++; + } + /* Build the current combination and enqueue it. */ + file = emalloc(otherLen + cp - start + 1); + if (brace != toexpand) + memcpy(file, toexpand, brace-word); + if (cp != start) + memcpy(file+(brace-toexpand), start, cp-start); + strcpy(file+(brace-toexpand)+(cp-start), end); + Lst_EnQueue(&curled, file); + } + } } /*- @@ -604,89 +662,27 @@ DirPrintWord(word) * path matching the given pattern. * * Side Effects: - * Directories may be opened. Who knows? + * Directories may be opened. *----------------------------------------------------------------------- */ void -Dir_Expand (word, path, expansions) - char *word; /* the word to expand */ - Lst path; /* the list of directories in which to find - * the resulting files */ - Lst expansions; /* the list on which to place the results */ +Dir_Expand(word, path, expansions) + const char *word; /* the word to expand */ + Lst path; /* the list of directories in which to find + * the resulting files */ + Lst expansions; /* the list on which to place the results */ { - char *cp; + const char *cp; - if (DEBUG(DIR)) { + if (DEBUG(DIR)) printf("expanding \"%s\"...", word); - } cp = strchr(word, '{'); - if (cp) { - DirExpandCurly(word, cp, path, expansions); - } else { - cp = strchr(word, '/'); - if (cp) { - /* - * The thing has a directory component -- find the first wildcard - * in the string. - */ - for (cp = word; *cp; cp++) { - if (*cp == '?' || *cp == '[' || *cp == '*' || *cp == '{') { - break; - } - } - if (*cp == '{') { - /* This one will be fun. */ - DirExpandCurly(word, cp, path, expansions); - return; - } else if (*cp != '\0') { - /* Back up to the start of the component. */ - char *dirpath; - - while (cp > word && *cp != '/') - cp--; - if (cp != word) { - char sc; - /* - * If the glob isn't in the first component, try and find - * all the components up to the one with a wildcard. - */ - sc = cp[1]; - cp[1] = '\0'; - dirpath = Dir_FindFile(word, path); - cp[1] = sc; - /* - * dirpath is null if can't find the leading component - * XXX: Dir_FindFile won't find internal components. - * i.e. if the path contains ../Etc/Object and we're - * looking for Etc, it won't be found. Ah well. - * Probably not important. - */ - if (dirpath != NULL) { - LIST temp; - - char *dp = &dirpath[strlen(dirpath) - 1]; - if (*dp == '/') - *dp = '\0'; - Lst_Init(&temp); - Dir_AddDir(&temp, dirpath, NULL); - DirExpandInt(cp+1, &temp, expansions); - Lst_Destroy(&temp, NOFREE); - } - } else - /* Start the search from the local directory. */ - DirExpandInt(word, path, expansions); - } else - /* Return the file -- this should never happen. */ - DirExpandInt(word, path, expansions); - } else { - /* First the files in dot. */ - DirMatchFiles(word, dot, expansions); - - /* Then the files in every other directory on the path. */ - DirExpandInt(word, path, expansions); - } - } + if (cp) + DirExpandCurly(word, path, expansions); + else + DirExpandWild(word, path, expansions); + if (DEBUG(DIR)) { Lst_Every(expansions, DirPrintWord); fputc('\n', stdout); @@ -695,7 +691,7 @@ Dir_Expand (word, path, expansions) /*- *----------------------------------------------------------------------- - * Dir_FindFile -- + * Dir_FindFilei -- * Find the file with the given name along the given search path. * * Results: @@ -712,85 +708,77 @@ Dir_Expand (word, path, expansions) *----------------------------------------------------------------------- */ char * -Dir_FindFile(name, path) - char *name; /* the file to find */ - Lst path; /* the Lst of directories to search */ +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 */ { - register char *p1; /* pointer into p->name */ - register char *p2; /* pointer into name */ - LstNode ln; /* a list element */ - register char *file; /* the current filename to check */ - register Path *p; /* current path member */ - register char *cp; /* index of first slash, if any */ - Boolean hasSlash; /* true if 'name' contains a / */ - struct stat stb; /* Buffer for stat, if necessary */ - struct file_stamp - *entry; /* Entry for mtimes table */ - const char *e; - u_int32_t hv; - - /* - * Find the final component of the name and note whether it has a - * slash in it (the name, I mean) - */ - cp = strrchr(name, '/'); + 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; + 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 */ + + /* Find the final component of the name and note whether it has a + * slash in it (the name, I mean). */ + cp = lastchar(name, end, '/'); if (cp) { hasSlash = TRUE; - cp += 1; + cp++; } else { hasSlash = FALSE; cp = name; } - e = NULL; - hv = ohash_interval(cp, &e); + hv = ohash_interval(cp, &end); - if (DEBUG(DIR)) { + if (DEBUG(DIR)) printf("Searching for %s...", name); - } - /* - * No matter what, we always look for the file in the current directory + /* 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). - */ + * (fish.c) and what pmake finds (./fish.c). */ if ((!hasSlash || (cp - name == 2 && *name == '.')) && - find_file_hash(dot, cp, e, hv) != NULL) { + find_file_hash(dot, cp, end, hv) != NULL) { if (DEBUG(DIR)) printf("in '.'\n"); - hits += 1; - dot->hits += 1; - return (estrdup (name)); + hits++; + dot->hits++; + return interval_dup(name, end); } - /* - * We look through all the directories on the path seeking one which + /* 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... - */ + * we go on to phase two... */ 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, e, hv) != NULL) { + if (find_file_hash(p, cp, end, hv) != NULL) { if (DEBUG(DIR)) printf("here..."); if (hasSlash) { - /* - * If the name had a slash, its initial components and p's + /* If the name had a slash, its initial components and p's * final components must match. This is false if a mismatch * is encountered before all of the initial components * have been checked (p2 > name at the end of the loop), or * we matched only part of one of the components of p - * along with all the rest of them (*p1 != '/'). - */ - p1 = p->name + strlen (p->name) - 1; + * along with all the rest of them (*p1 != '/'). */ + p1 = p->name + strlen(p->name) - 1; p2 = cp - 2; while (p2 >= name && p1 >= p->name && *p1 == *p2) { - p1 -= 1; p2 -= 1; + p1--; + p2--; } if (p2 >= name || (p1 >= p->name && *p1 != '/')) { if (DEBUG(DIR)) @@ -798,22 +786,21 @@ Dir_FindFile(name, path) continue; } } - file = str_concat(p->name, cp, '/'); + file = str_concati(p->name, cp, end, '/'); if (DEBUG(DIR)) printf("returning %s\n", file); - p->hits += 1; - hits += 1; + p->hits++; + hits++; return file; } else if (hasSlash) { /* If the file has a leading path component and that component * exactly matches the entire name of the current search * directory, we assume the file doesn't exist and return NULL. */ - for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) { + for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) continue; - } if (*p1 == '\0' && p2 == cp - 1) { if (DEBUG(DIR)) - printf("must be here but isn't -- returing NULL\n"); + printf("has to be here but isn't -- returning NULL\n"); return NULL; } } @@ -832,44 +819,43 @@ Dir_FindFile(name, path) if (!hasSlash) { if (DEBUG(DIR)) printf("failed.\n"); - misses += 1; + misses++; return NULL; } if (*name != '/') { - Boolean checkedDot = FALSE; + Boolean checkedDot = FALSE; if (DEBUG(DIR)) printf("failed. Trying subdirectories..."); - Lst_Open(path); for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); if (p != dot) - file = str_concat(p->name, name, '/'); + file = str_concati(p->name, name, end, '/'); else { /* Checking in dot -- DON'T put a leading ./ on the thing. */ - file = estrdup(name); + file = interval_dup(name, end); checkedDot = TRUE; } if (DEBUG(DIR)) printf("checking %s...", file); if (stat(file, &stb) == 0) { - TIMESTAMP mtime; + TIMESTAMP mtime; grab_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 + * 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 + * 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! */ - cp = strrchr(file, '/'); - Dir_AddDir(path, file, cp); + * without having to do numerous access calls. Hurrah! */ + temp = strrchr(file, '/'); + Dir_AddDir(path, file, temp); /* Save the modification time so if it's needed, we don't have * to fetch it again. */ @@ -877,7 +863,7 @@ Dir_FindFile(name, path) printf("Caching %s for %s\n", Targ_FmtTime(mtime), file); record_stamp(file, mtime); - nearmisses += 1; + nearmisses++; return file; } else free(file); @@ -885,6 +871,7 @@ Dir_FindFile(name, path) if (DEBUG(DIR)) printf("failed. "); + if (checkedDot) { /* Already checked by the given name, since . was in the path, * so no point in proceeding... */ @@ -920,31 +907,33 @@ Dir_FindFile(name, path) p = (Path *)Lst_Datum(ln); if (find_file_hash(p, cp, e, hv) != NULL) - return estrdup (name); + return estrdup(name); else return NULL; #else /* !notdef */ + q = interval_dup(name, end); if (DEBUG(DIR)) - printf("Looking for \"%s\"...", name); + printf("Looking for \"%s\"...", q); - bigmisses += 1; - entry = find_stamp(name); + bigmisses++; + entry = find_stampi(name, end); if (entry != NULL) { if (DEBUG(DIR)) printf("got it (in mtime cache)\n"); - return estrdup(name); - } else if (stat(name, &stb) == 0) { - TIMESTAMP mtime; + return q; + } else if (stat(q, &stb) == 0) { + TIMESTAMP mtime; grab_stat(stb, mtime); if (DEBUG(DIR)) printf("Caching %s for %s\n", Targ_FmtTime(mtime), - name); - record_stamp(name, mtime); - return estrdup(name); + q); + record_stamp(q, mtime); + return q; } else { if (DEBUG(DIR)) printf("failed. Returning NULL\n"); + free(q); return NULL; } #endif /* notdef */ @@ -967,18 +956,19 @@ Dir_FindFile(name, path) */ TIMESTAMP Dir_MTime(gn) - GNode *gn; /* the file whose modification time is + 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 */ + char *fullName; /* the full pathname of name */ + struct stat stb; /* buffer for finding the mod time */ struct file_stamp - *entry; + *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) @@ -991,7 +981,7 @@ Dir_MTime(gn) 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. */ + * to the file system. */ if (DEBUG(DIR)) printf("Using cached time %s for %s\n", Targ_FmtTime(entry->mtime), fullName); @@ -999,7 +989,7 @@ Dir_MTime(gn) free(entry); ohash_remove(&mtimes, slot); } else if (stat(fullName, &stb) == 0) - grab_stat(stb, mtime); + grab_stat(stb, mtime); else { if (gn->type & OP_MEMBER) { if (fullName != gn->path) @@ -1018,13 +1008,13 @@ Dir_MTime(gn) /* Read a directory, either from the disk, or from the cache. */ static Path * DirReaddir(name, end) - const char *name; - const char *end; + const char *name; + const char *end; { - Path *p; /* pointer to new Path structure */ - DIR *d; /* for reading directory */ - struct dirent *dp; /* entry in directory */ - unsigned int slot; + Path *p; /* pointer to new Path structure */ + DIR *d; /* for reading directory */ + struct dirent *dp; /* entry in directory */ + unsigned int slot; slot = ohash_qlookupi(&openDirectories, name, &end); p = ohash_find(&openDirectories, slot); @@ -1042,8 +1032,8 @@ DirReaddir(name, end) fflush(stdout); } - if ((d = opendir(p->name)) == NULL) - return NULL; + if ((d = opendir(p->name)) == NULL) + return NULL; /* Skip the first two entries -- these will *always* be . and .. */ (void)readdir(d); (void)readdir(d); @@ -1078,10 +1068,10 @@ DirReaddir(name, end) * read and hashed. *----------------------------------------------------------------------- */ + void Dir_AddDir(path, name, end) - Lst path; /* the path to which the directory should be - * added */ + Lst path; /* the path to which the directory should be added */ const char *name; /* the name of the directory to add */ const char *end; { @@ -1089,13 +1079,11 @@ Dir_AddDir(path, name, end) p = DirReaddir(name, end); if (p == NULL) - return; + return; if (p->refCount == 0) - Lst_AtEnd(path, p); - else if (Lst_Member(path, p) != NULL) - return; - else - Lst_AtEnd(path, p); + Lst_AtEnd(path, p); + else if (Lst_AddNew(path, p) == FAILURE) + return; p->refCount++; } @@ -1110,15 +1098,13 @@ Dir_AddDir(path, name, end) * * Side Effects: * The refCount of the path is incremented. - * *----------------------------------------------------------------------- */ void * Dir_CopyDir(p) void *p; { - ((Path *)p)->refCount += 1; - + ((Path *)p)->refCount++; return p; } @@ -1134,15 +1120,12 @@ Dir_CopyDir(p) * The string mentioned above. Note that there is no space between * the given flag and each directory. The empty string is returned if * Things don't go well. - * - * Side Effects: - * None *----------------------------------------------------------------------- */ char * Dir_MakeFlags(flag, path) - char *flag; /* flag which should precede each directory */ - Lst path; /* list of directories */ + const char *flag; /* flag which should precede each directory */ + Lst path; /* list of directories */ { LstNode ln; /* the node of the current directory */ BUFFER buf; @@ -1164,23 +1147,19 @@ Dir_MakeFlags(flag, path) * Nuke a directory descriptor, if possible. Callback procedure * for the suffixes module when destroying a search path. * - * Results: - * None. - * * Side Effects: * If no other path references this directory (refCount == 0), * the Path and all its data are freed. - * *----------------------------------------------------------------------- */ void -Dir_Destroy (pp) - void *pp; /* The directory descriptor to nuke */ +Dir_Destroy(pp) + void *pp; /* The directory descriptor to nuke */ { - Path *p = (Path *) pp; + Path *p = (Path *)pp; if (--p->refCount == 0) { - ohash_remove(&openDirectories, ohash_qlookup(&openDirectories, p->name)); + ohash_remove(&openDirectories, ohash_qlookup(&openDirectories, p->name)); free_hash(&p->files); free(p); } @@ -1188,56 +1167,26 @@ Dir_Destroy (pp) /*- *----------------------------------------------------------------------- - * Dir_ClearPath -- - * Clear out all elements of the given search path. This is different - * from destroying the list, notice. - * - * Results: - * None. - * - * Side Effects: - * The path is set to the empty list. - * - *----------------------------------------------------------------------- - */ -void -Dir_ClearPath(path) - Lst path; /* Path to clear */ -{ - Path *p; - while ((p = (Path *)Lst_DeQueue(path)) != NULL) - Dir_Destroy(p); -} - - -/*- - *----------------------------------------------------------------------- * Dir_Concat -- * Concatenate two paths, adding the second to the end of the first. * Makes sure to avoid duplicates. * - * Results: - * None - * * Side Effects: * Reference counts for added dirs are upped. - * *----------------------------------------------------------------------- */ void Dir_Concat(path1, path2) - Lst path1; /* Dest */ - Lst path2; /* Source */ + Lst path1; /* Dest */ + Lst path2; /* Source */ { - LstNode ln; - Path *p; + LstNode ln; + Path *p; for (ln = Lst_First(path2); ln != NULL; ln = Lst_Adv(ln)) { p = (Path *)Lst_Datum(ln); - if (Lst_Member(path1, p) == NULL) { - p->refCount += 1; - Lst_AtEnd(path1, p); - } + if (Lst_AddNew(path1, p) == SUCCESS) + p->refCount++; } } @@ -1245,30 +1194,30 @@ Dir_Concat(path1, path2) void Dir_PrintDirectories() { - Path *p; - unsigned int i; + Path *p; + unsigned int i; - printf ("#*** Directory Cache:\n"); - printf ("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", + printf("#*** Directory Cache:\n"); + printf("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", hits, misses, nearmisses, bigmisses, (hits+bigmisses+nearmisses ? hits * 100 / (hits + bigmisses + nearmisses) : 0)); - printf ("# %-20s referenced\thits\n", "directory"); + printf("# %-20s referenced\thits\n", "directory"); for (p = ohash_first(&openDirectories, &i); p != NULL; - p = ohash_next(&openDirectories, &i)) + p = ohash_next(&openDirectories, &i)) printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); } -static void +static void DirPrintDir(p) - void *p; + void *p; { printf("%s ", ((Path *)p)->name); } void Dir_PrintPath(path) - Lst path; + Lst path; { Lst_Every(path, DirPrintDir); } diff --git a/usr.bin/make/dir.h b/usr.bin/make/dir.h index b1ea1b511a2..f7f595f052e 100644 --- a/usr.bin/make/dir.h +++ b/usr.bin/make/dir.h @@ -1,5 +1,6 @@ -/* $OpenBSD: dir.h,v 1.13 2001/03/02 16:57:26 espie Exp $ */ -/* $NetBSD: dir.h,v 1.4 1996/11/06 17:59:05 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: dir.h,v 1.14 2001/05/03 13:41:04 espie Exp $ */ +/* $NetBSD: dir.h,v 1.4 1996/11/06 17:59:05 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -38,37 +39,37 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)dir.h 8.1 (Berkeley) 6/6/93 + * from: @(#)dir.h 8.1 (Berkeley) 6/6/93 */ /* dir.h -- */ -#ifndef _DIR -#define _DIR +#ifndef DIR_H +#define DIR_H typedef struct Path_ { - int refCount; /* Number of paths with this directory */ - int hits; /* the number of times a file in this + 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 */ + struct ohash files; /* Hash table of files in directory */ + char name[1]; /* Name of directory */ } Path; -extern void Dir_Init __P((void)); -extern void Dir_End __P((void)); -extern Boolean Dir_HasWildcards __P((const char *)); -extern void Dir_Expand __P((char *, Lst, Lst)); -extern char *Dir_FindFile __P((char *, Lst)); -extern TIMESTAMP Dir_MTime __P((GNode *)); -extern void Dir_AddDir __P((Lst, const char *, const char *)); -extern char *Dir_MakeFlags __P((char *, Lst)); -extern void Dir_ClearPath __P((Lst)); -extern void Dir_Concat __P((Lst, Lst)); -extern void Dir_PrintDirectories __P((void)); -extern void Dir_PrintPath __P((Lst)); -extern void Dir_Destroy __P((void *)); -extern void *Dir_CopyDir __P((void *)); -extern int set_times __P((const char *)); +extern void Dir_Init(void); +extern void Dir_End(void); +extern Boolean Dir_HasWildcards(const char *); +extern void Dir_Expand(const char *, Lst, Lst); +extern char *Dir_FindFilei(const char *, const char *, Lst); +#define Dir_FindFile(n, e) Dir_FindFilei(n, strchr(n, '\0'), e) +extern TIMESTAMP Dir_MTime(GNode *); +extern void Dir_AddDir(Lst, const char *, const char *); +extern char *Dir_MakeFlags(const char *, Lst); +extern void Dir_Concat(Lst, Lst); +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 /* _DIR */ +#endif /* DIR_H */ diff --git a/usr.bin/make/error.c b/usr.bin/make/error.c index e6902228938..595f639eaa9 100644 --- a/usr.bin/make/error.c +++ b/usr.bin/make/error.c @@ -1,4 +1,5 @@ -/* $OpenBSD: error.c,v 1.4 2000/10/13 08:29:20 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: error.c,v 1.5 2001/05/03 13:41:04 espie Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -47,7 +48,13 @@ #include <unistd.h> #include "error.h" -static void enomem __P((size_t)); +#ifdef __GNUC__ +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + +static void enomem(size_t); /* * emalloc -- @@ -112,7 +119,7 @@ ecalloc(s1, s2) void * hash_alloc(s, u) size_t s; - void *u; + void *u UNUSED; { return ecalloc(s, 1); } @@ -120,8 +127,8 @@ hash_alloc(s, u) void hash_free(p, s, u) void *p; - size_t s; - void *u; + size_t s UNUSED; + void *u UNUSED; { free(p); } @@ -129,11 +136,13 @@ hash_free(p, s, u) void * element_alloc(s, u) size_t s; - void *u; + void *u UNUSED; { return emalloc(s); } - + + + /* * enomem -- * die when out of memory. @@ -162,6 +171,7 @@ esetenv(name, value) exit(2); } + /* * enunlink -- * Remove a file carefully, avoiding directories. @@ -181,3 +191,4 @@ eunlink(file) } return unlink(file); } + diff --git a/usr.bin/make/error.h b/usr.bin/make/error.h index 5872cad2efe..d78d5bd5026 100644 --- a/usr.bin/make/error.h +++ b/usr.bin/make/error.h @@ -1,4 +1,5 @@ -/* $OpenBSD: error.h,v 1.4 2000/10/13 08:29:20 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: error.h,v 1.5 2001/05/03 13:41:05 espie Exp $ */ /*- * Copyright (c) 1988, 1989, 1990, 1993 @@ -41,19 +42,19 @@ */ #ifndef ERROR_H #define ERROR_H -extern void *emalloc __P((size_t)); -extern char *estrdup __P((const char *)); -extern void *erealloc __P((void *, size_t)); -extern void *ecalloc __P((size_t, size_t)); -extern int eunlink __P((const char *)); -extern void esetenv __P((const char *, const char *)); +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 *hash_alloc __P((size_t, void *)); -extern void hash_free __P((void *, size_t, void *)); -extern void *element_alloc __P((size_t, void *)); +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 */ diff --git a/usr.bin/make/extern.h b/usr.bin/make/extern.h index 17c3593030d..fa147953930 100644 --- a/usr.bin/make/extern.h +++ b/usr.bin/make/extern.h @@ -1,4 +1,5 @@ -/* $OpenBSD: extern.h,v 1.36 2000/11/24 14:36:34 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: extern.h,v 1.37 2001/05/03 13:41:05 espie Exp $ */ /* $NetBSD: nonints.h,v 1.12 1996/11/06 17:59:19 christos Exp $ */ /*- @@ -42,126 +43,148 @@ */ /* arch.c */ -extern ReturnStatus Arch_ParseArchive __P((char **, Lst, SymTable *)); -extern void Arch_Touch __P((GNode *)); -extern void Arch_TouchLib __P((GNode *)); -extern TIMESTAMP Arch_MTime __P((GNode *)); -extern TIMESTAMP Arch_MemMTime __P((GNode *)); -extern void Arch_FindLib __P((GNode *, Lst)); -extern Boolean Arch_LibOODate __P((GNode *)); -extern void Arch_Init __P((void)); -extern void Arch_End __P((void)); -extern int Arch_IsLib __P((GNode *)); +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 __P((Lst)); +extern void Compat_Run(Lst); /* cond.c */ -extern int Cond_Eval __P((char *)); -extern void Cond_End __P((void)); +extern int Cond_Eval(char *); +extern void Cond_End(void); #include "error.h" /* for.c */ typedef struct For_ For; -extern For *For_Eval __P((char *)); -extern Boolean For_Accumulate __P((For *, const char *)); -extern void For_Run __P((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 __P((char *)); -extern char *Cmd_Exec __P((char *, char **)); -extern void Error __P((char *, ...)); -extern void Fatal __P((char *, ...)); -extern void Punt __P((char *, ...)); -extern void DieHorribly __P((void)); -extern void PrintAddr __P((void *)); -extern void Finish __P((int)); +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 __P((GNode *, GNode *)); -extern Boolean Make_OODate __P((GNode *)); -extern void Make_HandleUse __P((GNode *, GNode *)); -extern void Make_Update __P((GNode *)); -extern void Make_DoAllVar __P((GNode *)); -extern Boolean Make_Run __P((Lst)); +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 __P((int, char *, ...)); -extern Boolean Parse_AnyExport __P((void)); -extern Boolean Parse_IsVar __P((char *)); -extern void Parse_DoVar __P((char *, GSymT *)); -extern void Parse_AddIncludeDir __P((char *)); -extern void Parse_File __P((char *, FILE *)); -extern void Parse_Init __P((void)); -extern void Parse_End __P((void)); -extern void Parse_FromString __P((char *, unsigned long)); -extern void Parse_MainName __P((Lst)); -extern unsigned long Parse_Getlineno __P((void)); -extern const char *Parse_Getfilename __P((void)); +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 __P((void)); -extern void str_end __P((void)); -extern char *str_concat __P((const char *, const char *, char)); -extern char **brk_string __P((const char *, int *, Boolean, char **)); -extern const char *iterate_words __P((const char **)); -extern int Str_Match __P((const char *, const char *)); -extern const char *Str_SYSVMatch __P((const char *, const char *, size_t *len)); -extern void Str_SYSVSubst __P((Buffer, const char *, const char *, size_t)); -extern char *interval_dup __P((const char *begin, const char *end)); -extern char *escape_dup __P((const char *, const char *, const char *)); +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 __P((void)); -extern Boolean Suff_IsTransform __P((char *)); -extern GNode *Suff_AddTransform __P((char *)); -extern void Suff_EndTransform __P((void *)); -extern void Suff_AddSuffix __P((char *)); -extern Lst Suff_GetPath __P((char *)); -extern void Suff_DoPaths __P((void)); -extern void Suff_AddInclude __P((char *)); -extern void Suff_AddLib __P((char *)); -extern void Suff_FindDeps __P((GNode *)); -extern void Suff_SetNull __P((char *)); -extern void Suff_Init __P((void)); -extern void Suff_End __P((void)); -extern void Suff_PrintAll __P((void)); +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 __P((void)); -extern void Targ_End __P((void)); -extern GNode *Targ_NewGN __P((const char *, const char *)); -extern GNode *Targ_FindNode __P((const char *, int)); -extern void Targ_FindList __P((Lst, Lst)); -extern Boolean Targ_Ignore __P((GNode *)); -extern Boolean Targ_Silent __P((GNode *)); -extern Boolean Targ_Precious __P((GNode *)); -extern void Targ_SetMain __P((GNode *)); -extern void Targ_PrintCmd __P((void *)); -extern char *Targ_FmtTime __P((TIMESTAMP)); -extern void Targ_PrintType __P((int)); -extern void Targ_PrintGraph __P((int)); +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 __P((const char *, GSymT *)); -extern void Var_Set __P((const char *, const char *, GSymT *)); -extern void Varq_Set __P((int, const char *, GNode *)); -extern void Var_Append __P((const char *, const char *, GSymT *)); -extern void Varq_Append __P((int, const char *, GNode *)); -extern Boolean Var_Exists __P((const char *, GSymT *)); -extern Boolean Varq_Exists __P((int, GNode *)); -extern char *Var_Value __P((const char *, GSymT *)); -extern char *Varq_Value __P((int, GNode *)); -extern char *Var_Parse __P((char *, SymTable *, Boolean, size_t *, Boolean *)); -extern char *Var_Subst __P((char *, SymTable *, Boolean)); -extern char *Var_SubstVar __P((const char *, const char *, const char *, - size_t)); -extern char *Var_GetTail __P((char *)); -extern char *Var_GetHead __P((char *)); -extern void Var_Init __P((void)); -extern void Var_End __P((void)); -extern void Var_Dump __P((GSymT *)); -extern void SymTable_Init __P((SymTable *)); -extern void SymTable_Destroy __P((SymTable *)); -extern void Var_AddCmdline __P((const char *)); +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 *); diff --git a/usr.bin/make/for.c b/usr.bin/make/for.c index fb37dadb9ae..fb02b513ab2 100644 --- a/usr.bin/make/for.c +++ b/usr.bin/make/for.c @@ -1,5 +1,6 @@ -/* $OpenBSD: for.c,v 1.23 2000/11/24 14:29:55 espie Exp $ */ -/* $NetBSD: for.c,v 1.4 1996/11/06 17:59:05 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: for.c,v 1.24 2001/05/03 13:41:05 espie Exp $ */ +/* $NetBSD: for.c,v 1.4 1996/11/06 17:59:05 christos Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -66,9 +67,9 @@ * Functions to handle loops in a makefile. * * Interface: - * For_Eval Evaluate the .for in the passed line + * For_Eval Evaluate the .for in the passed line. * For_Accumulate Add lines to an accumulating loop - * For_Run Run accumulated loop + * For_Run Run accumulated loop * */ @@ -83,14 +84,14 @@ static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: for.c,v 1.23 2000/11/24 14:29:55 espie Exp $"; +static char rcsid[] = "$OpenBSD: for.c,v 1.24 2001/05/03 13:41:05 espie Exp $"; #endif #endif /* not lint */ /* * For statements are of the form: * - * .for <variable> in <varlist> + * .for <variable> [variable...] in <varlist> * ... * .endfor * @@ -103,30 +104,38 @@ static char rcsid[] = "$OpenBSD: for.c,v 1.23 2000/11/24 14:29:55 espie Exp $"; /* State of a for loop. */ struct For_ { - char *text; /* unexpanded text */ - char *var; /* Index name */ - LIST lst; /* List of items */ + 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 */ + BUFFER buf; /* Accumulating text */ + unsigned long lineno; /* Line number at start of loop */ unsigned long level; /* Nesting level */ + Boolean freeold; }; -static void ForExec __P((void *, void *)); -static void build_words_list __P((Lst, const char *)); +static void ForExec(void *, void *); +static unsigned long build_words_list(Lst, const char *); /* Cut a string into words, stuff that into list. */ -static void +static unsigned long build_words_list(lst, s) Lst lst; const char *s; { const char *end, *wrd; + unsigned long n; + n = 0; end = s; - while ((wrd = iterate_words(&end)) != NULL) - Lst_AtFront(lst, escape_dup(wrd, end, "\"'")); + while ((wrd = iterate_words(&end)) != NULL) { + Lst_AtFront(lst, escape_dup(wrd, end, "\"'")); + n++; + } + return n; } /* @@ -144,16 +153,15 @@ build_words_list(lst, s) For * For_Eval(line) - char *line; /* Line to parse */ + const char *line; /* Line to parse */ { - char *ptr = line; - char *wrd; - char *sub; - char *endVar; + const char *ptr = line; + const char *wrd; + char *sub; + const char *endVar; For *arg; + unsigned long n; - for (ptr++; *ptr && isspace(*ptr); ptr++) - continue; /* If we are not in a for loop quickly determine if the statement is * a for. */ if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' || @@ -166,39 +174,49 @@ For_Eval(line) /* We found a for loop, and now we are going to parse it. */ - /* Grab the variable. */ - for (wrd = ptr; *ptr && !isspace(*ptr); ptr++) - continue; - if (ptr - wrd == 0) { - Parse_Error(PARSE_FATAL, "missing variable in for"); - return 0; - } - endVar = ptr++; - - while (*ptr && isspace(*ptr)) - ptr++; + arg = emalloc(sizeof(*arg)); + arg->nvars = 0; + Lst_Init(&arg->vars); - /* Grab the `in'. */ - if (ptr[0] != 'i' || ptr[1] != 'n' || - !isspace(ptr[2])) { - Parse_Error(PARSE_FATAL, "missing `in' in for"); - printf("%s\n", ptr); - return NULL; + for (;;) { + /* Grab the variables. */ + for (wrd = ptr; *ptr && !isspace(*ptr); ptr++) + continue; + if (ptr - wrd == 0) { + Parse_Error(PARSE_FATAL, "Syntax error in for"); + return 0; + } + endVar = ptr++; + while (*ptr && isspace(*ptr)) + ptr++; + /* finished variable list */ + if (endVar - wrd == 2 && wrd[0] == 'i' && wrd[1] == 'n') + break; + Lst_AtEnd(&arg->vars, interval_dup(wrd, endVar)); + arg->nvars++; + } + if (arg->nvars == 0) { + Parse_Error(PARSE_FATAL, "Missing variable in for"); + return 0; } - ptr += 3; - - /* .for loop is go, collate what we need. */ - arg = emalloc(sizeof(*arg)); - arg->var = interval_dup(wrd, endVar); /* Make a list with the remaining words. */ sub = Var_Subst(ptr, NULL, FALSE); - if (DEBUG(FOR)) - (void)fprintf(stderr, "For: Iterator %s List %s\n", arg->var, sub); + if (DEBUG(FOR)) { + LstNode ln; + (void)fprintf(stderr, "For: Iterator "); + for (ln = Lst_First(&arg->vars); ln != NULL; ln = Lst_Adv(ln)) + (void)fprintf(stderr, "%s ", (char *)Lst_Datum(ln)); + (void)fprintf(stderr, "List %s\n", sub); + } Lst_Init(&arg->lst); - build_words_list(&arg->lst, sub); + n = build_words_list(&arg->lst, sub); free(sub); + if (arg->nvars != 1 && n % arg->nvars != 0) { + Parse_Error(PARSE_FATAL, "Wrong number of items in for loop"); + return 0; + } arg->lineno = Parse_Getlineno(); arg->level = 1; Buf_Init(&arg->buf, 0); @@ -206,7 +224,7 @@ For_Eval(line) return arg; } - + /*- *----------------------------------------------------------------------- * For_Accumulate -- @@ -222,8 +240,8 @@ For_Eval(line) */ Boolean For_Accumulate(arg, line) - For *arg; - const char *line; /* Line to parse */ + For *arg; + const char *line; /* Line to parse */ { const char *ptr = line; @@ -269,14 +287,30 @@ ForExec(namep, argp) { char *name = (char *)namep; For *arg = (For *)argp; + BUFFER buf; + + /* Parse_FromString pushes stuff back, so we need to go over vars in + reverse. */ + if (arg->var == NULL) { + arg->var = Lst_Last(&arg->vars); + arg->text = Buf_Retrieve(&arg->buf); + arg->freeold = FALSE; + } if (DEBUG(FOR)) - (void)fprintf(stderr, "--- %s = %s\n", arg->var, name); - Parse_FromString(Var_SubstVar(arg->text, arg->var, name, - arg->guess), arg->lineno); + (void)fprintf(stderr, "--- %s = %s\n", (char *)Lst_Datum(arg->var), name); + Buf_Init(&buf, arg->guess); + Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), name); + if (arg->freeold) + free(arg->text); + arg->text = Buf_Retrieve(&buf); + arg->freeold = TRUE; + arg->var = Lst_Rev(arg->var); + if (arg->var == NULL) + Parse_FromString(arg->text, arg->lineno); } - + /*- *----------------------------------------------------------------------- * For_Run -- @@ -291,9 +325,10 @@ For_Run(arg) arg->text = Buf_Retrieve(&arg->buf); arg->guess = Buf_Size(&arg->buf) + GUESS_EXPANSION; + arg->var = NULL; Lst_ForEach(&arg->lst, ForExec, arg); - free(arg->var); - free(arg->text); + Buf_Destroy(&arg->buf); + Lst_Destroy(&arg->vars, (SimpleProc)free); Lst_Destroy(&arg->lst, (SimpleProc)free); free(arg); } diff --git a/usr.bin/make/generate.c b/usr.bin/make/generate.c index 4fa1013f906..c5287495ba1 100644 --- a/usr.bin/make/generate.c +++ b/usr.bin/make/generate.c @@ -1,18 +1,15 @@ -/* $OpenBSD: generate.c,v 1.2 2001/03/02 16:57:26 espie Exp $ */ -/* Written by Marc Espie 1999. - * Public domain. - */ #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include "make.h" +#include "stats.h" #include "ohash.h" -#include "error.h" +#include "cond_int.h" #define M(x) x, #x -char *table[] = { +char *table_var[] = { M(TARGET), M(OODATE), M(ALLSRC), @@ -26,9 +23,41 @@ char *table[] = { M(LONGIMPSRC), M(LONGPREFIX), M(LONGARCHIVE), - M(LONGMEMBER) + M(LONGMEMBER), + M(FTARGET), + M(DTARGET), + M(FPREFIX), + M(DPREFIX), + M(FARCHIVE), + M(DARCHIVE), + M(FMEMBER), + M(DMEMBER), + NULL }; +char *table_cond[] = { + M(COND_IF), + M(COND_IFDEF), + M(COND_IFNDEF), + M(COND_IFMAKE), + M(COND_IFNMAKE), + M(COND_ELSE), + M(COND_ELIFDEF), + M(COND_ELIFNDEF), + M(COND_ELIFMAKE), + M(COND_ELIFNMAKE), + M(COND_ENDIF), + M(COND_FOR), + M(COND_INCLUDE), + M(COND_UNDEF), + NULL +}; + + +char **table[] = { + table_var, + table_cond +}; int main(int argc, char *argv[]) @@ -39,34 +68,48 @@ main(int argc, char *argv[]) u_int32_t slots; const char *e; char **occupied; + char **t; + int tn; #ifdef HAS_STATS Init_Stats(); #endif - if (argc < 2) + if (argc != 3) exit(1); - slots = atoi(argv[1]); - if (!slots) + tn = atoi(argv[1]); + if (!tn) exit(1); - occupied = emalloc(sizeof(char *) * slots); - for (i = 0; i < slots; i++) - occupied[i] = NULL; - - printf("/* Generated file, do not edit */\n"); - for (i = 0; i < sizeof(table)/sizeof(char *); i++) { - e = NULL; - v = ohash_interval(table[i], &e); - h = v % slots; - if (occupied[h]) { - fprintf(stderr, "Collision: %s / %s (%d)\n", occupied[h], - table[i], h); + t = table[tn-1]; + slots = atoi(argv[2]); + if (slots) { + occupied = malloc(sizeof(char *) * slots); + if (!occupied) exit(1); + for (i = 0; i < slots; i++) + occupied[i] = NULL; + } else + occupied = NULL; + + printf("/* File created by generate %d %d, do not edit */\n", + tn, slots); + for (i = 0; t[i] != NULL; i++) { + e = NULL; + v = ohash_interval(t[i], &e); + if (slots) { + h = v % slots; + if (occupied[h]) { + fprintf(stderr, + "Collision: %s / %s (%d)\n", occupied[h], + t[i], h); + exit(1); + } + occupied[h] = t[i]; } - occupied[h] = table[i++]; - printf("#define K_%s %u\n", table[i], v); + i++; + printf("#define K_%s %u\n", t[i], v); } - printf("#define MAGICSLOTS %u\n", slots); + if (slots) + printf("#define MAGICSLOTS%d %u\n", tn, slots); exit(0); } - diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index cc4310966ba..281e18fd326 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -1,4 +1,5 @@ -/* $OpenBSD: job.c,v 1.39 2000/12/27 19:07:58 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: job.c,v 1.40 2001/05/03 13:41:06 espie Exp $ */ /* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */ /* @@ -44,57 +45,57 @@ * handle the creation etc. of our child processes. * * Interface: - * Job_Make Start the creation of the given target. + * Job_Make Start the creation of the given target. * - * Job_CatchChildren Check for and handle the termination of any - * children. This must be called reasonably - * 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 - * should block waiting for a child to terminate. + * Job_CatchChildren Check for and handle the termination of any + * children. This must be called reasonably + * 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 + * should block waiting for a child to terminate. * - * Job_CatchOutput Print any output our children have produced. - * Should also be called fairly frequently to - * keep the user informed of what's going on. - * If no output is waiting, it will block for - * a time given by the SEL_* constants, below, - * or until output is ready. + * Job_CatchOutput Print any output our children have produced. + * Should also be called fairly frequently to + * keep the user informed of what's going on. + * If no output is waiting, it will block for + * a time given by the SEL_* constants, below, + * or until output is ready. * - * Job_Init Called to intialize this module. in addition, - * any commands attached to the .BEGIN target - * are executed before this function returns. - * Hence, the makefile must have been parsed - * before this function is called. + * Job_Init Called to intialize this module. in addition, + * any commands attached to the .BEGIN target + * are executed before this function returns. + * Hence, the makefile must have been parsed + * before this function is called. * - * Job_End Cleanup any memory used. + * 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 - * empty. + * 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. + * Job_ParseShell Given the line following a .SHELL target, parse + * the line as a shell specification. Returns + * FAILURE if the spec was incorrect. * - * Job_Finish Perform any final processing which needs doing. - * This includes the execution of any commands - * which have been/were attached to the .END - * target. It should only be called when the - * job table is empty. + * Job_Finish Perform any final processing which needs doing. + * This includes the execution of any commands + * which have been/were attached to the .END + * target. It should only be called when the + * job table is empty. * - * Job_AbortAll Abort all currently running jobs. It doesn't - * handle output or do anything for the jobs, - * just kills them. It should only be called in - * an emergency, as it were. + * Job_AbortAll Abort all currently running jobs. It doesn't + * handle output or do anything for the jobs, + * just kills them. It should only be called in + * an emergency, as it were. * - * Job_CheckCommands Verify that the commands for a target are - * ok. Provide them if necessary and possible. + * Job_CheckCommands Verify that the commands for a target are + * ok. Provide them if necessary and possible. * - * Job_Touch Update a target without really updating it. + * Job_Touch Update a target without really updating it. * - * Job_Wait Wait for all currently-running jobs to finish. + * Job_Wait Wait for all currently-running jobs to finish. */ #include <sys/types.h> @@ -126,18 +127,19 @@ static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: job.c,v 1.39 2000/12/27 19:07:58 espie Exp $"; +static char rcsid[] = "$OpenBSD: job.c,v 1.40 2001/05/03 13:41:06 espie Exp $"; #endif #endif /* not lint */ + /* * error handling variables */ -static int errors = 0; /* number of errors reported */ -static int aborting = 0; /* why is the make aborting? */ -#define ABORT_ERROR 1 /* Because of an error */ -#define ABORT_INTERRUPT 2 /* Because it was interrupted */ -#define ABORT_WAIT 3 /* Waiting for jobs to finish */ +static int errors = 0; /* number of errors reported */ +static int aborting = 0; /* why is the make aborting? */ +#define ABORT_ERROR 1 /* Because of an error */ +#define ABORT_INTERRUPT 2 /* Because it was interrupted */ +#define ABORT_WAIT 3 /* Waiting for jobs to finish */ /* * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file @@ -150,31 +152,32 @@ static int aborting = 0; /* why is the make aborting? */ * .END target but we keep it around to avoid having to search for it * all the time. */ -static GNode *postCommands; /* node containing commands to execute when +static GNode *postCommands; /* node containing commands to execute when * everything else is done */ -static int numCommands; /* The number of commands actually printed +static int numCommands; /* The number of commands actually printed * for a target. Should this number be * 0, no shell will be executed. */ /* * Return values from JobStart. */ -#define JOB_RUNNING 0 /* Job is running */ -#define JOB_ERROR 1 /* Error in starting the job */ -#define JOB_FINISHED 2 /* The job is already finished */ -#define JOB_STOPPED 3 /* The job is stopped */ +#define JOB_RUNNING 0 /* Job is running */ +#define JOB_ERROR 1 /* Error in starting the job */ +#define JOB_FINISHED 2 /* The job is already finished */ +#define JOB_STOPPED 3 /* The job is stopped */ /* - * tfile is used to build temp file names to store shell commands to - * execute. + * tfile is the name of a file into which all shell commands are put. It is + * used over by removing it before the child shell is executed. The XXXXXXXXXX + * in the string are replaced by mkstemp(3). */ -static char tfile[sizeof(TMPPAT)]; +static char tfile[sizeof(TMPPAT)]; /* * Descriptions for various shells. */ -static Shell shells[] = { +static Shell shells[] = { /* * CSH description. The csh can do echo control by playing * with the setting of the 'echo' shell variable. Sadly, @@ -203,53 +206,53 @@ static Shell shells[] = { * UNKNOWN. */ { - (char *) 0, - FALSE, (char *) 0, (char *) 0, (char *) 0, 0, - FALSE, (char *) 0, (char *) 0, - (char *) 0, (char *) 0, + (char *)0, + FALSE, (char *)0, (char *)0, (char *)0, 0, + FALSE, (char *)0, (char *)0, + (char *)0, (char *)0, } }; -static Shell *commandShell = &shells[DEFSHELL];/* this is the shell to +static Shell *commandShell = &shells[DEFSHELL];/* this is the shell to * which we pass all * commands in the Makefile. * It is set by the * Job_ParseShell function */ -static char *shellPath = NULL, /* full pathname of +static char *shellPath = NULL, /* full pathname of * executable image */ - *shellName = NULL, /* last component of shell */ + *shellName = NULL, /* last component of shell */ *shellArgv = NULL; /* Custom shell args */ -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 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 +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 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 * running jobs equals the maximum allowed or * (2) a job can only be run locally, but * nLocal equals maxLocal */ #ifndef RMT_WILL_WATCH -static fd_set *outputsp; /* Set of descriptors of pipes connected to +static fd_set *outputsp; /* Set of descriptors of pipes connected to * the output channels of children */ static int outputsn; #endif -STATIC GNode *lastNode; /* The node for which output was most recently +STATIC GNode *lastNode; /* The node for which output was most recently * produced. */ -STATIC char *targFmt; /* Format string to use to head output from a +STATIC char *targFmt; /* Format string to use to head output from a * job when it's not the most-recent job heard * from */ #ifdef REMOTE # define TARG_FMT "--- %s at %s ---\n" /* Default format */ # define MESSAGE(fp, gn) \ - (void) fprintf(fp, targFmt, gn->name, gn->rem.hname); + (void)fprintf(fp, targFmt, gn->name, gn->rem.hname); #else # define TARG_FMT "--- %s ---\n" /* Default format */ # define MESSAGE(fp, gn) \ - (void) fprintf(fp, targFmt, gn->name); + (void)fprintf(fp, targFmt, gn->name); #endif /* @@ -264,7 +267,7 @@ STATIC LIST stoppedJobs; /* Lst of Job structures describing #if defined(USE_PGRP) && defined(SYSV) -# define KILL(pid, sig) killpg(-(pid), (sig)) +# define KILL(pid, sig) killpg(-(pid), (sig)) #else # if defined(USE_PGRP) # define KILL(pid, sig) killpg((pid), (sig)) @@ -293,29 +296,29 @@ STATIC LIST stoppedJobs; /* Lst of Job structures describing #define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) -static void JobCondPassSig __P((void *, void *)); -static void JobPassSig __P((int)); -static int JobCmpPid __P((void *, void *)); -static int JobPrintCommand __P((void *, void *)); -static void JobSaveCommand __P((void *, void *)); -static void JobClose __P((Job *)); +static void JobCondPassSig(void *, void *); +static void JobPassSig(int); +static int JobCmpPid(void *, void *); +static int JobPrintCommand(void *, void *); +static void JobSaveCommand(void *, void *); +static void JobClose(Job *); #ifdef REMOTE -static int JobCmpRmtID __P((Job *, void *)); +static int JobCmpRmtID(Job *, int); # ifdef RMT_WILL_WATCH -static void JobLocalInput __P((int, Job *)); +static void JobLocalInput(int, Job *); # endif #else -static void JobFinish __P((Job *, int *)); -static void JobExec __P((Job *, char **)); +static void JobFinish(Job *, int *); +static void JobExec(Job *, char **); #endif -static void JobMakeArgv __P((Job *, char **)); -static void JobRestart __P((Job *)); -static int JobStart __P((GNode *, int, Job *)); -static char *JobOutput __P((Job *, char *, char *, int)); -static void JobDoOutput __P((Job *, Boolean)); -static Shell *JobMatchShell __P((char *)); -static void JobInterrupt __P((int, int)); -static void JobRestartJobs __P((void)); +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 Shell *JobMatchShell(char *); +static void JobInterrupt(int, int); +static void JobRestartJobs(void); /*- *----------------------------------------------------------------------- @@ -325,19 +328,18 @@ static void JobRestartJobs __P((void)); * * Side Effects: * None, except the job may bite it. - * *----------------------------------------------------------------------- */ static void JobCondPassSig(jobp, signop) - void *jobp; /* Job to biff */ - void *signop; /* Signal to send it */ + void *jobp; /* Job to biff */ + void *signop; /* Signal to send it */ { - Job *job = (Job *) jobp; - int signo = *(int *) signop; + Job *job = (Job *)jobp; + int signo = *(int *)signop; #ifdef RMT_WANTS_SIGNALS if (job->flags & JOB_REMOTE) { - (void) Rmt_Signal(job, signo); + (void)Rmt_Signal(job, signo); } else { KILL(job->pid, signo); } @@ -347,10 +349,10 @@ JobCondPassSig(jobp, signop) * job as well. */ if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "JobCondPassSig passing signal %d to child %d.\n", signo, job->pid); - (void) fflush(stdout); + (void)fflush(stdout); } KILL(job->pid, signo); #endif @@ -362,24 +364,20 @@ JobCondPassSig(jobp, signop) * Pass a signal on to all remote jobs and to all local jobs if * USE_PGRP is defined, then die ourselves. * - * Results: - * None. - * * Side Effects: * We die by the same signal. - * *----------------------------------------------------------------------- */ static void JobPassSig(signo) - int signo; /* The signal number we've received */ + int signo; /* The signal number we've received */ { sigset_t nmask, omask; struct sigaction act; if (DEBUG(JOB)) { - (void) fprintf(stdout, "JobPassSig(%d) called.\n", signo); - (void) fflush(stdout); + (void)fprintf(stdout, "JobPassSig(%d) called.\n", signo); + (void)fflush(stdout); } Lst_ForEach(&jobs, JobCondPassSig, &signo); @@ -390,7 +388,7 @@ JobPassSig(signo) */ if (signo == SIGINT) { JobInterrupt(TRUE, signo); - } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) { + } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { JobInterrupt(FALSE, signo); } @@ -417,19 +415,19 @@ JobPassSig(signo) sigaction(signo, &act, NULL); if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "JobPassSig passing signal to self, mask = %x.\n", ~0 & ~(1 << (signo-1))); - (void) fflush(stdout); + (void)fflush(stdout); } - (void) signal(signo, SIG_DFL); + (void)signal(signo, SIG_DFL); - (void) KILL(getpid(), signo); + (void)KILL(getpid(), signo); signo = SIGCONT; Lst_ForEach(&jobs, JobCondPassSig, &signo); - (void) sigprocmask(SIG_SETMASK, &omask, NULL); + (void)sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL); act.sa_handler = JobPassSig; sigaction(signo, &act, NULL); @@ -444,9 +442,6 @@ JobPassSig(signo) * * Results: * 0 if the pid's match - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static int @@ -460,23 +455,20 @@ JobCmpPid(job, pid) #ifdef REMOTE /*- *----------------------------------------------------------------------- - * JobCmpRmtID -- + * JobCmpRmtID -- * Compare the rmtID of the job with the given rmtID and return 0 if they * are equal. * * Results: * 0 if the rmtID's match - * - * Side Effects: - * None. *----------------------------------------------------------------------- */ static int JobCmpRmtID(job, rmtID) - void *job; /* job to examine */ - void *rmtID; /* remote id desired */ + void *job; /* job to examine */ + void *rmtID; /* remote id desired */ { - return *(int *) rmtID - *(int *) job->rmtID; + return *(int *)rmtID - *(int *)job->rmtID; } #endif @@ -494,7 +486,7 @@ JobCmpRmtID(job, rmtID) * made and return non-zero to signal that the end of the commands * was reached. These commands are later attached to the postCommands * node and executed by Job_End when all things are done. - * This function is called from JobStart via Lst_ForEach. + * This function is called from JobStart via Lst_Find * * Results: * Always 1, unless the command was "..." @@ -509,23 +501,23 @@ JobCmpRmtID(job, rmtID) */ static int JobPrintCommand(cmdp, jobp) - void *cmdp; /* command string to print */ - void *jobp; /* job for which to print it */ + void *cmdp; /* command string to print */ + void *jobp; /* job for which to print it */ { Boolean 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 + Boolean shutUp = FALSE; /* true if we put a no echo command * into the command file */ Boolean 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 + char *cmdTemplate; /* Template to use when printing the * command */ - char *cmdStart; /* Start of expanded command */ - LstNode cmdNode; /* Node for replacing the command */ - char *cmd = (char *) cmdp; - Job *job = (Job *) jobp; + char *cmdStart; /* Start of expanded command */ + LstNode cmdNode; /* Node for replacing the command */ + char *cmd = (char *)cmdp; + Job *job = (Job *)jobp; noSpecials = (noExecute && !(job->node->type & OP_MAKE)); @@ -539,18 +531,16 @@ JobPrintCommand(cmdp, jobp) } #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ - (void) fprintf(stdout, fmt, arg); \ - (void) fflush(stdout); \ + (void)fprintf(stdout, fmt, arg); \ + (void)fflush(stdout); \ } \ - (void) fprintf(job->cmdFILE, fmt, arg); \ - (void) fflush(job->cmdFILE); + (void)fprintf(job->cmdFILE, fmt, arg); \ + (void)fflush(job->cmdFILE); numCommands += 1; - /* - * For debugging, we replace each command with the result of expanding - * the variables in the command. - */ + /* 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); Lst_Replace(cmdNode, cmdStart); @@ -561,15 +551,15 @@ JobPrintCommand(cmdp, jobp) * Check for leading @' and -'s to control echoing and error checking. */ for (;; cmd++) { - if (*cmd == '@') - shutUp = TRUE; + if (*cmd == '@') + shutUp = DEBUG(LOUD) ? FALSE : TRUE; else if (*cmd == '-') errOff = TRUE; else if (*cmd != '+') break; } - while (isspace((unsigned char) *cmd)) + while (isspace(*cmd)) cmd++; if (shutUp) { @@ -661,17 +651,17 @@ JobPrintCommand(cmdp, jobp) * * Side Effects: * The command is tacked onto the end of postCommands's commands list. - * *----------------------------------------------------------------------- */ static void JobSaveCommand(cmd, gn) - void *cmd; - void *gn; + void *cmd; + void *gn; { - char *result; + GNode *g = (GNode *)gn; + char *result; - result = Var_Subst((char *)cmd, &((GNode *)gn)->context, FALSE); + result = Var_Subst((char *)cmd, &g->context, FALSE); Lst_AtEnd(&postCommands->commands, result); } @@ -681,12 +671,8 @@ JobSaveCommand(cmd, gn) * JobClose -- * Called to close both input and output pipes when a job is finished. * - * Results: - * Nada - * * Side Effects: * The file descriptors associated with the job are closed. - * *----------------------------------------------------------------------- */ static void @@ -700,12 +686,12 @@ JobClose(job) FD_CLR(job->inPipe, outputsp); #endif if (job->outPipe != job->inPipe) { - (void) close(job->outPipe); + (void)close(job->outPipe); } JobDoOutput(job, TRUE); - (void) close(job->inPipe); + (void)close(job->inPipe); } else { - (void) close(job->outFd); + (void)close(job->outFd); JobDoOutput(job, TRUE); } } @@ -720,9 +706,6 @@ JobClose(job) * or something, jstat.w_status is 0 and when called from * Job_CatchChildren, the status is zeroed if it s/b ignored. * - * Results: - * None - * * Side Effects: * Some nodes may be put on the toBeMade queue. * Final commands for the job are placed on postCommands. @@ -736,14 +719,14 @@ JobClose(job) /*ARGSUSED*/ static void JobFinish(job, status) - Job *job; /* job to finish */ - int *status; /* sub-why job went away */ + Job *job; /* job to finish */ + int *status; /* sub-why job went away */ { - Boolean done; + Boolean done; if ((WIFEXITED(*status) && - (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) || - (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT))) + WEXITSTATUS(*status) != 0 && !(job->flags & JOB_IGNERR)) || + (WIFSIGNALED(*status) && WTERMSIG(*status) != SIGCONT)) { /* * If it exited non-zero and either we're doing things our @@ -758,7 +741,7 @@ JobFinish(job, status) #endif JobClose(job); if (job->cmdFILE != NULL && job->cmdFILE != stdout) { - (void) fclose(job->cmdFILE); + (void)fclose(job->cmdFILE); } done = TRUE; #ifdef REMOTE @@ -794,7 +777,7 @@ JobFinish(job, status) if (done || WIFSTOPPED(*status) || - (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) || + (WIFSIGNALED(*status) && WTERMSIG(*status) == SIGCONT) || DEBUG(JOB)) { FILE *out; @@ -812,15 +795,15 @@ JobFinish(job, status) if (WIFEXITED(*status)) { if (DEBUG(JOB)) { - (void) fprintf(stdout, "Process %d exited.\n", job->pid); - (void) fflush(stdout); + (void)fprintf(stdout, "Process %d exited.\n", job->pid); + (void)fflush(stdout); } if (WEXITSTATUS(*status) != 0) { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } - (void) fprintf(out, "*** Error code %d%s\n", + (void)fprintf(out, "*** Error code %d%s\n", WEXITSTATUS(*status), (job->flags & JOB_IGNERR) ? "(ignored)" : ""); @@ -832,19 +815,19 @@ JobFinish(job, status) MESSAGE(out, job->node); lastNode = job->node; } - (void) fprintf(out, "*** Completed successfully\n"); + (void)fprintf(out, "*** Completed successfully\n"); } } else if (WIFSTOPPED(*status)) { if (DEBUG(JOB)) { - (void) fprintf(stdout, "Process %d stopped.\n", job->pid); - (void) fflush(stdout); + (void)fprintf(stdout, "Process %d stopped.\n", job->pid); + (void)fflush(stdout); } if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } if (!(job->flags & JOB_REMIGRATE)) { - (void) fprintf(out, "*** Stopped -- signal %d\n", + (void)fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status)); } job->flags |= JOB_RESUME; @@ -853,7 +836,7 @@ JobFinish(job, status) if (job->flags & JOB_REMIGRATE) JobRestart(job); #endif - (void) fflush(out); + (void)fflush(out); return; } else if (WTERMSIG(*status) == SIGCONT) { /* @@ -866,55 +849,55 @@ JobFinish(job, status) MESSAGE(out, job->node); lastNode = job->node; } - (void) fprintf(out, "*** Continued\n"); + (void)fprintf(out, "*** Continued\n"); } if (!(job->flags & JOB_CONTINUING)) { if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "Warning: process %d was not continuing.\n", job->pid); - (void) fflush(stdout); + (void)fflush(stdout); } #ifdef notdef /* * We don't really want to restart a job from scratch just * because it continued, especially not without killing the - * continuing process! That's why this is ifdef'ed out. + * continuing process! That's why this is ifdef'ed out. * FD - 9/17/90 */ JobRestart(job); #endif } job->flags &= ~JOB_CONTINUING; - Lst_AtEnd(&jobs, job); + Lst_AtEnd(&jobs, job); nJobs += 1; if (!(job->flags & JOB_REMOTE)) { if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "Process %d is continuing locally.\n", job->pid); - (void) fflush(stdout); - } + (void)fflush(stdout); + } nLocal += 1; } if (nJobs == maxJobs) { jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Job queue is full.\n"); - (void) fflush(stdout); - } - } - (void) fflush(out); - return; + (void)fprintf(stdout, "Job queue is full.\n"); + (void)fflush(stdout); + } + } + (void)fflush(out); + return; } else { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } - (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status)); + (void)fprintf(out, "*** Signal %d\n", WTERMSIG(*status)); } - (void) fflush(out); + (void)fflush(out); } /* @@ -922,8 +905,7 @@ JobFinish(job, status) * try and restart the job on the next command. If JobStart says it's * ok, it's ok. If there's an error, this puppy is done. */ - if (compatMake && (WIFEXITED(*status) && - !Lst_IsAtEnd(&job->node->commands))) { + if (compatMake && WIFEXITED(*status) && job->node->current != NULL) { switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { case JOB_RUNNING: done = FALSE; @@ -943,22 +925,17 @@ JobFinish(job, status) done = FALSE; break; } - } else { + } else done = TRUE; - } - if (done && - (aborting != ABORT_ERROR) && - (aborting != ABORT_INTERRUPT) && - (*status == 0)) - { - /* - * As long as we aren't aborting and the job didn't return a non-zero + aborting != ABORT_ERROR && + aborting != ABORT_INTERRUPT && + *status == 0) { + /* As long as we aren't aborting and the job didn't return a non-zero * status that we shouldn't ignore, we call Make_Update to update * the parents. In addition, any saved commands for the node are placed - * on the .END target. - */ + * on the .END target. */ Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node); job->node->made = MADE; Make_Update(job->node); @@ -973,7 +950,7 @@ JobFinish(job, status) /* * Set aborting if any error. */ - if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) { + if (errors && !keepgoing && aborting != ABORT_INTERRUPT) { /* * If we found any errors in this batch of children and the -k flag * wasn't given, we set the aborting flag so no more jobs get @@ -982,11 +959,13 @@ JobFinish(job, status) aborting = ABORT_ERROR; } - if ((aborting == ABORT_ERROR) && Job_Empty()) + if (aborting == ABORT_ERROR && Job_Empty()) { /* * If we are aborting and the job table is now empty, we finish. */ + (void)eunlink(tfile); Finish(errors); + } } /*- @@ -995,9 +974,6 @@ JobFinish(job, status) * Touch the given target. Called by JobStart when the -t flag was * given * - * Results: - * None - * * Side Effects: * The data modification of the file is changed. In addition, if the * file did not exist, it is created. @@ -1005,10 +981,10 @@ 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 */ + GNode *gn; /* the node of the file to touch */ + Boolean silent; /* TRUE if should not print messages */ { - int streamID; /* ID of stream opened to do the touch */ + int streamID; /* ID of stream opened to do the touch */ if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) { /* @@ -1019,8 +995,8 @@ Job_Touch(gn, silent) } if (!silent) { - (void) fprintf(stdout, "touch %s\n", gn->name); - (void) fflush(stdout); + (void)fprintf(stdout, "touch %s\n", gn->name); + (void)fflush(stdout); } if (noExecute) { @@ -1032,9 +1008,9 @@ Job_Touch(gn, silent) } else if (gn->type & OP_LIB) { Arch_TouchLib(gn); } else { - char *file = gn->path ? gn->path : gn->name; + const char *file = gn->path != NULL ? gn->path : gn->name; - if (set_times(file) == -1) { + if (set_times(file) == -1){ streamID = open(file, O_RDWR | O_CREAT, 0666); if (streamID >= 0) { @@ -1045,15 +1021,15 @@ Job_Touch(gn, silent) * modification time, then close the file. */ if (read(streamID, &c, 1) == 1) { - (void) lseek(streamID, 0, SEEK_SET); - (void) write(streamID, &c, 1); + (void)lseek(streamID, 0, SEEK_SET); + (void)write(streamID, &c, 1); } - (void) close(streamID); + (void)close(streamID); } else { - (void) fprintf(stdout, "*** couldn't touch %s: %s", + (void)fprintf(stdout, "*** couldn't touch %s: %s", file, strerror(errno)); - (void) fflush(stdout); + (void)fflush(stdout); } } } @@ -1074,9 +1050,9 @@ Job_Touch(gn, silent) */ Boolean Job_CheckCommands(gn, abortProc) - GNode *gn; /* The target whose commands need + GNode *gn; /* The target whose commands need * verifying */ - void (*abortProc) __P((char *, ...)); + void (*abortProc)(char *, ...); /* Function to abort with message */ { if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && @@ -1085,7 +1061,7 @@ Job_CheckCommands(gn, abortProc) * No commands. Look for .DEFAULT rule from which we might infer * commands */ - if ((DEFAULT != NULL) && !Lst_IsEmpty(&DEFAULT->commands)) { + if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { /* * Make only looks for a .DEFAULT if the node was never the * target of an operator, so that's what we do too. If @@ -1108,15 +1084,15 @@ Job_CheckCommands(gn, abortProc) static const char msg[] = "make: don't know how to make"; if (gn->type & OP_OPTIONAL) { - (void) fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); - (void) fflush(stdout); + (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); + (void)fflush(stdout); } else if (keepgoing) { - (void) fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); - (void) fflush(stdout); - return FALSE; + (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); + (void)fflush(stdout); + return FALSE; } else { (*abortProc)("%s %s. Stop in %s.", msg, gn->name, - Var_Value(".CURDIR", VAR_GLOBAL)); + Var_Value(".CURDIR")); return FALSE; } } @@ -1129,19 +1105,15 @@ Job_CheckCommands(gn, abortProc) * JobLocalInput -- * Handle a pipe becoming readable. Callback function for Rmt_Watch * - * Results: - * None - * * Side Effects: * JobDoOutput is called. - * *----------------------------------------------------------------------- */ /*ARGSUSED*/ static void JobLocalInput(stream, job) - int stream; /* Stream that's ready (ignored) */ - Job *job; /* Job to which the stream belongs */ + int stream; /* Stream that's ready (ignored) */ + Job *job; /* Job to which the stream belongs */ { JobDoOutput(job, FALSE); } @@ -1153,33 +1125,29 @@ JobLocalInput(stream, job) * Execute the shell for the given job. Called from JobStart and * JobRestart. * - * Results: - * None. - * * Side Effects: * A shell is executed, outputs is altered and the Job structure added * to the job table. - * *----------------------------------------------------------------------- */ static void JobExec(job, argv) - Job *job; /* Job to execute */ - char **argv; + Job *job; /* Job to execute */ + char **argv; { - int cpid; /* ID of new child */ + int cpid; /* ID of new child */ if (DEBUG(JOB)) { - int i; + int i; - (void) fprintf(stdout, "Running %s %sly\n", job->node->name, + (void)fprintf(stdout, "Running %s %sly\n", job->node->name, job->flags&JOB_REMOTE?"remote":"local"); - (void) fprintf(stdout, "\tCommand: "); + (void)fprintf(stdout, "\tCommand: "); for (i = 0; argv[i] != NULL; i++) { - (void) fprintf(stdout, "%s ", argv[i]); + (void)fprintf(stdout, "%s ", argv[i]); } - (void) fprintf(stdout, "\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "\n"); + (void)fflush(stdout); } /* @@ -1188,7 +1156,7 @@ JobExec(job, argv) * banner with their name in it never appears). This is an attempt to * provide that feedback, even if nothing follows it. */ - if ((lastNode != job->node) && (job->flags & JOB_FIRST) && + if (lastNode != job->node && (job->flags & JOB_FIRST) && !(job->flags & JOB_SILENT)) { MESSAGE(stdout, job->node); lastNode = job->node; @@ -1211,8 +1179,8 @@ JobExec(job, argv) */ if (dup2(FILENO(job->cmdFILE), 0) == -1) Punt("Cannot dup2: %s", strerror(errno)); - (void) fcntl(0, F_SETFD, 0); - (void) lseek(0, 0, SEEK_SET); + (void)fcntl(0, F_SETFD, 0); + (void)lseek(0, 0, SEEK_SET); if (usePipes) { /* @@ -1236,7 +1204,7 @@ JobExec(job, argv) * it before routing the shell's error output to the same place as * its standard output. */ - (void) fcntl(1, F_SETFD, 0); + (void)fcntl(1, F_SETFD, 0); if (dup2(1, 2) == -1) Punt("Cannot dup2: %s", strerror(errno)); @@ -1247,9 +1215,9 @@ JobExec(job, argv) * by killing its process family, but not commit suicide. */ # if defined(SYSV) - (void) setsid(); + (void)setsid(); # else - (void) setpgid(0, getpid()); + (void)setpgid(0, getpid()); # endif #endif /* USE_PGRP */ @@ -1258,9 +1226,9 @@ JobExec(job, argv) Rmt_Exec(shellPath, argv, FALSE); } else #endif /* REMOTE */ - (void) execv(shellPath, argv); + (void)execv(shellPath, argv); - (void) write(2, "Could not execute shell\n", + (void)write(2, "Could not execute shell\n", sizeof("Could not execute shell")); _exit(1); } else { @@ -1308,12 +1276,12 @@ JobExec(job, argv) * XXX: Used to not happen if REMOTE. Why? */ if (job->cmdFILE != NULL && job->cmdFILE != stdout) { - (void) fclose(job->cmdFILE); + (void)fclose(job->cmdFILE); job->cmdFILE = NULL; } } #ifdef REMOTE - (void) sigsetmask(omask); + (void)sigsetmask(omask); #endif } @@ -1334,27 +1302,21 @@ jobExecFinish: *----------------------------------------------------------------------- * JobMakeArgv -- * Create the argv needed to execute the shell for a given job. - * - * - * Results: - * - * Side Effects: - * *----------------------------------------------------------------------- */ static void JobMakeArgv(job, argv) - Job *job; + Job *job; char **argv; { - int argc; - static char args[10]; /* For merged arguments */ + int argc; + static char args[10]; /* For merged arguments */ argv[0] = shellName; argc = 1; - if ((commandShell->exit && (*commandShell->exit != '-')) || - (commandShell->echo && (*commandShell->echo != '-'))) + if ((commandShell->exit && *commandShell->exit != '-') || + (commandShell->echo && *commandShell->echo != '-')) { /* * At least one of the flags doesn't have a minus before it, so @@ -1390,17 +1352,13 @@ JobMakeArgv(job, argv) * JobRestart -- * Restart a job that stopped for some reason. * - * Results: - * None. - * * Side Effects: * jobFull will be set if the job couldn't be run. - * *----------------------------------------------------------------------- */ static void JobRestart(job) - Job *job; /* Job to restart */ + Job *job; /* Job to restart */ { #ifdef REMOTE int host; @@ -1412,16 +1370,16 @@ JobRestart(job) verboseRemigrates || #endif DEBUG(JOB)) { - (void) fprintf(stdout, "*** remigrating %x(%s)\n", + (void)fprintf(stdout, "*** remigrating %x(%s)\n", job->pid, job->node->name); - (void) fflush(stdout); + (void)fflush(stdout); } #ifdef REMOTE if (!Rmt_ReExport(job->pid, job->node, &host)) { if (verboseRemigrates || DEBUG(JOB)) { - (void) fprintf(stdout, "*** couldn't migrate...\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "*** couldn't migrate...\n"); + (void)fflush(stdout); } #endif if (nLocal != maxLocal) { @@ -1435,8 +1393,8 @@ JobRestart(job) verboseRemigrates || #endif DEBUG(JOB)) { - (void) fprintf(stdout, "*** resuming on local machine\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "*** resuming on local machine\n"); + (void)fflush(stdout); } KILL(job->pid, SIGCONT); nLocal +=1; @@ -1456,14 +1414,14 @@ JobRestart(job) verboseRemigrates || #endif DEBUG(JOB)) { - (void) fprintf(stdout, "*** holding\n"); - (void) fflush(stdout); - } + (void)fprintf(stdout, "*** holding\n"); + (void)fflush(stdout); + } Lst_AtFront(&stoppedJobs, job); jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Job queue is full.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Job queue is full.\n"); + (void)fflush(stdout); } return; } @@ -1485,8 +1443,8 @@ JobRestart(job) if (nJobs == maxJobs) { jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Job queue is full.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Job queue is full.\n"); + (void)fflush(stdout); } } } else if (job->flags & JOB_RESTART) { @@ -1503,12 +1461,12 @@ JobRestart(job) JobMakeArgv(job, argv); if (DEBUG(JOB)) { - (void) fprintf(stdout, "Restarting %s...", job->node->name); - (void) fflush(stdout); + (void)fprintf(stdout, "Restarting %s...", job->node->name); + (void)fflush(stdout); } #ifdef REMOTE if ((job->node->type&OP_NOEXPORT) || - (nLocal < maxLocal && runLocalFirst) + (nLocal < maxLocal && runLocalFirst) # ifdef RMT_NO_EXEC || !Rmt_Export(shellPath, argv, job) # else @@ -1516,20 +1474,20 @@ JobRestart(job) # endif #endif { - if (((nLocal >= maxLocal) && !(job->flags & JOB_SPECIAL))) { + if (nLocal >= maxLocal && !(job->flags & JOB_SPECIAL)) { /* * Can't be exported and not allowed to run locally -- put it * back on the hold queue and mark the table full */ if (DEBUG(JOB)) { - (void) fprintf(stdout, "holding\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "holding\n"); + (void)fflush(stdout); } Lst_AtFront(&stoppedJobs, job); jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Job queue is full.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Job queue is full.\n"); + (void)fflush(stdout); } return; } else { @@ -1537,8 +1495,8 @@ JobRestart(job) * Job may be run locally. */ if (DEBUG(JOB)) { - (void) fprintf(stdout, "running locally\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "running locally\n"); + (void)fflush(stdout); } job->flags &= ~JOB_REMOTE; } @@ -1549,8 +1507,8 @@ JobRestart(job) * Can be exported. Hooray! */ if (DEBUG(JOB)) { - (void) fprintf(stdout, "exporting\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "exporting\n"); + (void)fflush(stdout); } job->flags |= JOB_REMOTE; } @@ -1562,20 +1520,20 @@ JobRestart(job) * we don't know... */ if (DEBUG(JOB)) { - (void) fprintf(stdout, "Resuming %s...", job->node->name); - (void) fflush(stdout); + (void)fprintf(stdout, "Resuming %s...", job->node->name); + (void)fflush(stdout); } if (((job->flags & JOB_REMOTE) || - (nLocal < maxLocal) || + nLocal < maxLocal || #ifdef REMOTE - (((job->flags & JOB_SPECIAL) && - (job->node->type & OP_NOEXPORT)) && - (maxLocal == 0))) && + ((job->flags & JOB_SPECIAL) && + (job->node->type & OP_NOEXPORT) && + maxLocal == 0) #else ((job->flags & JOB_SPECIAL) && - (maxLocal == 0))) && + maxLocal == 0) #endif - (nJobs != maxJobs)) + ) && nJobs != maxJobs) { /* * If the job is remote, it's ok to resume it as long as the @@ -1592,7 +1550,7 @@ JobRestart(job) error = !Rmt_Signal(job, SIGCONT); } else #endif /* RMT_WANTS_SIGNALS */ - error = (KILL(job->pid, SIGCONT) != 0); + error = KILL(job->pid, SIGCONT) != 0; if (!error) { /* @@ -1605,8 +1563,8 @@ JobRestart(job) job->flags &= ~(JOB_RESUME|JOB_CONTINUING); if (DEBUG(JOB)) { - (void) fprintf(stdout, "done\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "done\n"); + (void)fflush(stdout); } } else { Error("couldn't resume %s: %s", @@ -1621,14 +1579,14 @@ JobRestart(job) * place the job back on the list of stopped jobs. */ if (DEBUG(JOB)) { - (void) fprintf(stdout, "table full\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "table full\n"); + (void)fflush(stdout); } Lst_AtFront(&stoppedJobs, job); jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Job queue is full.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Job queue is full.\n"); + (void)fflush(stdout); } } } @@ -1652,24 +1610,23 @@ JobRestart(job) */ static int JobStart(gn, flags, previous) - GNode *gn; /* target to create */ - int flags; /* flags for the job to override normal ones. + GNode *gn; /* target to create */ + int flags; /* flags for the job to override normal ones. * e.g. JOB_SPECIAL or JOB_IGNDOTS */ Job *previous; /* The previous Job structure for this node, * if any. */ { - register Job *job; /* new job descriptor */ + 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 */ - int tfd; /* where to stash those pesky commands */ + Boolean local; /* Set true if the job was run locally */ + Boolean noExec; /* Set true if we decide not to run the job */ if (previous != NULL) { previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE); job = previous; } else { - job = (Job *) emalloc(sizeof(Job)); + job = emalloc(sizeof(Job)); if (job == NULL) { Punt("JobStart out of memory"); } @@ -1718,16 +1675,11 @@ JobStart(gn, flags, previous) DieHorribly(); } - (void) strcpy(tfile, TMPPAT); - if ((tfd = mkstemp(tfile)) == -1) - Punt("Cannot create temp file: %s", strerror(errno)); - job->cmdFILE = fdopen(tfd, "w+"); - eunlink(tfile); + job->cmdFILE = fopen(tfile, "w+"); if (job->cmdFILE == NULL) { - close(tfd); Punt("Could not open %s", tfile); } - (void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1); + (void)fcntl(FILENO(job->cmdFILE), F_SETFD, 1); /* * Send the commands to the command file, flush all its buffers then * rewind and remove the thing. @@ -1739,7 +1691,6 @@ JobStart(gn, flags, previous) * per shell. */ if (compatMake) { - LstNode ln; /* * Be compatible: If this is the first time for this node, * verify its commands are ok and open the commands list for @@ -1749,12 +1700,14 @@ JobStart(gn, flags, previous) * ellipsis, note that there's nothing more to execute. */ if ((job->flags&JOB_FIRST)) - Lst_Open(&gn->commands); - ln = Lst_Next(&gn->commands); + gn->current = Lst_First(&gn->commands); + else + gn->current = Lst_Succ(gn->current); - if ((ln == NULL) || !JobPrintCommand(Lst_Datum(ln), job)) { + if (gn->current == NULL || + !JobPrintCommand(Lst_Datum(gn->current), job)) { noExec = TRUE; - Lst_Close(&gn->commands); + gn->current = NULL; } if (noExec && !(job->flags & JOB_FIRST)) { /* @@ -1800,8 +1753,9 @@ JobStart(gn, flags, previous) * not -- just let the user know they're bad and keep going. It * doesn't do any harm in this case and may do some good. */ - if (cmdsOK) + if (cmdsOK) { Lst_Find(&gn->commands, JobPrintCommand, job); + } /* * Don't execute the shell, thank you. */ @@ -1814,7 +1768,7 @@ JobStart(gn, flags, previous) * up the graph. */ job->cmdFILE = stdout; - Job_Touch(gn, job->flags&JOB_SILENT); + Job_Touch(gn, job->flags&JOB_SILENT); noExec = TRUE; } @@ -1826,10 +1780,11 @@ JobStart(gn, flags, previous) * Unlink and close the command file if we opened one */ if (job->cmdFILE != stdout) { + (void)eunlink(tfile); if (job->cmdFILE != NULL) - (void) fclose(job->cmdFILE); + (void)fclose(job->cmdFILE); } else { - (void) fflush(stdout); + (void)fflush(stdout); } /* @@ -1838,7 +1793,7 @@ JobStart(gn, flags, previous) */ if (cmdsOK) { if (aborting == 0) { - Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node); + Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node); Make_Update(job->node); } free(job); @@ -1848,7 +1803,8 @@ JobStart(gn, flags, previous) return JOB_ERROR; } } else { - (void) fflush(job->cmdFILE); + (void)fflush(job->cmdFILE); + (void)eunlink(tfile); } /* @@ -1869,15 +1825,15 @@ JobStart(gn, flags, previous) Punt("Cannot create pipe: %s", strerror(errno)); job->inPipe = fd[0]; job->outPipe = fd[1]; - (void) fcntl(job->inPipe, F_SETFD, 1); - (void) fcntl(job->outPipe, F_SETFD, 1); + (void)fcntl(job->inPipe, F_SETFD, 1); + (void)fcntl(job->outPipe, F_SETFD, 1); } else { - (void) fprintf(stdout, "Remaking `%s'\n", gn->name); - (void) fflush(stdout); - (void) strcpy(job->outFile, TMPPAT); + (void)fprintf(stdout, "Remaking `%s'\n", gn->name); + (void)fflush(stdout); + (void)strcpy(job->outFile, TMPPAT); if ((job->outFd = mkstemp(job->outFile)) == -1) Punt("Cannot create temp file: %s", strerror(errno)); - (void) fcntl(job->outFd, F_SETFD, 1); + (void)fcntl(job->outFd, F_SETFD, 1); } } @@ -1895,14 +1851,14 @@ JobStart(gn, flags, previous) #endif local = TRUE; - if (local && (((nLocal >= maxLocal) && + if (local && nLocal >= maxLocal && !(job->flags & JOB_SPECIAL) && #ifdef REMOTE - (!(gn->type & OP_NOEXPORT) || (maxLocal != 0)) + (!(gn->type & OP_NOEXPORT) || maxLocal != 0) #else - (maxLocal != 0) + maxLocal != 0 #endif - ))) + ) { /* * The job can only be run locally, but we've hit the limit of @@ -1916,35 +1872,35 @@ JobStart(gn, flags, previous) jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Can only run job locally.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Can only run job locally.\n"); + (void)fflush(stdout); } job->flags |= JOB_RESTART; Lst_AtEnd(&stoppedJobs, job); } else { - if ((nLocal >= maxLocal) && local) { + if (nLocal >= maxLocal && local) { /* * If we're running this job locally as a special case (see above), * at least say the table is full. */ jobFull = TRUE; if (DEBUG(JOB)) { - (void) fprintf(stdout, "Local job queue is full.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Local job queue is full.\n"); + (void)fflush(stdout); } } JobExec(job, argv); } - return(JOB_RUNNING); + return JOB_RUNNING; } static char * JobOutput(job, cp, endp, msg) - register Job *job; - register char *cp, *endp; + Job *job; + char *cp, *endp; int msg; { - register char *ecp; + char *ecp; if (commandShell->noPrint) { ecp = strstr(cp, commandShell->noPrint); @@ -1961,8 +1917,8 @@ JobOutput(job, cp, endp, msg) * however, since the non-printable comes after it, * there must be a newline, so we don't print one. */ - (void) fprintf(stdout, "%s", cp); - (void) fflush(stdout); + (void)fprintf(stdout, "%s", cp); + (void)fflush(stdout); } cp = ecp + commandShell->noPLen; if (cp != endp) { @@ -1986,7 +1942,7 @@ JobOutput(job, cp, endp, msg) /*- *----------------------------------------------------------------------- - * JobDoOutput -- + * JobDoOutput -- * This function is called at different times depending on * whether the user has specified that output is to be collected * via pipes or temporary files. In the former case, we are called @@ -2004,28 +1960,25 @@ JobOutput(job, cp, endp, msg) * alone on the line (the character after it is not \0 or \n), we * do print whatever follows it. * - * Results: - * None - * * Side Effects: * curPos may be shifted as may the contents of outBuf. *----------------------------------------------------------------------- */ STATIC void JobDoOutput(job, finish) - register Job *job; /* the job whose output needs printing */ + Job *job; /* the job whose output needs printing */ Boolean 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 */ - register int nr; /* number of bytes read */ - register int i; /* auxiliary index into outBuf */ - register int max; /* limit for i (end of current data) */ - int nRead; /* (Temporary) number of bytes read */ + Boolean gotNL = FALSE; /* true if got a newline */ + Boolean 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) */ + int nRead; /* (Temporary) number of bytes read */ - FILE *oFILE; /* Stream pointer to shell's output file */ - char inLine[132]; + FILE *oFILE; /* Stream pointer to shell's output file */ + char inLine[132]; if (usePipes) { @@ -2038,7 +1991,7 @@ end_loop: nRead = read(job->inPipe, &job->outBuf[job->curPos], JOB_BUFSIZE - job->curPos); - if (nRead < 0) { + if (nRead == -1) { if (DEBUG(JOB)) { perror("JobDoOutput(piperead)"); } @@ -2053,7 +2006,7 @@ end_loop: * output remaining in the buffer. * Also clear the 'finish' flag so we stop looping. */ - if ((nr == 0) && (job->curPos != 0)) { + if (nr == 0 && job->curPos != 0) { job->outBuf[job->curPos] = '\n'; nr = 1; finish = FALSE; @@ -2117,13 +2070,13 @@ end_loop: MESSAGE(stdout, job->node); lastNode = job->node; } - (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); - (void) fflush(stdout); + (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); + (void)fflush(stdout); } } if (i < max - 1) { /* shift the remaining characters down */ - (void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); + (void)memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); job->curPos = max - (i + 1); } else { @@ -2158,10 +2111,10 @@ end_loop: */ oFILE = fopen(job->outFile, "r"); if (oFILE != NULL) { - (void) fprintf(stdout, "Results of making %s:\n", job->node->name); - (void) fflush(stdout); + (void)fprintf(stdout, "Results of making %s:\n", job->node->name); + (void)fflush(stdout); while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { - register char *cp, *endp, *oendp; + char *cp, *endp, *oendp; cp = inLine; oendp = endp = inLine + strlen(inLine); @@ -2175,15 +2128,15 @@ end_loop: * we know there's no newline at the end, so we add one of * our own free will. */ - (void) fprintf(stdout, "%s", cp); - (void) fflush(stdout); + (void)fprintf(stdout, "%s", cp); + (void)fflush(stdout); if (endp != oendp) { - (void) fprintf(stdout, "\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "\n"); + (void)fflush(stdout); } } - (void) fclose(oFILE); - (void) eunlink(job->outFile); + (void)fclose(oFILE); + (void)eunlink(job->outFile); } } } @@ -2193,9 +2146,6 @@ end_loop: * Job_CatchChildren -- * Handle the exit of a child. Called from Make_Make. * - * Results: - * none. - * * Side Effects: * The job descriptor is removed from the list of children. * @@ -2204,17 +2154,16 @@ end_loop: * caller, until there are no more children to report. For each * job, call JobFinish to finish things off. This will take care of * putting jobs on the stoppedJobs queue. - * *----------------------------------------------------------------------- */ void Job_CatchChildren(block) - Boolean block; /* TRUE if should block on the wait. */ + Boolean block; /* TRUE if should block on the wait. */ { - int pid; /* pid of dead child */ - register Job *job; /* job descriptor for dead child */ - LstNode jnode; /* list element for finding job */ - int status; /* Exit/termination status */ + int pid; /* pid of dead child */ + Job *job; /* job descriptor for dead child */ + LstNode jnode; /* list element for finding job */ + int status; /* Exit/termination status */ /* * Don't even bother if we know there's no one around. @@ -2227,8 +2176,8 @@ Job_CatchChildren(block) (block?0:WNOHANG)|WUNTRACED)) > 0) { if (DEBUG(JOB)) { - (void) fprintf(stdout, "Process %d exited or stopped.\n", pid); - (void) fflush(stdout); + (void)fprintf(stdout, "Process %d exited or stopped.\n", pid); + (void)fflush(stdout); } @@ -2252,16 +2201,16 @@ Job_CatchChildren(block) Lst_Remove(&jobs, jnode); nJobs -= 1; if (jobFull && DEBUG(JOB)) { - (void) fprintf(stdout, "Job queue is no longer full.\n"); - (void) fflush(stdout); + (void)fprintf(stdout, "Job queue is no longer full.\n"); + (void)fflush(stdout); } jobFull = FALSE; #ifdef REMOTE if (!(job->flags & JOB_REMOTE)) { if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "Job queue has one fewer local process.\n"); - (void) fflush(stdout); + (void)fflush(stdout); } nLocal -= 1; } @@ -2283,9 +2232,6 @@ Job_CatchChildren(block) * just spinning when there's nothing to do and the reaping * of a child can wait for a while. * - * Results: - * None - * * Side Effects: * Output is read from pipes if we're piping. * ----------------------------------------------------------------------- @@ -2293,15 +2239,15 @@ Job_CatchChildren(block) void Job_CatchOutput() { - int nfds; + int nfds; struct timeval timeout; - register LstNode ln; - register Job *job; + LstNode ln; + Job *job; #ifdef RMT_WILL_WATCH - int pnJobs; /* Previous nJobs */ + int pnJobs; /* Previous nJobs */ #endif - (void) fflush(stdout); + (void)fflush(stdout); #ifdef RMT_WILL_WATCH pnJobs = nJobs; @@ -2340,15 +2286,13 @@ Job_CatchOutput() free(readfdsp); return; } else { - Lst_Open(&jobs); - while (nfds && (ln = Lst_Next(&jobs)) != NULL) { + 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); nfds -= 1; } } - Lst_Close(&jobs); } free(readfdsp); } @@ -2361,19 +2305,15 @@ Job_CatchOutput() * Start the creation of a target. Basically a front-end for * JobStart used by the Make module. * - * Results: - * None. - * * Side Effects: * Another job is started. - * *----------------------------------------------------------------------- */ void Job_Make(gn) GNode *gn; { - (void) JobStart(gn, 0, NULL); + (void)JobStart(gn, 0, NULL); } /*- @@ -2381,32 +2321,36 @@ Job_Make(gn) * Job_Init -- * Initialize the process module * - * Results: - * none - * * Side Effects: * lists and counters are initialized *----------------------------------------------------------------------- */ void Job_Init(maxproc, maxlocal) - int maxproc; /* the greatest number of jobs which may be + int maxproc; /* the greatest number of jobs which may be * running at one time */ - int maxlocal; /* the greatest number of local jobs which may + int maxlocal; /* the greatest number of local jobs which may * be running at once. */ { - GNode *begin; /* node for commands to do at the very start */ + GNode *begin; /* node for commands to do at the very start */ + int tfd; + + (void)strcpy(tfile, TMPPAT); + if ((tfd = mkstemp(tfile)) == -1) + Punt("Cannot create temp file: %s", strerror(errno)); + else + (void)close(tfd); Lst_Init(&jobs); Lst_Init(&stoppedJobs); - maxJobs = maxproc; - maxLocal = maxlocal; - nJobs = 0; - nLocal = 0; - jobFull = FALSE; + maxJobs = maxproc; + maxLocal = maxlocal; + nJobs = 0; + nLocal = 0; + jobFull = FALSE; - aborting = 0; - errors = 0; + aborting = 0; + errors = 0; lastNode = NULL; @@ -2448,16 +2392,16 @@ Job_Init(maxproc, maxlocal) * JobPassSig will take care of calling JobInterrupt if appropriate. */ if (signal(SIGINT, SIG_IGN) != SIG_IGN) { - (void) signal(SIGINT, JobPassSig); + (void)signal(SIGINT, JobPassSig); } if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { - (void) signal(SIGHUP, JobPassSig); + (void)signal(SIGHUP, JobPassSig); } if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { - (void) signal(SIGQUIT, JobPassSig); + (void)signal(SIGQUIT, JobPassSig); } if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTERM, JobPassSig); + (void)signal(SIGTERM, JobPassSig); } /* * There are additional signals that need to be caught and passed if @@ -2467,20 +2411,20 @@ Job_Init(maxproc, maxlocal) */ #if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP) if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTSTP, JobPassSig); + (void)signal(SIGTSTP, JobPassSig); } if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTTOU, JobPassSig); + (void)signal(SIGTTOU, JobPassSig); } if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTTIN, JobPassSig); + (void)signal(SIGTTIN, JobPassSig); } if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { - (void) signal(SIGWINCH, JobPassSig); + (void)signal(SIGWINCH, JobPassSig); } #endif - begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); + begin = Targ_FindNode(".BEGIN", NULL, TARG_NOCREATE); if (begin != NULL) { JobStart(begin, JOB_SPECIAL, (Job *)0); @@ -2491,7 +2435,7 @@ Job_Init(maxproc, maxlocal) #endif /* RMT_WILL_WATCH */ } } - postCommands = Targ_FindNode(".END", TARG_CREATE); + postCommands = Targ_FindNode(".END", NULL, TARG_CREATE); } /*- @@ -2504,30 +2448,24 @@ Job_Init(maxproc, maxlocal) * * Results: * TRUE if the job table is full, FALSE otherwise - * Side Effects: - * None. *----------------------------------------------------------------------- */ Boolean Job_Full() { - return(aborting || jobFull); + return aborting || jobFull; } /*- *----------------------------------------------------------------------- * Job_Empty -- - * See if the job table is empty. Because the local concurrency may + * See if the job table is empty. Because the local concurrency may * be set to 0, it is possible for the job table to become empty, * while the list of stoppedJobs remains non-empty. In such a case, * we want to restart as many jobs as we can. * * Results: * TRUE if it is. FALSE if it ain't. - * - * Side Effects: - * None. - * * ----------------------------------------------------------------------- */ Boolean @@ -2541,12 +2479,12 @@ Job_Empty() */ jobFull = FALSE; JobRestartJobs(); - return(FALSE); + return FALSE; } else { - return(TRUE); + return TRUE; } } else { - return(FALSE); + return FALSE; } } @@ -2557,19 +2495,15 @@ Job_Empty() * * Results: * A pointer to the Shell structure. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static Shell * JobMatchShell(name) char *name; /* Final component of shell path */ { - register Shell *sh; /* Pointer into shells table */ - Shell *match; /* Longest-matching shell */ - register char *cp1, + Shell *sh; /* Pointer into shells table */ + Shell *match; /* Longest-matching shell */ + char *cp1, *cp2; char *eoname; @@ -2589,7 +2523,7 @@ JobMatchShell(name) match = sh; } } - return(match == NULL ? sh : match); + return match == NULL ? sh : match; } /*- @@ -2615,45 +2549,44 @@ JobMatchShell(name) * provides the functionality it does in C. Each word consists of * keyword and value separated by an equal sign. There should be no * unnecessary spaces in the word. The keywords are as follows: - * name Name of shell. - * path Location of shell. Overrides "name" if given - * quiet Command to turn off echoing. - * echo Command to turn echoing on + * name Name of shell. + * path Location of shell. Overrides "name" if given + * quiet Command to turn off echoing. + * echo Command to turn echoing on * filter Result of turning off echoing that shouldn't be - * printed. + * printed. * echoFlag Flag to turn echoing on at the start * 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 - * for which error checking is off if hasErrCtl is - * FALSE. + * check Command to turn on error checking if hasErrCtl + * is TRUE or template of command to echo a command + * for which error checking is off if hasErrCtl is + * FALSE. * ignore Command to turn off error checking if hasErrCtl - * is TRUE or template of command to execute a - * command so as to ignore any errors it returns if - * hasErrCtl is FALSE. - * + * is TRUE or template of command to execute a + * command so as to ignore any errors it returns if + * hasErrCtl is FALSE. *----------------------------------------------------------------------- */ ReturnStatus Job_ParseShell(line) char *line; /* The shell spec */ { - char **words; - int wordCount; - register char **argv; - register int argc; - char *path; - Shell newShell; - Boolean fullSpec = FALSE; + char **words; + int wordCount; + char **argv; + int argc; + char *path; + Shell newShell; + Boolean fullSpec = FALSE; while (isspace(*line)) { line++; } efree(shellArgv); - - words = brk_string(line, &wordCount, TRUE, &shellArgv); + + words = brk_string(line, &wordCount, &shellArgv); memset(&newShell, 0, sizeof(newShell)); @@ -2681,8 +2614,8 @@ Job_ParseShell(line) newShell.exit = &argv[0][8]; } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) { char c = argv[0][10]; - newShell.hasErrCtl = !((c != 'Y') && (c != 'y') && - (c != 'T') && (c != 't')); + newShell.hasErrCtl = !(c != 'Y' && c != 'y' && + c != 'T' && c != 't'); } else if (strncmp(*argv, "check=", 6) == 0) { newShell.errCheck = &argv[0][6]; } else if (strncmp(*argv, "ignore=", 7) == 0) { @@ -2691,7 +2624,7 @@ Job_ParseShell(line) Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", *argv); free(words); - return(FAILURE); + return FAILURE; } fullSpec = TRUE; } @@ -2706,7 +2639,7 @@ Job_ParseShell(line) */ if (newShell.name == NULL) { Parse_Error(PARSE_FATAL, "Neither path nor name specified"); - return(FAILURE); + return FAILURE; } else { commandShell = JobMatchShell(newShell.name); shellName = newShell.name; @@ -2734,7 +2667,7 @@ Job_ParseShell(line) if (!fullSpec) { commandShell = JobMatchShell(shellName); } else { - commandShell = (Shell *) emalloc(sizeof(Shell)); + commandShell = emalloc(sizeof(Shell)); *commandShell = newShell; } } @@ -2765,9 +2698,6 @@ Job_ParseShell(line) * JobInterrupt -- * Handle the receipt of an interrupt. * - * Results: - * None - * * Side Effects: * All children are killed. Another job will be started if the * .INTERRUPT target was given. @@ -2775,24 +2705,23 @@ Job_ParseShell(line) */ static void JobInterrupt(runINTERRUPT, signo) - int runINTERRUPT; /* Non-zero if commands for the .INTERRUPT + int runINTERRUPT; /* Non-zero if commands for the .INTERRUPT * target should be executed */ - int signo; /* signal received */ + int signo; /* signal received */ { - LstNode ln; /* element in job table */ - Job *job; /* job descriptor in that element */ - GNode *interrupt; /* the node describing the .INTERRUPT target */ + LstNode ln; /* element in job table */ + Job *job; /* job descriptor in that element */ + GNode *interrupt; /* the node describing the .INTERRUPT target */ aborting = ABORT_INTERRUPT; - Lst_Open(&jobs); - while ((ln = Lst_Next(&jobs)) != NULL) { + for (ln = Lst_First(&jobs); ln != NULL; ln = Lst_Adv(ln)) { job = (Job *)Lst_Datum(ln); if (!Targ_Precious(job->node)) { - char *file = (job->node->path == NULL ? + const char *file = job->node->path == NULL ? job->node->name : - job->node->path); + job->node->path; if (!noExecute && eunlink(file) != -1) { Error("*** %s removed", file); } @@ -2819,10 +2748,10 @@ JobInterrupt(runINTERRUPT, signo) #else if (job->pid) { if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "JobInterrupt passing signal to child %d.\n", job->pid); - (void) fflush(stdout); + (void)fflush(stdout); } KILL(job->pid, signo); } @@ -2830,23 +2759,22 @@ JobInterrupt(runINTERRUPT, signo) } #ifdef REMOTE - Lst_Open(&stoppedJobs); - while ((ln = Lst_Next(&stoppedJobs)) != NULL) { + for (ln = Lst_First(&stoppedJobs); ln != NULL; ln = Lst_Adv(ln)) { job = (Job *)Lst_Datum(ln); if (job->flags & JOB_RESTART) { if (DEBUG(JOB)) { - (void) fprintf(stdout, "%s%s", + (void)fprintf(stdout, "%s%s", "JobInterrupt skipping job on stopped queue", "-- it was waiting to be restarted.\n"); - (void) fflush(stdout); + (void)fflush(stdout); } continue; } if (!Targ_Precious(job->node)) { - char *file = (job->node->path == NULL ? + char *file = job->node->path == NULL ? job->node->name : - job->node->path); + job->node->path; if (eunlink(file) == 0) { Error("*** %s removed", file); } @@ -2855,10 +2783,10 @@ JobInterrupt(runINTERRUPT, signo) * Resume the thing so it will take the signal. */ if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "JobInterrupt passing CONT to stopped child %d.\n", job->pid); - (void) fflush(stdout); + (void)fflush(stdout); } KILL(job->pid, SIGCONT); #ifdef RMT_WANTS_SIGNALS @@ -2878,20 +2806,19 @@ JobInterrupt(runINTERRUPT, signo) } } else if (job->pid) { if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "JobInterrupt passing interrupt to stopped child %d.\n", job->pid); - (void) fflush(stdout); + (void)fflush(stdout); } KILL(job->pid, SIGINT); } #endif /* RMT_WANTS_SIGNALS */ } #endif - Lst_Close(&stoppedJobs); if (runINTERRUPT && !touchFlag) { - interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); + interrupt = Targ_FindNode(".INTERRUPT", NULL, TARG_NOCREATE); if (interrupt != NULL) { ignoreErrors = FALSE; @@ -2904,6 +2831,7 @@ JobInterrupt(runINTERRUPT, signo) } } } + (void)eunlink(tfile); exit(signo); } @@ -2915,6 +2843,10 @@ JobInterrupt(runINTERRUPT, signo) * * Results: * Number of errors reported. + * + * Side Effects: + * The process' temporary file (tfile) is removed if it still + * existed. *----------------------------------------------------------------------- */ int @@ -2934,7 +2866,8 @@ Job_Finish() } } } - return(errors); + (void)eunlink(tfile); + return errors; } /*- @@ -2942,9 +2875,6 @@ Job_Finish() * Job_End -- * Cleanup any memory used by the jobs module * - * Results: - * None. - * * Side Effects: * Memory is freed *----------------------------------------------------------------------- @@ -2956,16 +2886,13 @@ Job_End() efree(shellArgv); #endif } - + /*- *----------------------------------------------------------------------- * Job_Wait -- * Waits for all running jobs to finish and returns. Sets 'aborting' * to ABORT_WAIT to prevent other jobs from starting. * - * Results: - * None. - * * Side Effects: * Currently running jobs finish. * @@ -2991,9 +2918,6 @@ Job_Wait() * This function is to be called only in the event of a major * error. Most definitely NOT to be called from JobInterrupt. * - * Results: - * None - * * Side Effects: * All children are killed, not just the firstborn *----------------------------------------------------------------------- @@ -3001,16 +2925,14 @@ Job_Wait() void Job_AbortAll() { - LstNode ln; /* element in job table */ - Job *job; /* the job descriptor in that element */ - int foo; + LstNode ln; /* element in job table */ + Job *job; /* the job descriptor in that element */ + int foo; aborting = ABORT_ERROR; if (nJobs) { - - Lst_Open(&jobs); - while ((ln = Lst_Next(&jobs)) != NULL) { + for (ln = Lst_First(&jobs); ln != NULL; ln = Lst_Adv(ln)) { job = (Job *)Lst_Datum(ln); /* @@ -3037,6 +2959,7 @@ Job_AbortAll() */ while (waitpid((pid_t) -1, &foo, WNOHANG) > 0) continue; + (void)eunlink(tfile); } #ifdef REMOTE @@ -3046,24 +2969,20 @@ Job_AbortAll() * Handle the eviction of a child. Called from RmtStatusChange. * Flags the child as remigratable and then suspends it. * - * Results: - * none. - * * Side Effects: * The job descriptor is flagged for remigration. - * *----------------------------------------------------------------------- */ void JobFlagForMigration(hostID) - int hostID; /* ID of host we used, for matching children. */ + int hostID; /* ID of host we used, for matching children. */ { - register Job *job; /* job descriptor for dead child */ - LstNode jnode; /* list element for finding job */ + Job *job; /* job descriptor for dead child */ + LstNode jnode; /* list element for finding job */ if (DEBUG(JOB)) { - (void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID); - (void) fflush(stdout); + (void)fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID); + (void)fflush(stdout); } jnode = Lst_Find(&jobs, JobCmpRmtID, &hostID); @@ -3079,10 +2998,10 @@ JobFlagForMigration(hostID) job = (Job *)Lst_Datum(jnode); if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "JobFlagForMigration(%d) found job '%s'.\n", hostID, job->node->name); - (void) fflush(stdout); + (void)fflush(stdout); } KILL(job->pid, SIGSTOP); @@ -3091,7 +3010,7 @@ JobFlagForMigration(hostID) } #endif - + /*- *----------------------------------------------------------------------- * JobRestartJobs -- @@ -3099,12 +3018,8 @@ JobFlagForMigration(hostID) * Note that this tries to restart them regardless of pending errors. * It's not good to leave stopped jobs lying around! * - * Results: - * None. - * * Side Effects: * Resumes(and possibly migrates) jobs. - * *----------------------------------------------------------------------- */ static void @@ -3112,11 +3027,11 @@ JobRestartJobs() { Job *job; - while (!jobFull && (job = (Job *)Lst_DeQueue(&stoppedJobs)) != NULL) { + while (!jobFull && (job = (Job *)Lst_DeQueue(&stoppedJobs)) != NULL) { if (DEBUG(JOB)) { - (void) fprintf(stdout, + (void)fprintf(stdout, "Job queue is not full. Restarting a stopped job.\n"); - (void) fflush(stdout); + (void)fflush(stdout); } JobRestart(job); } diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h index 40aa45ce3f7..6a03a50bf84 100644 --- a/usr.bin/make/job.h +++ b/usr.bin/make/job.h @@ -1,5 +1,6 @@ -/* $OpenBSD: job.h,v 1.8 2000/09/14 13:32:07 espie Exp $ */ -/* $NetBSD: job.h,v 1.5 1996/11/06 17:59:10 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: job.h,v 1.9 2001/05/03 13:41:06 espie Exp $ */ +/* $NetBSD: job.h,v 1.5 1996/11/06 17:59:10 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -38,7 +39,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)job.h 8.1 (Berkeley) 6/6/93 + * from: @(#)job.h 8.1 (Berkeley) 6/6/93 */ /*- @@ -56,10 +57,10 @@ * before coming out to see if a child has finished. SEL_SEC is the number of * seconds and SEL_USEC is the number of micro-seconds */ -#define SEL_SEC 0 +#define SEL_SEC 0 #define SEL_USEC 500000 - + /*- * Job Table definitions. * @@ -93,20 +94,20 @@ * traversal of the dependency graph. */ #define JOB_BUFSIZE 1024 -typedef struct Job { - int pid; /* The child's process ID */ - GNode *node; /* The target the child is making */ - LstNode tailCmds; /* The node of the first command to be +typedef struct Job_ { + int pid; /* The child's process ID */ + GNode *node; /* The target the child is making */ + LstNode tailCmds; /* The node of the first command to be * saved when the job has been run */ - FILE *cmdFILE; /* When creating the shell script, this is + FILE *cmdFILE; /* When creating the shell script, this is * where the commands go */ - int rmtID; /* ID returned from Rmt module */ - short flags; /* Flags to control treatment of job */ -#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ -#define JOB_SILENT 0x002 /* no output */ + int rmtID; /* ID returned from Rmt module */ + short flags; /* Flags to control treatment of job */ +#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ +#define JOB_SILENT 0x002 /* no output */ #define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally * if we can't export it and maxLocal is 0 */ -#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing +#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing * commands */ #define JOB_REMOTE 0x010 /* Job is running remotely */ #define JOB_FIRST 0x020 /* Job is first job for the node */ @@ -119,38 +120,38 @@ typedef struct Job { * JobFinish and JobRestart */ union { struct { - int op_inPipe; /* Input side of pipe associated + int op_inPipe; /* Input side of pipe associated * with job's output channel */ - int op_outPipe; /* Output side of pipe associated with + int op_outPipe; /* Output side of pipe associated with * job's output channel */ - char op_outBuf[JOB_BUFSIZE + 1]; - /* Buffer for storing the output of the + char op_outBuf[JOB_BUFSIZE + 1]; + /* Buffer for storing the output of the * job, line by line */ - int op_curPos; /* Current position in op_outBuf */ - } o_pipe; /* data used when catching the output via + int op_curPos; /* Current position in op_outBuf */ + } o_pipe; /* data used when catching the output via * a pipe */ struct { - char of_outFile[sizeof(TMPPAT)]; - /* Name of file to which shell output + char of_outFile[sizeof(TMPPAT)]; + /* Name of file to which shell output * was rerouted */ - int of_outFd; /* Stream open to the output + int of_outFd; /* Stream open to the output * file. Used to funnel all * from a single job to one file * while still allowing * multiple shell invocations */ - } o_file; /* Data used when catching the output in + } o_file; /* Data used when catching the output in * a temporary file */ - } output; /* Data for tracking a shell's output */ + } output; /* Data for tracking a shell's output */ } Job; -#define outPipe output.o_pipe.op_outPipe -#define inPipe output.o_pipe.op_inPipe +#define outPipe output.o_pipe.op_outPipe +#define inPipe output.o_pipe.op_inPipe #define outBuf output.o_pipe.op_outBuf #define curPos output.o_pipe.op_curPos -#define outFile output.o_file.of_outFile -#define outFd output.o_file.of_outFd +#define outFile output.o_file.of_outFile +#define outFd output.o_file.of_outFd + - /*- * Shell Specifications: * Each shell type has associated with it the following information: @@ -177,20 +178,20 @@ typedef struct Job { * 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 { +typedef struct Shell_ { char *name; /* the name of the shell. For Bourne and C * shells, this is used only to find the * shell description when used as the single * 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 */ - 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 + Boolean 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 */ + int noPLen; /* length of noPrint command */ Boolean hasErrCtl; /* set if can control error checking for * individual commands */ char *errCheck; /* string to turn error checking on */ @@ -198,40 +199,43 @@ typedef struct Shell { /* * command-line flags */ - char *echo; /* echo commands */ - char *exit; /* exit on error */ -} Shell; + char *echo; /* echo commands */ + char *exit; /* exit on error */ +} Shell; -extern char *targFmt; /* Format string for banner that separates +#ifdef REMOTE +extern char *targFmt; /* Format string for banner that separates * output from multiple jobs. Contains a * single %s where the name of the node being * made should be put. */ -extern GNode *lastNode; /* Last node for which a banner was printed. +extern GNode *lastNode; /* Last node for which a banner was printed. * If Rmt module finds it necessary to print * a banner, it should set this to the node * for which the 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 LIST stoppedJobs; /* List of jobs that are stopped or didn't +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 LIST stoppedJobs; /* List of jobs that are stopped or didn't * quite get started */ -extern Boolean jobFull; /* Non-zero if no more jobs should/will start*/ +#endif -extern void Job_Touch __P((GNode *, Boolean)); -extern Boolean Job_CheckCommands __P((GNode *, void (*abortProc )(char *, ...))); -extern void Job_CatchChildren __P((Boolean)); -extern void Job_CatchOutput __P((void)); -extern void Job_Make __P((GNode *)); -extern void Job_Init __P((int, int)); -extern Boolean Job_Full __P((void)); -extern Boolean Job_Empty __P((void)); -extern ReturnStatus Job_ParseShell __P((char *)); -extern int Job_Finish __P((void)); -extern void Job_End __P((void)); -extern void Job_Wait __P((void)); -extern void Job_AbortAll __P((void)); -extern void JobFlagForMigration __P((int)); +extern void Job_Touch(GNode *, Boolean); +extern Boolean Job_CheckCommands(GNode *, + void (*abortProc )(char *, ...)); +extern void Job_CatchChildren(Boolean); +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 int Job_Finish(void); +extern void Job_End(void); +extern void Job_Wait(void); +extern void Job_AbortAll(void); +extern void JobFlagForMigration(int); #endif /* _JOB_H_ */ diff --git a/usr.bin/make/lowparse.c b/usr.bin/make/lowparse.c index 9563ab47fad..7e74ce66b48 100644 --- a/usr.bin/make/lowparse.c +++ b/usr.bin/make/lowparse.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lowparse.c,v 1.5 2000/11/24 14:27:19 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lowparse.c,v 1.6 2001/05/03 13:41:07 espie Exp $ */ /* low-level parsing functions. */ @@ -42,32 +43,31 @@ static LIST fileNames; /* file names to free at end */ /* 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 */ + 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 */ } IFile; static IFile *current; - - -static LIST includes; /* stack of IFiles generated by +static LIST includes; /* stack of IFiles generated by * #includes */ -static IFile *new_ifile __P((char *, FILE *)); -static IFile *new_istring __P((char *, char *, unsigned long)); -static void free_ifile __P((IFile *)); -static void ParseVErrorInternal __P((char *, unsigned long, int, char *, va_list)); -static int newline __P((void)); -#define ParseReadc() current->ptr < current->end ? *current->ptr++ : newline() -static void ParseUnreadc __P((char)); +static IFile *new_ifile(char *, FILE *); +static IFile *new_istring(char *, char *, unsigned long); +static void free_ifile(IFile *); +static void ParseVErrorInternal(char *, unsigned long, int, char *, va_list); +static int newline(void); +static int skiptoendofline(void); +static void ParseFoldLF(Buffer, int); +static int ParseSkipEmptyLines(Buffer); static int fatals = 0; /*- - * ParseVErrorInternal -- + * 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. @@ -96,7 +96,7 @@ ParseVErrorInternal(va_alist) } /*- - * Parse_Error -- + * Parse_Error -- * External interface to ParseVErrorInternal; uses the default filename * Line number. */ @@ -148,9 +148,9 @@ free_ifile(ifile) IFile *ifile; { if (ifile->F) - (void)fclose(ifile->F); + (void)fclose(ifile->F); else - free(ifile->str); + free(ifile->str); /* Note we can't free the file names yet, as they are embedded in GN for * error reports. */ free(ifile); @@ -165,7 +165,7 @@ new_istring(str, name, lineno) IFile *ifile; ifile = emalloc(sizeof(*ifile)); - /* No malloc, name is always taken from an existing ifile */ + /* No malloc, name is always taken from an already existing ifile */ ifile->fname = name; ifile->F = NULL; /* Strings are used from for loops... */ @@ -188,8 +188,8 @@ new_istring(str, name, lineno) */ void Parse_FromString(str, lineno) - char *str; - unsigned long lineno; + char *str; + unsigned long lineno; { if (DEBUG(FOR)) (void)fprintf(stderr, "%s\n----\n", str); @@ -200,19 +200,19 @@ Parse_FromString(str, lineno) } -void +void Parse_FromFile(name, stream) char *name; FILE *stream; { if (current != NULL) - Lst_AtFront(&includes, current); + Lst_AtFront(&includes, current); current = new_ifile(name, stream); } /*- *--------------------------------------------------------------------- - * Parse_NextFile -- + * 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. @@ -235,12 +235,11 @@ Parse_NextFile() if (current != NULL) free_ifile(current); current = next; - return TRUE; + return TRUE; } else - return FALSE; + return FALSE; } - /* guts for ParseReadc. Grab a new line off fgetln when we hit "\n" */ static int newline() @@ -259,325 +258,240 @@ newline() return EOF; } -void -ParseUnreadc(c) - char c; +#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() { - current->ptr--; - *current->ptr = c; + if (current->F) { + if (current->end - current->ptr > 1) + current->ptr = current->end - 1; + if (*current->ptr == '\n') + return *current->ptr++; + return EOF; + } else { + int c; + + do { + c = ParseReadc(); + } while (c != '\n' && c != EOF); + return c; + } } -/* ParseSkipLine(): - * Grab the next line + +/* ParseSkipGetLine(): + * Return the first logical line that starts with '.' */ char * -ParseSkipLine(skip) - int skip; /* Skip lines that don't start with . */ +ParseSkipGetLine(linebuf) + Buffer linebuf; { - char *line; - int c, lastc; - BUFFER buf; + int c; + + /* If first char isn't dot, skip to end of line, handling \ */ + while ((c = ParseReadc()) != '.') { + for (;c != '\n'; c = ParseReadc()) { + if (c == '\\') { + c = ParseReadc(); + if (c == '\n') + current->lineno++; + } + if (c == EOF) { + Parse_Error(PARSE_FATAL, "Unclosed conditional"); + return NULL; + } + } + current->lineno++; + } - Buf_Init(&buf, MAKE_BSIZE); + /* This is the line we need to copy */ + return ParseGetLine(linebuf, "conditional"); +} +/* Grab logical line into linebuf. + * The first character is already in c. */ +static void +ParseFoldLF(linebuf, c) + Buffer linebuf; + int c; +{ for (;;) { - Buf_Reset(&buf); - lastc = '\0'; - - while (((c = ParseReadc()) != '\n' || lastc == '\\') - && c != EOF) { - if (c == '\n') { - Buf_ReplaceLastChar(&buf, ' '); - current->lineno++; - - while ((c = ParseReadc()) == ' ' || c == '\t'); - - if (c == EOF) - break; - } - - Buf_AddChar(&buf, c); - lastc = c; - } - - line = Buf_Retrieve(&buf); - current->lineno++; - /* allow for non-newline terminated lines while skipping */ - if (line[0] == '.') + if (c == '\n') { + current->lineno++; break; - - if (c == EOF) { - Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop"); - Buf_Destroy(&buf); - return NULL; - } - if (skip == 0) + } + if (c == EOF) break; - + Buf_AddChar(linebuf, c); + c = ParseReadc(); + while (c == '\\') { + c = ParseReadc(); + if (c == '\n') { + Buf_AddSpace(linebuf); + current->lineno++; + do { + c = ParseReadc(); + } while (c == ' ' || c == '\t'); + } else { + Buf_AddChar(linebuf, '\\'); + if (c == '\\') { + Buf_AddChar(linebuf, '\\'); + c = ParseReadc(); + } + break; + } + } } - - return line; } - -/*- - *--------------------------------------------------------------------- - * ParseReadLine -- - * Read an entire line from the input file. Called only by Parse_File. - * To facilitate escaped newlines and what have you, a character is - * buffered in 'lastc', which is '\0' when no characters have been - * read. When we break out of the loop, c holds the terminating - * character and lastc holds a character that should be added to - * the line (unless we don't read anything but a terminator). - * - * Results: - * A line w/o its newline - * - * Side Effects: - * Only those associated with reading a character - *--------------------------------------------------------------------- +/* ParseGetLine: + * Simply get line, no parsing beyond \ */ char * -ParseReadLine () +ParseGetLine(linebuf, type) + Buffer linebuf; + const char *type; { - BUFFER buf; /* Buffer for current line */ - register int c; /* the current character */ - register int lastc; /* The most-recent character */ - Boolean semiNL; /* treat semi-colons as newlines */ - Boolean ignDepOp; /* TRUE if should ignore dependency operators - * for the purposes of setting semiNL */ - Boolean ignComment; /* TRUE if should ignore comments (in a - * shell command */ - char *line; /* Result */ - char *ep; /* to strip trailing blanks */ - - semiNL = FALSE; - ignDepOp = FALSE; - ignComment = FALSE; - - /* - * Handle special-characters at the beginning of the line. Either a - * leading tab (shell command) or pound-sign (possible conditional) - * forces us to ignore comments and dependency operators and treat - * semi-colons as semi-colons (by leaving semiNL FALSE). This also - * discards completely blank lines. - */ - for (;;) { - c = ParseReadc(); + int c; - if (c == '\t') { - ignComment = ignDepOp = TRUE; - break; - } else if (c == '\n') { + Buf_Reset(linebuf); + c = ParseReadc(); + if (c == EOF) { + Parse_Error(PARSE_FATAL, "Unclosed %s", type); + return NULL; + } + + /* Handle '\' at beginning of line, since \\n needs special treatment */ + while (c == '\\') { + c = ParseReadc(); + if (c == '\n') { current->lineno++; - } else if (c == '#') { - ParseUnreadc(c); - break; + do { + c = ParseReadc(); + } while (c == ' ' || c == '\t'); } else { - /* - * Anything else breaks out without doing anything - */ + Buf_AddChar(linebuf, '\\'); + if (c == '\\') { + Buf_AddChar(linebuf, '\\'); + c = ParseReadc(); + } break; } } + ParseFoldLF(linebuf, c); - if (c != EOF) { - lastc = c; - Buf_Init(&buf, MAKE_BSIZE); - - while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) && - (c != EOF)) - { -test_char: - switch(c) { - case '\n': - /* - * Escaped newline: read characters until a non-space or an - * unescaped newline and replace them all by a single space. - * This is done by storing the space over the backslash and - * dropping through with the next nonspace. If it is a - * semi-colon and semiNL is TRUE, it will be recognized as a - * newline in the code below this... - */ - current->lineno++; - lastc = ' '; - while ((c = ParseReadc ()) == ' ' || c == '\t') { - continue; - } - if (c == EOF || c == '\n') { - goto line_read; - } else { - /* - * Check for comments, semiNL's, etc. -- easier than - * ParseUnreadc(c); continue; - */ - goto test_char; - } - /*NOTREACHED*/ - break; + return Buf_Retrieve(linebuf); +} - case ';': - /* - * Semi-colon: Need to see if it should be interpreted as a - * newline - */ - if (semiNL) { - /* - * To make sure the command that may be following this - * semi-colon begins with a tab, we push one back into the - * input stream. This will overwrite the semi-colon in the - * buffer. If there is no command following, this does no - * harm, since the newline remains in the buffer and the - * whole line is ignored. - */ - ParseUnreadc('\t'); - goto line_read; - } - break; - case '=': - if (!semiNL) { - /* - * Haven't seen a dependency operator before this, so this - * must be a variable assignment -- don't pay attention to - * dependency operators after this. - */ - ignDepOp = TRUE; - } else if (lastc == ':' || lastc == '!') { - /* - * Well, we've seen a dependency operator already, but it - * was the previous character, so this is really just an - * expanded variable assignment. Revert semi-colons to - * being just semi-colons again and ignore any more - * dependency operators. - * - * XXX: Note that a line like "foo : a:=b" will blow up, - * but who'd write a line like that anyway? - */ - ignDepOp = TRUE; semiNL = FALSE; - } - break; - case '#': - if (!ignComment) { - if ( -#if 0 - compatMake && -#endif - (lastc != '\\')) { - /* - * If the character is a hash mark and it isn't escaped - * (or we're being compatible), the thing is a comment. - * Skip to the end of the line. - */ - do { - c = ParseReadc(); - } while ((c != '\n') && (c != EOF)); - goto line_read; - } else { - /* - * Don't add the backslash. Just let the # get copied - * over. - */ - lastc = c; - continue; +/* 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.) + */ +static int +ParseSkipEmptyLines(linebuf) + Buffer linebuf; +{ + int c; /* the current character */ + + for (;;) { + Buf_Reset(linebuf); + c = ParseReadc(); + /* Strip leading spaces, fold on '\n' */ + if (c == ' ') { + do { + c = ParseReadc(); + } while (c == ' ' || c == '\t'); + while (c == '\\') { + c = ParseReadc(); + if (c == '\n') { + current->lineno++; + do { + c = ParseReadc(); + } while (c == ' ' || c == '\t'); + } else { + Buf_AddChar(linebuf, '\\'); + if (c == '\\') { + Buf_AddChar(linebuf, '\\'); + c = ParseReadc(); } + if (c == EOF) + return '\n'; + else + return c; } - break; - case ':': - case '!': - if (!ignDepOp && (c == ':' || c == '!')) { - /* - * A semi-colon is recognized as a newline only on - * dependency lines. Dependency lines are lines with a - * colon or an exclamation point. Ergo... - */ - semiNL = TRUE; - } - break; } - /* - * Copy in the previous character and save this one in lastc. - */ - Buf_AddChar(&buf, lastc); - lastc = c; - - } - line_read: - current->lineno++; - - if (lastc != '\0') - Buf_AddChar(&buf, lastc); - line = Buf_Retrieve(&buf); - - /* - * Strip trailing blanks and tabs from the line. - * Do not strip a blank or tab that is preceeded by - * a '\' - */ - ep = line; - while (*ep) - ++ep; - while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { - if (ep > line + 1 && ep[-2] == '\\') - break; - --ep; + assert(c != '\t'); } - *ep = 0; - - if (line[0] == '.') { - /* - * The line might be a conditional. Ask the conditional module - * about it and act accordingly - */ - switch (Cond_Eval (line)) { - case COND_SKIP: - /* - * Skip to next conditional that evaluates to COND_PARSE. - */ - do { - free (line); - line = ParseSkipLine(1); - } while (line && Cond_Eval(line) != COND_PARSE); - if (line == NULL) - break; - /* FALLTHROUGH */ - case COND_PARSE: - free(line); - line = ParseReadLine(); - break; - case COND_INVALID: - { - For *loop; - - loop = For_Eval(line); - if (loop != NULL) { - Boolean ok; - - free(line); + if (c == '#') + c = skiptoendofline(); + /* Almost identical to spaces, except this occurs after comments + * have been taken care of, and we keep the tab itself. */ + if (c == '\t') { + Buf_AddChar(linebuf, '\t'); + do { + c = ParseReadc(); + } while (c == ' ' || c == '\t'); + while (c == '\\') { + c = ParseReadc(); + if (c == '\n') { + current->lineno++; do { - /* Find the matching endfor. */ - line = ParseSkipLine(0); - if (line == NULL) { - Parse_Error(PARSE_FATAL, - "Unexpected end of file in for loop.\n"); - return line; - } - ok = For_Accumulate(loop, line); - free(line); - } while (ok); - For_Run(loop); - line = ParseReadLine(); - } - break; + c = ParseReadc(); + } while (c == ' ' || c == '\t'); + } else { + Buf_AddChar(linebuf, '\\'); + if (c == '\\') { + Buf_AddChar(linebuf, '\\'); + c = ParseReadc(); + } + if (c == EOF) + return '\n'; + else + return c; + return c; } } } - return (line); + if (c == '\n') + current->lineno++; + else + return c; + } +} - } else { - /* - * Hit end-of-file, so return a NULL line to indicate this. - */ - return((char *)NULL); +/*- + *--------------------------------------------------------------------- + * ParseReadLine -- + * Read an entire line from the input file. + * + * Results: + * A line without a new line, or NULL at EOF. + * + * 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. + *--------------------------------------------------------------------- + */ +char * +ParseReadLine(linebuf) + Buffer linebuf; +{ + int c; /* the current character */ + + c = ParseSkipEmptyLines(linebuf); + + if (c == EOF) + return NULL; + else { + ParseFoldLF(linebuf, c); + Buf_KillTrailingSpaces(linebuf); + return Buf_Retrieve(linebuf); } } @@ -607,13 +521,13 @@ LowParse_End() Lst_Destroy(&includes, NOFREE); /* Should be empty now */ } #endif - + void Finish_Errors() { if (current != NULL) { - free_ifile(current); + free_ifile(current); current = NULL; } if (fatals) { diff --git a/usr.bin/make/lowparse.h b/usr.bin/make/lowparse.h index 0ceb3939218..b39e70c2278 100644 --- a/usr.bin/make/lowparse.h +++ b/usr.bin/make/lowparse.h @@ -1,4 +1,5 @@ -/* $OpenBSD: lowparse.h,v 1.2 2000/06/23 16:40:50 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lowparse.h,v 1.3 2001/05/03 13:41:07 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -28,13 +29,14 @@ */ #ifndef LOWPARSE_H #define LOWPARSE_H -extern void Parse_FromFile __P((char *, FILE *)); -extern Boolean Parse_NextFile __P((void)); +extern void Parse_FromFile(char *, FILE *); +extern Boolean Parse_NextFile(void); #ifdef CLEANUP -extern void LowParse_Init __P((void)); -extern void LowParse_End __P((void)); +extern void LowParse_Init(void); +extern void LowParse_End(void); #endif -extern char *ParseReadLine __P((void)); -extern char *ParseSkipLine __P((int)); -extern void Finish_Errors __P((void)); +extern char *ParseReadLine(Buffer); +extern char *ParseSkipGetLine(Buffer); +extern char *ParseGetLine(Buffer, const char *); +extern void Finish_Errors(void); #endif diff --git a/usr.bin/make/lst.h b/usr.bin/make/lst.h index 05f58935f32..53ff01ddb9f 100644 --- a/usr.bin/make/lst.h +++ b/usr.bin/make/lst.h @@ -1,5 +1,6 @@ -/* $OpenBSD: lst.h,v 1.18 2000/09/14 13:32:07 espie Exp $ */ -/* $NetBSD: lst.h,v 1.7 1996/11/06 17:59:12 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lst.h,v 1.19 2001/05/03 13:41:07 espie Exp $ */ +/* $NetBSD: lst.h,v 1.7 1996/11/06 17:59:12 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -38,7 +39,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)lst.h 8.1 (Berkeley) 6/6/93 + * from: @(#)lst.h 8.1 (Berkeley) 6/6/93 */ /*- @@ -58,137 +59,121 @@ * 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_ *prevPtr; /* previous element in list */ - struct ListNode_ *nextPtr; /* next in list */ - short useCount:8, /* Count of functions using the node. - * node may not be deleted until count - * goes to 0 */ - flags:8; /* Node status flags */ + struct ListNode_ *prevPtr; /* previous element in list */ + struct ListNode_ *nextPtr; /* next in list */ void *datum; /* datum associated with this element */ } *LstNode; -typedef enum { - Head, Middle, Tail, Unknown -} Where; - typedef struct { - LstNode firstPtr; /* first node in list */ - LstNode lastPtr; /* last node in list */ -/* - * fields for sequential access - */ - Where atEnd; /* Where in the list the last access was */ - Boolean isOpen; /* true if list has been Lst_Open'ed */ - LstNode curPtr; /* current node, if open. NULL if - * *just* opened */ - LstNode prevPtr; /* Previous node, if open. Used by - * Lst_Remove */ + LstNode firstPtr; /* first node in list */ + LstNode lastPtr; /* last node in list */ } LIST; typedef LIST *Lst; -/* - * basic typedef. This is what the Lst_ functions handle - */ -typedef int (*FindProc) __P((void *, void *)); -typedef void (*SimpleProc) __P((void *)); -typedef void (*ForEachProc) __P((void *, void *)); -typedef void * (*DuplicateProc) __P((void *)); +typedef void (*SimpleProc)(void *); +typedef int (*FindProc)(void *, void *); +typedef int (*FindProcConst)(void *, const void *); +typedef void (*ForEachProc)(void *, void *); +typedef void *(*DuplicateProc)(void *); /* * NOFREE can be used as the freeProc to Lst_Destroy when the elements are * not to be freed. - * NOCOPY performs similarly when given as the copyProc to Lst_Clone. + * NOCOPY performs similarly when given as the copyProc to Lst_Duplicate. */ -#define NOFREE ((SimpleProc)0) -#define NOCOPY ((DuplicateProc)0) +#define NOFREE ((SimpleProc) 0) +#define NOCOPY ((DuplicateProc) 0) /* - * Constructors/destructors + * Creation/destruction functions */ /* Create a new list */ -extern void Lst_Init __P((Lst)); -/* Destroy an old one */ -extern void Lst_Destroy __P((Lst, SimpleProc)); - +extern void Lst_Init(LIST *); /* Duplicate an existing list */ -extern Lst Lst_Clone __P((Lst, Lst, DuplicateProc)); +extern Lst Lst_Clone(Lst, Lst, DuplicateProc); +/* Destroy an old one */ +extern void Lst_Destroy(LIST *, SimpleProc); /* True if list is empty */ -extern Boolean Lst_IsEmpty __P((Lst)); +#define Lst_IsEmpty(l) ((l)->firstPtr == NULL) /* - * List modifications + * Functions to modify a list */ /* Insert an element before another */ -extern void Lst_Insert __P((Lst, LstNode, void *)); +extern void Lst_Insert(Lst, LstNode, void *); +extern void Lst_AtFront(Lst, void *); /* Insert an element after another */ -extern void Lst_Append __P((Lst, LstNode, void *)); -/* Place an element at the front of a lst. */ -extern void Lst_AtFront __P((Lst, void *)); -/* Place an element at the end of a lst. */ -extern void Lst_AtEnd __P((Lst, void *)); +extern void Lst_Append(Lst, LstNode, void *); +extern void Lst_AtEnd(Lst, void *); /* Remove an element */ -extern void Lst_Remove __P((Lst, LstNode)); +extern void Lst_Remove(Lst, LstNode); /* Replace a node with a new value */ -extern void Lst_Replace __P((LstNode, void *)); -/* Concatenate two lists, destructive. */ -extern void Lst_ConcatDestroy __P((Lst, Lst)); -/* Concatenate two lists, non destructive */ -extern void Lst_Concat __P((Lst, Lst)); +extern void Lst_Replace(LstNode, void *); +/* Concatenate two lists, destructive. */ +extern void Lst_ConcatDestroy(Lst, Lst); +/* Concatenate two lists, non-destructive. */ +extern void Lst_Concat(Lst, Lst); /* - * Node handling + * Node-specific functions */ /* Return first element in list */ -#define Lst_First(l) ((l)->firstPtr) /* Return last element in list */ -#define Lst_Last(l) ((l)->lastPtr) /* Return successor to given element */ -extern LstNode Lst_Succ __P((LstNode)); -/* Return successor to existing element */ -#define Lst_Adv(ln) ((ln)->nextPtr) -/* Get datum from LstNode */ -#define Lst_Datum(ln) ((ln)->datum) +extern LstNode Lst_Succ(LstNode); /* - * Apply to entire lists + * Functions for entire lists */ - -/* Find an element in a list */ -#define Lst_Find(l, cProc, d) Lst_FindFrom(Lst_First(l), cProc, d) - /* Find an element starting from somewhere */ -extern LstNode Lst_FindFrom __P((LstNode, FindProc, void *)); - -/* Apply a function to all elements of a lst */ -#define Lst_ForEach(l, proc, d) Lst_ForEachFrom(Lst_First(l), proc, d) -/* Apply a function to all elements of a lst starting from a certain point. */ -extern void Lst_ForEachFrom __P((LstNode, ForEachProc, void *)); -extern void Lst_Every __P((Lst, SimpleProc)); - - -/* Find datum in a list. Returns the LstNode containing the datum */ -extern LstNode Lst_Member __P((Lst, void *)); - +extern LstNode Lst_FindFrom(LstNode, FindProc, void *); /* - * Visitor-like pattern. Except the visitor is kept in the list. - * Error-prone and wasteful (used by only a few lists), to be killed. + * See if the given datum is on the list. Returns the LstNode containing + * the datum */ -/* Open the list */ -extern void Lst_Open __P((Lst)); -/* Next element please */ -extern LstNode Lst_Next __P((Lst)); -/* Done yet? */ -extern Boolean Lst_IsAtEnd __P((Lst)); -/* Finish table access */ -extern void Lst_Close __P((Lst)); +extern LstNode Lst_Member(Lst, void *); +/* Apply a function to elements of a lst starting from a certain point. */ +extern void Lst_ForEachFrom(LstNode, ForEachProc, void *); +extern void Lst_Every(Lst, SimpleProc); +extern ReturnStatus Lst_AddNew(Lst, void *); /* - * Queue manipulators + * for using the list as a queue */ /* Place an element at tail of queue */ -extern void Lst_EnQueue __P((Lst, void *)); +#define Lst_EnQueue Lst_AtEnd +#define Lst_QueueNew Lst_AddNew + /* Remove an element from head of queue */ -extern void * Lst_DeQueue __P((Lst)); +extern void * Lst_DeQueue(Lst); + +#define Lst_Datum(ln) ((ln)->datum) +#define Lst_First(l) ((l)->firstPtr) +#define Lst_Last(l) ((l)->lastPtr) +#define Lst_ForEach(l, proc, d) Lst_ForEachFrom(Lst_First(l), proc, d) +#define Lst_Find(l, cProc, d) Lst_FindFrom(Lst_First(l), cProc, d) +#define Lst_Adv(ln) ((ln)->nextPtr) +#define Lst_Rev(ln) ((ln)->prevPtr) + + +#ifdef HAS_INLINES +static INLINE LstNode +Lst_FindConst(Lst l, FindProcConst cProc, const void *d) +{ + return Lst_FindFrom(Lst_First(l), (FindProc)cProc, (void *)d); +} + +static INLINE LstNode +Lst_FindFromConst(LstNode ln, FindProcConst cProc, const void *d) +{ + return Lst_FindFrom(ln, (FindProc)cProc, (void *)d); +} +#else +#define Lst_FindConst(l, cProc, d) \ + Lst_FindFrom(Lst_First(l), (FindProc)cProc, (void *)d) +#define Lst_FindFromConst(ln, cProc, d) \ + Lst_FindFrom(ln, (FindProc)cProc, (void *)d) +#endif #endif /* _LST_H_ */ diff --git a/usr.bin/make/lst.lib/Makefile b/usr.bin/make/lst.lib/Makefile index e02ddf6c560..16975809789 100644 --- a/usr.bin/make/lst.lib/Makefile +++ b/usr.bin/make/lst.lib/Makefile @@ -1,11 +1,11 @@ -# $OpenBSD: Makefile,v 1.9 2000/06/23 16:15:50 espie Exp $ +# $OpenPackages$ +# $OpenBSD: Makefile,v 1.10 2001/05/03 13:41:16 espie Exp $ # $NetBSD: Makefile,v 1.4 1996/11/06 17:59:31 christos Exp $ -OBJ=lstAppend.o lstDupl.o lstInit.o lstOpen.o lstAtEnd.o lstEnQueue.o \ - lstInsert.o lstAtFront.o lstIsAtEnd.o lstClose.o lstIsEmpty.o \ - lstRemove.o lstConcat.o lstConcatDestroy.o lstFindFrom.o lstReplace.o \ - lstMember.o lstSucc.o lstDeQueue.o lstForEachFrom.o \ - lstDestroy.o lstNext.o +OBJ=lstAppend.o lstDupl.o lstInit.o lstEnQueue.o lstInsert.o \ + lstRemove.o lstConcat.o lstFindFrom.o lstLast.o lstReplace.o lstFirst.o \ + lstMember.o lstSucc.o lstDeQueue.o \ + lstForEachFrom.o lstDestroy.o lstAddNew.o lstConcatDestroy.o CFLAGS+=-I.. all: ${OBJ} diff --git a/usr.bin/make/lst.lib/lstAddNew.c b/usr.bin/make/lst.lib/lstAddNew.c new file mode 100644 index 00000000000..2c74119b371 --- /dev/null +++ b/usr.bin/make/lst.lib/lstAddNew.c @@ -0,0 +1,55 @@ +/* $OpenPackages$ */ +/* $OpenBSD: lstAddNew.c,v 1.1 2001/05/03 13:41:16 espie Exp $ */ +/* ex:ts=8 sw=4: + */ + +/* + * Copyright (c) 1999 Marc Espie. + * + * Code written for the OpenBSD project. + * + * 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 "lstInt.h" + +#ifndef lint +UNUSED +static char rcsid[] = "$OpenBSD: lstAddNew.c,v 1.1 2001/05/03 13:41:16 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. + */ +ReturnStatus +Lst_AddNew(l, d) + Lst l; + void *d; +{ + if (Lst_Member(l, d) != NULL) + return FAILURE; + else { + Lst_AtEnd(l, d); + return SUCCESS; + } +} + diff --git a/usr.bin/make/lst.lib/lstAppend.c b/usr.bin/make/lst.lib/lstAppend.c index f0ecb75dc19..86316326bc3 100644 --- a/usr.bin/make/lst.lib/lstAppend.c +++ b/usr.bin/make/lst.lib/lstAppend.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstAppend.c,v 1.11 2000/09/14 13:32:08 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstAppend.c,v 1.12 2001/05/03 13:41:17 espie Exp $ */ /* $NetBSD: lstAppend.c,v 1.5 1996/11/06 17:59:31 christos Exp $ */ /* @@ -43,24 +44,21 @@ */ #include "lstInt.h" + #ifndef lint #if 0 -static char sccsid[] = "@(#)lstAppend.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lstAppend.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstAppend.c,v 1.11 2000/09/14 13:32:08 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstAppend.c,v 1.12 2001/05/03 13:41:17 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Append -- * Create a new node and add it to the given list after the given node. * - * Results: - * SUCCESS if all went well. - * * Side Effects: * A new ListNode is created and linked in to the List. The lastPtr * field of the List will be altered if ln is the last node in the @@ -71,22 +69,20 @@ static char rcsid[] = "$OpenBSD: lstAppend.c,v 1.11 2000/09/14 13:32:08 espie Ex */ void Lst_Append(l, ln, d) - Lst l; /* affected list */ + Lst l; /* affected list */ LstNode ln; /* node after which to append the datum */ - void *d; /* said datum */ + void *d; /* said datum */ { LstNode nLNode; - if (ln == NULL && LstIsEmpty(l)) - goto ok; + if (ln == NULL && !Lst_IsEmpty(l)) + return; - if (LstIsEmpty(l) || ! LstNodeValid(ln, l)) + if (ln != NULL && Lst_IsEmpty(l)) return; - ok: PAlloc(nLNode, LstNode); nLNode->datum = d; - nLNode->useCount = nLNode->flags = 0; if (ln == NULL) { nLNode->nextPtr = nLNode->prevPtr = NULL; @@ -104,3 +100,21 @@ Lst_Append(l, ln, d) } } +void +Lst_AtEnd(l, d) + Lst l; + void *d; +{ + LstNode ln; + + PAlloc(ln, LstNode); + ln->datum = d; + + ln->prevPtr = l->lastPtr; + ln->nextPtr = NULL; + if (l->lastPtr == NULL) + l->firstPtr = ln; + else + l->lastPtr->nextPtr = ln; + l->lastPtr = ln; +} diff --git a/usr.bin/make/lst.lib/lstAtEnd.c b/usr.bin/make/lst.lib/lstAtEnd.c deleted file mode 100644 index 45b39a49a7c..00000000000 --- a/usr.bin/make/lst.lib/lstAtEnd.c +++ /dev/null @@ -1,72 +0,0 @@ -/* $OpenBSD: lstAtEnd.c,v 1.7 2000/09/14 13:32:08 espie Exp $ */ -/* $NetBSD: lstAtEnd.c,v 1.5 1996/11/06 17:59:32 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstAtEnd.c -- - * Add a node at the end of the list - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstAtEnd.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstAtEnd.c,v 1.7 2000/09/14 13:32:08 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_AtEnd -- - * Add a node to the end of the given list - * - * Side Effects: - * A new ListNode is created and added to the list. - * - *----------------------------------------------------------------------- - */ -void -Lst_AtEnd(l, d) - Lst l; /* List to which to add the datum */ - void *d; /* Datum to add */ -{ - Lst_Append(l, Lst_Last(l), d); -} diff --git a/usr.bin/make/lst.lib/lstAtFront.c b/usr.bin/make/lst.lib/lstAtFront.c deleted file mode 100644 index 070bea0e9ff..00000000000 --- a/usr.bin/make/lst.lib/lstAtFront.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $OpenBSD: lstAtFront.c,v 1.7 2000/09/14 13:32:08 espie Exp $ */ -/* $NetBSD: lstAtFront.c,v 1.5 1996/11/06 17:59:33 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstAtFront.c -- - * Add a node at the front of the list - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstAtFront.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstAtFront.c,v 1.7 2000/09/14 13:32:08 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_AtFront -- - * Place a piece of data at the front of a list - * - * Side Effects: - * A new ListNode is created and stuck at the front of the list. - * hence, firstPtr (and possible lastPtr) in the list are altered. - * - *----------------------------------------------------------------------- - */ -void -Lst_AtFront(l, d) - Lst l; - void *d; -{ - Lst_Insert(l, Lst_First(l), d); -} diff --git a/usr.bin/make/lst.lib/lstClose.c b/usr.bin/make/lst.lib/lstClose.c deleted file mode 100644 index 05fc360bb77..00000000000 --- a/usr.bin/make/lst.lib/lstClose.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $OpenBSD: lstClose.c,v 1.7 2000/09/14 13:32:08 espie Exp $ */ -/* $NetBSD: lstClose.c,v 1.5 1996/11/06 17:59:34 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstClose.c -- - * Close a list for sequential access. - * The sequential functions access the list in a slightly different way. - * CurPtr points to their idea of the current node in the list and they - * access the list based on it. Because the list is circular, Lst_Next - * and Lst_Prev will go around the list forever. Lst_IsAtEnd must be - * used to determine when to stop. - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstClose.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstClose.c,v 1.7 2000/09/14 13:32:08 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_Close -- - * Close a list which was opened for sequential access. - * - * Results: - * None. - * - * Side Effects: - * The list is closed. - * - *----------------------------------------------------------------------- - */ -void -Lst_Close(l) - Lst l; /* The list to close */ -{ - l->isOpen = FALSE; - l->atEnd = Unknown; -} - diff --git a/usr.bin/make/lst.lib/lstConcat.c b/usr.bin/make/lst.lib/lstConcat.c index 15618b47f81..c56ff3d0f2d 100644 --- a/usr.bin/make/lst.lib/lstConcat.c +++ b/usr.bin/make/lst.lib/lstConcat.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstConcat.c,v 1.11 2000/09/14 13:32:08 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstConcat.c,v 1.12 2001/05/03 13:41:19 espie Exp $ */ /* $NetBSD: lstConcat.c,v 1.6 1996/11/06 17:59:34 christos Exp $ */ /* @@ -39,60 +40,53 @@ /*- * listConcat.c -- - * Function to concatentate two lists. + * Function to copy a list and append it to another. */ #include "lstInt.h" + #ifndef lint #if 0 -static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstConcat.c,v 1.11 2000/09/14 13:32:08 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstConcat.c,v 1.12 2001/05/03 13:41:19 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Concat -- * Concatenate two lists. New elements are created to hold the data - * elements, but the elements themselves are not copied. - * If the elements should be duplicated to avoid confusion with another - * list, the Lst_Duplicate function should be called first. - * - * Results: - * SUCCESS if all went well. FAILURE otherwise. + * elements but the elements themselves are not copied. + * If the elements themselves should be duplicated to avoid + * confusion with another list, the Lst_Duplicate function + * should be called first. * * Side Effects: - * New elements are created and appended to the first list. + * New elements are created and appended the the first list. *----------------------------------------------------------------------- */ void Lst_Concat(l1, l2) - Lst l1; /* The list to which l2 is to be appended */ - Lst l2; /* The list to append to l1 */ + Lst l1; /* The list to which l2 is to be appended */ + Lst l2; /* The list to append to l1 */ { - LstNode ln; /* original LstNode */ - LstNode nln; /* new LstNode */ - LstNode last; /* the last element in the list. Keeps + LstNode ln; /* original LstNode */ + LstNode nln; /* new LstNode */ + LstNode last; /* the last element in the list. Keeps * bookkeeping until the end */ - if (l2->firstPtr != NULL) { - /* - * We set the nextPtr of the last element of list 2 to be NULL to make - * the loop less difficult. The loop simply goes through the entire - * second list creating new LstNodes and filling in the nextPtr, and - * prevPtr to fit into l1 and its datum field from the - * datum field of the corresponding element in l2. The 'last' node - * follows the last of the new nodes along until the entire l2 has - * been appended. Only then does the bookkeeping catch up with the - * changes. During the first iteration of the loop, if 'last' is NULL, - * the first list must have been empty so the newly-created node is - * made the first node of the list. - */ - l2->lastPtr->nextPtr = NULL; - for (last = l1->lastPtr, ln = l2->firstPtr; ln != NULL; + /* The loop simply goes through the entire second list creating new + * LstNodes and filling in the nextPtr, and prevPtr to fit into l1 + * and its datum field from the datum field of the corresponding + * element in l2. The 'last' node follows the last of the new nodes + * along until the entire l2 has been appended. Only then does the + * bookkeeping catch up with the changes. During the first iteration + * of the loop, if 'last' is NULL, the first list must have been empty + * so the newly-created node is made the first node of the list. */ + for (last = l1->lastPtr, ln = l2->firstPtr; + ln != NULL; ln = ln->nextPtr) { PAlloc(nln, LstNode); nln->datum = ln->datum; @@ -101,19 +95,13 @@ Lst_Concat(l1, l2) else l1->firstPtr = nln; nln->prevPtr = last; - nln->flags = nln->useCount = 0; last = nln; } - /* - * Finish bookkeeping. The last new element becomes the last element - * of list one. - */ + /* Finish bookkeeping. The last new element becomes the last element + * of l1. */ l1->lastPtr = last; - last->nextPtr = NULL; - - l2->lastPtr->nextPtr = l2->firstPtr; } } diff --git a/usr.bin/make/lst.lib/lstConcatDestroy.c b/usr.bin/make/lst.lib/lstConcatDestroy.c index b45df54a8c3..83f95d278f4 100644 --- a/usr.bin/make/lst.lib/lstConcatDestroy.c +++ b/usr.bin/make/lst.lib/lstConcatDestroy.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstConcatDestroy.c,v 1.2 2000/09/14 13:32:08 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstConcatDestroy.c,v 1.3 2001/05/03 13:41:19 espie Exp $ */ /* $NetBSD: lstConcat.c,v 1.6 1996/11/06 17:59:34 christos Exp $ */ /* @@ -38,52 +39,40 @@ */ /*- - * listConcatDestroy.c -- + * listConcat.c -- * Function to concatentate two lists. */ #include "lstInt.h" + #ifndef lint #if 0 -static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstConcatDestroy.c,v 1.2 2000/09/14 13:32:08 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstConcatDestroy.c,v 1.3 2001/05/03 13:41:19 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_ConcatDestroy -- - * Concatenate two lists. The elements of the second list are - * destructively added to the first list. If the elements should - * be duplicated to avoid confusion with another list, the + * Concatenate two lists. The elements of the second list are + * destructively added to the first list. If the elements should + * be duplicated to avoid confusion with another list, the * Lst_Duplicate function should be called first. * - * Results: - * SUCCESS if all went well. FAILURE otherwise. - * * Side Effects: - * The second list is destroyed + * The second list is destroyed. *----------------------------------------------------------------------- */ void Lst_ConcatDestroy(l1, l2) - Lst l1; /* The list to which l2 is to be appended */ - Lst l2; /* The list to append to l1 */ + Lst l1; /* The list to which l2 is to be appended */ + Lst l2; /* The list to append to l1 */ { if (l2->firstPtr != NULL) { /* - * We set the nextPtr of the - * last element of list two to be NULL to make the loop easier and - * so we don't need an extra case should the first list turn - * out to be non-circular -- the final element will already point - * to NULL space and the first element will be untouched if it - * existed before and will also point to NULL space if it didn't. - */ - l2->lastPtr->nextPtr = NULL; - /* * So long as the second list isn't empty, we just link the * first element of the second list to the last element of the * first list. If the first list isn't empty, we then link the @@ -92,11 +81,10 @@ Lst_ConcatDestroy(l1, l2) * the last element of the first list. */ l2->firstPtr->prevPtr = l1->lastPtr; - if (l1->lastPtr != NULL) { + if (l1->lastPtr != NULL) l1->lastPtr->nextPtr = l2->firstPtr; - } else { + else l1->firstPtr = l2->firstPtr; - } l1->lastPtr = l2->lastPtr; } } diff --git a/usr.bin/make/lst.lib/lstDeQueue.c b/usr.bin/make/lst.lib/lstDeQueue.c index 3c09db5e7dc..272e8a41ebe 100644 --- a/usr.bin/make/lst.lib/lstDeQueue.c +++ b/usr.bin/make/lst.lib/lstDeQueue.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstDeQueue.c,v 1.10 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstDeQueue.c,v 1.11 2001/05/03 13:41:19 espie Exp $ */ /* $NetBSD: lstDeQueue.c,v 1.5 1996/11/06 17:59:36 christos Exp $ */ /* @@ -43,43 +44,46 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstDeQueue.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstDeQueue.c,v 1.10 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstDeQueue.c,v 1.11 2001/05/03 13:41:19 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_DeQueue -- * Remove and return the datum at the head of the given list. * * Results: - * The datum in the node at the head or (ick) NULL if the list - * is empty. + * The datum in the node at the head or NULL if the list is empty. * * Side Effects: * The head node is removed from the list. - * *----------------------------------------------------------------------- */ void * Lst_DeQueue(l) - Lst l; + Lst l; { - void *rd; - LstNode tln; + void *rd; + LstNode tln; - tln = Lst_First(l); + tln = l->firstPtr; if (tln == NULL) return NULL; rd = tln->datum; - Lst_Remove(l, tln); + l->firstPtr = tln->nextPtr; + if (l->firstPtr) + l->firstPtr->prevPtr = NULL; + else + l->lastPtr = NULL; + free(tln); return rd; } diff --git a/usr.bin/make/lst.lib/lstDestroy.c b/usr.bin/make/lst.lib/lstDestroy.c index cae5dbed8f8..73f8aa108ed 100644 --- a/usr.bin/make/lst.lib/lstDestroy.c +++ b/usr.bin/make/lst.lib/lstDestroy.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstDestroy.c,v 1.11 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstDestroy.c,v 1.12 2001/05/03 13:41:19 espie Exp $ */ /* $NetBSD: lstDestroy.c,v 1.6 1996/11/06 17:59:37 christos Exp $ */ /* @@ -43,16 +44,17 @@ */ #include "lstInt.h" +#include <stdio.h> + #ifndef lint #if 0 static char sccsid[] = "@(#)lstDestroy.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstDestroy.c,v 1.11 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstDestroy.c,v 1.12 2001/05/03 13:41:19 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Destroy -- @@ -67,7 +69,7 @@ static char rcsid[] = "$OpenBSD: lstDestroy.c,v 1.11 2000/09/14 13:32:09 espie E */ void Lst_Destroy(l, freeProc) - Lst l; + Lst l; SimpleProc freeProc; { LstNode ln; @@ -86,3 +88,4 @@ Lst_Destroy(l, freeProc) } } } + diff --git a/usr.bin/make/lst.lib/lstDupl.c b/usr.bin/make/lst.lib/lstDupl.c index d8e28c0915a..55abac5ad87 100644 --- a/usr.bin/make/lst.lib/lstDupl.c +++ b/usr.bin/make/lst.lib/lstDupl.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstDupl.c,v 1.13 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstDupl.c,v 1.14 2001/05/03 13:41:20 espie Exp $ */ /* $NetBSD: lstDupl.c,v 1.6 1996/11/06 17:59:37 christos Exp $ */ /* @@ -44,16 +45,16 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstDupl.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstDupl.c,v 1.13 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstDupl.c,v 1.14 2001/05/03 13:41:20 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Clone -- @@ -61,7 +62,7 @@ static char rcsid[] = "$OpenBSD: lstDupl.c,v 1.13 2000/09/14 13:32:09 espie Exp * given, the individual client elements will be duplicated as well. * * Results: - * Returns the new list. + * returns the new list. * * Side Effects: * The new list is created. @@ -69,20 +70,20 @@ static char rcsid[] = "$OpenBSD: lstDupl.c,v 1.13 2000/09/14 13:32:09 espie Exp */ Lst Lst_Clone(nl, l, copyProc) - Lst nl; - Lst l; - DuplicateProc copyProc; + Lst nl; + Lst l; /* the list to duplicate */ + DuplicateProc copyProc; /* A function to duplicate each void * */ { - LstNode ln; + LstNode ln; Lst_Init(nl); for (ln = l->firstPtr; ln != NULL; ln = ln->nextPtr) { - if (copyProc != NOCOPY) + if (copyProc != NOCOPY) Lst_AtEnd(nl, (*copyProc)(ln->datum)); else Lst_AtEnd(nl, ln->datum); } - return nl; } + diff --git a/usr.bin/make/lst.lib/lstEnQueue.c b/usr.bin/make/lst.lib/lstEnQueue.c deleted file mode 100644 index 5cd86f1147c..00000000000 --- a/usr.bin/make/lst.lib/lstEnQueue.c +++ /dev/null @@ -1,74 +0,0 @@ -/* $OpenBSD: lstEnQueue.c,v 1.8 2000/09/14 13:32:09 espie Exp $ */ -/* $NetBSD: lstEnQueue.c,v 1.5 1996/11/06 17:59:38 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstEnQueue.c-- - * Treat the list as a queue and place a datum at its end - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstEnQueue.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstEnQueue.c,v 1.8 2000/09/14 13:32:09 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_EnQueue -- - * Add the datum to the tail of the given list. - * - * Side Effects: - * the lastPtr field is altered all the time and the firstPtr field - * will be altered if the list used to be empty. - * - *----------------------------------------------------------------------- - */ -void -Lst_EnQueue(l, d) - Lst l; - void *d; -{ - Lst_AtEnd(l, d); -} - diff --git a/usr.bin/make/lst.lib/lstFindFrom.c b/usr.bin/make/lst.lib/lstFindFrom.c index 680257061e5..05e18146f76 100644 --- a/usr.bin/make/lst.lib/lstFindFrom.c +++ b/usr.bin/make/lst.lib/lstFindFrom.c @@ -1,5 +1,6 @@ -/* $OpenBSD: lstFindFrom.c,v 1.9 2000/09/14 13:32:09 espie Exp $ */ -/* $NetBSD: lstFindFrom.c,v 1.6 1996/11/06 17:59:40 christos Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstFindFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $ */ +/* $NetBSD: lstFindFrom.c,v 1.6 1996/11/06 17:59:40 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -43,40 +44,39 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstFindFrom.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char *rcsid = "$OpenBSD: lstFindFrom.c,v 1.9 2000/09/14 13:32:09 espie Exp $"; +static char *rcsid = "$OpenBSD: lstFindFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_FindFrom -- - * Search for a node through a list, starting with the given node, - * using the comparison function and passed datum to determine when - * it has been found. + * Search for a node starting and ending with the given one on the + * given list using the passed datum and comparison function to + * determine when it has been found. * * Results: - * The node if found, or NULL - * - * Side Effects: - * Whatever cProc incurs. + * The found node or NULL *----------------------------------------------------------------------- */ LstNode Lst_FindFrom(ln, cProc, d) - LstNode ln; - FindProc cProc; - void *d; + LstNode ln; + FindProc cProc; + void *d; { - LstNode tln; + LstNode tln; for (tln = ln; tln != NULL; tln = tln->nextPtr) - if ((*cProc)(tln->datum, d) == 0) + if ((*cProc)(tln->datum, d) == 0) return tln; + return NULL; } + diff --git a/usr.bin/make/lst.lib/lstForEachFrom.c b/usr.bin/make/lst.lib/lstForEachFrom.c index d3b352d7376..dfff0580f73 100644 --- a/usr.bin/make/lst.lib/lstForEachFrom.c +++ b/usr.bin/make/lst.lib/lstForEachFrom.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstForEachFrom.c,v 1.9 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstForEachFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $ */ /* $NetBSD: lstForEachFrom.c,v 1.5 1996/11/06 17:59:42 christos Exp $ */ /* @@ -44,45 +45,47 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstForEachFrom.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstForEachFrom.c,v 1.9 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstForEachFrom.c,v 1.10 2001/05/03 13:41:21 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_ForEachFrom -- - * Apply the given function to each element of the given list. + * Apply the given function to each element of the given list. The + * function should return 0 if traversal should continue and non- + * zero if it should abort. * * Side Effects: * Only those created by the passed-in function. - * *----------------------------------------------------------------------- */ void Lst_ForEachFrom(ln, proc, d) - LstNode ln; - ForEachProc proc; + LstNode ln; + ForEachProc proc; void *d; { - LstNode tln; + LstNode tln; for (tln = ln; tln != NULL; tln = tln->nextPtr) - (*proc)(tln->datum, d); + (*proc)(tln->datum, d); } void Lst_Every(l, proc) - Lst l; - SimpleProc proc; + Lst l; + SimpleProc proc; { - LstNode tln; + LstNode tln; - for (tln = Lst_First(l); tln != NULL; tln = tln->nextPtr) - (*proc)(tln->datum); + for (tln = l->firstPtr; tln != NULL; tln = tln->nextPtr) + (*proc)(tln->datum); } + diff --git a/usr.bin/make/lst.lib/lstInit.c b/usr.bin/make/lst.lib/lstInit.c index 1e4cdcd9b41..fec822b7ec4 100644 --- a/usr.bin/make/lst.lib/lstInit.c +++ b/usr.bin/make/lst.lib/lstInit.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstInit.c,v 1.10 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstInit.c,v 1.11 2001/05/03 13:41:21 espie Exp $ */ /* $NetBSD: lstInit.c,v 1.5 1996/11/06 17:59:43 christos Exp $ */ /* @@ -43,20 +44,20 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstInit.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstInit.c,v 1.10 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstInit.c,v 1.11 2001/05/03 13:41:21 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Init -- - * Initialize a new list. + * Create and initialize a new list. *----------------------------------------------------------------------- */ void @@ -65,6 +66,5 @@ Lst_Init(l) { l->firstPtr = NULL; l->lastPtr = NULL; - l->isOpen = FALSE; - l->atEnd = Unknown; } + diff --git a/usr.bin/make/lst.lib/lstInsert.c b/usr.bin/make/lst.lib/lstInsert.c index 356393f7d92..6337f4e17e2 100644 --- a/usr.bin/make/lst.lib/lstInsert.c +++ b/usr.bin/make/lst.lib/lstInsert.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstInsert.c,v 1.11 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstInsert.c,v 1.12 2001/05/03 13:41:21 espie Exp $ */ /* $NetBSD: lstInsert.c,v 1.5 1996/11/06 17:59:44 christos Exp $ */ /* @@ -43,22 +44,25 @@ */ #include "lstInt.h" + #ifndef lint #if 0 -static char sccsid[] = "@(#)lstInsert.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lstInsert.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstInsert.c,v 1.11 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstInsert.c,v 1.12 2001/05/03 13:41:21 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Insert -- * 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. @@ -67,27 +71,22 @@ static char rcsid[] = "$OpenBSD: lstInsert.c,v 1.11 2000/09/14 13:32:09 espie Ex */ void Lst_Insert(l, ln, d) - Lst l; /* list to manipulate */ - LstNode ln; /* node before which to insert d */ + Lst l; /* list to manipulate */ + LstNode ln; /* node before which to insert d */ void *d; /* datum to be inserted */ { - LstNode nLNode; /* new lnode for d */ + LstNode nLNode; /* new lnode for d */ - /* - * check validity of arguments - */ - if (LstIsEmpty(l) && ln == NULL) - goto ok; + if (ln == NULL && !Lst_IsEmpty(l)) + return; - if (LstIsEmpty(l) || !LstNodeValid(ln, l)) + if (ln != NULL && Lst_IsEmpty(l)) return; - ok: PAlloc(nLNode, LstNode); nLNode->datum = d; - nLNode->useCount = nLNode->flags = 0; if (ln == NULL) { nLNode->prevPtr = nLNode->nextPtr = NULL; @@ -105,3 +104,21 @@ Lst_Insert(l, ln, d) } } +void +Lst_AtFront(l, d) + Lst l; + void *d; +{ + LstNode ln; + + PAlloc(ln, LstNode); + ln->datum = d; + + ln->nextPtr = l->firstPtr; + ln->prevPtr = NULL; + if (l->firstPtr == NULL) + l->lastPtr = ln; + else + l->firstPtr->prevPtr = ln; + l->firstPtr = ln; +} diff --git a/usr.bin/make/lst.lib/lstInt.h b/usr.bin/make/lst.lib/lstInt.h index 78c5db8d65f..3b616769489 100644 --- a/usr.bin/make/lst.lib/lstInt.h +++ b/usr.bin/make/lst.lib/lstInt.h @@ -1,4 +1,5 @@ -/* $OpenBSD: lstInt.h,v 1.11 2000/06/17 14:43:40 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstInt.h,v 1.12 2001/05/03 13:41:22 espie Exp $ */ /* $NetBSD: lstInt.h,v 1.7 1996/11/06 17:59:44 christos Exp $ */ /* @@ -50,27 +51,9 @@ #include "lst.h" /* - * Flags required for synchronization - */ -#define LN_DELETED 0x0001 /* List node should be removed when done */ - - -/* - * PAlloc (var, ptype) -- + * PAlloc(var, ptype) -- * Allocate a pointer-typedef structure 'ptype' into the variable 'var' */ -#define PAlloc(var,ptype) var = (ptype) emalloc (sizeof (*var)) - -/* - * LstNodeValid (ln, l) -- - * Return TRUE if the LstNode ln is valid with respect to l - */ -#define LstNodeValid(ln, l) ((ln) == NULL ? FALSE : TRUE) - -/* - * LstIsEmpty (l) -- - * TRUE if the list l is empty. - */ -#define LstIsEmpty(l) ((l)->firstPtr == NULL) +#define PAlloc(var,ptype) var = (ptype) emalloc (sizeof (*var)) #endif /* _LSTINT_H_ */ diff --git a/usr.bin/make/lst.lib/lstIsAtEnd.c b/usr.bin/make/lst.lib/lstIsAtEnd.c deleted file mode 100644 index 29eb4fdc81c..00000000000 --- a/usr.bin/make/lst.lib/lstIsAtEnd.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $OpenBSD: lstIsAtEnd.c,v 1.7 2000/09/14 13:32:09 espie Exp $ */ -/* $NetBSD: lstIsAtEnd.c,v 1.5 1996/11/06 17:59:45 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstIsAtEnd.c -- - * Tell if the current node is at the end of the list. - * The sequential functions access the list in a slightly different way. - * CurPtr points to their idea of the current node in the list and they - * access the list based on it. Because the list is circular, Lst_Next - * and Lst_Prev will go around the list forever. Lst_IsAtEnd must be - * used to determine when to stop. - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstIsAtEnd.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstIsAtEnd.c,v 1.7 2000/09/14 13:32:09 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_IsAtEnd -- - * Return true if have reached the end of the given list. - * - * Results: - * TRUE if at the end of the list (this includes the list not being - * open or being invalid) or FALSE if not. We return TRUE if the list - * is invalid or unopend so as to cause the caller to exit its loop - * asap, the assumption being that the loop is of the form - * while (!Lst_IsAtEnd (l)) { - * ... - * } - *----------------------------------------------------------------------- - */ -Boolean -Lst_IsAtEnd(l) - Lst l; -{ - return !l->isOpen || l->atEnd == Head || l->atEnd == Tail; -} - diff --git a/usr.bin/make/lst.lib/lstIsEmpty.c b/usr.bin/make/lst.lib/lstIsEmpty.c deleted file mode 100644 index 29b18a9f27c..00000000000 --- a/usr.bin/make/lst.lib/lstIsEmpty.c +++ /dev/null @@ -1,68 +0,0 @@ -/* $OpenBSD: lstIsEmpty.c,v 1.7 2000/09/14 13:32:09 espie Exp $ */ -/* $NetBSD: lstIsEmpty.c,v 1.5 1996/11/06 17:59:47 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstIsEmpty.c -- - * A single function to decide if a list is empty - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstIsEmpty.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstIsEmpty.c,v 1.7 2000/09/14 13:32:09 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_IsEmpty -- - * Return TRUE if the given list is empty. - *----------------------------------------------------------------------- - */ -Boolean -Lst_IsEmpty(l) - Lst l; -{ - return LstIsEmpty(l); -} - diff --git a/usr.bin/make/lst.lib/lstMember.c b/usr.bin/make/lst.lib/lstMember.c index b78ce79f10d..294aab46816 100644 --- a/usr.bin/make/lst.lib/lstMember.c +++ b/usr.bin/make/lst.lib/lstMember.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstMember.c,v 1.8 2000/09/14 13:32:09 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstMember.c,v 1.9 2001/05/03 13:41:23 espie Exp $ */ /* $NetBSD: lstMember.c,v 1.5 1996/11/06 17:59:48 christos Exp $ */ /* @@ -43,22 +44,22 @@ */ #include "lstInt.h" + #ifndef lint #if 0 -static char sccsid[] = "@(#)lstMember.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lstMember.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstMember.c,v 1.8 2000/09/14 13:32:09 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstMember.c,v 1.9 2001/05/03 13:41:23 espie Exp $"; #endif #endif /* not lint */ - LstNode Lst_Member(l, d) - Lst l; + Lst l; void *d; { - LstNode lNode; + LstNode lNode; for (lNode = l->firstPtr; lNode != NULL; lNode = lNode->nextPtr) if (lNode->datum == d) diff --git a/usr.bin/make/lst.lib/lstNext.c b/usr.bin/make/lst.lib/lstNext.c deleted file mode 100644 index 902a6de1029..00000000000 --- a/usr.bin/make/lst.lib/lstNext.c +++ /dev/null @@ -1,118 +0,0 @@ -/* $OpenBSD: lstNext.c,v 1.8 2000/09/14 13:32:10 espie Exp $ */ -/* $NetBSD: lstNext.c,v 1.5 1996/11/06 17:59:49 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstNext.c -- - * Return the next node for a list. - * The sequential functions access the list in a slightly different way. - * CurPtr points to their idea of the current node in the list and they - * access the list based on it. Because the list is circular, Lst_Next - * and Lst_Prev will go around the list forever. Lst_IsAtEnd must be - * used to determine when to stop. - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstNext.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstNext.c,v 1.8 2000/09/14 13:32:10 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_Next -- - * Return the next node for the given list. - * - * Results: - * The next node or NULL if the list has yet to be opened. Also - * if the list is non-circular and the end has been reached, NULL - * is returned. - * - * Side Effects: - * the curPtr field is updated. - * - *----------------------------------------------------------------------- - */ -LstNode -Lst_Next(l) - Lst l; -{ - LstNode tln; - - if (l->isOpen == FALSE) - return NULL; - - l->prevPtr = l->curPtr; - - if (l->curPtr == NULL) { - if (l->atEnd == Unknown) { - /* - * If we're just starting out, atEnd will be Unknown. - * Then we want to start this thing off in the right - * direction -- at the start with atEnd being Middle. - */ - l->curPtr = tln = l->firstPtr; - l->atEnd = Middle; - } else { - tln = NULL; - l->atEnd = Tail; - } - } else { - tln = l->curPtr->nextPtr; - l->curPtr = tln; - - if (tln == l->firstPtr || tln == NULL) - /* - * If back at the front, then we've hit the end... - */ - l->atEnd = Tail; - else - /* - * Reset to Middle if gone past first. - */ - l->atEnd = Middle; - } - - return tln; -} - diff --git a/usr.bin/make/lst.lib/lstOpen.c b/usr.bin/make/lst.lib/lstOpen.c deleted file mode 100644 index 08e0f4f56c9..00000000000 --- a/usr.bin/make/lst.lib/lstOpen.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $OpenBSD: lstOpen.c,v 1.9 2000/09/14 13:32:10 espie Exp $ */ -/* $NetBSD: lstOpen.c,v 1.5 1996/11/06 17:59:50 christos Exp $ */ - -/* - * Copyright (c) 1988, 1989, 1990, 1993 - * The Regents of the University of California. 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. - */ - -/*- - * LstOpen.c -- - * Open a list for sequential access. The sequential functions access the - * list in a slightly different way. CurPtr points to their idea of the - * current node in the list and they access the list based on it. - * If the list is circular, Lst_Next and Lst_Prev will go around - * the list forever. Lst_IsAtEnd must be used to determine when to stop. - */ - -#include "lstInt.h" -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lstOpen.c 8.1 (Berkeley) 6/6/93"; -#else -UNUSED -static char rcsid[] = "$OpenBSD: lstOpen.c,v 1.9 2000/09/14 13:32:10 espie Exp $"; -#endif -#endif /* not lint */ - - -/*- - *----------------------------------------------------------------------- - * Lst_Open -- - * Open a list for sequential access. A list can still be searched, - * etc., without confusing these functions. - * - * Side Effects: - * isOpen is set TRUE and curPtr is set to NULL so the - * other sequential functions no it was just opened and can choose - * the first element accessed based on this. - * - *----------------------------------------------------------------------- - */ -void -Lst_Open(l) - Lst l; -{ - l->isOpen = TRUE; - l->atEnd = LstIsEmpty(l) ? Head : Unknown; - l->curPtr = NULL; -} - diff --git a/usr.bin/make/lst.lib/lstRemove.c b/usr.bin/make/lst.lib/lstRemove.c index d4d900768df..f2be845d888 100644 --- a/usr.bin/make/lst.lib/lstRemove.c +++ b/usr.bin/make/lst.lib/lstRemove.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstRemove.c,v 1.10 2000/09/14 13:32:10 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstRemove.c,v 1.11 2001/05/03 13:41:25 espie Exp $ */ /* $NetBSD: lstRemove.c,v 1.5 1996/11/06 17:59:50 christos Exp $ */ /* @@ -43,24 +44,21 @@ */ #include "lstInt.h" + #ifndef lint #if 0 -static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstRemove.c,v 1.10 2000/09/14 13:32:10 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstRemove.c,v 1.11 2001/05/03 13:41:25 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Remove -- * Remove the given node from the given list. * - * Results: - * SUCCESS or FAILURE. - * * Side Effects: * The list's firstPtr will be set to NULL if ln is the last * node on the list. firsPtr and lastPtr will be altered if ln is @@ -70,11 +68,11 @@ static char rcsid[] = "$OpenBSD: lstRemove.c,v 1.10 2000/09/14 13:32:10 espie Ex */ void Lst_Remove(l, ln) - Lst l; - LstNode ln; + Lst l; + LstNode ln; { - if (!LstNodeValid(ln, l)) - return; + if (ln == NULL) + return; /* unlink it from the list */ if (ln->nextPtr != NULL) @@ -82,42 +80,15 @@ Lst_Remove(l, ln) if (ln->prevPtr != NULL) ln->prevPtr->nextPtr = ln->nextPtr; - /* - * if either the firstPtr or lastPtr of the list point to this node, - * adjust them accordingly - */ + /* if either the firstPtr or lastPtr of the list point to this node, + * adjust them accordingly */ if (l->firstPtr == ln) l->firstPtr = ln->nextPtr; if (l->lastPtr == ln) l->lastPtr = ln->prevPtr; - /* - * Sequential access stuff. If the node we're removing is the current - * node in the list, reset the current node to the previous one. If the - * previous one was non-existent (prevPtr == NULL), we set the - * end to be Unknown, since it is. - */ - if (l->isOpen && l->curPtr == ln) { - l->curPtr = l->prevPtr; - if (l->curPtr == NULL) - l->atEnd = Unknown; - } - - /* - * the only way firstPtr can still point to ln is if ln is the last - * node on the list (the list is circular, so ln->nextptr == ln in - * this case). The list is, therefore, empty and is marked as such - */ - if (l->firstPtr == ln) - l->firstPtr = NULL; - - /* - * note that the datum is unmolested. The caller must free it as - * necessary and as expected. - */ - if (ln->useCount == 0) - free(ln); - else - ln->flags |= LN_DELETED; + /* note that the datum is unmolested. The caller must free it as + * necessary and as expected. */ + free(ln); } diff --git a/usr.bin/make/lst.lib/lstReplace.c b/usr.bin/make/lst.lib/lstReplace.c index 67d8796caf1..f5ec891de52 100644 --- a/usr.bin/make/lst.lib/lstReplace.c +++ b/usr.bin/make/lst.lib/lstReplace.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstReplace.c,v 1.9 2000/09/14 13:32:10 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstReplace.c,v 1.10 2001/05/03 13:41:26 espie Exp $ */ /* $NetBSD: lstReplace.c,v 1.5 1996/11/06 17:59:51 christos Exp $ */ /* @@ -43,31 +44,28 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstReplace.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstReplace.c,v 1.9 2000/09/14 13:32:10 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstReplace.c,v 1.10 2001/05/03 13:41:26 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Replace -- * Replace the datum in the given node with the new datum - * - * Side Effects: - * The datum field fo the node is altered. - * *----------------------------------------------------------------------- */ void Lst_Replace(ln, d) - LstNode ln; - void *d; + LstNode ln; + void *d; { - if (ln != NULL) + if (ln != NULL) ln->datum = d; } + diff --git a/usr.bin/make/lst.lib/lstSucc.c b/usr.bin/make/lst.lib/lstSucc.c index d71cf026365..d6acc4816b5 100644 --- a/usr.bin/make/lst.lib/lstSucc.c +++ b/usr.bin/make/lst.lib/lstSucc.c @@ -1,4 +1,5 @@ -/* $OpenBSD: lstSucc.c,v 1.7 2000/09/14 13:32:10 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: lstSucc.c,v 1.8 2001/05/03 13:41:27 espie Exp $ */ /* $NetBSD: lstSucc.c,v 1.5 1996/11/06 17:59:52 christos Exp $ */ /* @@ -43,25 +44,24 @@ */ #include "lstInt.h" + #ifndef lint #if 0 static char sccsid[] = "@(#)lstSucc.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: lstSucc.c,v 1.7 2000/09/14 13:32:10 espie Exp $"; +static char rcsid[] = "$OpenBSD: lstSucc.c,v 1.8 2001/05/03 13:41:27 espie Exp $"; #endif #endif /* not lint */ - /*- *----------------------------------------------------------------------- * Lst_Succ -- * Return the sucessor to the given node on its list. * * Results: - * The successor of the node, if it exists (note that on a circular - * list, if the node is the only one in the list, it is its own - * successor). + * The successor of the node, if it exists. + * *----------------------------------------------------------------------- */ LstNode diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 36552c8b9db..b97e15e0476 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -1,4 +1,5 @@ -/* $OpenBSD: main.c,v 1.45 2000/11/24 14:36:34 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: main.c,v 1.46 2001/05/03 13:41:07 espie Exp $ */ /* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ /* @@ -92,6 +93,7 @@ #include "dir.h" #include "job.h" #include "pathnames.h" +#include "stats.h" #ifndef lint UNUSED @@ -105,21 +107,21 @@ static char copyright[] = static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: main.c,v 1.45 2000/11/24 14:36:34 espie Exp $"; +static char rcsid[] = "$OpenBSD: main.c,v 1.46 2001/05/03 13:41:07 espie Exp $"; #endif #endif /* not lint */ -#ifndef DEFMAXLOCAL -#define DEFMAXLOCAL DEFMAXJOBS +#ifndef DEFMAXLOCAL +#define DEFMAXLOCAL DEFMAXJOBS #endif /* DEFMAXLOCAL */ -#define MAKEFLAGS ".MAKEFLAGS" +#define MAKEFLAGS ".MAKEFLAGS" -LIST create; /* Targets to be made */ +LIST create; /* Targets to be made */ TIMESTAMP now; /* Time at start of make */ GNode *DEFAULT; /* .DEFAULT node */ -Boolean allPrecious; /* .PRECIOUS given on line by itself */ +Boolean allPrecious; /* .PRECIOUS given on line by itself */ static Boolean noBuiltins; /* -r flag */ static LIST makefiles; /* ordered list of makefiles to read */ @@ -127,33 +129,33 @@ static Boolean printVars; /* print value of one or more vars */ static LIST variables; /* 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 */ +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 */ -static void MainParseArgs __P((int, char **)); -char * chdir_verify_path __P((char *, char *)); -static int ReadMakefile __P((void *, void *)); -static void add_dirpath __P((Lst, const char *)); -static void usage __P((void)); -static void posixParseOptLetter __P((char)); -int main __P((int, char **)); +static void MainParseArgs(int, char **); +static char * chdir_verify_path(char *, char *); +static int ReadMakefile(void *, void *); +static void add_dirpath(Lst, const char *); +static void usage(void); +static void posixParseOptLetter(int); static char *curdir; /* startup directory */ static char *objdir; /* where we chdir'ed to */ + static void posixParseOptLetter(c) - char c; + int c; { switch(c) { case 'B': @@ -213,9 +215,6 @@ posixParseOptLetter(c) * * XXX: Deal with command line overriding .MAKEFLAGS in makefile * - * Results: - * None - * * Side Effects: * Various global and local flags will be set depending on the flags * given @@ -237,8 +236,8 @@ MainParseArgs(argc, argv) # define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst" #endif # define OPTLETTERS "BPSiknqrst" -rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { - switch(c) { +rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { + switch (c) { case 'D': Var_Set(optarg, "1", VAR_GLOBAL); Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); @@ -304,6 +303,9 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { case 'j': debug |= DEBUG_JOB; break; + case 'l': + debug |= DEBUG_LOUD; + break; case 'm': debug |= DEBUG_MAKE; break; @@ -383,9 +385,9 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { Punt("illegal (null) argument."); if (**argv == '-') { if ((*argv)[1]) - optind = 0; /* -flag... */ + optind = 0; /* -flag... */ else - optind = 1; /* - */ + optind = 1; /* - */ goto rearg; } Lst_AtEnd(&create, estrdup(*argv)); @@ -394,16 +396,13 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { /*- * Main_ParseArgLine -- - * Used by the parse module when a .MFLAGS or .MAKEFLAGS target + * Used by the parse module when a .MFLAGS or .MAKEFLAGS target * is encountered and by main() when reading the .MAKEFLAGS envariable. * Takes a line of arguments and breaks it into its - * component words and passes those words and the number of them to the + * component words and passes those words and the number of them to the * MainParseArgs function. * The line should have all its leading whitespace removed. * - * Results: - * None - * * Side Effects: * Only those that come from the various arguments. */ @@ -418,6 +417,7 @@ Main_ParseArgLine(line) char *argv0; char *s; + if (line == NULL) return; for (; *line == ' '; ++line) @@ -429,18 +429,18 @@ Main_ParseArgLine(line) * any blanks or dashes. */ for (s = line;; s++) { if (*s == '\0') { - while (line != s) + while (line != s) posixParseOptLetter(*line++); return; - } + } if (strchr(OPTLETTERS, *s) == NULL) break; } - argv0 = Var_Value(".MAKE", VAR_GLOBAL); + argv0 = Var_Value(".MAKE"); buf = emalloc(strlen(line) + strlen(argv0) + 2); (void)sprintf(buf, "%s %s", argv0, line); - argv = brk_string(buf, &argc, TRUE, &args); + argv = brk_string(buf, &argc, &args); free(buf); MainParseArgs(argc, argv); @@ -450,36 +450,35 @@ Main_ParseArgLine(line) char * chdir_verify_path(path, obpath) - char *path; - char *obpath; + char *path; + char *obpath; { - struct stat sb; + struct stat sb; - if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { - if (chdir(path)) { - (void)fprintf(stderr, "make warning: %s: %s.\n", - path, strerror(errno)); - return 0; - } - else { - if (path[0] != '/') { - (void) snprintf(obpath, MAXPATHLEN, "%s/%s", - curdir, path); - return obpath; - } - else - return path; - } + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + if (chdir(path)) { + (void)fprintf(stderr, "make warning: %s: %s.\n", + path, strerror(errno)); + return NULL; + } else { + if (path[0] != '/') { + (void)snprintf(obpath, MAXPATHLEN, "%s/%s", curdir, path); + return obpath; + } + else + return path; } + } - return 0; + return NULL; } + /* Add a :-separated path to a Lst of directories. */ static void add_dirpath(l, n) Lst l; - const char *n; + const char *n; { const char *start; const char *cp; @@ -495,7 +494,7 @@ add_dirpath(l, n) } } - +int main(int, char **); /*- * main -- * The main function, for obvious reasons. Initializes variables @@ -518,19 +517,23 @@ main(argc, argv) int argc; char **argv; { - LIST targs; /* target nodes to create -- passed to Make_Init */ - Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ + LIST targs; /* target nodes to create */ + Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ struct stat sb, sa; char *p, *path, *pathp, *pwd; char mdpath[MAXPATHLEN + 1]; char obpath[MAXPATHLEN + 1]; char cdpath[MAXPATHLEN + 1]; - char *machine = getenv("MACHINE"); + 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 + #ifdef RLIMIT_NOFILE /* * get rid of resource limit on file descriptors @@ -540,7 +543,7 @@ main(argc, argv) if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && rl.rlim_cur != rl.rlim_max) { rl.rlim_cur = rl.rlim_max; - (void) setrlimit(RLIMIT_NOFILE, &rl); + (void)setrlimit(RLIMIT_NOFILE, &rl); } } #endif @@ -564,7 +567,7 @@ main(argc, argv) if ((pwd = getenv("PWD")) != NULL) { if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && sa.st_dev == sb.st_dev) - (void) strcpy(curdir, pwd); + (void)strcpy(curdir, pwd); } /* @@ -614,11 +617,11 @@ main(argc, argv) if (!(path = getenv("MAKEOBJDIR"))) { path = _PATH_OBJDIR; pathp = _PATH_OBJDIRPREFIX; - (void) snprintf(mdpath, MAXPATHLEN, "%s.%s", + (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", path, machine); if (!(objdir = chdir_verify_path(mdpath, obpath))) if (!(objdir=chdir_verify_path(path, obpath))) { - (void) snprintf(mdpath, MAXPATHLEN, + (void)snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); if (!(objdir=chdir_verify_path(mdpath, obpath))) @@ -629,7 +632,7 @@ main(argc, argv) objdir = curdir; } else { - (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); + (void)snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); if (!(objdir = chdir_verify_path(mdpath, obpath))) objdir = curdir; } @@ -653,7 +656,7 @@ main(argc, argv) debug = 0; /* No debug verbosity, please. */ jobsRunning = FALSE; - maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ + maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ #ifdef REMOTE maxJobs = DEFMAXJOBS; /* Set default max concurrency */ #else @@ -692,21 +695,15 @@ main(argc, argv) Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); /* - * First snag any flags out of the MAKE environment variable. - * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's - * in a different format). + * First snag any flags out of the MAKEFLAGS environment variable. */ -#ifdef POSIX Main_ParseArgLine(getenv("MAKEFLAGS")); -#else - Main_ParseArgLine(getenv("MAKE")); -#endif MainParseArgs(argc, argv); -#ifdef POSIX + /* And set up everything for sub-makes */ Var_AddCmdline(MAKEFLAGS); -#endif + /* * Initialize archive, target and suffix modules in preparation for @@ -746,12 +743,12 @@ main(argc, argv) /* * Read in the built-in rules first, followed by the specified - * makefile, if it was (makefile != (char *) NULL), or the default + * makefile, if it was (makefile != (char *)NULL), or the default * Makefile and makefile, in that order, if it wasn't. */ if (!noBuiltins) { LstNode ln; - LIST sysMkPath; /* Path of sys.mk */ + LIST sysMkPath; /* Path of sys.mk */ Lst_Init(&sysMkPath); Dir_Expand(_PATH_DEFSYSMK, &sysIncPath, &sysMkPath); @@ -777,15 +774,12 @@ main(argc, argv) (void)ReadMakefile(".depend", NULL); - Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL); + Var_Append("MFLAGS", Var_Value(MAKEFLAGS), + VAR_GLOBAL); - /* Install all the flags into the MAKE envariable. */ - if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL)) != NULL) && *p) -#ifdef POSIX + /* Install all the flags into the MAKEFLAGS env variable. */ + if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) esetenv("MAKEFLAGS", p); -#else - esetenv("MAKE", p); -#endif /* * For compatibility, look at the directories in the VPATH variable @@ -793,47 +787,36 @@ main(argc, argv) * variable's value is in the same format as the PATH envariable, i.e. * <directory>:<directory>:<directory>... */ - if (Var_Exists("VPATH", VAR_CMD)) { - char *vpath; - /* - * GCC stores string constants in read-only memory, but - * Var_Subst will want to write this thing, so store it - * in an array - */ - static char VPATH[] = "${VPATH}"; + if (Var_Value("VPATH") != NULL) { + char *vpath; - vpath = Var_Subst(VPATH, (SymTable *)VAR_CMD, FALSE); - add_dirpath(&dirSearchPath, vpath); - (void)free(vpath); + vpath = Var_Subst("${VPATH}", NULL, FALSE); + add_dirpath(&dirSearchPath, vpath); + (void)free(vpath); } - /* - * Now that all search paths have been read for suffixes et al, it's - * time to add the default search path to their lists... - */ + /* Now that all search paths have been read for suffixes et al, it's + * time to add the default search path to their lists... */ Suff_DoPaths(); - /* print the initial graph, if the user requested it */ + /* Print the initial graph, if the user requested it. */ if (DEBUG(GRAPH1)) Targ_PrintGraph(1); - /* print the values of any variables requested by the user */ + /* Print the values of any variables requested by the user. */ if (printVars) { LstNode ln; for (ln = Lst_First(&variables); ln != NULL; ln = Lst_Adv(ln)) { - char *value = Var_Value((char *)Lst_Datum(ln), - VAR_GLOBAL); + 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 + /* 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. - */ + * parsing module to find the main target(s) to create. */ Lst_Init(&targs); if (!Lst_IsEmpty(&create)) Targ_FindList(&targs, &create); @@ -841,12 +824,10 @@ main(argc, argv) Parse_MainName(&targs); if (!compatMake && !printVars) { - /* - * Initialize job module before traversing the graph, now that - * any .BEGIN and .END targets have been read. This is done + /* 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 - * being executed should it exist). - */ + * being executed should it exist). */ if (!queryFlag) { if (maxLocal == -1) maxLocal = maxJobs; @@ -854,13 +835,11 @@ main(argc, argv) jobsRunning = TRUE; } - /* Traverse the graph, checking on all the targets */ + /* 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_Init will take care of creating all the targets as + * well as initializing the module. */ Compat_Run(&targs); } @@ -874,7 +853,7 @@ main(argc, argv) Targ_PrintGraph(2); Suff_End(); - Targ_End(); + Targ_End(); Arch_End(); Var_End(); Parse_End(); @@ -882,9 +861,9 @@ main(argc, argv) Job_End(); if (queryFlag && outOfDate) - return(1); + return 1; else - return(0); + return 0; } /*- @@ -899,8 +878,8 @@ main(argc, argv) */ static Boolean ReadMakefile(p, q) - void *p; - void *q; + void * p; + void * q UNUSED; { char *fname = p; /* makefile to read */ extern LIST parseIncPath; @@ -908,8 +887,8 @@ ReadMakefile(p, q) char *name, path[MAXPATHLEN + 1]; if (!strcmp(fname, "-")) { - Parse_File(estrdup("(stdin)"), stdin); Var_Set("MAKEFILE", "", VAR_GLOBAL); + Parse_File(estrdup("(stdin)"), stdin); } else { if ((stream = fopen(fname, "r")) != NULL) goto found; @@ -926,7 +905,7 @@ ReadMakefile(p, q) if (!name) 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 @@ -937,7 +916,7 @@ found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); Parse_File(fname, stream); (void)fclose(stream); } - return(TRUE); + return TRUE; } /*- @@ -954,19 +933,19 @@ found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); */ char * Cmd_Exec(cmd, err) - char *cmd; + 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 *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 */ + int status; /* command exit status */ BUFFER buf; /* buffer to store the result */ char *cp; ssize_t cc; - size_t length; + size_t length; *err = NULL; @@ -976,7 +955,7 @@ Cmd_Exec(cmd, err) */ args[0] = "sh"; args[1] = "-c"; - args[2] = cmd; + args[2] = (char *)cmd; args[3] = NULL; /* @@ -995,17 +974,18 @@ Cmd_Exec(cmd, err) /* * Close input side of pipe */ - (void) close(fds[0]); + (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); - (void) close(fds[1]); + (void)dup2(fds[1], 1); + if (fds[1] != 1) + (void)close(fds[1]); - (void) execv("/bin/sh", args); + (void)execv("/bin/sh", args); _exit(1); /*NOTREACHED*/ @@ -1017,7 +997,7 @@ Cmd_Exec(cmd, err) /* * No need for the writing half */ - (void) close(fds[1]); + (void)close(fds[1]); Buf_Init(&buf, MAKE_BSIZE); @@ -1032,60 +1012,46 @@ Cmd_Exec(cmd, err) /* * Close the input side of the pipe. */ - (void) close(fds[0]); + (void)close(fds[0]); /* * Wait for the process to exit. */ - while(((pid = wait(&status)) != cpid) && (pid >= 0)) + while ((pid = wait(&status)) != cpid && pid >= 0) continue; - res = Buf_Retrieve(&buf); - length = Buf_Size(&buf); - if (cc == -1) *err = "Couldn't read shell's output for \"%s\""; if (status) *err = "\"%s\" returned non-zero status"; - /* - * Null-terminate the result, convert newlines to spaces and - * install it in the variable. - */ - res[length] = '\0'; + 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 - */ + if (*cp == '\n') + /* A final newline is just stripped. */ *cp-- = '\0'; - } + while (cp >= res) { - if (*cp == '\n') { + if (*cp == '\n') *cp = ' '; - } cp--; } break; } return res; bad: - res = emalloc(1); - *res = '\0'; - return res; + return estrdup(""); } /*- * Error -- * Print an error message given its format. - * - * Results: - * None. - * - * Side Effects: - * The message is printed. */ /* VARARGS */ void @@ -1108,7 +1074,6 @@ Error(va_alist) (void)vfprintf(stderr, fmt, ap); va_end(ap); (void)fprintf(stderr, "\n"); - (void)fflush(stderr); } /*- @@ -1116,9 +1081,6 @@ Error(va_alist) * Produce a Fatal error message. If jobs are running, waits for them * to finish. * - * Results: - * None - * * Side Effects: * The program exits */ @@ -1146,7 +1108,6 @@ Fatal(va_alist) (void)vfprintf(stderr, fmt, ap); va_end(ap); (void)fprintf(stderr, "\n"); - (void)fflush(stderr); if (DEBUG(GRAPH2)) Targ_PrintGraph(2); @@ -1158,9 +1119,6 @@ Fatal(va_alist) * Major exception once jobs are being created. Kills all jobs, prints * a message and exits. * - * Results: - * None - * * Side Effects: * All children are killed indiscriminately and the program Lib_Exits */ @@ -1187,7 +1145,6 @@ Punt(va_alist) (void)vfprintf(stderr, fmt, ap); va_end(ap); (void)fprintf(stderr, "\n"); - (void)fflush(stderr); DieHorribly(); } @@ -1196,9 +1153,6 @@ Punt(va_alist) * DieHorribly -- * Exit without giving a message. * - * Results: - * None - * * Side Effects: * A big one... */ @@ -1217,9 +1171,6 @@ DieHorribly() * Called when aborting due to errors in child shell to signal * abnormal exit. * - * Results: - * None - * * Side Effects: * The program exits */ @@ -1230,6 +1181,7 @@ Finish(errors) Fatal("%d error%s", errors, errors == 1 ? "" : "s"); } + /* * usage -- * exit with usage message @@ -1239,8 +1191,8 @@ usage() { (void)fprintf(stderr, "usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\ - [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ - [variable=value] [target ...]\n"); + [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ + [variable=value] [target ...]\n"); exit(2); } @@ -1249,5 +1201,5 @@ void PrintAddr(a) void *a; { - printf("%lx ", (unsigned long) a); + printf("%lx ", (unsigned long)a); } diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c index 4d23caf28ec..809eab06a5a 100644 --- a/usr.bin/make/make.c +++ b/usr.bin/make/make.c @@ -1,4 +1,5 @@ -/* $OpenBSD: make.c,v 1.24 2000/11/24 14:36:34 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: make.c,v 1.25 2001/05/03 13:41:08 espie Exp $ */ /* $NetBSD: make.c,v 1.10 1996/11/06 17:59:15 christos Exp $ */ /* @@ -45,27 +46,27 @@ * their suitability for creation * * 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 - * otherwise. + * Make_Run Initialize things for the module and recreate + * 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 - * various bookkeeping chores like the updating - * of the cmtime field of the parent, filling - * of the IMPSRC context variable, etc. It will - * place the parent on the toBeMade queue if it - * should be. + * Make_Update Update all parents of a given child. Performs + * various bookkeeping chores like the updating + * of the cmtime field of the parent, filling + * of the IMPSRC context variable, etc. It will + * place the parent on the toBeMade queue if it + * should be. * - * Make_TimeStamp Function to set the parent's cmtime field - * based on a child's modification time. + * Make_TimeStamp Function to set the parent's cmtime field + * based on a child's modification time. * - * Make_DoAllVar Set up the various local variables for a - * target, including the .ALLSRC variable, making - * sure that any variable that needs to exist - * at the very least has the empty value. + * Make_DoAllVar Set up the various local variables for a + * target, including the .ALLSRC variable, making + * sure that any variable that needs to exist + * at the very least has the empty value. * - * Make_OODate Determine if a target is out-of-date. + * Make_OODate Determine if a target is out-of-date. * * Make_HandleUse See if a child is a .USE node for a parent * and perform the .USE actions if so. @@ -82,30 +83,31 @@ static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; #else UNUSED -static char rcsid[] = "$OpenBSD: make.c,v 1.24 2000/11/24 14:36:34 espie Exp $"; +static char rcsid[] = "$OpenBSD: make.c,v 1.25 2001/05/03 13:41:08 espie Exp $"; #endif #endif /* not lint */ -static LIST toBeMade; /* The current fringe of the graph. These + +static LIST toBeMade; /* The current fringe of the graph. These * are nodes which await examination by * MakeOODate. It is added to by * Make_Update and subtracted from by * MakeStartJobs */ -static int numNodes; /* Number of nodes to be processed. If this +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 */ -static void MakeAddChild __P((void *, void *)); -static void MakeAddAllSrc __P((void *, void *)); -static void MakeTimeStamp __P((void *, void *)); -static void MakeHandleUse __P((void *, void *)); -static Boolean MakeStartJobs __P((void)); -static void MakePrintStatus __P((void *, void *)); +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 void MakePrintStatus(void *, void *); /*- *----------------------------------------------------------------------- * Make_TimeStamp -- * Set the cmtime field of a parent node based on the mtime stamp in its - * child. Called from MakeOODate via Lst_ForEach. + * child. * * Side Effects: * The cmtime of the parent node will be changed if the mtime @@ -114,14 +116,14 @@ static void MakePrintStatus __P((void *, void *)); */ void Make_TimeStamp(pgn, cgn) - GNode *pgn; /* the current parent */ - GNode *cgn; /* the child we've just examined */ + GNode *pgn; /* the current parent */ + GNode *cgn; /* the child we've just examined */ { if (is_before(pgn->cmtime, cgn->mtime)) pgn->cmtime = cgn->mtime; } -/* Wrapper to call Make_TimeStamp from a forEach loop */ +/* Wrapper to call Make_TimeStamp from a forEach loop. */ static void MakeTimeStamp(pgn, cgn) void *pgn; /* the current parent */ @@ -129,7 +131,7 @@ MakeTimeStamp(pgn, cgn) { Make_TimeStamp((GNode *)pgn, (GNode *)cgn); } - + /*- *----------------------------------------------------------------------- * Make_OODate -- @@ -149,10 +151,10 @@ MakeTimeStamp(pgn, cgn) *----------------------------------------------------------------------- */ Boolean -Make_OODate (gn) - register GNode *gn; /* the node to check */ +Make_OODate(gn) + GNode *gn; /* the node to check */ { - Boolean oodate; + Boolean oodate; /* * Certain types of targets needn't even be sought as their datedness @@ -162,9 +164,9 @@ Make_OODate (gn) (void)Dir_MTime(gn); if (DEBUG(MAKE)) { if (!is_out_of_date(gn->mtime)) { - printf ("modified %s...", Targ_FmtTime(gn->mtime)); + printf("modified %s...", Targ_FmtTime(gn->mtime)); } else { - printf ("non-existent..."); + printf("non-existent..."); } } } @@ -201,7 +203,7 @@ Make_OODate (gn) * always out of date if no children and :: target */ - oodate = Arch_LibOODate (gn) || + oodate = Arch_LibOODate(gn) || (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP)); } else if (gn->type & OP_JOIN) { /* @@ -270,9 +272,9 @@ Make_OODate (gn) if (!oodate) Lst_ForEach(&gn->parents, MakeTimeStamp, gn); - return (oodate); + return oodate; } - + /*- *----------------------------------------------------------------------- * MakeAddChild -- @@ -288,13 +290,13 @@ MakeAddChild(gnp, lp) void *gnp; /* the node to add */ void *lp; /* the list to which to add it */ { - GNode *gn = (GNode *)gnp; - Lst l = (Lst)lp; + GNode *gn = (GNode *)gnp; + Lst l = (Lst)lp; if (!gn->make && !(gn->type & OP_USE)) Lst_EnQueue(l, gn); } - + /*- *----------------------------------------------------------------------- * Make_HandleUse -- @@ -318,31 +320,26 @@ MakeAddChild(gnp, lp) void Make_HandleUse(cgn, pgn) GNode *cgn; /* The .USE node */ - GNode *pgn; /* The target of the .USE node */ + GNode *pgn; /* The target of the .USE node */ { - GNode *gn; /* A child of the .USE node */ - LstNode ln; /* An element in the children list */ + GNode *gn; /* A child of the .USE node */ + LstNode ln; /* An element in the children list */ if (cgn->type & (OP_USE|OP_TRANSFORM)) { if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) { - /* - * .USE or transformation and target has no commands -- append - * the child's commands to the parent. - */ + /* .USE or transformation and target has no commands -- append + * the child's commands to the parent. */ Lst_Concat(&pgn->commands, &cgn->commands); } - Lst_Open(&cgn->children); - while ((ln = Lst_Next(&cgn->children)) != NULL) { + for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) { gn = (GNode *)Lst_Datum(ln); - if (Lst_Member(&pgn->children, gn) == NULL) { - Lst_AtEnd(&pgn->children, gn); + if (Lst_AddNew(&pgn->children, gn) == SUCCESS) { Lst_AtEnd(&gn->parents, pgn); pgn->unmade += 1; } } - Lst_Close(&cgn->children); pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM); @@ -365,10 +362,10 @@ MakeHandleUse(pgn, cgn) { Make_HandleUse((GNode *)pgn, (GNode *)cgn); } - + /*- *----------------------------------------------------------------------- - * Make_Update -- + * Make_Update -- * Perform update on the parents of a node. Used by JobFinish once * a node has been dealt with and by MakeStartJobs if it finds an * up-to-date node. @@ -380,7 +377,7 @@ MakeHandleUse(pgn, cgn) * The unmade field of pgn is decremented and pgn may be placed on * the toBeMade queue if this field becomes 0. * - * If the child was made, the parent's childMade field will be set true + * If the child was made, the parent's childMade field will be set true * and its cmtime set to now. * * If the child wasn't made, the cmtime field of the parent will be @@ -392,12 +389,12 @@ MakeHandleUse(pgn, cgn) *----------------------------------------------------------------------- */ void -Make_Update (cgn) - register GNode *cgn; /* the child node */ +Make_Update(cgn) + GNode *cgn; /* the child node */ { - register GNode *pgn; /* the parent node */ - register char *cname; /* the child's name */ - register LstNode ln; /* Element in parents and iParents lists */ + GNode *pgn; /* the parent node */ + char *cname; /* the child's name */ + LstNode ln; /* Element in parents and iParents lists */ cname = Varq_Value(TARGET_INDEX, cgn); @@ -416,10 +413,10 @@ Make_Update (cgn) * parse.h : parse.o * * parse.o : parse.y - * yacc -d parse.y - * cc -c y.tab.c - * mv y.tab.o parse.o - * cmp -s y.tab.h parse.h || mv y.tab.h parse.h + * yacc -d parse.y + * cc -c y.tab.c + * mv y.tab.o parse.o + * cmp -s y.tab.h parse.h || mv y.tab.h parse.h * * In this case, if the definitions produced by yacc haven't changed * from before, parse.h won't have been updated and cgn->mtime will @@ -455,11 +452,11 @@ Make_Update (cgn) * -- ardeb 1/12/88 */ /* - * Christos, 4/9/92: If we are saving commands pretend that + * Christos, 4/9/92: If we are saving commands pretend that * the target is made now. Otherwise archives with ... rules * don't work! */ - if (noExecute || (cgn->type & OP_SAVE_CMDS) || + if (noExecute || (cgn->type & OP_SAVE_CMDS) || is_out_of_date(Dir_MTime(cgn))) { cgn->mtime = now; } @@ -469,8 +466,7 @@ Make_Update (cgn) #endif } - Lst_Open(&cgn->parents); - while ((ln = Lst_Next(&cgn->parents)) != NULL) { + for (ln = Lst_First(&cgn->parents); ln != NULL; ln = Lst_Adv(ln)) { pgn = (GNode *)Lst_Datum(ln); if (pgn->make) { pgn->unmade -= 1; @@ -478,9 +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)) { + if (is_before(pgn->cmtime, cgn->mtime)) pgn->cmtime = cgn->mtime; - } } else { (void)Make_TimeStamp(pgn, cgn); } @@ -492,44 +487,36 @@ Make_Update (cgn) */ Lst_EnQueue(&toBeMade, pgn); } else if (pgn->unmade < 0) { - Error ("Graph cycles through %s", pgn->name); + Error("Graph cycles through %s", pgn->name); } } } - Lst_Close(&cgn->parents); - /* - * Deal with successor nodes. If any is marked for making and has an unmade + /* Deal with successor nodes. If any is marked for making and has an unmade * count of 0, has not been made and isn't in the examination queue, * it means we need to place it in the queue as it restrained itself - * before. - */ + * before. */ for (ln = Lst_First(&cgn->successors); ln != NULL; ln = Lst_Adv(ln)) { GNode *succ = (GNode *)Lst_Datum(ln); - if (succ->make && succ->unmade == 0 && succ->made == UNMADE && - Lst_Member(&toBeMade, succ) == NULL) - Lst_EnQueue(&toBeMade, succ); + if (succ->make && succ->unmade == 0 && succ->made == UNMADE) + (void)Lst_QueueNew(&toBeMade, succ); } - /* - * Set the .PREFIX and .IMPSRC variables for all the implied parents - * of this node. - */ + /* Set the .PREFIX and .IMPSRC variables for all the implied parents + * of this node. */ { char *cpref = Varq_Value(PREFIX_INDEX, cgn); - Lst_Open(&cgn->iParents); - while ((ln = Lst_Next(&cgn->iParents)) != NULL) { - pgn = (GNode *)Lst_Datum (ln); - if (pgn->make) { - Varq_Set(IMPSRC_INDEX, cname, pgn); - Varq_Set(PREFIX_INDEX, cpref, pgn); - } + for (ln = Lst_First(&cgn->iParents); ln != NULL; ln = Lst_Adv(ln)) { + pgn = (GNode *)Lst_Datum(ln); + if (pgn->make) { + Varq_Set(IMPSRC_INDEX, cname, pgn); + Varq_Set(PREFIX_INDEX, cpref, pgn); } - Lst_Close(&cgn->iParents); + } } } - + /*- *----------------------------------------------------------------------- * MakeAddAllSrc -- @@ -549,27 +536,28 @@ Make_Update (cgn) */ static void MakeAddAllSrc(cgnp, pgnp) - void *cgnp; /* The child to add */ - void *pgnp; /* The parent to whose ALLSRC variable it should be */ + void *cgnp; /* The child to add */ + void *pgnp; /* The parent to whose ALLSRC variable it should be */ /* added */ { - GNode *cgn = (GNode *) cgnp; - GNode *pgn = (GNode *) pgnp; + GNode *cgn = (GNode *)cgnp; + GNode *pgn = (GNode *)pgnp; if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) { - char *child; + const char *child; if (OP_NOP(cgn->type) || (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) { /* * this node is only source; use the specific pathname for it */ - child = cgn->path ? cgn->path : cgn->name; + child = cgn->path != NULL ? cgn->path : cgn->name; } Varq_Append(ALLSRC_INDEX, child, pgn); if (pgn->type & OP_JOIN) { - if (cgn->made == MADE) + 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)) { @@ -593,7 +581,7 @@ MakeAddAllSrc(cgnp, pgnp) } } } - + /*- *----------------------------------------------------------------------- * Make_DoAllVar -- @@ -607,30 +595,27 @@ MakeAddAllSrc(cgnp, pgnp) * variable. As for ALLSRC, the ordering is important and not * guaranteed when in native mode, so it must be set here, too. * - * Results: - * None - * * Side Effects: * The ALLSRC and OODATE variables of the given node is filled in. * If the node is a .JOIN node, its TARGET variable will be set to - * match its ALLSRC variable. + * match its ALLSRC variable. *----------------------------------------------------------------------- */ void -Make_DoAllVar (gn) +Make_DoAllVar(gn) GNode *gn; { Lst_ForEach(&gn->children, MakeAddAllSrc, gn); - if (!Varq_Exists(OODATE_INDEX, gn)) + if (Varq_Value(OODATE_INDEX, gn) == NULL) Varq_Set(OODATE_INDEX, "", gn); - if (!Varq_Exists(ALLSRC_INDEX, gn)) + if (Varq_Value(ALLSRC_INDEX, gn) == NULL) Varq_Set(ALLSRC_INDEX, "", gn); if (gn->type & OP_JOIN) Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn); } - + /*- *----------------------------------------------------------------------- * MakeStartJobs -- @@ -644,17 +629,16 @@ Make_DoAllVar (gn) * Side Effects: * Nodes are removed from the toBeMade queue and job table slots * are filled. - * *----------------------------------------------------------------------- */ static Boolean -MakeStartJobs () +MakeStartJobs() { - register GNode *gn; + GNode *gn; while (!Job_Full() && (gn = (GNode *)Lst_DeQueue(&toBeMade)) != NULL) { if (DEBUG(MAKE)) { - printf ("Examining %s...", gn->name); + printf("Examining %s...", gn->name); } /* * Make sure any and all predecessors that are going to be made, @@ -674,7 +658,7 @@ MakeStartJobs () } } /* - * If ln isn't null, there's a predecessor as yet unmade, so we + * If ln isn't NULL, there's a predecessor as yet unmade, so we * just drop this node on the floor. When the node in question * has been made, it will notice this node as being ready to * make but as yet unmade and will place the node on the queue. @@ -685,18 +669,18 @@ MakeStartJobs () } numNodes--; - if (Make_OODate (gn)) { + if (Make_OODate(gn)) { if (DEBUG(MAKE)) { - printf ("out-of-date\n"); + printf("out-of-date\n"); } if (queryFlag) { - return (TRUE); + return TRUE; } - Make_DoAllVar (gn); - Job_Make (gn); + Make_DoAllVar(gn); + Job_Make(gn); } else { if (DEBUG(MAKE)) { - printf ("up-to-date\n"); + printf("up-to-date\n"); } gn->made = UPTODATE; if (gn->type & OP_JOIN) { @@ -706,34 +690,37 @@ MakeStartJobs () * value for .TARGET when building up the context variables * of its parent(s)... */ - Make_DoAllVar (gn); + Make_DoAllVar(gn); } - Make_Update (gn); + Make_Update(gn); } } - return (FALSE); + return FALSE; } - + /*- *----------------------------------------------------------------------- * MakePrintStatus -- * Print the status of a top-level node, viz. it being up-to-date * already or not created due to an error in a lower level. * Callback function for Make_Run via Lst_ForEach. + * + * Side Effects: + * A message may be printed. *----------------------------------------------------------------------- */ static void MakePrintStatus(gnp, cyclep) - void *gnp; /* Node to examine */ - void *cyclep; /* True if gn->unmade being non-zero implies + void *gnp; /* Node to examine */ + void *cyclep; /* True if gn->unmade being non-zero implies * a cycle in the graph, not an error in an * inferior */ { - GNode *gn = (GNode *) gnp; - Boolean cycle = *(Boolean *) cyclep; + GNode *gn = (GNode *)gnp; + Boolean cycle = *(Boolean *)cyclep; if (gn->made == UPTODATE) { - printf ("`%s' is up to date.\n", gn->name); + printf("`%s' is up to date.\n", gn->name); } else if (gn->unmade != 0) { if (cycle) { Boolean t = TRUE; @@ -757,11 +744,11 @@ MakePrintStatus(gnp, cyclep) Lst_ForEach(&gn->children, MakePrintStatus, &t); } } else { - printf ("`%s' not remade because of errors.\n", gn->name); + printf("`%s' not remade because of errors.\n", gn->name); } } } - + /*- *----------------------------------------------------------------------- @@ -786,11 +773,11 @@ MakePrintStatus(gnp, cyclep) */ Boolean Make_Run(targs) - Lst targs; /* the initial list of targets */ + Lst targs; /* the initial list of targets */ { - register GNode *gn; /* a temporary pointer */ - LIST examine; /* List of targets to examine */ - int errors; /* Number of errors the Job module reports */ + GNode *gn; /* a temporary pointer */ + LIST examine; /* List of targets to examine */ + int errors; /* Number of errors the Job module reports */ Lst_Init(&toBeMade); @@ -806,7 +793,6 @@ Make_Run(targs) * and go on about our business. */ while ((gn = (GNode *)Lst_DeQueue(&examine)) != NULL) { - if (!gn->make) { gn->make = TRUE; numNodes++; @@ -816,7 +802,7 @@ Make_Run(targs) * to make sure everything has commands that should... */ Lst_ForEach(&gn->children, MakeHandleUse, gn); - Suff_FindDeps (gn); + Suff_FindDeps(gn); if (gn->unmade != 0) { Lst_ForEach(&gn->children, MakeAddChild, &examine); @@ -826,15 +812,13 @@ Make_Run(targs) } } - Lst_Destroy(&examine, NOFREE); - if (queryFlag) { /* * We wouldn't do any work unless we could start some jobs in the * next loop... (we won't actually start any, of course, this is just * to see if any of the targets was out of date) */ - return (MakeStartJobs()); + return MakeStartJobs(); } else { /* * Initialization. At the moment, no jobs are running and until some @@ -843,7 +827,7 @@ Make_Run(targs) * the finishing of a job. So we fill the Job table as much as we can * before going into our loop. */ - (void) MakeStartJobs(); + (void)MakeStartJobs(); } /* @@ -856,9 +840,9 @@ Make_Run(targs) * Note that the Job module will exit if there were any errors unless the * keepgoing flag was given. */ - while (!Job_Empty ()) { - Job_CatchOutput (); - Job_CatchChildren (!usePipes); + while (!Job_Empty()) { + Job_CatchOutput(); + Job_CatchChildren(!usePipes); (void)MakeStartJobs(); } @@ -868,8 +852,8 @@ Make_Run(targs) * Print the final status of each target. E.g. if it wasn't made * because some inferior reported an error. */ - errors = ((errors == 0) && (numNodes != 0)); + 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 b8d64d31561..d785d92e772 100644 --- a/usr.bin/make/make.h +++ b/usr.bin/make/make.h @@ -1,4 +1,5 @@ -/* $OpenBSD: make.h,v 1.30 2001/03/02 16:57:26 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: make.h,v 1.31 2001/05/03 13:41:08 espie Exp $ */ /* $NetBSD: make.h,v 1.15 1997/03/10 21:20:00 christos Exp $ */ /* @@ -56,29 +57,21 @@ #include <ctype.h> #ifdef __GNUC__ -#define UNUSED __attribute__((unused)) +# define UNUSED __attribute__((__unused__)) +# define HAS_INLINES +# define INLINE __inline__ #else -#define UNUSED +# define UNUSED +#endif + +#ifdef HAS_INLINES +# ifndef INLINE +# define INLINE inline +# endif #endif #if !defined(MAKE_BOOTSTRAP) && defined(BSD4_4) # include <sys/cdefs.h> -#else -# ifndef __P -# if defined(__STDC__) || defined(__cplusplus) -# define __P(protos) protos /* full-blown ANSI C */ -# else -# define __P(protos) () /* traditional C preprocessor */ -# endif -# endif -# ifndef __STDC__ -# ifndef const -# define const -# endif -# ifndef volatile -# define volatile -# endif -# endif #endif #ifdef __STDC__ @@ -121,7 +114,7 @@ do { \ 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) \ +#define grab_stat(s, t) \ do { \ (t) = (s).st_mtime; \ if (is_out_of_date(t)) \ @@ -138,17 +131,32 @@ do { \ #define timestamp2time_t(t) (t) #endif -/* Variables that are kept in local GNodes. */ +/* local contexts are real small */ #define TARGET_INDEX 0 -#define OODATE_INDEX 1 -#define ALLSRC_INDEX 2 -#define IMPSRC_INDEX 3 -#define PREFIX_INDEX 4 -#define ARCHIVE_INDEX 5 -#define MEMBER_INDEX 6 +#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 */ @@ -157,6 +165,7 @@ typedef struct { } SymTable; typedef struct ohash GSymT; + /*- * The structure for an individual graph node. Each node has several * pieces of data associated with it. @@ -186,66 +195,63 @@ typedef struct ohash GSymT; * 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 */ + 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 */ + 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 + } 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) + * 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) + * made (used only in compat mode) * ABORTED - The target was aborted due to - * an error making an inferior (compat). + * 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. + * 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. + * printed. Go back and unmark all its + * members. */ - Boolean childMade; /* TRUE if one of this target's children was + Boolean childMade; /* TRUE if one of this target's children was * made */ - int unmade; /* The number of unmade children */ + int unmade; /* The number of unmade children */ - TIMESTAMP mtime; /* Its modification time */ - TIMESTAMP cmtime; /* The modification time of its youngest + TIMESTAMP mtime; /* Its modification time */ + TIMESTAMP cmtime; /* The modification time of its youngest * child */ - LIST iParents; /* Links to parents for which this is an + 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 */ + 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 */ + SymTable context; /* The local variables */ unsigned long lineno; /* First line number of commands. */ const char * fname; /* File name of commands. */ - LIST commands; /* Creation 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 */ + char name[1]; /* The target's name */ } GNode; /* - * Manifest constants - */ - -/* * 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 @@ -264,7 +270,7 @@ typedef struct GNode_ { #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 +#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 */ @@ -272,13 +278,13 @@ typedef struct GNode_ { #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 +#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 +#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 @@ -289,10 +295,10 @@ typedef struct GNode_ { #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. +#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) */ @@ -307,11 +313,10 @@ typedef struct GNode_ { #define OP_NOTARGET (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM) /* - * The TARG_ constants are used when calling the Targ_FindNode function in - * targ.c. They simply tell the function what to do if the desired node(s) - * is (are) 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. + * 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 */ @@ -329,19 +334,6 @@ typedef struct GNode_ { #define MAKE_BSIZE 256 /* starting size for expandable buffers */ /* - * These constants are all used by the Str_Concat function to decide how the - * final string should look. If STR_ADDSPACE is given, a space will be - * placed between the two strings. If STR_ADDSLASH is given, a '/' will - * be used instead of a space. If neither is given, no intervening characters - * will be placed between the two strings in the final output. If the - * STR_DOFREE bit is set, the two input strings will be freed before - * Str_Concat returns. - */ -#define STR_ADDSPACE 0x01 /* add a space when Str_Concat'ing */ -#define STR_DOFREE 0x02 /* free source strings after concatenation */ -#define STR_ADDSLASH 0x04 /* add a slash when Str_Concat'ing */ - -/* * 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. @@ -352,20 +344,20 @@ typedef struct GNode_ { /* * 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 */ +#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 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" @@ -374,58 +366,63 @@ typedef struct GNode_ { #define LONGARCHIVE ".ARCHIVE" #define LONGMEMBER ".MEMBER" - -#define FTARGET "@F" /* file part of TARGET */ -#define DTARGET "@D" /* directory part of TARGET */ -#define FIMPSRC "<F" /* file part of IMPSRC */ -#define DIMPSRC "<D" /* directory part of IMPSRC */ -#define FPREFIX "*F" /* file part of PREFIX */ -#define DPREFIX "*D" /* directory part of PREFIX */ +/* 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 +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 +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 +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' +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 +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 +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 GNode *DEFAULT; /* .DEFAULT rule */ -extern GSymT *VAR_GLOBAL; /* Variables defined in a global context, e.g +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 +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 +extern TIMESTAMP now; /* The time at the start of this whole * process */ -extern Boolean oldVars; /* Do old-style variable substitution */ +extern Boolean oldVars; /* Do old-style variable substitution */ extern LIST sysIncPath; /* The system include path. */ @@ -435,26 +432,27 @@ extern LIST sysIncPath; /* The system include path. */ * 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_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 I(a) a #define CONCAT(a,b) I(a)b #endif /* __STDC__ */ -#define DEBUG(module) (debug & CONCAT(DEBUG_,module)) +#define DEBUG(module) (debug & CONCAT(DEBUG_,module)) #include "extern.h" diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index 35b315b72d9..b2d813a267d 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1,7 +1,34 @@ -/* $OpenBSD: parse.c,v 1.58 2000/11/24 14:27:20 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: parse.c,v 1.59 2001/05/03 13:41:08 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* + * Copyright (c) 1999 Marc Espie. + * + * Extensive code changes for the OpenBSD project. + * + * 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. + */ +/* * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks @@ -58,27 +85,27 @@ * messages can be more meaningful. * * Interface: - * Parse_Init Initialization function which must be - * called before anything else in this module - * is used. + * 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_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_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. + * 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__ @@ -86,6 +113,7 @@ #else #include <varargs.h> #endif +#include <assert.h> #include <stddef.h> #include <stdio.h> #include <ctype.h> @@ -103,22 +131,22 @@ static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: parse.c,v 1.58 2000/11/24 14:27:20 espie Exp $"; +static char rcsid[] = "$OpenBSD: parse.c,v 1.59 2001/05/03 13:41:08 espie Exp $"; #endif #endif /* not lint */ -static LIST targets; /* targets we're working on */ +LIST parseIncPath; /* list of directories for "..." includes */ +LIST sysIncPath; /* list of directories for <...> includes */ + +static LIST targets; /* targets we're working on */ #ifdef CLEANUP -static LIST targCmds; /* command lines for targets */ +static LIST targCmds; /* command lines for targets */ +static LIST fileNames; #endif -static Boolean inLine; /* true if currently in a dependency - * line or its commands */ + static GNode *mainNode; /* The main target to create. This is the * first target on the first dependency * line in the first makefile */ -LIST parseIncPath; /* list of directories for "..." includes */ -LIST sysIncPath; /* list of directories for <...> includes */ - /*- * specType contains the SPECial TYPE of the current target. It is * Not if the target is unspecial. If it *is* special, however, the children @@ -126,9 +154,9 @@ LIST sysIncPath; /* list of directories for <...> includes */ * set in ParseDoDependency */ typedef enum { - Begin, /* .BEGIN */ + Begin, /* .BEGIN */ Default, /* .DEFAULT */ - End, /* .END */ + End, /* .END */ Ignore, /* .IGNORE */ Includes, /* .INCLUDES */ Interrupt, /* .INTERRUPT */ @@ -140,8 +168,8 @@ typedef enum { NoPath, /* .NOPATH */ Not, /* Not special */ NotParallel, /* .NOTPARALELL */ - Null, /* .NULL */ - Order, /* .ORDER */ + Null, /* .NULL */ + Order, /* .ORDER */ Parallel, /* .PARALLEL */ ExPath, /* .PATH */ Phony, /* .PHONY */ @@ -171,64 +199,70 @@ static GNode *predecessor; * keyword is used as a source ("0" if the keyword isn't special as a source) */ static struct { - char *name; /* Name of keyword */ - ParseSpecial spec; /* Type when used as a target */ - int op; /* Operator when used as a source */ + char *name; /* Name of keyword */ + ParseSpecial spec; /* Type when used as a target */ + int op; /* Operator when used as a source */ } parseKeywords[] = { -{ ".BEGIN", Begin, 0 }, -{ ".DEFAULT", Default, 0 }, -{ ".END", End, 0 }, -{ ".EXEC", Attribute, OP_EXEC }, -{ ".IGNORE", Ignore, OP_IGNORE }, -{ ".INCLUDES", Includes, 0 }, -{ ".INTERRUPT", Interrupt, 0 }, -{ ".INVISIBLE", Attribute, OP_INVISIBLE }, -{ ".JOIN", Attribute, OP_JOIN }, -{ ".LIBS", Libs, 0 }, +{ ".BEGIN", Begin, 0 }, +{ ".DEFAULT", Default, 0 }, +{ ".END", End, 0 }, +{ ".EXEC", Attribute, OP_EXEC }, +{ ".IGNORE", Ignore, OP_IGNORE }, +{ ".INCLUDES", Includes, 0 }, +{ ".INTERRUPT", Interrupt, 0 }, +{ ".INVISIBLE", Attribute, OP_INVISIBLE }, +{ ".JOIN", Attribute, OP_JOIN }, +{ ".LIBS", Libs, 0 }, { ".MADE", Attribute, OP_MADE }, -{ ".MAIN", Main, 0 }, -{ ".MAKE", Attribute, OP_MAKE }, -{ ".MAKEFLAGS", MFlags, 0 }, -{ ".MFLAGS", MFlags, 0 }, +{ ".MAIN", Main, 0 }, +{ ".MAKE", Attribute, OP_MAKE }, +{ ".MAKEFLAGS", MFlags, 0 }, +{ ".MFLAGS", MFlags, 0 }, #if 0 /* basic scaffolding for NOPATH, not working yet */ { ".NOPATH", NoPath, OP_NOPATH }, #endif -{ ".NOTMAIN", Attribute, OP_NOTMAIN }, +{ ".NOTMAIN", Attribute, OP_NOTMAIN }, { ".NOTPARALLEL", NotParallel, 0 }, { ".NO_PARALLEL", NotParallel, 0 }, -{ ".NULL", Null, 0 }, -{ ".OPTIONAL", Attribute, OP_OPTIONAL }, -{ ".ORDER", Order, 0 }, +{ ".NULL", Null, 0 }, +{ ".OPTIONAL", Attribute, OP_OPTIONAL }, +{ ".ORDER", Order, 0 }, { ".PARALLEL", Parallel, 0 }, { ".PATH", ExPath, 0 }, { ".PHONY", Phony, OP_PHONY }, -{ ".PRECIOUS", Precious, OP_PRECIOUS }, -{ ".RECURSIVE", Attribute, OP_MAKE }, -{ ".SHELL", ExShell, 0 }, -{ ".SILENT", Silent, OP_SILENT }, +{ ".PRECIOUS", Precious, OP_PRECIOUS }, +{ ".RECURSIVE", Attribute, OP_MAKE }, +{ ".SHELL", ExShell, 0 }, +{ ".SILENT", Silent, OP_SILENT }, { ".SINGLESHELL", SingleShell, 0 }, -{ ".SUFFIXES", Suffixes, 0 }, -{ ".USE", Attribute, OP_USE }, +{ ".SUFFIXES", Suffixes, 0 }, +{ ".USE", Attribute, OP_USE }, { ".WAIT", Wait, 0 }, }; -static int ParseFindKeyword __P((char *)); -static void ParseLinkSrc __P((void *, void *)); -static int ParseDoOp __P((void *, void *)); -static int ParseAddDep __P((void *, void *)); -static void ParseDoSrc __P((int, char *, Lst)); -static int ParseFindMain __P((void *, void *)); -static void ParseAddDir __P((void *, void *)); -static void ParseClearPath __P((void *)); -static void ParseDoDependency __P((char *)); -static void ParseAddCmd __P((void *, void *)); -static void ParseHasCommands __P((void *)); -static void ParseDoInclude __P((char *)); -#ifdef SYSVINCLUDE -static void ParseTraditionalInclude __P((char *)); -#endif -static void ParseLookupIncludeFile __P((char *, char *, Boolean)); -static void ParseFinishLine __P((void)); +static int ParseFindKeyword(const char *); +static void ParseLinkSrc(GNode *, GNode *); +static int ParseDoOp(void *, void *); +static int ParseAddDep(void *, void *); +static void ParseDoSrc(int, const char *, Lst); +static int ParseFindMain(void *, void *); +static void ParseAddDir(void *, void *); +static void ParseClearPath(void *); +static void ParseDoDependency(char *); +static void ParseAddCmd(void *, void *); +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 ParseFinishDependency(void); +static Boolean 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 *); /*- *---------------------------------------------------------------------- @@ -237,42 +271,38 @@ static void ParseFinishLine __P((void)); * * Results: * The index of the keyword, or -1 if it isn't there. - * - * Side Effects: - * None *---------------------------------------------------------------------- */ static int -ParseFindKeyword (str) - char *str; /* String to find */ +ParseFindKeyword(str) + const char *str; /* String to find */ { - register int start, + int start, end, cur; - register int diff; + int diff; start = 0; end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1; do { - cur = start + ((end - start) / 2); - diff = strcmp (str, parseKeywords[cur].name); + cur = start + (end - start) / 2; + diff = strcmp(str, parseKeywords[cur].name); if (diff == 0) { - return (cur); + return cur; } else if (diff < 0) { end = cur - 1; } else { start = cur + 1; } } while (start <= end); - return (-1); + return -1; } - /*- *--------------------------------------------------------------------- * ParseLinkSrc -- - * Link the parent node to its new child. Used in a Lst_ForEach by + * Link the parent node to its new child. Used by * ParseDoDependency. If the specType isn't 'Not', the parent * isn't linked as a parent of the child. * @@ -283,17 +313,14 @@ ParseFindKeyword (str) *--------------------------------------------------------------------- */ static void -ParseLinkSrc(pgnp, cgnp) - void *pgnp; /* The parent node */ - void *cgnp; /* The child node */ +ParseLinkSrc(pgn, cgn) + GNode *pgn; /* The parent node */ + GNode *cgn; /* The child node */ { - GNode *pgn = (GNode *)pgnp; - GNode *cgn = (GNode *)cgnp; - if (Lst_Member(&pgn->children, cgn) == NULL) { - Lst_AtEnd(&pgn->children, cgn); + if (Lst_AddNew(&pgn->children, cgn) == SUCCESS) { if (specType == Not) Lst_AtEnd(&cgn->parents, pgn); - pgn->unmade += 1; + pgn->unmade++; } } @@ -305,22 +332,19 @@ ParseLinkSrc(pgnp, cgnp) * been found and their operator parsed. If the previous and new * operators are incompatible, a major error is taken. * - * Results: - * 0 if a problem, 1 if ok. - * * Side Effects: * The type field of the node is altered to reflect any new bits in * the op. *--------------------------------------------------------------------- */ static int -ParseDoOp (gnp, opp) - void *gnp; /* The node to which the operator is to be - * applied */ - void *opp; /* The operator to apply */ +ParseDoOp(gnp, opp) + void *gnp; /* The node to which the operator is to be + * applied */ + void *opp; /* The operator to apply */ { - GNode *gn = (GNode *) gnp; - int op = *(int *) opp; + GNode *gn = (GNode *)gnp; + int op = *(int *)opp; /* * If the dependency mask of the operator and the node don't match and * the node has actually had an operator applied to it before, and @@ -332,58 +356,50 @@ ParseDoOp (gnp, opp) return 0; } - if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { - /* - * If the node was the object of a :: operator, we need to create a + if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { + /* If the node was the object of a :: operator, we need to create a * new instance of it for the children and commands on this dependency * line. The new instance is placed on the 'cohorts' list of the * initial one (note the initial one is not on its own cohorts list) * and the new instance is linked to all parents of the initial - * instance. - */ - register GNode *cohort; - LstNode ln; + * instance. */ + GNode *cohort; + LstNode ln; cohort = Targ_NewGN(gn->name, NULL); - /* - * Duplicate links to parents so graph traversal is simple. Perhaps + /* Duplicate links to parents so graph traversal is simple. Perhaps * some type bits should be duplicated? * * Make the cohort invisible as well to avoid duplicating it into * other variables. True, parents of this target won't tend to do * anything with their local variables, but better safe than - * sorry. - */ - Lst_ForEach(&gn->parents, ParseLinkSrc, cohort); + * sorry. */ + for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln)) + ParseLinkSrc((GNode *)Lst_Datum(ln), cohort); cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; Lst_AtEnd(&gn->cohorts, cohort); - /* - * Replace the node in the targets list with the new copy - */ + /* Replace the node in the targets list with the new copy */ ln = Lst_Member(&targets, gn); Lst_Replace(ln, cohort); gn = cohort; } - /* - * We don't want to nuke any previous flags (whatever they were) so we - * just OR the new operator into the old - */ + /* We don't want to nuke any previous flags (whatever they were) so we + * just OR the new operator into the old. */ gn->type |= op; - return 1; } /*- *--------------------------------------------------------------------- - * ParseAddDep -- + * ParseAddDep -- * Check if the pair of GNodes given needs to be synchronized. * This has to be when two nodes are on different sides of a * .WAIT directive. * * Results: * Returns 0 if the two targets need to be ordered, 1 otherwise. - * If it returns 0, the search can stop + * If it returns 0, the search can stop. * * Side Effects: * A dependency can be added between the two nodes. @@ -395,15 +411,13 @@ ParseAddDep(pp, sp) void *pp; void *sp; { - GNode *p = (GNode *) pp; - GNode *s = (GNode *) sp; + GNode *p = (GNode *)pp; + GNode *s = (GNode *)sp; if (p->order < s->order) { - /* - * XXX: This can cause loops, and loops can cause unmade targets, + /* XXX: This can cause loops, and loops can cause unmade targets, * but checking is tedious, and the debugging output can show the - * problem - */ + * problem. */ Lst_AtEnd(&p->successors, s); Lst_AtEnd(&s->preds, p); return 1; @@ -422,24 +436,21 @@ ParseAddDep(pp, sp) * of some special target and apply it if so. Otherwise, make the * source be a child of the targets in the list 'targets' * - * Results: - * None - * * Side Effects: * Operator bits may be added to the list of targets or to the source. * The targets may have a new source added to their lists of children. *--------------------------------------------------------------------- */ static void -ParseDoSrc (tOp, src, allsrc) - int tOp; /* operator (if any) from special targets */ - char *src; /* name of the source to handle */ - Lst allsrc; /* List of all sources to wait for */ +ParseDoSrc(tOp, src, allsrc) + int tOp; /* operator (if any) from special targets */ + const char *src; /* name of the source to handle */ + Lst allsrc; /* List of all sources to wait for */ { GNode *gn = NULL; - if (*src == '.' && isupper (src[1])) { + if (*src == '.' && isupper(src[1])) { int keywd = ParseFindKeyword(src); if (keywd != -1) { int op = parseKeywords[keywd].op; @@ -477,7 +488,7 @@ ParseDoSrc (tOp, src, allsrc) * Create proper predecessor/successor links between the previous * source and the current one. */ - gn = Targ_FindNode(src, TARG_CREATE); + gn = Targ_FindNode(src, NULL, TARG_CREATE); if (predecessor != NULL) { Lst_AtEnd(&predecessor->successors, gn); Lst_AtEnd(&gn->preds, predecessor); @@ -500,22 +511,28 @@ ParseDoSrc (tOp, src, allsrc) * the 'cohorts' list of the node) or all the cohorts are linked * to all the targets. */ - gn = Targ_FindNode (src, TARG_CREATE); + gn = Targ_FindNode(src, NULL, TARG_CREATE); if (tOp) { gn->type |= tOp; } else { - Lst_ForEach(&targets, ParseLinkSrc, gn); + LstNode ln; + + for (ln = Lst_First(&targets); ln != NULL; ln = Lst_Adv(ln)) + ParseLinkSrc((GNode *)Lst_Datum(ln), gn); } if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { - register GNode *cohort; - register LstNode ln; + GNode *cohort; + LstNode ln; for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)){ cohort = (GNode *)Lst_Datum(ln); if (tOp) { cohort->type |= tOp; } else { - Lst_ForEach(&targets, ParseLinkSrc, cohort); + LstNode ln; + + for (ln = Lst_First(&targets); ln != NULL; ln = Lst_Adv(ln)) + ParseLinkSrc((GNode *)Lst_Datum(ln), cohort); } } } @@ -524,8 +541,9 @@ ParseDoSrc (tOp, src, allsrc) gn->order = waiting; Lst_AtEnd(allsrc, gn); - if (waiting) + if (waiting) { Lst_Find(allsrc, ParseAddDep, gn); + } } /*- @@ -540,21 +558,21 @@ ParseDoSrc (tOp, src, allsrc) * * Side Effects: * mainNode is changed and Targ_SetMain is called. - * *----------------------------------------------------------------------- */ static int ParseFindMain(gnp, dummy) - void *gnp; /* Node to examine */ - void *dummy UNUSED; + void *gnp; /* Node to examine */ + void *dummy UNUSED; { - GNode *gn = (GNode *) gnp; + GNode *gn = (GNode *)gnp; if ((gn->type & OP_NOTARGET) == 0) { mainNode = gn; Targ_SetMain(gn); return 0; - } else + } else { return 1; + } } /*- @@ -564,7 +582,6 @@ ParseFindMain(gnp, dummy) * * Side Effects: * See Dir_AddDir. - * *----------------------------------------------------------------------- */ static void @@ -578,18 +595,17 @@ ParseAddDir(path, name) /*- *----------------------------------------------------------------------- * ParseClearPath -- - * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going - * - * Side Effects: - * See Dir_ClearPath - * + * Reinit path to an empty path *----------------------------------------------------------------------- */ static void -ParseClearPath(path) - void *path; +ParseClearPath(p) + void *p; { - Dir_ClearPath((Lst)path); + Lst path = (Lst)p; + + Lst_Destroy(path, Dir_Destroy); + Lst_Init(path); } /*- @@ -597,9 +613,6 @@ ParseClearPath(path) * ParseDoDependency -- * Parse the dependency line in line. * - * Results: - * None - * * Side Effects: * The nodes of the sources are linked as children to the nodes of the * targets. Some nodes may be created. @@ -609,7 +622,7 @@ ParseClearPath(path) * until a character is encountered which is an operator character. Currently * these are only ! and :. At this point the operator is parsed and the * pointer into the line advanced until the first source is encountered. - * The parsed operator is applied to each node in the 'targets' list, + * The parsed operator is applied to each node in the 'targets' list, * which is where the nodes found for the targets are kept, by means of * the ParseDoOp function. * The sources are read in much the same way as the targets were except @@ -627,17 +640,17 @@ ParseClearPath(path) *--------------------------------------------------------------------- */ static void -ParseDoDependency (line) - char *line; /* the line to parse */ +ParseDoDependency(line) + char *line; /* the line to parse */ { - char *cp; /* our current position */ - GNode *gn; /* a general purpose temporary node */ - int op; /* the operator on the line */ - char savec; /* a place to save a character */ - LIST paths; /* List of search paths to alter when parsing + char *cp; /* our current position */ + GNode *gn; /* a general purpose temporary node */ + int op; /* the operator on the line */ + char savec; /* a place to save a character */ + LIST paths; /* List of search paths to alter when parsing * a list of .PATH targets */ - int tOp; /* operator from special target */ - LIST curTargs; /* list of target names to be found and added + int tOp; /* operator from special target */ + LIST curTargs; /* list of target names to be found and added * to the targets list */ LIST curSrcs; /* list of sources in order */ @@ -651,68 +664,59 @@ ParseDoDependency (line) Lst_Init(&curSrcs); do { - for (cp = line; - *cp && !isspace (*cp) && (*cp != '('); - cp++) - { - /* - * We don't want to end a word on ':' or '!' if there is a - * better match later on in the string. By "better" I mean - * one that is followed by whitespace. This allows the user - * to have targets like: - * fie::fi:fo: fum - * where "fie::fi:fo" is the target. In real life this is used - * for perl5 library man pages where "::" separates an object - * from its class. Ie: "File::Spec::Unix". This behaviour - * is also consistent with other versions of make. - */ - if (*cp == '!' || *cp == ':') { - char *p = cp + 1; - - if (*p == '\0') - break; /* no chance, not enough room */ - /* - * Only end the word on ':' or '!' if there is not - * a match later on followed by whitespace. - */ - while ((p = strchr(p + 1, *cp)) && !isspace(*(p + 1))) - ; - if (!p || !isspace(*(p + 1))) - break; - } else if (*cp == '$') { - /* - * Must be a dynamic source (would have been expanded + for (cp = line; *cp && !isspace(*cp) && *cp != '(';) + if (*cp == '$') + /* Must be a dynamic source (would have been expanded * otherwise), so call the Var module to parse the puppy * so we can safely advance beyond it...There should be * no errors in this, as they would have been discovered - * in the initial Var_Subst and we wouldn't be here. - */ - size_t length; - Boolean freeIt; - char *result; + * in the initial Var_Subst and we wouldn't be here. */ + cp += Var_ParseSkip(cp, NULL, NULL); + else { + /* We don't want to end a word on ':' or '!' if there is a + * better match later on in the string. By "better" I mean + * one that is followed by whitespace. This allows the user + * to have targets like: + * fie::fi:fo: fum + * where "fie::fi:fo" is the target. In real life this is used + * for perl5 library man pages where "::" separates an object + * from its class. Ie: "File::Spec::Unix". This behaviour + * is also consistent with other versions of make. */ + if (*cp == '!' || *cp == ':') { + char *p = cp + 1; + + if (*cp == ':' && *p == ':') + p++; + + /* Found the best match already. */ + if (isspace(*p) || *p == '\0') + break; - result=Var_Parse(cp, NULL, TRUE, &length, &freeIt); + do { + p += strcspn(p, "!:"); + if (*p == '\0') + break; + p++; + } while (!isspace(*p)); + + /* No better match later on... */ + if (*p == '\0') + break; - if (freeIt) { - free(result); } - cp += length-1; + cp++; } - continue; - } if (*cp == '(') { - /* - * Archives must be handled specially to make sure the OP_ARCHV + /* Archives must be handled specially to make sure the OP_ARCHV * flag is set in their 'type' field, for one thing, and because * 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 - * specification. On error, line should remain untouched. - */ + * specification. On error, line should remain untouched. */ if (Arch_ParseArchive(&line, &targets, NULL) != SUCCESS) { - Parse_Error (PARSE_FATAL, + Parse_Error(PARSE_FATAL, "Error in archive specification: \"%s\"", line); return; } else { @@ -721,24 +725,17 @@ ParseDoDependency (line) } savec = *cp; - if (!*cp) { - /* - * Ending a dependency line without an operator is a Bozo - * no-no - */ - Parse_Error (PARSE_FATAL, "Need an operator"); + if (*cp == '\0') { + /* Ending a dependency line without an operator is a Bozo no-no */ + Parse_Error(PARSE_FATAL, "Need an operator"); return; } *cp = '\0'; - /* - * Have a word in line. See if it's a special target and set - * specType to match it. - */ - if (*line == '.' && isupper (line[1])) { - /* - * See if the target is a special target that must have it - * or its sources handled specially. - */ + /* Have a word in line. See if it's a special target and set + * specType to match it. */ + if (*line == '.' && isupper(line[1])) { + /* See if the target is a special target that must have it + * or its sources handled specially. */ int keywd = ParseFindKeyword(line); if (keywd != -1) { if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { @@ -756,7 +753,7 @@ ParseDoDependency (line) * .MAIN Its sources are only used if * nothing has been specified to * create. - * .DEFAULT Need to create a node to hang + * .DEFAULT Need to create a node to hang * commands on, but we don't want * it in the graph, nor do we want * it to be the Main Target, so we @@ -764,19 +761,19 @@ ParseDoDependency (line) * add it to the list, setting * DEFAULT to the new node for * later use. We claim the node is - * A transformation rule to make - * life easier later, when we'll - * use Make_HandleUse to actually - * apply the .DEFAULT commands. + * A transformation rule to make + * life easier later, when we'll + * use Make_HandleUse to actually + * apply the .DEFAULT commands. * .PHONY The list of targets - * .NOPATH Don't search for file in the path + * .NOPATH Don't search for file in the path * .BEGIN * .END - * .INTERRUPT Are not to be considered the + * .INTERRUPT Are not to be considered the * main target. - * .NOTPARALLEL Make only one target at a time. - * .SINGLESHELL Create a shell for each command. - * .ORDER Must set initial predecessor to NULL + * .NOTPARALLEL Make only one target at a time. + * .SINGLESHELL Create a shell for each command. + * .ORDER Must set initial predecessor to NULL */ switch (specType) { case ExPath: @@ -790,13 +787,13 @@ ParseDoDependency (line) case Begin: case End: case Interrupt: - gn = Targ_FindNode(line, TARG_CREATE); + gn = Targ_FindNode(line, NULL, TARG_CREATE); gn->type |= OP_NOTMAIN; Lst_AtEnd(&targets, gn); break; case Default: gn = Targ_NewGN(".DEFAULT", NULL); - gn->type |= (OP_NOTMAIN|OP_TRANSFORM); + gn->type |= OP_NOTMAIN|OP_TRANSFORM; Lst_AtEnd(&targets, gn); DEFAULT = gn; break; @@ -816,13 +813,13 @@ ParseDoDependency (line) default: break; } - } else if (strncmp (line, ".PATH", 5) == 0) { + } else if (strncmp(line, ".PATH", 5) == 0) { /* * .PATH<suffix> has to be handled specially. * Call on the suffix module to give us a path to * modify. */ - Lst path; + Lst path; specType = ExPath; path = Suff_GetPath(&line[5]); @@ -831,8 +828,9 @@ ParseDoDependency (line) "Suffix '%s' not defined (yet)", &line[5]); return; - } else + } else { Lst_AtEnd(&paths, path); + } } } @@ -840,7 +838,7 @@ ParseDoDependency (line) * Have word in line. Get or create its node and stick it at * the end of the targets list */ - if ((specType == Not) && (*line != '\0')) { + if (specType == Not && *line != '\0') { char *targName; if (Dir_HasWildcards(line)) { @@ -851,11 +849,9 @@ ParseDoDependency (line) * Dir module could have added a directory to the path... */ LIST emptyPath; - - Lst_Init(&emptyPath); + Lst_Init(&emptyPath); Dir_Expand(line, &emptyPath, &curTargs); - Lst_Destroy(&emptyPath, Dir_Destroy); } else { /* @@ -865,11 +861,11 @@ ParseDoDependency (line) Lst_AtEnd(&curTargs, line); } - while((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) { - if (!Suff_IsTransform (targName)) { - gn = Targ_FindNode (targName, TARG_CREATE); + while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) { + if (!Suff_IsTransform(targName)) { + gn = Targ_FindNode(targName, NULL, TARG_CREATE); } else { - gn = Suff_AddTransform (targName); + gn = Suff_AddTransform(targName); } if (gn != NULL) @@ -887,7 +883,7 @@ ParseDoDependency (line) if (specType != Not && specType != ExPath) { Boolean warn = FALSE; - while ((*cp != '!') && (*cp != ':') && *cp) { + while (*cp != '!' && *cp != ':' && *cp) { if (*cp != ' ' && *cp != '\t') { warn = TRUE; } @@ -897,18 +893,20 @@ ParseDoDependency (line) Parse_Error(PARSE_WARNING, "Extra target ignored"); } } else { - while (*cp && isspace (*cp)) { + while (*cp && isspace(*cp)) { cp++; } } line = cp; - } while ((*line != '!') && (*line != ':') && *line); + } while (*line != '!' && *line != ':' && *line); - /* Don't need the list of target names any more */ + /* + * Don't need the list of target names anymore... + */ Lst_Destroy(&curTargs, NOFREE); if (!Lst_IsEmpty(&targets)) { - switch(specType) { + switch (specType) { default: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); break; @@ -916,22 +914,16 @@ ParseDoDependency (line) case Begin: case End: case Interrupt: - /* - * These four create nodes on which to hang commands, so - * targets shouldn't be empty... - */ + /* These four create nodes on which to hang commands, so + * targets shouldn't be empty... */ case Not: - /* - * Nothing special here -- targets can be empty if it wants. - */ + /* Nothing special here -- targets can be empty if it wants. */ break; } } - /* - * Have now parsed all the target names. Must parse the operator next. The - * result is left in op . - */ + /* Have now parsed all the target names. Must parse the operator next. The + * result is left in op . */ if (*cp == '!') { op = OP_FORCE; } else if (*cp == ':') { @@ -942,7 +934,7 @@ ParseDoDependency (line) op = OP_DEPENDS; } } else { - Parse_Error (PARSE_FATAL, "Missing dependency operator"); + Parse_Error(PARSE_FATAL, "Missing dependency operator"); return; } @@ -953,7 +945,7 @@ ParseDoDependency (line) /* * Get to the first source */ - while (*cp && isspace (*cp)) { + while (*cp && isspace(*cp)) { cp++; } line = cp; @@ -970,7 +962,7 @@ ParseDoDependency (line) if (!*line) { switch (specType) { case Suffixes: - Suff_ClearSuffixes (); + Suff_ClearSuffixes(); break; case Precious: allPrecious = TRUE; @@ -993,25 +985,24 @@ ParseDoDependency (line) * set the initial character to a null-character so the loop to * get sources won't get anything */ - Main_ParseArgLine (line); + Main_ParseArgLine(line); *line = '\0'; } else if (specType == ExShell) { - if (Job_ParseShell (line) != SUCCESS) { - Parse_Error (PARSE_FATAL, "improper shell specification"); + if (Job_ParseShell(line) != SUCCESS) { + Parse_Error(PARSE_FATAL, "improper shell specification"); return; } *line = '\0'; - } else if ((specType == NotParallel) || (specType == SingleShell)) { + } else if (specType == NotParallel || specType == SingleShell) { *line = '\0'; } /* * NOW GO FOR THE SOURCES */ - if ((specType == Suffixes) || (specType == ExPath) || - (specType == Includes) || (specType == Libs) || - (specType == Null)) - { + if (specType == Suffixes || specType == ExPath || + specType == Includes || specType == Libs || + specType == Null) { while (*line) { /* * If the target was one that doesn't take files as its sources @@ -1038,26 +1029,26 @@ ParseDoDependency (line) * has no valid suffix. */ char savec; - while (*cp && !isspace (*cp)) { + while (*cp && !isspace(*cp)) { cp++; } savec = *cp; *cp = '\0'; switch (specType) { case Suffixes: - Suff_AddSuffix (line); + Suff_AddSuffix(line); break; case ExPath: Lst_ForEach(&paths, ParseAddDir, line); break; case Includes: - Suff_AddInclude (line); + Suff_AddInclude(line); break; case Libs: - Suff_AddLib (line); + Suff_AddLib(line); break; case Null: - Suff_SetNull (line); + Suff_SetNull(line); break; default: break; @@ -1066,7 +1057,7 @@ ParseDoDependency (line) if (savec != '\0') { cp++; } - while (*cp && isspace (*cp)) { + while (*cp && isspace(*cp)) { cp++; } line = cp; @@ -1079,8 +1070,8 @@ ParseDoDependency (line) * specifications (i.e. things with left parentheses in them) * and handle them accordingly. */ - while (*cp && !isspace (*cp)) { - if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) { + while (*cp && !isspace(*cp)) { + if (*cp == '(' && cp > line && cp[-1] != '$') { /* * Only stop for a left parenthesis if it isn't at the * start of a word (that'll be for variable changes @@ -1095,19 +1086,18 @@ ParseDoDependency (line) if (*cp == '(') { GNode *gn; - LIST sources; /* list of archive source names after - * expansion */ + LIST sources; /* list of archive source names after + * expansion */ Lst_Init(&sources); if (Arch_ParseArchive(&line, &sources, NULL) != SUCCESS) { - Parse_Error (PARSE_FATAL, + Parse_Error(PARSE_FATAL, "Error in source archive spec \"%s\"", line); return; } while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL) ParseDoSrc(tOp, gn->name, &curSrcs); - Lst_Destroy(&sources, NOFREE); cp = line; } else { if (*cp) { @@ -1117,7 +1107,7 @@ ParseDoDependency (line) ParseDoSrc(tOp, line, &curSrcs); } - while (*cp && isspace (*cp)) { + while (*cp && isspace(*cp)) { cp++; } line = cp; @@ -1125,12 +1115,10 @@ ParseDoDependency (line) } if (mainNode == NULL) { - /* - * If we have yet to decide on a main target to make, in the + /* If we have yet to decide on a main target to make, in the * absence of any user input, we want the first target on * the first dependency line that is actually a real target - * (i.e. isn't a .USE or .EXEC rule) to be made. - */ + * (i.e. isn't a .USE or .EXEC rule) to be made. */ Lst_Find(&targets, ParseFindMain, NULL); } @@ -1140,7 +1128,7 @@ ParseDoDependency (line) /*- *--------------------------------------------------------------------- - * Parse_IsVar -- + * 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. @@ -1149,33 +1137,22 @@ ParseDoDependency (line) * * Results: * TRUE if it is. FALSE if it ain't - * - * Side Effects: - * none *--------------------------------------------------------------------- */ Boolean -Parse_IsVar (line) - register char *line; /* the line to check */ +Parse_IsVar(line) + char *line; /* the line to check */ { - register Boolean wasSpace = FALSE; /* set TRUE if found a space */ - register Boolean haveName = FALSE; /* Set TRUE if have a variable name */ + 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) == '!')) - - /* - * Skip to variable name - */ - for (;(*line == ' ') || (*line == '\t'); line++) - continue; + ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') for (; *line != '=' || level != 0; line++) switch (*line) { case '\0': - /* - * end-of-line -- can't be a variable assignment. - */ + /* end-of-line -- can't be a variable assignment. */ return FALSE; case ' ': @@ -1200,30 +1177,21 @@ Parse_IsVar (line) default: if (wasSpace && haveName) { if (ISEQOPERATOR(*line)) { - /* - * We must have a finished word - */ + /* We must have a finished word. */ if (level != 0) return FALSE; - /* - * When an = operator [+?!:] is found, the next + /* When an = operator [+?!:] is found, the next * character must be an = or it ain't a valid - * assignment. - */ + * assignment. */ if (line[1] == '=') return haveName; -#ifdef SUNSHCMD - /* - * This is a shell command - */ - if (strncmp(line, ":sh", 3) == 0) + /* This is a shell command. */ + if (FEATURES(FEATURE_SUNSHCMD) && + strncmp(line, ":sh", 3) == 0) return haveName; -#endif } - /* - * This is the start of another word, so not assignment. - */ + /* This is the start of another word, so not assignment. */ return FALSE; } else { @@ -1236,9 +1204,37 @@ Parse_IsVar (line) 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 -- + * Parse_DoVar -- * Take the variable assignment in the passed line and do it in the * global context. * @@ -1248,107 +1244,73 @@ Parse_IsVar (line) * C++=/usr/bin/CC * is interpreted as "C+ +=" instead of "C++ =". * - * Results: - * none - * * Side Effects: * the variable structure of the given variable name is altered in the * global context. *--------------------------------------------------------------------- */ void -Parse_DoVar (line, ctxt) - char *line; /* a line guaranteed to be a variable +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 */ + GSymT *ctxt; /* Context in which to do the assignment */ { - char *cp; /* pointer into line */ + const char *end; + const char *arg; enum { VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL - } type; /* Type of assignment */ - char *opc; /* ptr to operator character to - * null-terminate the variable name */ - /* - * Avoid clobbered variable warnings by forcing the compiler - * to ``unregister'' variables - */ -#if __GNUC__ - (void) &cp; - (void) &line; -#endif + } type; /* Type of assignment */ + struct Name name; - /* - * Skip to variable name - */ - while ((*line == ' ') || (*line == '\t')) { - line++; - } + end = Var_Name_Get(line, &name, (SymTable *)ctxt, TRUE, + FEATURES(FEATURE_SUNSHCMD) ? find_op1 : find_op2); - /* - * Skip to operator character, nulling out whitespace as we go - */ - for (cp = line + 1; *cp != '='; cp++) { - if (isspace (*cp)) { - *cp = '\0'; - } - } - opc = cp-1; /* operator is the previous character */ - *cp++ = '\0'; /* nuke the = */ + while (isspace(*end)) + end++; - /* - * Check operator type - */ - switch (*opc) { + /* Check operator type. */ + switch (*end) { case '+': type = VAR_APPEND; - *opc = '\0'; break; case '?': - /* - * If the variable already has a value, we don't do anything. - */ - *opc = '\0'; - if (Var_Exists(line, ctxt)) { + /* 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; - } else { - type = VAR_NORMAL; } + type = VAR_NORMAL; break; case ':': type = VAR_SUBST; - *opc = '\0'; break; case '!': type = VAR_SHELL; - *opc = '\0'; break; default: -#ifdef SUNSHCMD - while (*opc != ':') - if (--opc < line) - break; - - if (strncmp(opc, ":sh", 3) == 0) { + if (FEATURES(FEATURE_SUNSHCMD) && strncmp(end, ":sh", 3) == 0) type = VAR_SHELL; - *opc = '\0'; - break; - } -#endif - type = VAR_NORMAL; + else + type = VAR_NORMAL; break; } - while (isspace (*cp)) { - cp++; - } - - if (type == VAR_APPEND) { - Var_Append (line, cp, ctxt); - } else if (type == VAR_SUBST) { + /* 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. @@ -1360,49 +1322,47 @@ Parse_DoVar (line, ctxt) * * And not get an error. */ - Boolean oldOldVars = oldVars; + Boolean oldOldVars = oldVars; oldVars = FALSE; - cp = Var_Subst(cp, (SymTable *)ctxt, 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(line, cp, ctxt); - free(cp); + Var_Set_interval(name.s, name.e, sub, ctxt); + free(sub); } else if (type == VAR_SHELL) { - Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e. - * if any variable expansion was performed */ char *res, *err; - if (strchr(cp, '$') != NULL) { - /* - * There's a dollar sign in the command, so perform variable - * expansion on the whole thing. The resulting string will need - * freeing when we're done, so set freeCmd to TRUE. - */ - cp = Var_Subst(cp, NULL, TRUE); - freeCmd = TRUE; - } - - res = Cmd_Exec(cp, &err); - Var_Set(line, res, ctxt); + 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, cp); + Parse_Error(PARSE_WARNING, err, arg); - if (freeCmd) - free(cp); - } else { - /* - * Normal assignment -- just do it. - */ - Var_Set(line, cp, ctxt); - } + } else + /* Normal assignment -- just do it. */ + Var_Set_interval(name.s, name.e, arg, ctxt); + Var_Name_Free(&name); } /*- - * ParseAddCmd -- + * ParseAddCmd -- * Lst_ForEach function to add a command line to all targets * * Side Effects: @@ -1432,19 +1392,15 @@ ParseAddCmd(gnp, cmd) * having commands if it does, to keep from having shell commands * on multiple dependency lines. * - * Results: - * None - * * Side Effects: * OP_HAS_COMMANDS may be set for the target. - * *----------------------------------------------------------------------- */ static void ParseHasCommands(gnp) void *gnp; /* Node to examine */ { - GNode *gn = (GNode *) gnp; + GNode *gn = (GNode *)gnp; if (!Lst_IsEmpty(&gn->commands)) { gn->type |= OP_HAS_COMMANDS; } @@ -1455,18 +1411,11 @@ ParseHasCommands(gnp) * Parse_AddIncludeDir -- * Add a directory to the path searched for included makefiles * bracketed by double-quotes. Used by functions in main.c - * - * Results: - * None. - * - * Side Effects: - * The directory is appended to the list. - * *----------------------------------------------------------------------- */ void Parse_AddIncludeDir(dir) - char *dir; /* The name of the directory to add */ + const char *dir; /* The name of the directory to add */ { Dir_AddDir(&parseIncPath, dir, NULL); } @@ -1482,24 +1431,24 @@ Parse_AddIncludeDir(dir) * options * * Side Effects: - * old parse context is pushed on the stack, new file becomes + * old parse context is pushed on the stack, new file becomes * current context. *--------------------------------------------------------------------- */ static void ParseDoInclude(file) - char *file; /* file specification */ + char *file; /* file specification */ { - 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 */ + 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 */ - /* Skip to delimiter character so we know where to look */ + /* Skip to delimiter character so we know where to look. */ while (*file == ' ' || *file == '\t') file++; if (*file != '"' && *file != '<') { - Parse_Error (PARSE_FATAL, + Parse_Error(PARSE_FATAL, ".include filename must be delimited by '\"' or '<'"); return; } @@ -1515,19 +1464,18 @@ ParseDoInclude(file) endc = '"'; } - /* Skip to matching delimiter */ - for (cp = ++file; *cp && *cp != endc; cp++) { - if (*cp == '\0') { + /* Skip to matching delimiter. */ + for (cp = ++file; *cp != endc; cp++) { + if (*cp == '\0') { Parse_Error(PARSE_FATAL, "Unclosed %cinclude filename. '%c' expected", '.', endc); return; } } - ParseLookupIncludeFile(file, cp, isSystem); + ParseLookupIncludeFile(file, cp, isSystem, TRUE); } -#ifdef SYSVINCLUDE /*- *--------------------------------------------------------------------- * ParseTraditionalInclude -- @@ -1537,47 +1485,77 @@ ParseDoInclude(file) * the string following the "include". * * Side Effects: - * old parse context is pushed on the stack, new file becomes + * old parse context is pushed on the stack, new file becomes * current context. + * + * XXX May wish to support multiple files and wildcards ? *--------------------------------------------------------------------- */ static void ParseTraditionalInclude(file) - char *file; /* file specification */ + char *file; /* file specification */ { - char *cp; /* current position in file spec */ + char *cp; /* current position in file spec */ - /* Skip over whitespace */ - while (*file == ' ' || *file == '\t') + /* Skip over whitespace. */ + while (isspace(*file)) file++; - if (*file == '\0') { - Parse_Error (PARSE_FATAL, + Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); return; } + /* Skip to end of line or next whitespace. */ + for (cp = file; *cp != '\0' && !isspace(*cp);) + cp++; + + ParseLookupIncludeFile(file, cp, TRUE, TRUE); +} - /* Skip to end of line or next whitespace */ +/*- + *--------------------------------------------------------------------- + * ParseConditionalInclude -- + * May push to another file. + * + * No error if the file does not exist. + * See ParseTraditionalInclude otherwise. + *--------------------------------------------------------------------- + */ +static void +ParseConditionalInclude(file) + char *file; /* file specification */ +{ + char *cp; /* current position in file spec */ + + /* Skip over whitespace. */ + while (isspace(*file)) + file++; + if (*file == '\0') { + Parse_Error(PARSE_FATAL, + "Filename missing from \"include\""); + return; + } + /* Skip to end of line or next whitespace. */ for (cp = file; *cp != '\0' && !isspace(*cp);) - cp++; + cp++; - ParseLookupIncludeFile(file, cp, TRUE); + ParseLookupIncludeFile(file, cp, TRUE, FALSE); } -#endif /* Common part to lookup and read an include file. */ static void -ParseLookupIncludeFile(spec, endSpec, isSystem) +ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound) char *spec; char *endSpec; Boolean isSystem; + Boolean errIfNotFound; { char *file; char *fullname; char endc; /* Substitute for any variables in the file name before trying to - * find the thing. */ + * find the thing. */ endc = *endSpec; *endSpec = '\0'; file = Var_Subst(spec, NULL, FALSE); @@ -1590,11 +1568,11 @@ ParseLookupIncludeFile(spec, endSpec, isSystem) /* Handle non-system non-absolute files... */ if (!isSystem && file[0] != '/') { - /* ... by first searching relative to the including file's - * location. We don't want to cd there, of course, so we - * just tack on the old file's leading path components + /* ... by first searching relative to the including file's + * 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; slash = strrchr(Parse_Getfilename(), '/'); if (slash != NULL) { @@ -1610,10 +1588,10 @@ ParseLookupIncludeFile(spec, endSpec, isSystem) } } - /* Now look first on the -I search path, then on the .PATH + /* Now look first on the -I search path, then on the .PATH * search path, if not found in a -I directory. * XXX: Suffix specific? */ - if (fullname == NULL) + if (fullname == NULL) fullname = Dir_FindFile(file, &parseIncPath); if (fullname == NULL) fullname = Dir_FindFile(file, &dirSearchPath); @@ -1623,48 +1601,167 @@ ParseLookupIncludeFile(spec, endSpec, isSystem) if (fullname == NULL) fullname = Dir_FindFile(file, &sysIncPath); - if (fullname == NULL) - Parse_Error(PARSE_FATAL, "Could not find %s", file); + if (fullname == NULL && errIfNotFound) + Parse_Error(PARSE_FATAL, "Could not find %s", file); + free(file); if (fullname != NULL) { - FILE *f; + FILE *f; f = fopen(fullname, "r"); - if (f == NULL) { + if (f == NULL && errIfNotFound) { Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); } else { /* Once we find the absolute path to the file, we push the current * stream to the includes stack, and start reading from the new * file. We set up the file name to be its absolute name so that - * error messages are informative. */ + * error messages are informative. */ Parse_FromFile(fullname, f); } } } + + + +/* Strip comments from the line. May return either a copy of the line, or + * the line itself. */ +static char * +strip_comments(copy, line) + Buffer copy; + const char *line; +{ + const char *comment; + const char *p; + + comment = strchr(line, '#'); + assert(comment != line); + if (comment == NULL) + return (char *)line; + else { + Buf_Reset(copy); + + for (p = line; *p != '\0'; p++) { + if (*p == '\\') { + if (p[1] == '#') { + Buf_AddInterval(copy, line, p); + Buf_AddChar(copy, '#'); + line = p+2; + } + if (p[1] != '\0') + p++; + } else if (*p == '#') + break; + } + Buf_AddInterval(copy, line, p); + Buf_KillTrailingSpaces(copy); + return Buf_Retrieve(copy); + } +} + +static Boolean +ParseIsCond(linebuf, copy, line) + Buffer linebuf; + Buffer copy; + char *line; +{ + + char *stripped; + + while (*line != '\0' && isspace(*line)) + line++; + + /* The line might be a conditional. Ask the conditional module + * about it and act accordingly. */ + switch (Cond_Eval(line)) { + case COND_SKIP: + /* Skip to next conditional that evaluates to COND_PARSE. */ + do { + line = ParseSkipGetLine(linebuf); + if (line != NULL) { + while (*line != '\0' && isspace(*line)) + line++; + stripped = strip_comments(copy, line); + } + } while (line != NULL && Cond_Eval(stripped) != COND_PARSE); + /* FALLTHROUGH */ + case COND_PARSE: + return TRUE; + default: + break; + } + + { + For *loop; + + loop = For_Eval(line); + if (loop != NULL) { + Boolean ok; + do { + /* Find the matching endfor. */ + line = ParseGetLoopLine(linebuf); + if (line == NULL) { + Parse_Error(PARSE_FATAL, + "Unexpected end of file in for loop.\n"); + return FALSE; + } + ok = For_Accumulate(loop, line); + } while (ok); + For_Run(loop); + return TRUE; + } + } + + if (strncmp(line, "include", 7) == 0) { + ParseDoInclude(line + 7); + return TRUE; + } else if (strncmp(line, "undef", 5) == 0) { + char *cp; + + line+=5; + while (*line != '\0' && isspace(*line)) + line++; + for (cp = line; !isspace(*cp) && *cp != '\0';) + cp++; + *cp = '\0'; + Var_Delete(line); + return TRUE; + } + return FALSE; +} + /*- *----------------------------------------------------------------------- - * ParseFinishLine -- + * ParseFinishDependency -- * Handle the end of a dependency group. * * Side Effects: - * inLine set FALSE. 'targets' list destroyed. + * 'targets' list destroyed. * *----------------------------------------------------------------------- */ static void -ParseFinishLine() +ParseFinishDependency() { - if (inLine) { - Lst_Every(&targets, Suff_EndTransform); - Lst_Destroy(&targets, ParseHasCommands); - Lst_Init(&targets); - inLine = FALSE; - } + Lst_Every(&targets, Suff_EndTransform); + Lst_Destroy(&targets, ParseHasCommands); } +static void +ParseDoCommands(line) + const char *line; +{ + /* add the command to the list of + * commands of all targets in the dependency spec */ + char *cmd = estrdup(line); + + Lst_ForEach(&targets, ParseAddCmd, cmd); +#ifdef CLEANUP + Lst_AtEnd(&targCmds, cmd); +#endif +} /*- *--------------------------------------------------------------------- @@ -1673,9 +1770,6 @@ ParseFinishLine() * current dependency graph. This is the main function and controls * almost every other function in this module * - * Results: - * None - * * Side Effects: * Loads. Nodes are added to the list of all targets, nodes and links * are added to the dependency graph. etc. etc. etc. @@ -1683,160 +1777,109 @@ ParseFinishLine() */ void Parse_File(name, stream) - char *name; /* the name of the file being read */ - FILE * stream; /* Stream open to makefile to parse */ + char *name; /* the name of the file being read */ + FILE *stream; /* Stream open to makefile to parse */ { - register char *cp, /* pointer into the line */ - *line; /* the line we're working on */ - - inLine = FALSE; - Parse_FromFile(name, stream); - do { - while ((line = ParseReadLine ()) != NULL) { - if (*line == '.') { - /* - * Lines that begin with the special character are either - * include or undef directives. - */ - for (cp = line + 1; isspace (*cp); cp++) { - continue; - } - if (strncmp (cp, "include", 7) == 0) { - ParseDoInclude (cp + 7); - goto nextLine; - } else if (strncmp(cp, "undef", 5) == 0) { - char *cp2; - for (cp += 5; isspace((unsigned char) *cp); cp++) { - continue; - } + char *cp, /* pointer into the line */ + *line; /* the line we're working on */ + Boolean inDependency; /* true if currently in a dependency + * line or its commands */ - for (cp2 = cp; !isspace((unsigned char) *cp2) && - (*cp2 != '\0'); cp2++) { - continue; - } - - *cp2 = '\0'; + BUFFER buf; + BUFFER copy; - Var_Delete(cp, VAR_GLOBAL); - goto nextLine; - } - } - if (*line == '#') { - /* If we're this far, the line must be a comment. */ - goto nextLine; - } + Buf_Init(&buf, MAKE_BSIZE); + Buf_Init(©, MAKE_BSIZE); + inDependency = FALSE; + Parse_FromFile(name, stream); + do { + while ((line = ParseReadLine(&buf)) != NULL) { if (*line == '\t') { - /* - * If a line starts with a tab, it can only hope to be - * a creation command. - */ -#ifndef POSIX - shellCommand: -#endif - for (cp = line + 1; isspace (*cp); cp++) { - continue; - } - if (*cp) { - if (inLine) { - /* - * So long as it's not a blank line and we're actually - * in a dependency spec, add the command to the list of - * commands of all targets in the dependency spec - */ - Lst_ForEach(&targets, ParseAddCmd, cp); -#ifdef CLEANUP - Lst_AtEnd(&targCmds, line); -#endif - continue; - } else { - Parse_Error (PARSE_FATAL, - "Unassociated shell command \"%s\"", - cp); - } - } -#ifdef SYSVINCLUDE - } else if (strncmp (line, "include", 7) == 0 && - isspace((unsigned char) line[7]) && - strchr(line, ':') == NULL) { - /* - * It's an S3/S5-style "include". - */ - ParseTraditionalInclude (line + 7); - goto nextLine; -#endif - } else if (Parse_IsVar (line)) { - ParseFinishLine(); - Parse_DoVar (line, VAR_GLOBAL); + if (inDependency) + ParseDoCommands(line+1); + else + Parse_Error(PARSE_FATAL, + "Unassociated shell command \"%s\"", + line); } else { - /* - * We now know it's a dependency line so it needs to have all - * variables expanded before being parsed. Tell the variable - * module to complain if some variable is undefined... - * To make life easier on novices, if the line is indented we - * first make sure the line has a dependency operator in it. - * If it doesn't have an operator and we're in a dependency - * line's script, we assume it's actually a shell command - * and add it to the current list of targets. - */ -#ifndef POSIX - Boolean nonSpace = FALSE; -#endif - - cp = line; - if (isspace((unsigned char) line[0])) { - while ((*cp != '\0') && isspace((unsigned char) *cp)) { - cp++; - } - if (*cp == '\0') { - goto nextLine; - } -#ifndef POSIX - while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) { - nonSpace = TRUE; - cp++; - } -#endif - } - -#ifndef POSIX - if (*cp == '\0') { - if (inLine) { - Parse_Error (PARSE_WARNING, - "Shell command needs a leading tab"); - goto shellCommand; - } else if (nonSpace) { - Parse_Error (PARSE_FATAL, "Missing operator"); - } + char *stripped; + stripped = strip_comments(©, line); + if (*stripped == '.' && ParseIsCond(&buf, ©, stripped+1)) + ; + else if (FEATURES(FEATURE_SYSVINCLUDE) && + strncmp(stripped, "include", 7) == 0 && + isspace(stripped[7]) && + strchr(stripped, ':') == NULL) { + /* It's an S3/S5-style "include". */ + ParseTraditionalInclude(stripped + 7); + } else if (FEATURES(FEATURE_CONDINCLUDE) && + (*stripped == '-' || *stripped == 's') && + strncmp(stripped+1, "include", 7) == 0 && + isspace(stripped[8]) && + strchr(stripped, ':') == NULL) { + ParseConditionalInclude(stripped+8); } else { -#endif - ParseFinishLine(); - - cp = Var_Subst(line, NULL, TRUE); - free (line); - line = cp; + char *dep; - /* Need a new list for the target nodes */ - Lst_Destroy(&targets, NOFREE); - Lst_Init(&targets); - inLine = TRUE; - - ParseDoDependency (line); -#ifndef POSIX + if (inDependency) + ParseFinishDependency(); + if (Parse_IsVar(stripped)) { + inDependency = FALSE; + Parse_DoVar(stripped, VAR_GLOBAL); + } else { + size_t pos; + char *end; + + /* Need a new list for the target nodes. */ + Lst_Init(&targets); + inDependency = TRUE; + + dep = NULL; + /* First we need to find eventual dependencies */ + pos = strcspn(stripped, ":!"); + /* go over :!, and find ; */ + if (stripped[pos] != '\0' && + (end = strchr(stripped+pos+1, ';')) != NULL) { + if (line != stripped) + /* find matching ; in original... The + * original might be slightly longer. */ + dep = strchr(line+(end-stripped), ';'); + else + dep = end; + /* kill end of line. */ + *end = '\0'; + } + /* We now know it's a dependency line so it needs to + * have all variables expanded before being parsed. + * Tell the variable module to complain if some + * variable is undefined... */ + cp = Var_Subst(stripped, NULL, TRUE); + ParseDoDependency(cp); + free(cp); + + /* Parse dependency if it's not empty. */ + if (dep != NULL) { + do { + dep++; + } while (isspace(*dep)); + if (*dep != '\0') + ParseDoCommands(dep); + } + } } -#endif } - - nextLine: - - free (line); } } while (Parse_NextFile()); - /* Make sure conditionals are clean */ + if (inDependency) + ParseFinishDependency(); + /* Make sure conditionals are clean. */ Cond_End(); Finish_Errors(); + Buf_Destroy(&buf); + Buf_Destroy(©); } /*- @@ -1868,7 +1911,7 @@ Parse_End() #ifdef CLEANUP Lst_Destroy(&targCmds, (SimpleProc)free); Lst_Destroy(&fileNames, (SimpleProc)free); - Lst_Delete(&targets, NOFREE); + Lst_Destroy(&targets, NOFREE); Lst_Destroy(&sysIncPath, Dir_Destroy); Lst_Destroy(&parseIncPath, Dir_Destroy); LowParse_End(); @@ -1882,23 +1925,23 @@ Parse_End() * 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 Effects: + * Side effect: * Add the node to create to the list. - * *----------------------------------------------------------------------- */ void Parse_MainName(listmain) - Lst listmain; /* result list */ + Lst listmain; /* result list */ { - if (mainNode == NULL) - Punt ("no target to make."); - /*NOTREACHED*/ - else if (mainNode->type & OP_DOUBLEDEP) { + if (mainNode == NULL) { + Punt("no target to make."); + /*NOTREACHED*/ + } else if (mainNode->type & OP_DOUBLEDEP) { Lst_AtEnd(listmain, mainNode); Lst_Concat(listmain, &mainNode->cohorts); } else Lst_AtEnd(listmain, mainNode); } + diff --git a/usr.bin/make/pathnames.h b/usr.bin/make/pathnames.h index e21f8e31e26..2649cac31fc 100644 --- a/usr.bin/make/pathnames.h +++ b/usr.bin/make/pathnames.h @@ -1,4 +1,5 @@ -/* $OpenBSD: pathnames.h,v 1.7 1998/12/05 00:06:29 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: pathnames.h,v 1.8 2001/05/03 13:41:09 espie Exp $ */ /* $NetBSD: pathnames.h,v 1.6 1996/11/06 17:59:21 christos Exp $ */ /* @@ -37,17 +38,17 @@ */ #ifndef _PATH_OBJDIR -#define _PATH_OBJDIR "obj" +#define _PATH_OBJDIR "obj" #endif /* !_PATH_OBJDIR */ #ifndef _PATH_OBJDIRPREFIX -#define _PATH_OBJDIRPREFIX "/usr/obj" +#define _PATH_OBJDIRPREFIX "/usr/obj" #endif /* !_PATH_OBJDIRPREFIX */ #ifndef _PATH_DEFSHELLDIR -#define _PATH_DEFSHELLDIR "/bin" +#define _PATH_DEFSHELLDIR "/bin" #endif /* !_PATH_DEFSHELLDIR */ #ifndef _PATH_DEFSYSMK -#define _PATH_DEFSYSMK "sys.mk" +#define _PATH_DEFSYSMK "sys.mk" #endif /* ! _PATH_DEFSYSMK */ #ifndef _PATH_DEFSYSPATH -#define _PATH_DEFSYSPATH "/usr/share/mk" +#define _PATH_DEFSYSPATH "/usr/share/mk" #endif /* ! _PATH_DEFSYSPATH */ diff --git a/usr.bin/make/regress.c b/usr.bin/make/regress.c index 60fe9072382..0a12f90f2f9 100644 --- a/usr.bin/make/regress.c +++ b/usr.bin/make/regress.c @@ -1,10 +1,11 @@ -/* $OpenBSD: regress.c,v 1.2 2000/07/17 23:03:50 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: regress.c,v 1.3 2001/05/03 13:41:10 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. * * Code written for the OpenBSD project. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,19 +32,19 @@ #include "make.h" #include <stdio.h> -int main __P((void)); +int main(void); #define CHECK(s) \ do { \ printf("%-65s", #s); \ if (s) \ - printf("ok\n"); \ + printf("ok\n"); \ else { \ - printf("failed\n"); \ + printf("failed\n"); \ errors++; \ } \ } while (0); -int +int main() { unsigned int errors = 0; diff --git a/usr.bin/make/sprite.h b/usr.bin/make/sprite.h index 3bc56c7ff80..c64799acec2 100644 --- a/usr.bin/make/sprite.h +++ b/usr.bin/make/sprite.h @@ -1,4 +1,5 @@ -/* $OpenBSD: sprite.h,v 1.9 2000/09/14 13:32:07 espie Exp $ */ +/* $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 $ */ /* @@ -55,7 +56,7 @@ typedef int Boolean; #endif typedef int ReturnStatus; -#define SUCCESS 0 +#define SUCCESS 0 #define FAILURE 1 #endif /* _SPRITE */ diff --git a/usr.bin/make/stats.c b/usr.bin/make/stats.c new file mode 100644 index 00000000000..6a97d807d55 --- /dev/null +++ b/usr.bin/make/stats.c @@ -0,0 +1,167 @@ +/* $OpenPackages$ */ +/* $OpenBSD: stats.c,v 1.1 2001/05/03 13:41:10 espie Exp $ */ + +/* + * Copyright (c) 1999 Marc Espie. + * + * Code written for the OpenBSD project. + * + * 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. + */ + + +/* statistics gathering */ + +/* collection across make invocations is done with an mmap shared file, + to allow for concurrent adjustment to variables. + */ + +#include "make.h" +#include "stats.h" + +#ifdef HAS_STATS +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/resource.h> + +static void print_stats(void); +void Init_Stats(void); +static float average_runs(unsigned long val); +unsigned long *statarray; + +static Boolean mmapped = FALSE; + +static float +average_runs(val) + unsigned long val; +{ + return (float)val / STAT_INVOCATIONS; +} + +static void +print_stats() +{ + struct rusage ru; + + if (getrusage(RUSAGE_SELF, &ru) != -1) { + STAT_USER_SECONDS += ru.ru_utime.tv_sec; + STAT_USER_MS += ru.ru_utime.tv_usec; + if (STAT_USER_MS > 1000000) { + STAT_USER_MS -= 1000000; + STAT_USER_SECONDS++; + } + STAT_SYS_SECONDS += ru.ru_stime.tv_sec; + STAT_SYS_MS += ru.ru_stime.tv_usec; + if (STAT_SYS_MS > 1000000) { + STAT_SYS_MS -= 1000000; + STAT_SYS_SECONDS++; + } + } + fprintf(stderr, "Make runs: %lu\n", STAT_INVOCATIONS); + fprintf(stderr, "Time user: %lu.%06lu, sys %lu.%06lu\n", + STAT_USER_SECONDS, STAT_USER_MS, + STAT_SYS_SECONDS, STAT_SYS_MS); +#ifdef STATS_VAR_LOOKUP + /* to get the average total of MAXSIZE, we need this value */ + STAT_VAR_POWER += + STAT_VAR_HASH_MAXSIZE * STAT_VAR_HASH_CREATION; + fprintf(stderr, "Var finds: %f, lookups: %f, average: %f, max: %lu\n", + average_runs(STAT_VAR_FIND), + average_runs(STAT_VAR_SEARCHES), + (float)STAT_VAR_COUNT/STAT_VAR_SEARCHES, + STAT_VAR_MAXCOUNT); + fprintf(stderr, "Average hash: %f, creation: %f, from env %f\n", + average_runs(STAT_VAR_HASH_CREATION), + average_runs(STAT_VAR_CREATION), + average_runs(STAT_VAR_FROM_ENV)); + fprintf(stderr, "Local hash max: %lu, global hash max: %lu, average local: %f\n", + STAT_VAR_HASH_MAXSIZE, + STAT_VAR_GHASH_MAXSIZE, + (float)STAT_VAR_POWER/STAT_VAR_HASH_CREATION); +#endif +#ifdef STATS_GN_CREATION + fprintf(stderr, "Average GN: %f\n", average_runs(STAT_GN_COUNT)); +#endif +#ifdef STATS_BUF + fprintf(stderr, "Buf tot: %f, def: %f, exp %f, weird %f, bad %f\n", + average_runs(STAT_TOTAL_BUFS), + average_runs(STAT_DEFAULT_BUFS), + average_runs(STAT_BUFS_EXPANSION), + average_runs(STAT_WEIRD_BUFS), + average_runs(STAT_WEIRD_INEFFICIENT)); +#endif +#ifdef STATS_HASH + fprintf(stderr, "Hashes new: %f, exp: %f, lookup %f, l: %f, +: %f, ent : %f\n", + average_runs(STAT_HASH_CREATION), + average_runs(STAT_HASH_EXPAND), + average_runs(STAT_HASH_LOOKUP), + (float)STAT_HASH_LENGTH/STAT_HASH_LOOKUP, + (float)STAT_HASH_POSITIVE/STAT_HASH_LOOKUP, + (float)STAT_HASH_ENTRIES/STAT_HASH_SIZE); +#endif + if (mmapped) + munmap(statarray, STAT_NUMBER * sizeof(unsigned long)); +} + +void +Init_Stats() +{ + char *name; + int fd; + + /* try to get ahold of a stats collecting file */ + name = getenv("MAKESTATS"); + if (name) { + while ((fd = open(name, O_RDWR)) == -1) { + /* if collecting file does not already exist, fill it with + * zeros (so all stats starting values should be 0) */ + unsigned long n; + int i; + FILE *f; + + f = fopen(name, "w"); + + n = 0; + for (i = 0; i < STAT_NUMBER; i++) + fwrite(&n, sizeof(unsigned long), 1, f); + fclose(f); + } + + /* either we've got the file -> share it across makes */ + if (fd) { + statarray = mmap(0, STAT_NUMBER * sizeof(unsigned long), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (statarray == MAP_FAILED) + exit(1); + mmapped = TRUE; + } + } else + /* or we don't -> simple stats gathering */ + statarray = emalloc(sizeof(unsigned long) * STAT_NUMBER); + STAT_INVOCATIONS++; + atexit(print_stats); +} + +#endif + diff --git a/usr.bin/make/stats.h b/usr.bin/make/stats.h new file mode 100644 index 00000000000..546e68fad77 --- /dev/null +++ b/usr.bin/make/stats.h @@ -0,0 +1,74 @@ +/* $OpenPackages$ */ +/* $OpenBSD: stats.h,v 1.1 2001/05/03 13:41:11 espie Exp $ */ + +/* + * Copyright (c) 1999 Marc Espie. + * + * Code written for the OpenBSD project. + * + * 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. + */ + +/* statistical information gathering */ + +#if defined(STATS_VAR_LOOKUP) || \ + defined(STATS_GN_CREATION) || \ + defined(STATS_BUF) || \ + defined(STATS_HASH) +#define HAS_STATS +#endif + +#ifdef HAS_STATS +extern unsigned long *statarray; +#define STAT_INVOCATIONS statarray[0] +#define STAT_VAR_SEARCHES statarray[1] +#define STAT_VAR_COUNT statarray[2] +#define STAT_VAR_MAXCOUNT statarray[3] +#define STAT_GN_COUNT statarray[4] +#define STAT_TOTAL_BUFS statarray[5] +#define STAT_DEFAULT_BUFS statarray[6] +#define STAT_WEIRD_BUFS statarray[7] +#define STAT_BUFS_EXPANSION statarray[8] +#define STAT_WEIRD_INEFFICIENT statarray[9] +#define STAT_VAR_HASH_CREATION statarray[10] +#define STAT_VAR_FROM_ENV statarray[11] +#define STAT_VAR_CREATION statarray[12] +#define STAT_VAR_FIND statarray[13] +#define STAT_HASH_CREATION statarray[14] +#define STAT_HASH_ENTRIES statarray[15] +#define STAT_HASH_EXPAND statarray[16] +#define STAT_HASH_LOOKUP statarray[17] +#define STAT_HASH_LENGTH statarray[18] +#define STAT_HASH_SIZE statarray[19] +#define STAT_HASH_POSITIVE statarray[20] +#define STAT_USER_SECONDS statarray[21] +#define STAT_USER_MS statarray[22] +#define STAT_SYS_SECONDS statarray[23] +#define STAT_SYS_MS statarray[24] +#define STAT_VAR_HASH_MAXSIZE statarray[25] +#define STAT_VAR_GHASH_MAXSIZE statarray[26] +#define STAT_VAR_POWER statarray[27] + +#define STAT_NUMBER 30 + +#endif + diff --git a/usr.bin/make/str.c b/usr.bin/make/str.c index 2490b4dd90b..d51f0cc6e29 100644 --- a/usr.bin/make/str.c +++ b/usr.bin/make/str.c @@ -1,4 +1,5 @@ -/* $OpenBSD: str.c,v 1.16 2000/09/14 13:35:38 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: str.c,v 1.17 2001/05/03 13:41:11 espie Exp $ */ /* $NetBSD: str.c,v 1.13 1996/11/06 17:59:23 christos Exp $ */ /*- @@ -43,31 +44,31 @@ #ifndef lint #if 0 -static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90"; +static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90"; #else UNUSED -static char rcsid[] = "$OpenBSD: str.c,v 1.16 2000/09/14 13:35:38 espie Exp $"; +static char rcsid[] = "$OpenBSD: str.c,v 1.17 2001/05/03 13:41:11 espie Exp $"; #endif #endif /* not lint */ /*- - * str_concat -- + * str_concati -- * concatenate the two strings, possibly inserting a separator * * returns -- * the resulting string in allocated space. */ char * -str_concat(s1, s2, sep) - const char *s1, *s2; - char sep; +str_concati(s1, s2, e2, sep) + const char *s1, *s2, *e2; + int sep; { size_t len1, len2; char *result; /* get the length of both strings */ len1 = strlen(s1); - len2 = strlen(s2); + len2 = e2 - s2; /* space for separator */ if (sep) @@ -78,7 +79,7 @@ str_concat(s1, s2, sep) memcpy(result, s1, len1); /* add separator character */ - if (sep) + if (sep) result[len1-1] = sep; /* copy second string plus EOS into place */ @@ -93,130 +94,117 @@ str_concat(s1, s2, sep) * are ignored. * * returns -- - * Pointer to the array of pointers to the words. To make life easier, + * Pointer to the array of pointers to the words. To make life easier, * the first word is always the value of the .MAKE variable. */ char ** -brk_string(str, store_argc, expand, buffer) - const char *str; - int *store_argc; - Boolean expand; - char **buffer; +brk_string(str, store_argc, buffer) + const char *str; + int *store_argc; + char **buffer; { - register int argc, ch; - char inquote; - const char *p; - char *start, *t; - size_t len; - int argmax = 50; - size_t curlen = 0; - char **argv = (char **)emalloc((argmax + 1) * sizeof(char *)); - - /* skip leading space chars. */ - for (; *str == ' ' || *str == '\t'; ++str) - continue; - - /* allocate room for a copy of the string */ - if ((len = strlen(str) + 1) > curlen) - *buffer = emalloc(curlen = len); - - /* - * copy the string; at the same time, parse backslashes, - * quotes and build the argument list. - */ - argc = 0; - inquote = '\0'; - for (p = str, start = t = *buffer;; ++p) { - switch(ch = *p) { - case '"': - case '\'': - if (inquote) { - if (inquote == ch) - inquote = '\0'; - else - break; - } else { - inquote = (char) ch; - /* Don't miss "" or '' */ - if (start == NULL && p[1] == inquote) { - start = t + 1; - break; - } - } - if (!expand) { - if (!start) - start = t; - *t++ = ch; - } - continue; - case ' ': - case '\t': - case '\n': - if (inquote) - break; - if (!start) - continue; - /* FALLTHROUGH */ - case '\0': - /* - * end of a token -- make sure there's enough argv - * space and save off a pointer. - */ - if (!start) - goto done; - - *t++ = '\0'; - if (argc == argmax) { - argmax *= 2; /* ramp up fast */ - argv = (char **)erealloc(argv, - (argmax + 1) * sizeof(char *)); - } - argv[argc++] = start; - start = (char *)NULL; - if (ch == '\n' || ch == '\0') - goto done; - continue; - case '\\': - if (!expand) { - if (!start) - start = t; - *t++ = '\\'; - ch = *++p; - break; - } - - switch (ch = *++p) { - case '\0': - case '\n': - /* hmmm; fix it up as best we can */ - ch = '\\'; - --p; - break; - case 'b': - ch = '\b'; - break; - case 'f': - ch = '\f'; - break; - case 'n': - ch = '\n'; - break; - case 'r': - ch = '\r'; - break; - case 't': - ch = '\t'; - break; - } - break; + int argc; + char ch; + char inquote; + const char *p; + char *start, *t; + size_t len; + int argmax = 50; + size_t curlen = 0; + char **argv = emalloc((argmax + 1) * sizeof(char *)); + + /* skip leading space chars. */ + for (; *str == ' ' || *str == '\t'; ++str) + continue; + + /* allocate room for a copy of the string */ + if ((len = strlen(str) + 1) > curlen) + *buffer = emalloc(curlen = len); + + /* + * copy the string; at the same time, parse backslashes, + * quotes and build the argument list. + */ + argc = 0; + inquote = '\0'; + for (p = str, start = t = *buffer;; ++p) { + switch (ch = *p) { + case '"': + case '\'': + if (inquote) { + if (inquote == ch) + inquote = '\0'; + else + break; + } else { + inquote = ch; + /* Don't miss "" or '' */ + if (start == NULL && p[1] == inquote) { + start = t + 1; + break; } - if (!start) - start = t; - *t++ = (char) ch; + } + continue; + case ' ': + case '\t': + case '\n': + if (inquote) + break; + if (!start) + continue; + /* FALLTHROUGH */ + case '\0': + /* + * end of a token -- make sure there's enough argv + * space and save off a pointer. + */ + if (!start) + goto done; + + *t++ = '\0'; + if (argc == argmax) { + argmax *= 2; /* ramp up fast */ + argv = erealloc(argv, (argmax + 1) * sizeof(char *)); + } + argv[argc++] = start; + start = NULL; + if (ch == '\n' || ch == '\0') + goto done; + continue; + case '\\': + switch (ch = *++p) { + case '\0': + case '\n': + /* hmmm; fix it up as best we can */ + ch = '\\'; + --p; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + } + break; } -done: argv[argc] = (char *)NULL; - *store_argc = argc; - return(argv); + if (!start) + start = t; + *t++ = ch; + } +done: + argv[argc] = NULL; + *store_argc = argc; + return argv; } /* Iterate through a string word by word, @@ -230,45 +218,45 @@ done: argv[argc] = (char *)NULL; */ const char * iterate_words(end) - const char **end; + const char **end; { - const char *start, *p; + const char *start, *p; char state = 0; start = *end; while (isspace(*start)) - start++; + start++; if (*start == '\0') - return NULL; + return NULL; for (p = start;; p++) - switch(*p) { + switch(*p) { case '\\': - if (p[1] != '\0') + if (p[1] != '\0') p++; break; case '\'': case '"': - if (state == *p) + if (state == *p) state = 0; else if (state == 0) state = *p; break; case ' ': case '\t': - if (state != 0) + if (state != 0) break; - /* FALLTHROUGH */ + /* FALLTHROUGH */ case '\0': - *end = p; + *end = p; return start; default: - break; + break; } } - + /* - * Str_Match -- + * Str_Matchi -- * * See if a particular string matches a particular pattern. * @@ -277,11 +265,12 @@ iterate_words(end) * pattern: *?\[] (see the man page for details on what these mean). */ Boolean -Str_Match(string, pattern) - const char *string; /* String */ +Str_Matchi(string, pattern, end) + const char *string; /* String */ const char *pattern; /* Pattern */ + const char *end; /* End of Pattern */ { - while (*pattern != '\0') { + while (pattern != end) { /* Check for a "*" as the next pattern character. It matches * any substring. We handle this by calling ourselves * recursively for each postfix of string, until either we @@ -290,7 +279,7 @@ Str_Match(string, pattern) pattern++; /* Skip over contiguous sequences of `?*', so that recursive * calls only occur on `real' characters. */ - while (*pattern == '?' || *pattern == '*') { + while (pattern != end && (*pattern == '?' || *pattern == '*')) { if (*pattern == '?') { if (*string == '\0') return FALSE; @@ -299,35 +288,35 @@ Str_Match(string, pattern) } pattern++; } - if (*pattern == '\0') + if (pattern == end) return TRUE; for (; *string != '\0'; string++) - if (Str_Match(string, pattern)) + if (Str_Matchi(string, pattern, end)) return TRUE; return FALSE; - } else if (*string == '\0') + } else if (*string == '\0') 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 == '\0') - return FALSE; + if (pattern == end) + return FALSE; if (*pattern == '!' || *pattern == '^') { pattern++; - if (*pattern == '\0') + if (pattern == end) return FALSE; /* Negative match */ for (;;) { if (*pattern == '\\') { - if (*++pattern == '\0') + if (++pattern == end) return FALSE; } if (*pattern == *string) return FALSE; if (pattern[1] == '-') { - if (pattern[2] == '\0') + if (pattern + 2 == end) return FALSE; if (*pattern < *string && *string <= pattern[2]) return FALSE; @@ -336,23 +325,23 @@ Str_Match(string, pattern) pattern += 3; } else pattern++; - if (*pattern == '\0') - return FALSE; + if (pattern == end) + return FALSE; /* The test for ']' is done at the end so that ']' * can be used at the start of the range without '\' */ if (*pattern == ']') - break; + break; } } else { for (;;) { if (*pattern == '\\') { - if (*++pattern == '\0') + if (++pattern == end) return FALSE; } if (*pattern == *string) break; if (pattern[1] == '-') { - if (pattern[2] == '\0') + if (pattern + 2 == end) return FALSE; if (*pattern < *string && *string <= pattern[2]) break; @@ -363,15 +352,15 @@ Str_Match(string, pattern) pattern++; /* The test for ']' is done at the end so that ']' * can be used at the start of the range without '\' */ - if (*pattern == '\0' || *pattern == ']') - return FALSE; + if (pattern == end || *pattern == ']') + return FALSE; } /* Found matching character, skip over rest of class. */ while (*pattern != ']') { if (*pattern == '\\') pattern++; - /* A non-terminated character class is ok. */ - if (*pattern == '\0') + /* A non-terminated character class is ok. */ + if (pattern == end) break; pattern++; } @@ -382,10 +371,10 @@ Str_Match(string, pattern) /* If the next pattern character is '\', just strip off the * '\' so we do exact matching on the character that follows. */ if (*pattern == '\\') { - if (*++pattern == '\0') + if (++pattern == end) return FALSE; } - /* There's no special character. Just make sure that + /* There's no special character. Just make sure that * the next characters of each string match. */ if (*pattern != *string) return FALSE; @@ -399,6 +388,7 @@ Str_Match(string, pattern) return FALSE; } + /*- *----------------------------------------------------------------------- * Str_SYSVMatch -- @@ -420,21 +410,21 @@ Str_SYSVMatch(word, pattern, len) const char *m; if (*p == '\0') { - /* Null pattern is the whole string */ + /* Null pattern is the whole string. */ *len = strlen(w); return w; } if ((m = strchr(p, '%')) != NULL) { - /* check that the prefix matches */ + /* Check that the prefix matches. */ for (; p != m && *w && *w == *p; w++, p++) continue; if (p != m) - return NULL; /* No match */ + return NULL; /* No match. */ if (*++p == '\0') { - /* No more pattern, return the rest of the string */ + /* No more pattern, return the rest of the string. */ *len = strlen(w); return w; } @@ -442,13 +432,14 @@ Str_SYSVMatch(word, pattern, len) m = w; - /* Find a matching tail */ - do + /* Find a matching tail. */ + do { if (strcmp(p, w) == 0) { *len = w - m; return m; } - while (*w++ != '\0'); + } while (*w++ != '\0'); + return NULL; } @@ -475,16 +466,16 @@ Str_SYSVSubst(buf, pat, src, len) const char *m; if ((m = strchr(pat, '%')) != NULL) { - /* Copy the prefix */ + /* Copy the prefix. */ Buf_AddInterval(buf, pat, m); - /* skip the % */ + /* Skip the %. */ pat = m + 1; } - /* Copy the pattern */ + /* Copy the pattern. */ Buf_AddChars(buf, len, src); - /* append the rest */ + /* Append the rest. */ Buf_AddString(buf, pat); } @@ -512,14 +503,14 @@ escape_dup(begin, end, set) t = s = emalloc(end - begin + 1); while (begin != end) { - if (*begin == '\\') { + if (*begin == '\\') { begin++; if (begin == end) { - *t++ = '\\'; + *t++ = '\\'; break; } - if (strchr(set, *begin) == NULL) - *t++ = '\\'; + if (strchr(set, *begin) == NULL) + *t++ = '\\'; } *t++ = *begin++; } @@ -527,3 +518,16 @@ escape_dup(begin, end, set) return s; } +char * +lastchar(s, e, c) + const char *s; + const char *e; + int c; +{ + if (s != e) + do { + if (*--e == c) + return (char *)e; + } while (e != s); + return NULL; +} diff --git a/usr.bin/make/suff.c b/usr.bin/make/suff.c index fa7f0ce20e3..42f0acf6a98 100644 --- a/usr.bin/make/suff.c +++ b/usr.bin/make/suff.c @@ -1,4 +1,5 @@ -/* $OpenBSD: suff.c,v 1.40 2000/11/24 14:27:20 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: suff.c,v 1.41 2001/05/03 13:41:11 espie Exp $ */ /* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */ /* @@ -45,53 +46,53 @@ * using suffix transformation rules * * Interface: - * Suff_Init Initialize all things to do with suffixes. + * Suff_Init Initialize all things to do with suffixes. * - * Suff_End Cleanup the module + * Suff_End Cleanup the module * - * Suff_DoPaths This function is used to make life easier - * when searching for a file according to its - * suffix. It takes the global search path, - * as defined using the .PATH: target, and appends - * its directories to the path of each of the - * defined suffixes, as specified using - * .PATH<suffix>: targets. In addition, all - * directories given for suffixes labeled as - * include files or libraries, using the .INCLUDES - * or .LIBS targets, are played with using - * Dir_MakeFlags to create the .INCLUDES and - * .LIBS global variables. + * Suff_DoPaths This function is used to make life easier + * when searching for a file according to its + * suffix. It takes the global search path, + * as defined using the .PATH: target, and appends + * its directories to the path of each of the + * defined suffixes, as specified using + * .PATH<suffix>: targets. In addition, all + * directories given for suffixes labeled as + * include files or libraries, using the .INCLUDES + * or .LIBS targets, are played with using + * Dir_MakeFlags to create the .INCLUDES and + * .LIBS global variables. * - * Suff_ClearSuffixes Clear out all the suffixes and defined - * transformations. + * Suff_ClearSuffixes Clear out all the suffixes and defined + * transformations. * - * Suff_IsTransform Return TRUE if the passed string is the lhs - * of a transformation rule. + * 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. + * Suff_AddSuffix Add the passed string as another known suffix. * - * Suff_GetPath Return the search path for the given suffix. + * Suff_GetPath Return the search path for the given suffix. * - * Suff_AddInclude Mark the given suffix as denoting an include - * file. + * Suff_AddInclude Mark the given suffix as denoting an include + * file. * - * Suff_AddLib Mark the given suffix as denoting a library. + * Suff_AddLib Mark the given suffix as denoting a library. * - * Suff_AddTransform Add another transformation to the suffix - * graph. Returns GNode suitable for framing, I - * mean, tacking commands, attributes, etc. on. + * Suff_AddTransform Add another transformation to the suffix + * graph. Returns GNode suitable for framing, I + * mean, tacking commands, attributes, etc. on. * - * Suff_SetNull Define the suffix to consider the suffix of - * any file that doesn't have a known one. + * Suff_SetNull Define the suffix to consider the suffix of + * any file that doesn't have a known one. * - * Suff_FindDeps Find implicit sources for and the location of - * a target based on its suffix. Returns the - * bottom-most node added to the graph or NULL - * if the target had no implicit sources. + * Suff_FindDeps Find implicit sources for and the location of + * a target based on its suffix. Returns the + * bottom-most node added to the graph or NULL + * if the target had no implicit sources. */ -#include <stddef.h> -#include <stdio.h> +#include <stddef.h> +#include <stdio.h> #include "make.h" #include "ohash.h" #include "dir.h" @@ -101,34 +102,34 @@ static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: suff.c,v 1.40 2000/11/24 14:27:20 espie Exp $"; +static char rcsid[] = "$OpenBSD: suff.c,v 1.41 2001/05/03 13:41:11 espie Exp $"; #endif #endif /* not lint */ -static LIST sufflist; /* Lst of suffixes */ +static LIST sufflist; /* Lst of suffixes */ #ifdef CLEANUP static LIST suffClean; /* Lst of suffixes to be cleaned */ #endif static LIST srclist; /* Lst of sources */ -static LIST transforms; /* Lst of transformation rules */ +static LIST transforms; /* Lst of transformation rules */ -static int sNum = 0; /* Counter for assigning suffix numbers */ +static int sNum = 0; /* Counter for assigning suffix numbers */ /* * Structure describing an individual suffix. */ typedef struct Suff_ { - char *name; /* The suffix itself */ - int nameLen; /* Length of the suffix */ - short flags; /* Type of suffix */ + char *name; /* The suffix itself */ + int nameLen; /* Length of the suffix */ + short flags; /* Type of suffix */ #define SUFF_INCLUDE 0x01 /* One which is #include'd */ #define SUFF_LIBRARY 0x02 /* One which contains a library */ -#define SUFF_NULL 0x04 /* The empty suffix */ - LIST searchPath; /* The path along which files of this suffix +#define SUFF_NULL 0x04 /* The empty suffix */ + LIST searchPath; /* The path along which files of this suffix * may be found */ - int sNum; /* The suffix number */ - LIST parents; /* Suffixes we have a transformation to */ - LIST children; /* Suffixes we have a transformation from */ + int sNum; /* The suffix number */ + LIST parents; /* Suffixes we have a transformation to */ + LIST children; /* Suffixes we have a transformation from */ LIST ref; /* List of lists this suffix is referenced */ } Suff; @@ -136,15 +137,15 @@ typedef struct Suff_ { * Structure used in the search for implied sources. */ typedef struct Src_ { - char *file; /* The file to look for */ - char *pref; /* Prefix from which file was formed */ - Suff *suff; /* The suffix on the file */ + char *file; /* The file to look for */ + char *pref; /* Prefix from which file was formed */ + Suff *suff; /* The suffix on the file */ struct Src_ *parent; /* The Src for which this is a source */ - GNode *node; /* The node describing the file */ - int children; /* Count of existing children (so we don't free + GNode *node; /* The node describing the file */ + int children; /* Count of existing children (so we don't free * this thing too early or never nuke it) */ #ifdef DEBUG_SRC - LIST cp; /* Debug; children list */ + LIST cp; /* Debug; children list */ #endif } Src; @@ -153,39 +154,43 @@ typedef struct Src_ { * function... */ typedef struct { - Lst l; - Src *s; + Lst l; + Src *s; } LstSrc; -static Suff *suffNull; /* The NULL suffix for this run */ -static Suff *emptySuff; /* The empty suffix required for POSIX +static Suff *suffNull; /* The NULL suffix for this run */ +static Suff *emptySuff; /* The empty suffix required for POSIX * single-suffix transformation rules */ -static char *SuffStrIsPrefix __P((char *, char *)); -static char *SuffSuffIsSuffix __P((Suff *, char *)); -static int SuffSuffIsSuffixP __P((void *, void *)); -static int SuffSuffHasNameP __P((void *, void *)); -static int SuffSuffIsPrefix __P((void *, void *)); -static int SuffGNHasNameP __P((void *, void *)); -static void SuffUnRef __P((Lst, Suff *)); -static void SuffInsert __P((Lst, Suff *)); -static void SuffRemove __P((Lst, Suff *)); -static Boolean SuffParseTransform __P((char *, Suff **, Suff **)); -static void SuffRebuildGraph __P((void *, void *)); -static void SuffAddSrc __P((void *, void *)); -static int SuffRemoveSrc __P((Lst)); -static void SuffAddLevel __P((Lst, Src *)); -static Src *SuffFindThem __P((Lst, Lst)); -static Src *SuffFindCmds __P((Src *, Lst)); -static void SuffExpandChildren __P((void *, void *)); -static Boolean SuffApplyTransform __P((GNode *, GNode *, Suff *, Suff *)); -static void SuffFindDeps __P((GNode *, Lst)); -static void SuffFindArchiveDeps __P((GNode *, Lst)); -static void SuffFindNormalDeps __P((GNode *, Lst)); -static void SuffPrintName __P((void *)); -static void SuffPrintSuff __P((void *)); -static void SuffPrintTrans __P((void *)); +static char *SuffStrIsPrefix(const char *, const char *); +static char *SuffSuffIsSuffix(Suff *, const char *); +static int SuffSuffIsSuffixP(void *, const void *); +static int SuffSuffHasNameP(void *, const void *); +static int SuffSuffIsPrefix(void *, const void *); +static int SuffGNHasNameP(void *, const void *); +static void SuffUnRef(Lst, Suff *); +#ifdef CLEANUP +static void SuffFree(void *); +#endif +static void SuffInsert(Lst, Suff *); +static Boolean SuffParseTransform(const char *, Suff **, Suff **); +static void SuffRebuildGraph(void *, void *); +static void SuffAddSrc(void *, void *); +static int SuffRemoveSrc(Lst); +static void SuffAddLevel(Lst, Src *); +static Src *SuffFindThem(Lst, Lst); +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 void SuffFindDeps(GNode *, Lst); +static void SuffFindArchiveDeps(GNode *, Lst); +static void SuffFindNormalDeps(GNode *, Lst); +static void SuffPrintName(void *); +static void SuffPrintSuff(void *); +static void SuffPrintTrans(void *); /*************** Lst Predicates ****************/ /*- @@ -195,55 +200,51 @@ static void SuffPrintTrans __P((void *)); * * Results: * NULL if it ain't, pointer to character in str after prefix if so - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static char * -SuffStrIsPrefix (pref, str) - register char *pref; /* possible prefix */ - register char *str; /* string to check */ +SuffStrIsPrefix(pref, str) + const char *pref; /* possible prefix */ + const char *str; /* string to check */ { while (*str && *pref == *str) { pref++; str++; } - return (*pref ? NULL : str); + return *pref ? NULL : (char *)str; } /*- *----------------------------------------------------------------------- * SuffSuffIsSuffix -- - * See if suff is a suffix of str. Str should point to THE END of the - * string to check. (THE END == the null byte) + * See if suff is a suffix of str. str should point to the end of the + * string to check. * * Results: - * NULL if it ain't, pointer to character in str before suffix if + * NULL if it ain't, pointer to first character of suffix in str if * it is. - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static char * -SuffSuffIsSuffix (s, str) - register Suff *s; /* possible suffix */ - char *str; /* string to examine */ +SuffSuffIsSuffix(s, str) + Suff *s; /* possible suffix */ + const char *str; /* string to examine */ { - register char *p1; /* Pointer into suffix name */ - register char *p2; /* Pointer into string being examined */ + const char *p1; /* Pointer into suffix name */ + const char *p2; /* Pointer into string being examined */ p1 = s->name + s->nameLen; p2 = str; - while (p1 >= s->name && *p1 == *p2) { + while (p1 != s->name) { p1--; p2--; + if (*p1 != *p2) + return NULL; } - return (p1 == s->name - 1 ? p2 : NULL); + return (char *)p2; } /*- @@ -254,18 +255,14 @@ SuffSuffIsSuffix (s, str) * * Results: * 0 if the suffix is the one desired, non-zero if not. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static int SuffSuffIsSuffixP(s, str) - void *s; - void *str; + void *s; + const void *str; { - return !SuffSuffIsSuffix((Suff *)s, (char *)str); + return !SuffSuffIsSuffix((Suff *)s, (const char *)str); } /*- @@ -276,17 +273,14 @@ SuffSuffIsSuffixP(s, str) * * Results: * 0 if the suffix is of the given name. non-zero otherwise. - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static int -SuffSuffHasNameP (s, sname) - void *s; /* Suffix to check */ - void *sname; /* Desired name */ +SuffSuffHasNameP(s, sname) + void *s; /* Suffix to check */ + const void *sname; /* Desired name */ { - return (strcmp ((char *) sname, ((Suff *) s)->name)); + return strcmp((const char *)sname, ((Suff *)s)->name); } /*- @@ -299,17 +293,14 @@ SuffSuffHasNameP (s, sname) * * Results: * 0 if s is a prefix of str. non-zero otherwise - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static int SuffSuffIsPrefix(s, str) - void *s; /* suffix to compare */ - void *str; /* string to examine */ + void *s; /* suffix to compare */ + const void *str; /* string to examine */ { - return SuffStrIsPrefix (((Suff *)s)->name, (char *)str) == NULL ? 1 : 0; + return SuffStrIsPrefix(((Suff *)s)->name, (const char *)str) == NULL ? 1 : 0; } /*- @@ -319,75 +310,85 @@ SuffSuffIsPrefix(s, str) * * Results: * 0 if it does. non-zero if it doesn't - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static int SuffGNHasNameP(gn, name) - void *gn; /* current node we're looking at */ - void *name; /* name we're looking for */ + void *gn; /* current node we're looking at */ + const void *name; /* name we're looking for */ { - return strcmp((char *)name, ((GNode *)gn)->name); + return strcmp((const char *)name, ((GNode *)gn)->name); } - /*********** Maintenance Functions ************/ + /*********** Maintenance Functions ************/ static void -SuffUnRef(l, s) - Lst l; - Suff *s; +SuffUnRef(l, sp) + Lst l; + Suff *sp; { - LstNode ln = Lst_Member(l, s); + LstNode ln = Lst_Member(l, sp); if (ln != NULL) Lst_Remove(l, ln); } +#ifdef CLEANUP /*- *----------------------------------------------------------------------- - * SuffRemove -- - * Remove the suffix from the list + * SuffFree -- + * Free up all memory associated with the given suffix structure. + * + * Side Effects: + * the suffix entry is detroyed *----------------------------------------------------------------------- */ static void -SuffRemove(l, s) - Lst l; - Suff *s; +SuffFree(sp) + void *sp; { - SuffUnRef(l, s); + Suff *s = (Suff *)sp; + + if (s == suffNull) + suffNull = NULL; + + if (s == emptySuff) + emptySuff = NULL; + + Lst_Destroy(&s->ref, NOFREE); + Lst_Destroy(&s->children, NOFREE); + Lst_Destroy(&s->parents, NOFREE); + Lst_Destroy(&s->searchPath, Dir_Destroy); + + free(s->name); + free(s); } - +#endif + + /*- *----------------------------------------------------------------------- * SuffInsert -- * Insert the suffix into the list keeping the list ordered by suffix * numbers. * - * Results: - * None - * * Side Effects: * The reference count of the suffix is incremented *----------------------------------------------------------------------- */ static void -SuffInsert (l, s) - Lst l; /* the list where in s should be inserted */ - Suff *s; /* the suffix to insert */ +SuffInsert(l, s) + Lst l; /* the list where in s should be inserted */ + Suff *s; /* the suffix to insert */ { - LstNode ln; /* current element in l we're examining */ - Suff *s2 = NULL; /* the suffix descriptor in this element */ + LstNode ln; /* current element in l we're examining */ + Suff *s2 = NULL; /* the suffix descriptor in this element */ - Lst_Open(l); - while ((ln = Lst_Next(l)) != NULL) { + for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) { s2 = (Suff *)Lst_Datum(ln); - if (s2->sNum >= s->sNum) { + if (s2->sNum >= s->sNum) break; - } } - Lst_Close (l); if (DEBUG(SUFF)) { printf("inserting %s(%d)...", s->name, s->sNum); } @@ -418,15 +419,12 @@ SuffInsert (l, s) * This function is called from the parse module when a * .SUFFIXES:\n line is encountered. * - * Results: - * none - * * Side Effects: * the sufflist and its graph nodes are destroyed *----------------------------------------------------------------------- */ void -Suff_ClearSuffixes () +Suff_ClearSuffixes() { #ifdef CLEANUP Lst_ConcatDestroy(&suffClean, &sufflist); @@ -446,22 +444,21 @@ Suff_ClearSuffixes () * * Side Effects: * The passed pointers are overwritten. - * *----------------------------------------------------------------------- */ static Boolean SuffParseTransform(str, srcPtr, targPtr) - char *str; /* String being parsed */ - Suff **srcPtr; /* Place to store source of trans. */ - Suff **targPtr; /* Place to store target of trans. */ + const char *str; /* String being parsed */ + Suff **srcPtr; /* Place to store source of trans. */ + Suff **targPtr; /* Place to store target of trans. */ { - register LstNode srcLn; /* element in suffix list of trans source*/ - register Suff *src; /* Source of transformation */ - register LstNode targLn; /* element in suffix list of trans target*/ - register char *str2; /* Extra pointer (maybe target suffix) */ - LstNode singleLn; /* element in suffix list of any suffix + LstNode srcLn; /* element in suffix list of trans source*/ + Suff *src; /* Source of transformation */ + LstNode targLn; /* element in suffix list of trans target*/ + const char *str2; /* Extra pointer (maybe target suffix) */ + LstNode singleLn; /* element in suffix list of any suffix * that exactly matches str */ - Suff *single = NULL;/* Source of possible transformation to + Suff *single = NULL;/* Source of possible transformation to * null suffix */ srcLn = NULL; @@ -474,12 +471,10 @@ SuffParseTransform(str, srcPtr, targPtr) * parsed the string. */ for (;;) { - if (srcLn == NULL) { - srcLn = Lst_Find(&sufflist, SuffSuffIsPrefix, str); - } else { - srcLn = Lst_FindFrom(Lst_Succ(srcLn), - SuffSuffIsPrefix, str); - } + if (srcLn == NULL) + srcLn = Lst_FindConst(&sufflist, SuffSuffIsPrefix, str); + else + srcLn = Lst_FindFromConst(Lst_Succ(srcLn), SuffSuffIsPrefix, str); if (srcLn == NULL) { /* * Ran out of source suffixes -- no such rule @@ -496,9 +491,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; @@ -506,11 +501,11 @@ SuffParseTransform(str, srcPtr, targPtr) single = src; singleLn = srcLn; } else { - targLn = Lst_Find(&sufflist, SuffSuffHasNameP, str2); + targLn = Lst_FindConst(&sufflist, SuffSuffHasNameP, str2); if (targLn != NULL) { *srcPtr = src; *targPtr = (Suff *)Lst_Datum(targLn); - return (TRUE); + return TRUE; } } } @@ -521,22 +516,18 @@ SuffParseTransform(str, srcPtr, targPtr) * Suff_IsTransform -- * Return TRUE if the given string is a transformation rule * - * * Results: * TRUE if the string is a concatenation of two known suffixes. * FALSE otherwise - * - * Side Effects: - * None *----------------------------------------------------------------------- */ Boolean -Suff_IsTransform (str) - char *str; /* string to check */ +Suff_IsTransform(str) + const char *str; /* string to check */ { - Suff *src, *targ; + Suff *src, *targ; - return (SuffParseTransform(str, &src, &targ)); + return SuffParseTransform(str, &src, &targ); } /*- @@ -554,15 +545,15 @@ Suff_IsTransform (str) *----------------------------------------------------------------------- */ GNode * -Suff_AddTransform (line) - char *line; /* name of transformation to add */ +Suff_AddTransform(line) + const char *line; /* name of transformation to add */ { - GNode *gn; /* GNode of transformation rule */ - Suff *s, /* source suffix */ - *t; /* target suffix */ - LstNode ln; /* Node for existing transformation */ + GNode *gn; /* GNode of transformation rule */ + Suff *s, /* source suffix */ + *t; /* target suffix */ + LstNode ln; /* Node for existing transformation */ - ln = Lst_Find(&transforms, SuffGNHasNameP, line); + ln = Lst_FindConst(&transforms, SuffGNHasNameP, line); if (ln == NULL) { /* * Make a new graph node for the transformation. It will be filled in @@ -579,8 +570,8 @@ Suff_AddTransform (line) */ gn = (GNode *)Lst_Datum(ln); Lst_Destroy(&gn->commands, NOFREE); - Lst_Destroy(&gn->children, NOFREE); Lst_Init(&gn->commands); + Lst_Destroy(&gn->children, NOFREE); Lst_Init(&gn->children); } @@ -598,7 +589,7 @@ Suff_AddTransform (line) SuffInsert(&t->children, s); SuffInsert(&s->parents, t); - return (gn); + return gn; } /*- @@ -612,12 +603,11 @@ Suff_AddTransform (line) * Side Effects: * If the node has no commands or children, the children and parents * lists of the affected suffices are altered. - * *----------------------------------------------------------------------- */ void Suff_EndTransform(gnp) - void *gnp; /* Node for transformation */ + void *gnp; /* Node for transformation */ { GNode *gn = (GNode *)gnp; @@ -634,17 +624,18 @@ Suff_EndTransform(gnp) } /* - * Remove the source from the target's children list. + * Remove the source from the target's children list. * * We'll be called twice when the next target is seen, but .c and .o * are only linked once... */ - SuffRemove(&t->children, s); + SuffUnRef(&t->children, s); /* * Remove the target from the source's parents list */ - SuffRemove(&s->parents, t); + if (s != NULL) + SuffUnRef(&s->parents, t); } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) { printf("transformation %s complete\n", gn->name); } @@ -663,31 +654,26 @@ Suff_EndTransform(gnp) * Side Effects: * The appropriate links will be made between this suffix and * others if transformation rules exist for it. - * *----------------------------------------------------------------------- */ static void SuffRebuildGraph(transformp, sp) - void *transformp; /* Transformation to test */ - void *sp; /* Suffix to rebuild */ + void *transformp; /* Transformation to test */ + void *sp; /* Suffix to rebuild */ { - GNode *transform = (GNode *)transformp; - Suff *s = (Suff *)sp; - char *cp; + GNode *transform = (GNode *)transformp; + Suff *s = (Suff *)sp; + char *cp; LstNode ln; - Suff *s2; + Suff *s2; - /* - * First see if it is a transformation from this suffix. - */ + /* First see if it is a transformation from this suffix. */ cp = SuffStrIsPrefix(s->name, transform->name); if (cp != NULL) { - ln = Lst_Find(&sufflist, SuffSuffHasNameP, cp); + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, cp); if (ln != NULL) { - /* - * Found target. Link in and return, since it can't be anything - * else. - */ + /* Found target. Link in and return, since it can't be anything + * else. */ s2 = (Suff *)Lst_Datum(ln); SuffInsert(&s2->children, s); SuffInsert(&s->parents, s2); @@ -695,24 +681,16 @@ SuffRebuildGraph(transformp, sp) } } - /* - * Not from, maybe to? - */ + /* Not from, maybe to? */ cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name)); if (cp != NULL) { - /* - * Null-terminate the source suffix in order to find it. - */ - cp[1] = '\0'; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, transform->name); - /* - * Replace the start of the target suffix - */ - cp[1] = s->name[0]; + /* Null-terminate the source suffix in order to find it. */ + *cp = '\0'; + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, transform->name); + /* Replace the start of the target suffix. */ + *cp = s->name[0]; if (ln != NULL) { - /* - * Found it -- establish the proper relationship - */ + /* Found it -- establish the proper relationship. */ s2 = (Suff *)Lst_Datum(ln); SuffInsert(&s->children, s2); SuffInsert(&s2->parents, s); @@ -726,33 +704,30 @@ SuffRebuildGraph(transformp, sp) * Add the suffix in string to the end of the list of known suffixes. * Should we restructure the suffix graph? Make doesn't... * - * Results: - * None - * * Side Effects: * A GNode is created for the suffix and a Suff structure is created and * added to the suffixes list unless the suffix was already known. *----------------------------------------------------------------------- */ void -Suff_AddSuffix (str) - char *str; /* the name of the suffix to add */ +Suff_AddSuffix(str) + char *str; /* the name of the suffix to add */ { - Suff *s; /* new suffix descriptor */ - LstNode ln; + Suff *s; /* new suffix descriptor */ + LstNode ln; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, str); + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, str); if (ln == NULL) { - s = (Suff *) emalloc (sizeof (Suff)); + s = emalloc(sizeof(Suff)); - s->name = estrdup(str); - s->nameLen = strlen(s->name); + s->name = estrdup(str); + s->nameLen = strlen(s->name); Lst_Init(&s->searchPath); Lst_Init(&s->children); Lst_Init(&s->parents); Lst_Init(&s->ref); - s->sNum = sNum++; - s->flags = 0; + s->sNum = sNum++; + s->flags = 0; Lst_AtEnd(&sufflist, s); /* @@ -775,15 +750,15 @@ Suff_AddSuffix (str) */ Lst Suff_GetPath(sname) - char *sname; + char *sname; { - LstNode ln; - Suff *s; + LstNode ln; + Suff *s; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, sname); - if (ln == NULL) + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, sname); + if (ln == NULL) { return NULL; - else { + } else { s = (Suff *)Lst_Datum(ln); return &s->searchPath; } @@ -795,9 +770,6 @@ Suff_GetPath(sname) * Extend the search paths for all suffixes to include the default * search path. * - * Results: - * None. - * * Side Effects: * The searchPath field of all the suffixes is extended by the * directories in dirSearchPath. If paths were specified for the @@ -810,18 +782,16 @@ Suff_GetPath(sname) void Suff_DoPaths() { - register Suff *s; - register LstNode ln; + Suff *s; + LstNode ln; char *ptr; - LIST inIncludes; /* Cumulative .INCLUDES path */ - LIST inLibs; /* Cumulative .LIBS path */ - - Lst_Open(&sufflist); + LIST inIncludes; /* Cumulative .INCLUDES path */ + LIST inLibs; /* Cumulative .LIBS path */ Lst_Init(&inIncludes); Lst_Init(&inLibs); - while ((ln = Lst_Next(&sufflist)) != NULL) { + for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Adv(ln)) { s = (Suff *)Lst_Datum(ln); if (!Lst_IsEmpty(&s->searchPath)) { #ifdef INCLUDES @@ -848,8 +818,6 @@ Suff_DoPaths() Lst_Destroy(&inIncludes, Dir_Destroy); Lst_Destroy(&inLibs, Dir_Destroy); - - Lst_Close(&sufflist); } /*- @@ -859,22 +827,18 @@ Suff_DoPaths() * Called from the parse module when a .INCLUDES line is parsed. * The suffix must have already been defined. * - * Results: - * None. - * * Side Effects: * The SUFF_INCLUDE bit is set in the suffix's flags field - * *----------------------------------------------------------------------- */ void -Suff_AddInclude (sname) +Suff_AddInclude(sname) char *sname; /* Name of suffix to mark */ { LstNode ln; Suff *s; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, sname); + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, sname); if (ln != NULL) { s = (Suff *)Lst_Datum(ln); s->flags |= SUFF_INCLUDE; @@ -889,29 +853,25 @@ Suff_AddInclude (sname) * suffix must have been defined via .SUFFIXES before this is * called. * - * Results: - * None. - * * Side Effects: * The SUFF_LIBRARY bit is set in the suffix's flags field - * *----------------------------------------------------------------------- */ void -Suff_AddLib (sname) +Suff_AddLib(sname) char *sname; /* Name of suffix to mark */ { LstNode ln; Suff *s; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, sname); + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, sname); if (ln != NULL) { s = (Suff *)Lst_Datum(ln); s->flags |= SUFF_LIBRARY; } } - /********** Implicit Source Search Functions *********/ + /********** Implicit Source Search Functions *********/ /*- *----------------------------------------------------------------------- @@ -930,24 +890,24 @@ SuffAddSrc(sp, lsp) void *lsp; /* list and parent for the new Src */ { Suff *s = (Suff *)sp; - LstSrc *ls = (LstSrc *)lsp; - Src *s2; /* new Src structure */ - Src *targ; /* Target structure */ + LstSrc *ls = (LstSrc *)lsp; + Src *s2; /* new Src structure */ + Src *targ; /* Target structure */ targ = ls->s; - if ((s->flags & SUFF_NULL) && (*s->name != '\0')) { + if ((s->flags & SUFF_NULL) && *s->name != '\0') { /* * If the suffix has been marked as the NULL suffix, also create a Src * structure for a file with no suffix attached. Two birds, and all * that... */ - s2 = (Src *) emalloc (sizeof (Src)); - s2->file = estrdup(targ->pref); - s2->pref = targ->pref; - s2->parent = targ; - s2->node = NULL; - s2->suff = s; + s2 = emalloc(sizeof(Src)); + s2->file = estrdup(targ->pref); + s2->pref = targ->pref; + s2->parent = targ; + s2->node = NULL; + s2->suff = s; s2->children = 0; targ->children += 1; Lst_AtEnd(ls->l, s2); @@ -959,12 +919,12 @@ SuffAddSrc(sp, lsp) printf("\n"); #endif } - s2 = (Src *) emalloc (sizeof (Src)); - s2->file = str_concat(targ->pref, s->name, 0); + s2 = emalloc(sizeof(Src)); + s2->file = str_concat(targ->pref, s->name, 0); s2->pref = targ->pref; s2->parent = targ; - s2->node = NULL; - s2->suff = s; + s2->node = NULL; + s2->suff = s; s2->children = 0; targ->children += 1; Lst_AtEnd(ls->l, s2); @@ -975,6 +935,7 @@ SuffAddSrc(sp, lsp) Lst_Every(ls->l, PrintAddr); printf("\n"); #endif + } /*- @@ -982,19 +943,16 @@ SuffAddSrc(sp, lsp) * SuffAddLevel -- * Add all the children of targ as Src structures to the given list * - * Results: - * None - * * Side Effects: - * Lots of structures are created and added to the list + * Lots of structures are created and added to the list *----------------------------------------------------------------------- */ static void -SuffAddLevel (l, targ) - Lst l; /* list to which to add the new level */ - Src *targ; /* Src structure to use as the parent */ +SuffAddLevel(l, targ) + Lst l; /* list to which to add the new level */ + Src *targ; /* Src structure to use as the parent */ { - LstSrc ls; + LstSrc ls; ls.s = targ; ls.l = l; @@ -1008,29 +966,28 @@ SuffAddLevel (l, targ) * Free all src structures in list that don't have a reference count * * Results: - * True if an src was removed + * Ture if an src was removed * * Side Effects: * The memory is free'd. *---------------------------------------------------------------------- */ static int -SuffRemoveSrc (l) +SuffRemoveSrc(l) Lst l; { LstNode ln; Src *s; int t = 0; - Lst_Open(l); #ifdef DEBUG_SRC - printf("cleaning %lx: ", (unsigned long) l); + printf("cleaning %lx: ", (unsigned long)l); Lst_Every(l, PrintAddr); printf("\n"); #endif - while ((ln = Lst_Next (l)) != NULL) { + for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) { s = (Src *)Lst_Datum(ln); if (s->children == 0) { free(s->file); @@ -1038,9 +995,9 @@ SuffRemoveSrc (l) free(s->pref); else { #ifdef DEBUG_SRC - LstNode ln = Lst_Member(&s->parent->cp, s); - if (ln != NULL) - Lst_Remove(&s->parent->cp, ln); + LstNode ln2 = Lst_Member(&s->parent->cp, s); + if (ln2 != NULL) + Lst_Remove(&s->parent->cp, ln2); #endif --s->parent->children; } @@ -1051,7 +1008,6 @@ SuffRemoveSrc (l) Lst_Remove(l, ln); free(s); t |= 1; - Lst_Close(l); return TRUE; } #ifdef DEBUG_SRC @@ -1063,8 +1019,6 @@ SuffRemoveSrc (l) #endif } - Lst_Close(l); - return t; } @@ -1075,32 +1029,29 @@ SuffRemoveSrc (l) * * Results: * The lowest structure in the chain of transformations - * - * Side Effects: - * None *----------------------------------------------------------------------- */ static Src * -SuffFindThem (srcs, slst) - Lst srcs; /* list of Src structures to search through */ - Lst slst; +SuffFindThem(srcs, slst) + Lst srcs; /* list of Src structures to search through */ + Lst slst; { - Src *s; /* current Src */ - Src *rs; /* returned Src */ + Src *s; /* current Src */ + Src *rs; /* returned Src */ char *ptr; - rs = (Src *) NULL; + rs = NULL; while ((s = (Src *)Lst_DeQueue(srcs)) != NULL) { if (DEBUG(SUFF)) { - printf ("\ttrying %s...", s->file); + printf("\ttrying %s...", s->file); } /* * 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, TARG_NOCREATE) != NULL) { + if (Targ_FindNode(s->file, NULL, TARG_NOCREATE) != NULL) { #ifdef DEBUG_SRC printf("remove %x from %x\n", s, srcs); #endif @@ -1118,17 +1069,17 @@ SuffFindThem (srcs, slst) } if (DEBUG(SUFF)) { - printf ("not there\n"); + printf("not there\n"); } - SuffAddLevel (srcs, s); + SuffAddLevel(srcs, s); Lst_AtEnd(slst, s); } if (DEBUG(SUFF) && rs) { - printf ("got it\n"); + printf("got it\n"); } - return (rs); + return rs; } /*- @@ -1143,59 +1094,55 @@ SuffFindThem (srcs, slst) * * Side Effects: * A Src structure may be allocated. - * *----------------------------------------------------------------------- */ static Src * -SuffFindCmds (targ, slst) - Src *targ; /* Src structure to play with */ - Lst slst; +SuffFindCmds(targ, slst) + Src *targ; /* Src structure to play with */ + Lst slst; { - LstNode ln; /* General-purpose list node */ - register GNode *t, /* Target GNode */ - *s; /* Source GNode */ - int prefLen;/* The length of the defined prefix */ - Suff *suff; /* Suffix on matching beastie */ - Src *ret; /* Return value */ - char *cp; + LstNode ln; /* General-purpose list node */ + GNode *t, /* Target GNode */ + *s; /* Source GNode */ + int prefLen;/* The length of the defined prefix */ + Suff *suff; /* Suffix on matching beastie */ + Src *ret; /* Return value */ + const char *cp; t = targ->node; - Lst_Open(&t->children); - prefLen = strlen (targ->pref); + prefLen = strlen(targ->pref); - while ((ln = Lst_Next(&t->children)) != NULL) { + for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Adv(ln)) { s = (GNode *)Lst_Datum(ln); - cp = strrchr (s->name, '/'); - if (cp == (char *)NULL) { + cp = strrchr(s->name, '/'); + if (cp == NULL) { cp = s->name; } else { cp++; } - if (strncmp (cp, targ->pref, prefLen) == 0) { - /* - * The node matches the prefix ok, see if it has a known - * suffix. - */ - ln = Lst_Find(&sufflist, SuffSuffHasNameP, &cp[prefLen]); - if (ln != NULL) { + if (strncmp(cp, targ->pref, prefLen) == 0) { + /* The node matches the prefix ok, see if it has a known + * suffix. */ + LstNode ln2; + ln2 = Lst_FindConst(&sufflist, SuffSuffHasNameP, &cp[prefLen]); + if (ln2 != NULL) { /* * It even has a known suffix, see if there's a transformation * defined between the node's suffix and the target's suffix. * * XXX: Handle multi-stage transformations here, too. */ - suff = (Suff *)Lst_Datum(ln); + suff = (Suff *)Lst_Datum(ln2); - if (Lst_Member(&suff->parents, targ->suff) != NULL) - { + if (Lst_Member(&suff->parents, targ->suff) != NULL) { /* * Hot Damn! Create a new Src structure to describe * this transformation (making sure to duplicate the * source node's name so Suff_FindDeps can free it * again (ick)), and return the new structure. */ - ret = (Src *)emalloc (sizeof (Src)); + ret = emalloc(sizeof(Src)); ret->file = estrdup(s->name); ret->pref = targ->pref; ret->suff = suff; @@ -1212,226 +1159,199 @@ SuffFindCmds (targ, slst) if (DEBUG(SUFF)) { printf ("\tusing existing source %s\n", s->name); } - return (ret); + return ret; } } } } - Lst_Close(&t->children); - return ((Src *)NULL); + return NULL; } -/*- - *----------------------------------------------------------------------- - * SuffExpandChildren -- - * Expand the names of any children of a given node that contain - * variable invocations or file wildcards into actual targets. - * - * Side Effects: - * The expanded node is removed from the parent's list of children, - * and the parent's unmade counter is decremented, but other nodes - * may be added. - * - *----------------------------------------------------------------------- - */ static void -SuffExpandChildren(cgnp, pgnp) - void *cgnp; /* Child to examine */ - void *pgnp; /* Parent node being processed */ +SuffExpandVarChildren(after, cgn, pgn) + LstNode after; + GNode *cgn; + GNode *pgn; { - GNode *cgn = (GNode *)cgnp; - GNode *pgn = (GNode *)pgnp; - GNode *gn; /* New source 8) */ - LstNode prevLN; /* Node after which new source should be put */ - LstNode ln; /* List element for old source */ - char *cp; /* Expanded value */ + GNode *gn; /* New source 8) */ + char *cp; /* Expanded value */ + LIST members; - /* - * New nodes effectively take the place of the child, so place them - * after the child - */ - prevLN = Lst_Member(&pgn->children, cgn); - - /* - * First do variable expansion -- this takes precedence over - * wildcard expansion. If the result contains wildcards, they'll be gotten - * to later since the resulting words are tacked on to the end of - * the children list. - */ - if (strchr(cgn->name, '$') != NULL) { - if (DEBUG(SUFF)) - printf("Expanding \"%s\"...", cgn->name); - cp = Var_Subst(cgn->name, &pgn->context, TRUE); - if (cp != NULL) { - LIST members; + if (DEBUG(SUFF)) + printf("Expanding \"%s\"...", cgn->name); - Lst_Init(&members); - if (cgn->type & OP_ARCHV) { - /* - * Node was an archive(member) target, so we want to call - * on the Arch module to find the nodes for us, expanding - * variables in the parent's context. - */ - char *sacrifice = cp; + cp = Var_Subst(cgn->name, &pgn->context, TRUE); + if (cp == NULL) { + printf("Problem substituting in %s", cgn->name); + printf("\n"); + return; + } - (void)Arch_ParseArchive(&sacrifice, &members, &pgn->context); - } else { - /* - * Break the result into a vector of strings whose nodes - * we can find, then add those nodes to the members list. - * Unfortunately, we can't use brk_string b/c it - * doesn't understand about variable specifications with - * spaces in them... - */ - char *start; - char *initcp = cp; /* For freeing... */ - - for (start = cp; *start == ' ' || *start == '\t'; start++) - continue; - for (cp = start; *cp != '\0'; cp++) { - if (*cp == ' ' || *cp == '\t') { - /* - * White-space -- terminate element, find the node, - * add it, skip any further spaces. - */ - *cp++ = '\0'; - gn = Targ_FindNode(start, TARG_CREATE); - Lst_AtEnd(&members, gn); - while (*cp == ' ' || *cp == '\t') { - cp++; - } - /* - * Adjust cp for increment at start of loop, but - * set start to first non-space. - */ - start = cp--; - } else if (*cp == '$') { - /* - * Start of a variable spec -- contact variable module - * to find the end so we can skip over it. - */ - char *junk; - size_t len; - Boolean doFree; - - junk = Var_Parse(cp, &pgn->context, TRUE, &len, &doFree); - if (junk != var_Error) - cp += len - 1; - - if (doFree) - free(junk); - } else if (*cp == '\\' && *cp != '\0') { - /* - * Escaped something -- skip over it - */ - cp++; - } - } + Lst_Init(&members); - if (cp != start) { - /* - * Stuff left over -- add it to the list too - */ - gn = Targ_FindNode(start, TARG_CREATE); - Lst_AtEnd(&members, gn); - } - /* - * Point cp back at the beginning again so the variable value - * can be freed. - */ - cp = initcp; - } - /* Add all elements of the members list to the parent node. */ - while((gn = (GNode *)Lst_DeQueue(&members)) != NULL) { - if (DEBUG(SUFF)) - printf("%s...", gn->name); - if (Lst_Member(&pgn->children, gn) == NULL) { - Lst_Append(&pgn->children, prevLN, gn); - prevLN = Lst_Succ(prevLN); - Lst_AtEnd(&gn->parents, pgn); - pgn->unmade++; - } - } - Lst_Destroy(&members, NOFREE); - /* Free the result */ - free(cp); - } + if (cgn->type & OP_ARCHV) { /* - * Now the source is expanded, remove it from the list of children to - * keep it from being processed. + * Node was an archive(member) target, so we want to call + * on the Arch module to find the nodes for us, expanding + * variables in the parent's context. */ - ln = Lst_Member(&pgn->children, cgn); - pgn->unmade--; - Lst_Remove(&pgn->children, ln); - if (DEBUG(SUFF)) - printf("\n"); - } else if (Dir_HasWildcards(cgn->name)) { - LIST exp; /* List of expansions */ - Lst path; /* Search path along which to expand */ + char *sacrifice = cp; - /* - * Find a path along which to expand the word. - * - * If the word has a known suffix, use that path. - * If it has no known suffix and we're allowed to use the null - * suffix, use its path. - * Else use the default system search path. - */ - cp = cgn->name + strlen(cgn->name); - ln = Lst_Find(&sufflist, SuffSuffIsSuffixP, cp); + (void)Arch_ParseArchive(&sacrifice, &members, &pgn->context); + } else { + /* Break the result into a vector of strings whose nodes + * we can find, then add those nodes to the members list. + * Unfortunately, we can't use brk_string because it + * doesn't understand about variable specifications with + * spaces in them... */ + char *start, *cp2; + + for (start = cp; *start == ' ' || *start == '\t'; start++) + continue; + for (cp2 = start; *cp2 != '\0';) { + if (isspace(*cp2)) { + /* White-space -- terminate element, find the node, + * add it, skip any further spaces. */ + gn = Targ_FindNode(start, cp2, TARG_CREATE); + cp2++; + Lst_AtEnd(&members, gn); + while (isspace(*cp2)) + cp2++; + /* Adjust cp2 for increment at start of loop, but + * set start to first non-space. */ + start = cp2; + } else if (*cp2 == '$') + /* Start of a variable spec -- contact variable module + * to find the end so we can skip over it. */ + cp2 += Var_ParseSkip(cp2, &pgn->context, NULL); + else if (*cp2 == '\\' && cp2[1] != '\0') + /* Escaped something -- skip over it. */ + cp2+=2; + } + if (cp2 != start) { + /* Stuff left over -- add it to the list too. */ + gn = Targ_FindNode(start, cp2, TARG_CREATE); + Lst_AtEnd(&members, gn); + } + } + /* Add all elements of the members list to the parent node. */ + while ((gn = (GNode *)Lst_DeQueue(&members)) != NULL) { if (DEBUG(SUFF)) - printf("Wildcard expanding \"%s\"...", cgn->name); - - if (ln != NULL) { - Suff *s = (Suff *)Lst_Datum(ln); - - if (DEBUG(SUFF)) - printf("suffix is \"%s\"...", s->name); - path = &s->searchPath; - } else { - /* - * Use default search path - */ - path = &dirSearchPath; + printf("%s...", gn->name); + if (Lst_Member(&pgn->children, gn) == NULL) { + Lst_Append(&pgn->children, after, gn); + after = Lst_Adv(after); + Lst_AtEnd(&gn->parents, pgn); + pgn->unmade++; } + } + /* Free the result. */ + free(cp); + if (DEBUG(SUFF)) + printf("\n"); +} - /* Expand the word along the chosen path */ - Lst_Init(&exp); - Dir_Expand(cgn->name, path, &exp); +static void +SuffExpandWildChildren(after, cgn, pgn) + LstNode after; + GNode *cgn; + GNode *pgn; +{ + LstNode ln; /* List element for old source */ + char *cp; /* Expanded value */ - /* Fetch next expansion off the list and find its GNode. */ - while ((cp = (char *)Lst_DeQueue(&exp)) != NULL) { - if (DEBUG(SUFF)) - printf("%s...", cp); - gn = Targ_FindNode(cp, TARG_CREATE); + LIST exp; /* List of expansions */ + Lst path; /* Search path along which to expand */ - /* - * If gn isn't already a child of the parent, make it so and - * up the parent's count of unmade children. - */ - if (Lst_Member(&pgn->children, gn) == NULL) { - Lst_Append(&pgn->children, prevLN, gn); - prevLN = Lst_Succ(prevLN); - Lst_AtEnd(&gn->parents, pgn); - pgn->unmade++; - } - } + if (DEBUG(SUFF)) + printf("Wildcard expanding \"%s\"...", cgn->name); - /* Nuke what's left of the list. */ - Lst_Destroy(&exp, NOFREE); + /* Find a path along which to expand the word. + * + * If the word has a known suffix, use that path. + * If it has no known suffix and we're allowed to use the null + * suffix, use its path. + * Else use the default system search path. */ + cp = cgn->name + strlen(cgn->name); + ln = Lst_FindConst(&sufflist, SuffSuffIsSuffixP, cp); + + if (ln != NULL) { + Suff *s = (Suff *)Lst_Datum(ln); - /* - * Now the source is expanded, remove it from the list of children to - * keep it from being processed. - */ - ln = Lst_Member(&pgn->children, cgn); - pgn->unmade--; - Lst_Remove(&pgn->children, ln); if (DEBUG(SUFF)) - printf("\n"); + printf("suffix is \"%s\"...", s->name); + path = &s->searchPath; + } else + /* Use default search path. */ + path = &dirSearchPath; + + /* Expand the word along the chosen path. */ + Lst_Init(&exp); + Dir_Expand(cgn->name, path, &exp); + + /* Fetch next expansion off the list and find its GNode. */ + while ((cp = (char *)Lst_DeQueue(&exp)) != NULL) { + GNode *gn; /* New source 8) */ + if (DEBUG(SUFF)) + printf("%s...", cp); + gn = Targ_FindNode(cp, NULL, TARG_CREATE); + + /* If gn isn't already a child of the parent, make it so and + * up the parent's count of unmade children. */ + if (Lst_Member(&pgn->children, gn) == NULL) { + Lst_Append(&pgn->children, after, gn); + after = Lst_Adv(after); + Lst_AtEnd(&gn->parents, pgn); + pgn->unmade++; + } } + + if (DEBUG(SUFF)) + printf("\n"); +} + +/*- + *----------------------------------------------------------------------- + * SuffExpandChildren -- + * Expand the names of any children of a given node that contain + * variable invocations or file wildcards into actual targets. + * + * Side Effects: + * The expanded node is removed from the parent's list of children, + * and the parent's unmade counter is decremented, but other nodes + * may be added. + *----------------------------------------------------------------------- + */ +static void +SuffExpandChildren(cgnp, pgnp) + void *cgnp; /* Child to examine */ + void *pgnp; /* Parent node being processed */ +{ + GNode *cgn = (GNode *)cgnp; + GNode *pgn = (GNode *)pgnp; + LstNode ln; + /* New nodes effectively take the place of the child, so we place them + * after the child. */ + ln = Lst_Member(&pgn->children, cgn); + + /* First do variable expansion -- this takes precedence over + * wildcard expansion. If the result contains wildcards, they'll be gotten + * to later since the resulting words are tacked on to the end of + * the children list. */ + if (strchr(cgn->name, '$') != NULL) + SuffExpandVarChildren(ln, cgn, pgn); + else if (Dir_HasWildcards(cgn->name)) + SuffExpandWildChildren(ln, cgn, pgn); + else + /* Third case: nothing to expand. */ + return; + + /* Since the source was expanded, remove it from the list of children to + * keep it from being processed. */ + pgn->unmade--; + Lst_Remove(&pgn->children, ln); } /*- @@ -1449,99 +1369,78 @@ SuffExpandChildren(cgnp, pgnp) * All attributes but OP_DEPMASK and OP_TRANSFORM are applied * to the target. The target also inherits all the sources for * the transformation rule. - * *----------------------------------------------------------------------- */ static Boolean SuffApplyTransform(tGn, sGn, t, s) - GNode *tGn; /* Target node */ - GNode *sGn; /* Source node */ - Suff *t; /* Target suffix */ - Suff *s; /* Source suffix */ + GNode *tGn; /* Target node */ + GNode *sGn; /* Source node */ + Suff *t; /* Target suffix */ + Suff *s; /* Source suffix */ { - LstNode ln; /* General node */ + LstNode ln; /* General node */ LstNode np; /* Next node for loop */ - char *tname; /* Name of transformation rule */ - GNode *gn; /* Node for same */ + char *tname; /* Name of transformation rule */ + GNode *gn; /* Node for same */ - if (Lst_Member(&tGn->children, sGn) == NULL) { - /* - * Not already linked, so form the proper links between the - * target and source. - */ - Lst_AtEnd(&tGn->children, sGn); + if (Lst_AddNew(&tGn->children, sGn) == SUCCESS) { + /* Not already linked, so form the proper links between the + * target and source. */ Lst_AtEnd(&sGn->parents, tGn); - tGn->unmade += 1; + tGn->unmade++; } if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) { - /* - * When a :: node is used as the implied source of a node, we have + /* When a :: node is used as the implied source of a node, we have * to link all its cohorts in as sources as well. Only the initial * sGn gets the target in its iParents list, however, as that - * will be sufficient to get the .IMPSRC variable set for tGn - */ + * will be sufficient to get the .IMPSRC variable set for tGn. */ for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) { gn = (GNode *)Lst_Datum(ln); - if (Lst_Member(&tGn->children, gn) == NULL) { - /* - * Not already linked, so form the proper links between the - * target and source. - */ - Lst_AtEnd(&tGn->children, gn); + if (Lst_AddNew(&tGn->children, gn) == SUCCESS) { + /* Not already linked, so form the proper links between the + * target and source. */ Lst_AtEnd(&gn->parents, tGn); - tGn->unmade += 1; + tGn->unmade++; } } } - /* - * Locate the transformation rule itself - */ + /* Locate the transformation rule itself. */ tname = str_concat(s->name, t->name, 0); - ln = Lst_Find(&transforms, SuffGNHasNameP, tname); + ln = Lst_FindConst(&transforms, SuffGNHasNameP, tname); free(tname); - if (ln == NULL) { + if (ln == NULL) /* * Not really such a transformation rule (can happen when we're * called to link an OP_MEMBER and OP_ARCHV node), so return * FALSE. */ - return(FALSE); - } + return FALSE; gn = (GNode *)Lst_Datum(ln); - if (DEBUG(SUFF)) { + if (DEBUG(SUFF)) printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); - } - /* - * Record last child for expansion purposes - */ + /* Record last child for expansion purposes. */ ln = Lst_Last(&tGn->children); - /* - * Pass the buck to Make_HandleUse to apply the rule - */ - (void)Make_HandleUse(gn, tGn); + /* Pass the buck to Make_HandleUse to apply the rule. */ + Make_HandleUse(gn, tGn); - /* - * Deal with wildcards and variables in any acquired sources - */ + /* Deal with wildcards and variables in any acquired sources. */ for (ln = Lst_Succ(ln); ln != NULL; ln = np) { np = Lst_Adv(ln); SuffExpandChildren(Lst_Datum(ln), tGn); } - /* - * Keep track of another parent to which this beast is transformed so - * the .IMPSRC variable can be set correctly for the parent. - */ + /* Keep track of another parent to which this beast is transformed so + * the .IMPSRC variable can be set correctly for the parent. */ Lst_AtEnd(&sGn->iParents, tGn); - return(TRUE); + return TRUE; } @@ -1550,56 +1449,45 @@ SuffApplyTransform(tGn, sGn, t, s) * SuffFindArchiveDeps -- * Locate dependencies for an OP_ARCHV node. * - * Results: - * None - * * Side Effects: * Same as Suff_FindDeps - * *----------------------------------------------------------------------- */ static void SuffFindArchiveDeps(gn, slst) - GNode *gn; /* Node for which to locate dependencies */ - Lst slst; + GNode *gn; /* Node for which to locate dependencies */ + Lst slst; { - char *eoarch; /* End of archive portion */ - char *eoname; /* End of member portion */ - GNode *mem; /* Node for member */ - Suff *ms; /* Suffix descriptor for member */ - char *name; /* Start of member's name */ - - /* - * The node is an archive(member) pair. so we must find a - * suffix for both of them. - */ - eoarch = strchr (gn->name, '('); - eoname = strchr (eoarch, ')'); - if (eoarch == NULL || eoname == NULL) + char *eoarch; /* End of archive portion */ + char *eoname; /* End of member portion */ + GNode *mem; /* Node for member */ + Suff *ms; /* Suffix descriptor for member */ + char *name; /* Start of member's name */ + + /* The node is an archive(member) pair. so we must find a suffix + * for both of them. */ + eoarch = strchr(gn->name, '('); + if (eoarch == NULL) return; - *eoname = '\0'; /* Nuke parentheses during suffix search */ - *eoarch = '\0'; /* So a suffix can be found */ - name = eoarch + 1; - /* - * To simplify things, call Suff_FindDeps recursively on the member now, + eoname = strchr(name, ')'); + if (eoname == NULL) + return; + + /* To simplify things, call Suff_FindDeps recursively on the member now, * so we can simply compare the member's .PREFIX and .TARGET variables * 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, TARG_CREATE); + * suffix list, backtracking for each one... */ + mem = Targ_FindNode(name, eoname, TARG_CREATE); SuffFindDeps(mem, slst); - /* - * Create the link between the two nodes right off - */ - if (Lst_Member(&gn->children, mem) == NULL) { - Lst_AtEnd(&gn->children, mem); + /* Create the link between the two nodes right off. */ + if (Lst_AddNew(&gn->children, mem) == SUCCESS) { Lst_AtEnd(&mem->parents, gn); - gn->unmade += 1; + gn->unmade++; } /* Copy variables from member node to this one. */ @@ -1608,20 +1496,15 @@ SuffFindArchiveDeps(gn, slst) ms = mem->suffix; if (ms == NULL) { - /* - * Didn't know what it was -- use .NULL suffix if not in make mode - */ - if (DEBUG(SUFF)) { + /* Didn't know what it was -- use .NULL suffix if not in make mode. */ + if (DEBUG(SUFF)) printf("using null suffix\n"); - } ms = suffNull; } - /* - * Set the other two local variables required for this target. - */ - Varq_Set(MEMBER_INDEX, name, gn); + /* Set the other two local variables required for this target. */ + Varq_Set(MEMBER_INDEX, mem->name, gn); Varq_Set(ARCHIVE_INDEX, gn->name, gn); if (ms != NULL) { @@ -1631,45 +1514,28 @@ SuffFindArchiveDeps(gn, slst) * through the entire list, we just look at suffixes to which the * member's suffix may be transformed... */ - LstNode ln; + LstNode ln; - /* - * Use first matching suffix... - */ - ln = Lst_Find(&ms->parents, SuffSuffIsSuffixP, eoarch); + /* Use first matching suffix... */ + ln = Lst_FindConst(&ms->parents, SuffSuffIsSuffixP, eoarch); if (ln != NULL) { - /* - * Got one -- apply it - */ + /* Got one -- apply it. */ if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) && DEBUG(SUFF)) - { printf("\tNo transformation from %s -> %s\n", ms->name, ((Suff *)Lst_Datum(ln))->name); - } } } - /* - * Replace the opening and closing parens now we've no need of the separate - * pieces. - */ - *eoarch = '('; *eoname = ')'; - - /* - * Pretend gn appeared to the left of a dependency operator so + /* Pretend gn appeared to the left of a dependency operator so * the user needn't provide a transformation from the member to the - * archive. - */ - if (OP_NOP(gn->type)) { + * archive. */ + if (OP_NOP(gn->type)) gn->type |= OP_DEPENDS; - } - /* - * Flag the member as such so we remember to look in the archive for - * its modification time. - */ + /* Flag the member as such so we remember to look in the archive for + * its modification time. */ mem->type |= OP_MEMBER; } @@ -1678,46 +1544,39 @@ SuffFindArchiveDeps(gn, slst) * SuffFindNormalDeps -- * Locate implicit dependencies for regular targets. * - * Results: - * None. - * * Side Effects: * Same as Suff_FindDeps... - * *----------------------------------------------------------------------- */ static void SuffFindNormalDeps(gn, slst) - GNode *gn; /* Node for which to find sources */ - Lst slst; + GNode *gn; /* Node for which to find sources */ + Lst slst; { - char *eoname; /* End of name */ - char *sopref; /* Start of prefix */ - LstNode ln; /* Next suffix node to check */ + char *eoname; /* End of name */ + char *sopref; /* Start of prefix */ + LstNode ln; /* Next suffix node to check */ LstNode np; - LIST srcs; /* List of sources at which to look */ - LIST targs; /* List of targets to which things can be + LIST srcs; /* List of sources at which to look */ + LIST targs; /* List of targets to which things can be * transformed. They all have the same file, * but different suff and pref fields */ - Src *bottom; /* Start of found transformation path */ + Src *bottom; /* Start of found transformation path */ Src *src; /* General Src pointer */ - char *pref; /* Prefix to use */ - Src *targ; /* General Src target pointer */ + char *pref; /* Prefix to use */ + Src *targ; /* General Src target pointer */ eoname = gn->name + strlen(gn->name); sopref = gn->name; - /* - * Begin at the beginning... - */ + /* Begin at the beginning... */ ln = Lst_First(&sufflist); Lst_Init(&srcs); Lst_Init(&targs); - /* - * We're caught in a catch-22 here. On the one hand, we want to use any + /* We're caught in a catch-22 here. On the one hand, we want to use any * transformation implied by the target's sources, but we can't examine * the sources until we've expanded any variables/wildcards they may hold, * and we can't do that until we've set up the target's local variables @@ -1732,36 +1591,29 @@ SuffFindNormalDeps(gn, slst) * checking transformations to all possible suffixes of the target, * use what we find to set the target's local variables, expand the * children, then look for any overriding transformations they imply. - * Should we find one, we discard the one we found before. - */ + * Should we find one, we discard the one we found before. */ while (ln != NULL) { - /* - * Look for next possible suffix... - */ - ln = Lst_FindFrom(ln, SuffSuffIsSuffixP, eoname); + /* Look for next possible suffix... */ + ln = Lst_FindFromConst(ln, SuffSuffIsSuffixP, eoname); if (ln != NULL) { - int prefLen; /* Length of the prefix */ - Src *targ; + int prefLen; /* Length of the prefix */ + Src *targ; - /* - * Allocate a Src structure to which things can be transformed - */ - targ = (Src *)emalloc(sizeof (Src)); + /* Allocate a Src structure to which things can be transformed. */ + targ = emalloc(sizeof(Src)); targ->file = estrdup(gn->name); targ->suff = (Suff *)Lst_Datum(ln); targ->node = gn; - targ->parent = (Src *)NULL; + targ->parent = NULL; targ->children = 0; #ifdef DEBUG_SRC Lst_Init(&targ->cp); #endif - /* - * Allocate room for the prefix, whose end is found by subtracting - * the length of the suffix from the end of the name. - */ + /* Allocate room for the prefix, whose end is found by subtracting + * the length of the suffix from the end of the name. */ prefLen = (eoname - targ->suff->nameLen) - sopref; targ->pref = emalloc(prefLen + 1); memcpy(targ->pref, sopref, prefLen); @@ -1778,29 +1630,25 @@ SuffFindNormalDeps(gn, slst) } } - /* - * Handle target of unknown suffix... - */ + /* Handle target of unknown suffix... */ if (Lst_IsEmpty(&targs) && suffNull != NULL) { if (DEBUG(SUFF)) { printf("\tNo known suffix on %s. Using .NULL suffix\n", gn->name); } - targ = (Src *)emalloc(sizeof (Src)); + targ = emalloc(sizeof(Src)); targ->file = estrdup(gn->name); targ->suff = suffNull; targ->node = gn; - targ->parent = (Src *)NULL; + targ->parent = NULL; targ->children = 0; targ->pref = estrdup(sopref); #ifdef DEBUG_SRC Lst_Init(&targ->cp); #endif - /* - * Only use the default suffix rules if we don't have commands - * or dependencies defined for this gnode - */ + /* Only use the default suffix rules if we don't have commands + * or dependencies defined for this gnode. */ if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children)) SuffAddLevel(&srcs, targ); else { @@ -1814,61 +1662,48 @@ SuffFindNormalDeps(gn, slst) Lst_AtEnd(&targs, targ); } - /* - * Using the list of possible sources built up from the target suffix(es), - * try and find an existing file/target that matches. - */ + /* Using the list of possible sources built up from the target suffix(es), + * try and find an existing file/target that matches. */ bottom = SuffFindThem(&srcs, slst); if (bottom == NULL) { - /* - * No known transformations -- use the first suffix found for setting - * the local variables. - */ + /* No known transformations -- use the first suffix found for setting + * the local variables. */ if (!Lst_IsEmpty(&targs)) targ = (Src *)Lst_Datum(Lst_First(&targs)); else targ = NULL; } else { - /* - * Work up the transformation path to find the suffix of the - * target to which the transformation was made. - */ + /* Work up the transformation path to find the suffix of the + * target to which the transformation was made. */ for (targ = bottom; targ->parent != NULL; targ = targ->parent) continue; } - /* - * The .TARGET variable we always set to be the name at this point, + /* The .TARGET variable we always set to be the name at this point, * since it's only set to the path if the thing is only a source and * if it's only a source, it doesn't matter what we put here as far - * as expanding sources is concerned, since it has none... - */ + * as expanding sources is concerned, since it has none... */ Varq_Set(TARGET_INDEX, gn->name, gn); - pref = (targ != NULL) ? targ->pref : gn->name; + pref = targ != NULL ? targ->pref : gn->name; Varq_Set(PREFIX_INDEX, pref, gn); - /* - * Now we've got the important local variables set, expand any sources - * that still contain variables or wildcards in their names. - */ + /* Now we've got the important local variables set, expand any sources + * that still contain variables or wildcards in their names. */ for (ln = Lst_First(&gn->children); ln != NULL; ln = np) { np = Lst_Adv(ln); SuffExpandChildren(Lst_Datum(ln), gn); } if (targ == NULL) { - if (DEBUG(SUFF)) { + if (DEBUG(SUFF)) printf("\tNo valid suffix on %s\n", gn->name); - } sfnd_abort: - /* - * Deal with finding the thing on the default search path if the + /* Deal with finding the thing on the default search path if the * node is only a source (not on the lhs of a dependency operator - * or [XXX] it has neither children or commands). - */ + * or [XXX] it has neither children or commands). */ if (OP_NOP(gn->type) || (Lst_IsEmpty(&gn->children) && Lst_IsEmpty(&gn->commands))) { @@ -1880,11 +1715,9 @@ sfnd_abort: Varq_Set(TARGET_INDEX, gn->path, gn); if (targ != NULL) { - /* - * Suffix known for the thing -- trim the suffix off - * the path to form the proper .PREFIX variable. - */ - int savep = strlen(gn->path) - targ->suff->nameLen; + /* Suffix known for the thing -- trim the suffix off + * the path to form the proper .PREFIX variable. */ + int savep = strlen(gn->path) - targ->suff->nameLen; char savec; gn->suffix = targ->suff; @@ -1901,10 +1734,8 @@ sfnd_abort: gn->path[savep] = savec; } else { - /* - * The .PREFIX gets the full path if the target has - * no known suffix. - */ + /* The .PREFIX gets the full path if the target has + * no known suffix. */ gn->suffix = NULL; if ((ptr = strrchr(gn->path, '/')) != NULL) @@ -1916,12 +1747,10 @@ sfnd_abort: } } } else { - /* - * Not appropriate to search for the thing -- set the + /* Not appropriate to search for the thing -- set the * path to be the name so Dir_MTime won't go grovelling for - * it. - */ - gn->suffix = (targ == NULL) ? NULL : targ->suff; + * it. */ + gn->suffix = targ == NULL ? NULL : targ->suff; efree(gn->path); gn->path = estrdup(gn->name); } @@ -1929,29 +1758,21 @@ sfnd_abort: goto sfnd_return; } - /* - * If the suffix indicates that the target is a library, mark that in - * the node's type field. - */ + /* If the suffix indicates that the target is a library, mark that in + * the node's type field. */ if (targ->suff->flags & SUFF_LIBRARY) { gn->type |= OP_LIB; } - /* - * Check for overriding transformation rule implied by sources - */ + /* Check for overriding transformation rule implied by sources. */ if (!Lst_IsEmpty(&gn->children)) { src = SuffFindCmds(targ, slst); - if (src != (Src *)NULL) { - /* - * Free up all the Src structures in the transformation path - * up to, but not including, the parent node. - */ + if (src != NULL) { + /* Free up all the Src structures in the transformation path + * up to, but not including, the parent node. */ while (bottom && bottom->parent != NULL) { - if (Lst_Member(slst, bottom) == NULL) { - Lst_AtEnd(slst, bottom); - } + (void)Lst_AddNew(slst, bottom); bottom = bottom->parent; } bottom = src; @@ -1959,14 +1780,11 @@ sfnd_abort: } if (bottom == NULL) { - /* - * No idea from where it can come -- return now. - */ + /* No idea from where it can come -- return now. */ goto sfnd_abort; } - /* - * We now have a list of Src structures headed by 'bottom' and linked via + /* We now have a list of Src structures headed by 'bottom' and linked via * their 'parent' pointers. What we do next is create links between * source and target nodes (which may or may not have been created) * and set the necessary local variables in each target. The @@ -1975,34 +1793,31 @@ sfnd_abort: * suffix. Note that this causes the commands list of the original * node, gn, to be replaced by the commands of the final * transformation rule. Also, the unmade field of gn is incremented. - * Etc. - */ + * Etc. */ if (bottom->node == NULL) { - bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); + bottom->node = Targ_FindNode(bottom->file, NULL, TARG_CREATE); } - for (src = bottom; src->parent != (Src *)NULL; src = src->parent) { + for (src = bottom; src->parent != NULL; src = src->parent) { targ = src->parent; src->node->suffix = src->suff; if (targ->node == NULL) { - targ->node = Targ_FindNode(targ->file, TARG_CREATE); + targ->node = Targ_FindNode(targ->file, NULL, TARG_CREATE); } SuffApplyTransform(targ->node, src->node, targ->suff, src->suff); if (targ->node != gn) { - /* - * Finish off the dependency-search process for any nodes + /* Finish off the dependency-search process for any nodes * between bottom and gn (no point in questing around the * filesystem for their implicit source when it's already * known). Note that the node can't have any sources that * need expanding, since SuffFindThem will stop on an existing * node, so all we need to do is set the standard and System V - * variables. - */ + * variables. */ targ->node->type |= OP_DEPS_FOUND; Varq_Set(PREFIX_INDEX, targ->pref, targ->node); @@ -2013,20 +1828,15 @@ sfnd_abort: gn->suffix = src->suff; - /* - * So Dir_MTime doesn't go questing for it... - */ + /* So Dir_MTime doesn't go questing for it... */ efree(gn->path); gn->path = estrdup(gn->name); - /* - * Nuke the transformation path and the Src structures left over in the - * two lists. - */ + /* Nuke the transformation path and the Src structures left over in the + * two lists. */ sfnd_return: if (bottom) - if (Lst_Member(slst, bottom) == NULL) - Lst_AtEnd(slst, bottom); + (void)Lst_AddNew(slst, bottom); while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs)) continue; @@ -2042,9 +1852,6 @@ sfnd_return: * Find implicit sources for the target described by the graph node * gn * - * Results: - * Nothing. - * * Side Effects: * Nodes are added to the graph below the passed-in node. The nodes * are marked to have their IMPSRC variable filled in. The @@ -2060,7 +1867,6 @@ sfnd_return: * the .c and .l files don't, the search will branch out in * all directions from .o and again from all the nodes on the * next level until the .l,v node is encountered. - * *----------------------------------------------------------------------- */ @@ -2076,9 +1882,9 @@ Suff_FindDeps(gn) static void -SuffFindDeps (gn, slst) - GNode *gn; /* node we're dealing with */ - Lst slst; +SuffFindDeps(gn, slst) + GNode *gn; /* node we're dealing with */ + Lst slst; { if (gn->type & OP_DEPS_FOUND) { /* @@ -2090,7 +1896,7 @@ SuffFindDeps (gn, slst) } if (DEBUG(SUFF)) { - printf ("SuffFindDeps (%s)\n", gn->name); + printf("SuffFindDeps (%s)\n", gn->name); } if (gn->type & OP_ARCHV) { @@ -2104,10 +1910,10 @@ SuffFindDeps (gn, slst) * set the TARGET variable to the node's name in order to give it a * value). */ - LstNode ln; + LstNode ln; Suff *s; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, LIBSUFF); + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, LIBSUFF); if (ln != NULL) { gn->suffix = s = (Suff *)Lst_Datum(ln); Arch_FindLib(gn, &s->searchPath); @@ -2121,9 +1927,8 @@ SuffFindDeps (gn, slst) * the thing. .PREFIX is simply made empty... */ Varq_Set(PREFIX_INDEX, "", gn); - } else { + } else SuffFindNormalDeps(gn, slst); - } } /*- @@ -2131,16 +1936,12 @@ SuffFindDeps (gn, slst) * Suff_SetNull -- * Define which suffix is the null suffix. * - * Results: - * None. - * * Side Effects: * 'suffNull' is altered. * * Notes: * Need to handle the changing of the null suffix gracefully so the * old transformation rules don't just go away. - * *----------------------------------------------------------------------- */ void @@ -2150,10 +1951,10 @@ Suff_SetNull(name) Suff *s; LstNode ln; - ln = Lst_Find(&sufflist, SuffSuffHasNameP, name); + ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, name); if (ln != NULL) { s = (Suff *)Lst_Datum(ln); - if (suffNull != (Suff *)NULL) { + if (suffNull != NULL) { suffNull->flags &= ~SUFF_NULL; } s->flags |= SUFF_NULL; @@ -2162,7 +1963,7 @@ Suff_SetNull(name) */ suffNull = s; } else { - Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.", + Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.", name); } } @@ -2172,15 +1973,12 @@ Suff_SetNull(name) * Suff_Init -- * Initialize suffixes module * - * Results: - * None - * * Side Effects: * Many *----------------------------------------------------------------------- */ void -Suff_Init () +Suff_Init() { Lst_Init(&sufflist); #ifdef CLEANUP @@ -2195,17 +1993,17 @@ Suff_Init () * actually go on the suffix list or everyone will think that's its * suffix. */ - emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff)); + emptySuff = suffNull = emalloc(sizeof(Suff)); - suffNull->name = estrdup (""); + suffNull->name = estrdup(""); suffNull->nameLen = 0; Lst_Init(&suffNull->searchPath); Dir_Concat(&suffNull->searchPath, &dirSearchPath); Lst_Init(&suffNull->children); Lst_Init(&suffNull->parents); Lst_Init(&suffNull->ref); - suffNull->sNum = sNum++; - suffNull->flags = SUFF_NULL; + suffNull->sNum = sNum++; + suffNull->flags = SUFF_NULL; } @@ -2215,9 +2013,6 @@ Suff_Init () * Suff_End -- * Cleanup the this module * - * Results: - * None - * * Side Effects: * The memory is free'd. *---------------------------------------------------------------------- @@ -2250,8 +2045,8 @@ SuffPrintSuff(sp) void *sp; { Suff *s = (Suff *)sp; - int flags; - int flag; + int flags; + int flag; printf("# `%s' ", s->name); @@ -2275,11 +2070,14 @@ SuffPrintSuff(sp) fputc(flags ? '|' : ')', stdout); } } - printf("\n#\tTo: "); + fputc('\n', stdout); + printf("#\tTo: "); Lst_Every(&s->parents, SuffPrintName); - printf("\n#\tFrom: "); + fputc('\n', stdout); + printf("#\tFrom: "); Lst_Every(&s->children, SuffPrintName); - printf("\n#\tSearch Path: "); + fputc('\n', stdout); + printf("#\tSearch Path: "); Dir_PrintPath(&s->searchPath); fputc('\n', stdout); } diff --git a/usr.bin/make/targ.c b/usr.bin/make/targ.c index 7e3ee9247fb..aec09a27c01 100644 --- a/usr.bin/make/targ.c +++ b/usr.bin/make/targ.c @@ -1,7 +1,34 @@ -/* $OpenBSD: targ.c,v 1.30 2001/03/02 16:57:26 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: targ.c,v 1.31 2001/05/03 13:41:12 espie Exp $ */ /* $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $ */ /* + * Copyright (c) 1999 Marc Espie. + * + * Extensive code changes for the OpenBSD project. + * + * 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. + */ +/* * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks @@ -44,35 +71,35 @@ * Target nodes are kept into a hash table. * * Interface: - * Targ_Init Initialization procedure. + * Targ_Init Initialization procedure. * - * Targ_End Cleanup the module + * Targ_End Cleanup the module * - * Targ_NewGN Create a new GNode for the passed target - * (string). The node is *not* placed in the - * hash table, though all its fields are - * initialized. + * Targ_NewGN Create a new GNode for the passed target + * (string). The node is *not* placed in the + * hash table, though all its fields are + * initialized. * - * Targ_FindNode Find the node for a given target, creating - * and storing it if it doesn't exist and the - * flags are right (TARG_CREATE) + * Targ_FindNode Find the node for a given target, creating + * and storing it if it doesn't exist and the + * flags are right (TARG_CREATE) * - * Targ_FindList Given a list of names, find nodes for all - * of them, creating nodes if needed. + * 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 - * creating the given target. + * Targ_Ignore Return TRUE if errors should be ignored when + * creating the given target. * - * Targ_Silent Return TRUE if we should be silent when - * creating the given target. + * Targ_Silent Return TRUE if we should be silent when + * creating the given target. * - * Targ_Precious Return TRUE if the target is precious and - * should not be removed if we are interrupted. + * Targ_Precious Return TRUE if the target is precious and + * should not be removed if we are interrupted. * * Debugging: - * Targ_PrintGraph Print out the entire graphm all variables - * and statistics for the directory cache. Should - * print something for suffixes, too, but... + * Targ_PrintGraph Print out the entire graphm all variables + * and statistics for the directory cache. Should + * print something for suffixes, too, but... */ #include <stddef.h> @@ -81,29 +108,28 @@ #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.30 2001/03/02 16:57:26 espie Exp $"; +static char *rcsid = "$OpenBSD: targ.c,v 1.31 2001/05/03 13:41:12 espie Exp $"; #endif #endif /* not lint */ -#ifdef CLEANUP -static LIST allGNs; /* List of all the GNodes */ -#endif -static struct ohash targets; /* a hash table of same */ -static struct ohash_info gnode_info = { - offsetof(GNode, name), + +static struct ohash targets; /* a hash table of same */ +static struct ohash_info gnode_info = { + offsetof(GNode, name), NULL, hash_alloc, hash_free, element_alloc }; -static void TargPrintOnlySrc __P((GNode *)); -static void TargPrintName __P((void *)); -static void TargPrintNode __P((GNode *, int)); +static void TargPrintOnlySrc(GNode *); +static void TargPrintName(void *); +static void TargPrintNode(GNode *, int); #ifdef CLEANUP -static void TargFreeGN __P((void *)); +static void TargFreeGN(void *); #endif /*- @@ -111,16 +137,13 @@ static void TargFreeGN __P((void *)); * Targ_Init -- * Initialize this module * -* Side Effects: + * Side Effects: * The targets hash table is initialized *----------------------------------------------------------------------- */ void Targ_Init() { -#ifdef CLEANUP - Lst_Init(&allGNs); -#endif /* A small make file already creates 200 targets. */ ohash_init(&targets, 10, &gnode_info); } @@ -135,10 +158,15 @@ Targ_Init() *----------------------------------------------------------------------- */ void -Targ_End () +Targ_End() { #ifdef CLEANUP - Lst_Destroy(&allGNs, TargFreeGN); + unsigned int i; + GNode *n; + + for (n = ohash_first(&targets, &i); n != NULL; n = ohash_next(&targets, &i)) + TargFreeGN(n); + ohash_delete(&targets); #endif } @@ -153,15 +181,15 @@ Targ_End () * of the passed name * * Side Effects: - * The gnode is added to the set of all gnodes. + * The gnode is added to the list of all gnodes. *----------------------------------------------------------------------- */ GNode * Targ_NewGN(name, end) - const char *name; /* the name to stick in the new node */ - const char *end; + const char *name; /* the name to stick in the new node */ + const char *end; { - GNode *gn; + GNode *gn; gn = ohash_create_entry(&gnode_info, name, &end); gn->path = NULL; @@ -170,11 +198,11 @@ Targ_NewGN(name, end) } else { gn->type = 0; } - gn->unmade = 0; - gn->make = FALSE; - gn->made = UNMADE; - gn->childMade = FALSE; - gn->order = 0; + gn->unmade = 0; + gn->make = FALSE; + gn->made = UNMADE; + gn->childMade = FALSE; + gn->order = 0; set_out_of_date(gn->mtime); set_out_of_date(gn->cmtime); Lst_Init(&gn->iParents); @@ -189,8 +217,8 @@ Targ_NewGN(name, end) Lst_Init(&gn->commands); gn->suffix = NULL; -#ifdef CLEANUP - Lst_AtEnd(&allGNs, gn); +#ifdef STATS_GN_CREATION + STAT_GN_COUNT++; #endif return gn; @@ -201,19 +229,13 @@ Targ_NewGN(name, end) *----------------------------------------------------------------------- * TargFreeGN -- * Destroy a GNode - * - * Results: - * None. - * - * Side Effects: - * None. *----------------------------------------------------------------------- */ static void TargFreeGN(gnp) void *gnp; { - GNode *gn = (GNode *) gnp; + GNode *gn = (GNode *)gnp; efree(gn->path); Lst_Destroy(&gn->iParents, NOFREE); @@ -222,8 +244,8 @@ TargFreeGN(gnp) Lst_Destroy(&gn->children, NOFREE); Lst_Destroy(&gn->successors, NOFREE); Lst_Destroy(&gn->preds, NOFREE); - SymTable_Destroy(&gn->context); Lst_Destroy(&gn->commands, NOFREE); + SymTable_Destroy(&gn->context); free(gn); } #endif @@ -235,30 +257,30 @@ TargFreeGN(gnp) * Find a node in the list using the given name for matching * * Results: - * The node in the list if it was. If it wasn't, return NULL of + * The node in the list if it was. If it wasn't, return NULL if * flags was TARG_NOCREATE or the newly created and initialized node - * if it was TARG_CREATE + * if flags was TARG_CREATE * * Side Effects: * Sometimes a node is created and added to the list *----------------------------------------------------------------------- */ GNode * -Targ_FindNode(name, flags) +Targ_FindNode(name, end, flags) const char *name; /* the name to find */ - int flags; /* flags governing events when target not + const char *end; + int flags; /* flags governing events when target not * found */ { - const char *end = NULL; - GNode *gn; /* node in that element */ + GNode *gn; /* node in that element */ unsigned int slot; slot = ohash_qlookupi(&targets, name, &end); gn = ohash_find(&targets, slot); - + if (gn == NULL && (flags & TARG_CREATE)) { - gn = Targ_NewGN(name, end); + gn = Targ_NewGN(name, end); ohash_insert(&targets, slot, gn); } @@ -271,30 +293,28 @@ Targ_FindNode(name, flags) * Make a complete list of GNodes from the given list of names * * Side Effects: - * Nodes will be created for all names which do not yet have graph + * Nodes will be created for all names in names which do not yet have graph * nodes. * - * A complete list of graph nodes corresponding to all instances of - * all names is added to nodes. + * A complete list of graph nodes corresponding to all instances of all + * the names in names is added to nodes. * ----------------------------------------------------------------------- */ void Targ_FindList(nodes, names) - Lst nodes; /* result list */ - Lst names; /* list of names to find */ + Lst nodes; /* result list */ + Lst names; /* list of names to find */ { - LstNode ln; /* name list element */ - GNode *gn; /* node in tLn */ - char *name; + LstNode ln; /* name list element */ + GNode *gn; /* node in tLn */ + char *name; for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) { name = (char *)Lst_Datum(ln); - 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. - */ + gn = Targ_FindNode(name, NULL, 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. */ Lst_AtEnd(nodes, gn); if (gn->type & OP_DOUBLEDEP) Lst_Concat(nodes, &gn->cohorts); @@ -303,13 +323,13 @@ Targ_FindList(nodes, names) /*- *----------------------------------------------------------------------- - * Targ_Ignore -- + * Targ_Ignore -- * Return true if should ignore errors when creating gn *----------------------------------------------------------------------- */ Boolean Targ_Ignore(gn) - GNode *gn; /* node to check for */ + GNode *gn; /* node to check for */ { if (ignoreErrors || gn->type & OP_IGNORE) return TRUE; @@ -319,13 +339,13 @@ Targ_Ignore(gn) /*- *----------------------------------------------------------------------- - * Targ_Silent -- + * Targ_Silent -- * Return true if be silent when creating gn *----------------------------------------------------------------------- */ Boolean Targ_Silent(gn) - GNode *gn; /* node to check for */ + GNode *gn; /* node to check for */ { if (beSilent || gn->type & OP_SILENT) return TRUE; @@ -340,8 +360,8 @@ Targ_Silent(gn) *----------------------------------------------------------------------- */ Boolean -Targ_Precious (gn) - GNode *gn; /* the node to check */ +Targ_Precious(gn) + GNode *gn; /* the node to check */ { if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) return TRUE; @@ -364,7 +384,7 @@ static GNode *mainTarg; /* the main target, as set by Targ_SetMain */ */ void Targ_SetMain(gn) - GNode *gn; /* The main target we'll create */ + GNode *gn; /* The main target we'll create */ { mainTarg = gn; } @@ -374,7 +394,6 @@ TargPrintName(gnp) void *gnp; { GNode *gn = (GNode *)gnp; - printf("%s ", gn->name); } @@ -397,23 +416,22 @@ Targ_PrintCmd(cmd) * Side Effects: * The time is placed in a static area, so it is overwritten * with each call. - * *----------------------------------------------------------------------- */ char * Targ_FmtTime(time) - TIMESTAMP time; + TIMESTAMP time; { - struct tm *parts; - static char buf[128]; + struct tm *parts; + static char buf[128]; time_t t; t = timestamp2time_t(time); parts = localtime(&t); - strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); + strftime(buf, sizeof buf, "%H:%M:%S %b %d, %Y", parts); buf[sizeof(buf) - 1] = '\0'; - return(buf); + return buf; } /*- @@ -433,8 +451,8 @@ Targ_PrintType(type) #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break #else -#define PRINTBIT(attr) case CONCAT(OP_,attr): printf(".attr "); break -#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break +#define PRINTBIT(attr) case CONCAT(OP_,attr): printf(".attr "); break +#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break #endif /* __STDC__ */ type &= ~OP_OPMASK; @@ -443,7 +461,7 @@ Targ_PrintType(type) tbit = 1 << (ffs(type) - 1); type &= ~tbit; - switch(tbit) { + switch (tbit) { PRINTBIT(OPTIONAL); PRINTBIT(USE); PRINTBIT(EXEC); @@ -470,34 +488,37 @@ Targ_PrintType(type) */ static void TargPrintNode(gn, pass) - GNode *gn; - int pass; + GNode *gn; + int pass; { if (!OP_NOP(gn->type)) { printf("#\n"); - if (gn == mainTarg) + if (gn == mainTarg) { printf("# *** MAIN TARGET ***\n"); + } if (pass == 2) { - if (gn->unmade) + if (gn->unmade) { printf("# %d unmade children\n", gn->unmade); - else + } else { printf("# No unmade children\n"); + } if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) { - if (!is_out_of_date(gn->mtime)) + if (!is_out_of_date(gn->mtime)) { printf("# last modified %s: %s\n", Targ_FmtTime(gn->mtime), (gn->made == UNMADE ? "unmade" : (gn->made == MADE ? "made" : (gn->made == UPTODATE ? "up-to-date" : "error when made")))); - else if (gn->made != UNMADE) + } else if (gn->made != UNMADE) { printf("# non-existent (maybe): %s\n", (gn->made == MADE ? "made" : (gn->made == UPTODATE ? "up-to-date" : (gn->made == ERROR ? "error when made" : "aborted")))); - else + } else { printf("# unmade\n"); + } } if (!Lst_IsEmpty(&gn->iParents)) { printf("# implicit parents: "); @@ -508,7 +529,7 @@ TargPrintNode(gn, pass) if (!Lst_IsEmpty(&gn->parents)) { printf("# parents: "); Lst_Every(&gn->parents, TargPrintName); - fputc ('\n', stdout); + fputc('\n', stdout); } printf("%-16s", gn->name); @@ -527,8 +548,8 @@ TargPrintNode(gn, pass) printf("\n\n"); if (gn->type & OP_DOUBLEDEP) { LstNode ln; - - for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)) + + for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)) TargPrintNode((GNode *)Lst_Datum(ln), pass); } } @@ -537,15 +558,16 @@ TargPrintNode(gn, pass) /*- *----------------------------------------------------------------------- * TargPrintOnlySrc -- - * Print only those targets that are just a source. + * Print targets that are just a source. *----------------------------------------------------------------------- */ static void TargPrintOnlySrc(gn) - GNode *gn; + GNode *gn; { if (OP_NOP(gn->type)) - printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name); + printf("#\t%s [%s]\n", gn->name, + gn->path != NULL ? gn->path : gn->name); } /*- @@ -556,25 +578,22 @@ TargPrintOnlySrc(gn) */ void Targ_PrintGraph(pass) - int pass; /* Which pass this is. 1 => no processing - * 2 => processing done */ + int pass; /* Which pass this is. 1 => no processing + * 2 => processing done */ { GNode *gn; unsigned int i; printf("#*** Input graph:\n"); - for (gn = ohash_first(&targets, &i); gn != NULL; + for (gn = ohash_first(&targets, &i); gn != NULL; gn = ohash_next(&targets, &i)) TargPrintNode(gn, pass); printf("\n\n"); printf("#\n# Files that are only sources:\n"); - for (gn = ohash_first(&targets, &i); gn != NULL; + for (gn = ohash_first(&targets, &i); gn != NULL; gn = ohash_next(&targets, &i)) TargPrintOnlySrc(gn); - printf("#*** Global Variables:\n"); - Var_Dump(VAR_GLOBAL); - printf("#*** Command-line Variables:\n"); - Var_Dump(VAR_CMD); + Var_Dump(); printf("\n"); Dir_PrintDirectories(); printf("\n"); diff --git a/usr.bin/make/util.c b/usr.bin/make/util.c index 8bbb1cde79f..c3ccc6358ee 100644 --- a/usr.bin/make/util.c +++ b/usr.bin/make/util.c @@ -1,19 +1,19 @@ -/* $OpenBSD: util.c,v 1.13 2000/09/14 13:32:08 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: util.c,v 1.14 2001/05/03 13:41:12 espie Exp $ */ /* $NetBSD: util.c,v 1.10 1996/12/31 17:56:04 christos Exp $ */ /* * Missing stuff from OS's */ +#ifndef lint +static char rcsid[] = "$OpenBSD: util.c,v 1.14 2001/05/03 13:41:12 espie Exp $"; +#endif + #include <stdio.h> #include "make.h" #include <sys/param.h> -#ifndef lint -UNUSED -static char rcsid[] = "$OpenBSD: util.c,v 1.13 2000/09/14 13:32:08 espie Exp $"; -#endif - #ifndef __STDC__ # ifndef const # define const @@ -75,11 +75,9 @@ setenv(name, value, dum) const char *value; int dum; { - register char *p; + char *p; int len = strlen(name) + strlen(value) + 2; /* = \0 */ - char *ptr = (char*) malloc(len); - - (void) dum; + char *ptr = (char*)malloc(len); if (ptr == NULL) return -1; @@ -137,22 +135,22 @@ random() /* turn into bsd signals */ void (* -signal(s, a)) () +signal(s, a))() int s; void (*a)(); { struct sigvec osv, sv; - (void) sigvector(s, (struct sigvec *) 0, &osv); + (void)sigvector(s, (struct sigvec *)0, &osv); sv = osv; sv.sv_handler = a; #ifdef SV_BSDSIG sv.sv_flags = SV_BSDSIG; #endif - if (sigvector(s, &sv, (struct sigvec *) 0) == -1) - return (SIG_ERR); - return (osv.sv_handler); + if (sigvector(s, &sv, (struct sigvec *)0) == -1) + return SIG_ERR; + return osv.sv_handler; } #if !defined(BSD) && !defined(d_fileno) @@ -162,7 +160,7 @@ signal(s, a)) () #ifndef DEV_DEV_COMPARE # define DEV_DEV_COMPARE(a, b) ((a) == (b)) #endif -#define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/'))) +#define ISDOT(c) ((c)[0] == '.' && ((c)[1] == '\0' || (c)[1] == '/')) #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1]))) @@ -171,14 +169,14 @@ signal(s, a)) () */ static char * strrcpy(ptr, str) - register char *ptr, *str; + char *ptr, *str; { - register int len = strlen(str); + size_t len = strlen(str); while (len) *--ptr = str[--len]; - return (ptr); + return ptr; } /* end strrcpy */ @@ -196,9 +194,9 @@ getwd(pathname) /* find the inode of root */ if (stat("/", &st_root) == -1) { - (void) sprintf(pathname, + (void)sprintf(pathname, "getwd: Cannot stat \"/\" (%s)", strerror(errno)); - return (NULL); + return NULL; } pathbuf[MAXPATHLEN - 1] = '\0'; pathptr = &pathbuf[MAXPATHLEN - 1]; @@ -207,9 +205,9 @@ getwd(pathname) /* find the inode of the current directory */ if (lstat(".", &st_cur) == -1) { - (void) sprintf(pathname, + (void)sprintf(pathname, "getwd: Cannot stat \".\" (%s)", strerror(errno)); - return (NULL); + return NULL; } nextpathptr = strrcpy(nextpathptr, "../"); @@ -219,22 +217,22 @@ getwd(pathname) /* look if we found root yet */ if (st_cur.st_ino == st_root.st_ino && DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) { - (void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr); - return (pathname); + (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr); + return pathname; } /* open the parent directory */ if (stat(nextpathptr, &st_dotdot) == -1) { - (void) sprintf(pathname, + (void)sprintf(pathname, "getwd: Cannot stat directory \"%s\" (%s)", nextpathptr, strerror(errno)); - return (NULL); + return NULL; } if ((dp = opendir(nextpathptr)) == NULL) { - (void) sprintf(pathname, + (void)sprintf(pathname, "getwd: Cannot open directory \"%s\" (%s)", nextpathptr, strerror(errno)); - return (NULL); + return NULL; } /* look in the parent for the entry with the same inode */ @@ -252,12 +250,12 @@ getwd(pathname) for (d = readdir(dp); d != NULL; d = readdir(dp)) { if (ISDOT(d->d_name) || ISDOTDOT(d->d_name)) continue; - (void) strcpy(cur_name_add, d->d_name); + (void)strcpy(cur_name_add, d->d_name); if (lstat(nextpathptr, &st_next) == -1) { - (void) sprintf(pathname, "getwd: Cannot stat \"%s\" (%s)", + (void)sprintf(pathname, "getwd: Cannot stat \"%s\" (%s)", d->d_name, strerror(errno)); - (void) closedir(dp); - return (NULL); + (void)closedir(dp); + return NULL; } /* check if we found it yet */ if (st_next.st_ino == st_cur.st_ino && @@ -266,54 +264,54 @@ getwd(pathname) } } if (d == NULL) { - (void) sprintf(pathname, "getwd: Cannot find \".\" in \"..\""); - (void) closedir(dp); - return (NULL); + (void)sprintf(pathname, "getwd: Cannot find \".\" in \"..\""); + (void)closedir(dp); + return NULL; } st_cur = st_dotdot; pathptr = strrcpy(pathptr, d->d_name); pathptr = strrcpy(pathptr, "/"); nextpathptr = strrcpy(nextpathptr, "../"); - (void) closedir(dp); + (void)closedir(dp); *cur_name_add = '\0'; } } /* end getwd */ -char *sys_siglist[] = { - "Signal 0", - "Hangup", /* SIGHUP */ - "Interrupt", /* SIGINT */ - "Quit", /* SIGQUIT */ - "Illegal instruction", /* SIGILL */ - "Trace/BPT trap", /* SIGTRAP */ - "IOT trap", /* SIGIOT */ - "EMT trap", /* SIGEMT */ - "Floating point exception", /* SIGFPE */ - "Killed", /* SIGKILL */ - "Bus error", /* SIGBUS */ - "Segmentation fault", /* SIGSEGV */ - "Bad system call", /* SIGSYS */ - "Broken pipe", /* SIGPIPE */ - "Alarm clock", /* SIGALRM */ - "Terminated", /* SIGTERM */ - "User defined signal 1", /* SIGUSR1 */ - "User defined signal 2", /* SIGUSR2 */ - "Child exited", /* SIGCLD */ - "Power-fail restart", /* SIGPWR */ - "Virtual timer expired", /* SIGVTALRM */ - "Profiling timer expired", /* SIGPROF */ - "I/O possible", /* SIGIO */ - "Window size changes", /* SIGWINDOW */ - "Stopped (signal)", /* SIGSTOP */ - "Stopped", /* SIGTSTP */ - "Continued", /* SIGCONT */ - "Stopped (tty input)", /* SIGTTIN */ - "Stopped (tty output)", /* SIGTTOU */ - "Urgent I/O condition", /* SIGURG */ - "Remote lock lost (NFS)", /* SIGLOST */ - "Signal 31", /* reserved */ - "DIL signal" /* SIGDIL */ +char *sys_siglist[] = { + "Signal 0", + "Hangup", /* SIGHUP */ + "Interrupt", /* SIGINT */ + "Quit", /* SIGQUIT */ + "Illegal instruction", /* SIGILL */ + "Trace/BPT trap", /* SIGTRAP */ + "IOT trap", /* SIGIOT */ + "EMT trap", /* SIGEMT */ + "Floating point exception", /* SIGFPE */ + "Killed", /* SIGKILL */ + "Bus error", /* SIGBUS */ + "Segmentation fault", /* SIGSEGV */ + "Bad system call", /* SIGSYS */ + "Broken pipe", /* SIGPIPE */ + "Alarm clock", /* SIGALRM */ + "Terminated", /* SIGTERM */ + "User defined signal 1", /* SIGUSR1 */ + "User defined signal 2", /* SIGUSR2 */ + "Child exited", /* SIGCLD */ + "Power-fail restart", /* SIGPWR */ + "Virtual timer expired", /* SIGVTALRM */ + "Profiling timer expired", /* SIGPROF */ + "I/O possible", /* SIGIO */ + "Window size changes", /* SIGWINDOW */ + "Stopped (signal)", /* SIGSTOP */ + "Stopped", /* SIGTSTP */ + "Continued", /* SIGCONT */ + "Stopped (tty input)", /* SIGTTIN */ + "Stopped (tty output)", /* SIGTTOU */ + "Urgent I/O condition", /* SIGURG */ + "Remote lock lost (NFS)", /* SIGLOST */ + "Signal 31", /* reserved */ + "DIL signal" /* SIGDIL */ }; int @@ -325,7 +323,7 @@ utimes(file, tvp) t.actime = tvp[0].tv_sec; t.modtime = tvp[1].tv_sec; - return(utime(file, &t)); + return utime(file, &t); } @@ -336,7 +334,7 @@ utimes(file, tvp) /* turn into bsd signals */ void (* -signal(s, a)) () +signal(s, a))() int s; void (*a)(); { @@ -363,9 +361,9 @@ signal(s, a)) () #endif #ifdef _IOSTRG -#define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */ +#define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */ #else -#define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */ +#define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */ #endif int @@ -382,7 +380,7 @@ vsnprintf(s, n, fmt, args) * Some os's are char * _ptr, others are unsigned char *_ptr... * We cast to void * to make everyone happy. */ - fakebuf._ptr = (void *) s; + fakebuf._ptr = (void *)s; fakebuf._cnt = n-1; fakebuf._file = -1; _doprnt(fmt, args, &fakebuf); @@ -390,7 +388,7 @@ vsnprintf(s, n, fmt, args) putc('\0', &fakebuf); if (fakebuf._cnt<0) fakebuf._cnt = 0; - return (n-fakebuf._cnt-1); + return n-fakebuf._cnt-1; } int @@ -421,7 +419,6 @@ snprintf(va_alist) return rv; } #endif - #ifdef NEED_STRSTR char * strstr(string, substring) @@ -462,7 +459,7 @@ fgetln(stream, len) static size_t buflen = 0; if (buflen == 0) { - buflen = 512; + buflen = 512; buffer = emalloc(buflen+1); } if (fgets(buffer, buflen+1, stream) == NULL) diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c index a40a5fb0d83..05b8c976b9b 100644 --- a/usr.bin/make/var.c +++ b/usr.bin/make/var.c @@ -1,8 +1,9 @@ -/* $OpenBSD: var.c,v 1.52 2001/03/02 16:57:26 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: var.c,v 1.53 2001/05/03 13:41:13 espie Exp $ */ /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */ /* - * Copyright (c) 1999 Marc Espie. + * Copyright (c) 1999,2000 Marc Espie. * * Extensive code modifications for the OpenBSD project. * @@ -27,7 +28,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - /* * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -70,60 +70,57 @@ * var.c -- * Variable-handling functions * - * 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. + * 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. + * 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_Exists See if a variable exists. + * Var_Value Return the value of a variable in a context or + * NULL if the variable is undefined. * - * 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_Subst Substitute named variable, or all variables if - * NULL 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_Init Initialize this module. * - * 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. + * Fast interface: + * Varq_Set, Varq_Append, Varq_Value: + * Use index form of local variables * - * Var_Parse Parse a variable expansion from a string and - * return the result and the number of characters - * consumed. + * 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_Delete Delete a variable in a context. + * 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_Init Initialize this module. + * 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 variables defined in the given - * context. - * - * XXX: There's a lot of duplication in these functions. + * Var_Dump Print out all global variables. */ +#include <assert.h> #include <ctype.h> -#ifndef MAKE_BOOTSTRAP -#include <sys/types.h> -#include <regex.h> -#endif #include <stdlib.h> #include <stddef.h> +#include <string.h> #include "make.h" #include "buf.h" +#include "stats.h" #include "ohash.h" -#include "hashconsts.h" #include "varmodifiers.h" #ifndef lint @@ -131,27 +128,17 @@ static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; #else UNUSED -static char rcsid[] = "$OpenBSD: var.c,v 1.52 2001/03/02 16:57:26 espie Exp $"; +static char rcsid[] = "$OpenBSD: var.c,v 1.53 2001/05/03 13:41:13 espie Exp $"; #endif #endif /* not lint */ -static SymTable *CTXT_GLOBAL, *CTXT_CMD, *CTXT_ENV; - -static char *varnames[] = { - TARGET, - OODATE, - ALLSRC, - IMPSRC, - PREFIX, - ARCHIVE, - MEMBER }; /* * This is a harmless return value for Var_Parse that can be used by Var_Subst * to determine if there was an error in parsing -- easier than returning * a flag, as things outside this module don't give a hoot. */ -char var_Error[] = ""; +char var_Error[] = ""; /* * Similar to var_Error, but returned when the 'err' flag for Var_Parse is @@ -161,10 +148,11 @@ char var_Error[] = ""; static char varNoError[] = ""; /* - * Internally, variables are contained in four different contexts. - * 1) the environment. They may not be changed. If an environment - * variable is appended-to, the result is placed in the global - * context. + * Variable values are obtained from four different contexts: + * 1) the process environment. The process environment itself + * may not be changed, but these variables may be modified, + * unless make is invoked with -e, in which case those variables + * are unmodifiable and supersede the global context. * 2) the global context. Variables set in the Makefile are located in * the global context. It is the penultimate context searched when * substituting. @@ -178,47 +166,130 @@ static char varNoError[] = ""; */ GSymT *VAR_GLOBAL; /* variables from the makefile */ GSymT *VAR_CMD; /* variables defined on the command-line */ -static GSymT *VAR_ENV; /* variables read from env */ + +static SymTable *CTXT_GLOBAL, *CTXT_CMD; + + +static char *varnames[] = { + TARGET, + PREFIX, + ARCHIVE, + MEMBER, + OODATE, + ALLSRC, + IMPSRC, + FTARGET, + DTARGET, + FPREFIX, + DPREFIX, + FARCHIVE, + DARCHIVE, + FMEMBER, + DMEMBER + }; + #define FIND_MINE 0x1 /* look in CTXT_CMD and CTXT_GLOBAL */ -#define FIND_ENV 0x2 /* look in the environment */ +#define FIND_ENV 0x2 /* look in the environment */ typedef struct Var_ { - BUFFER val; /* its value */ - int flags; /* miscellaneous status flags */ -#define VAR_IN_USE 1 /* Variable's value currently being used. - * Used to avoid recursion */ -#define VAR_JUNK 4 /* Variable is a junk variable that - * should be destroyed when done with - * it. Used by Var_Parse for undefined, - * modified variables */ - char name[1]; /* the variable's name */ + BUFFER val; /* its value */ + unsigned int flags; /* miscellaneous status flags */ +#define VAR_IN_USE 1 /* Variable's value currently being used. + * Used to avoid recursion */ +#define VAR_READ_ONLY 2 /* Environment variable not modifiable */ +#define VAR_FROM_ENV 4 /* Var was read from env */ +#define VAR_DUMMY 8 /* Var does not exist, actually */ + char name[1]; /* the variable's name */ } Var; -static struct ohash_info var_info = { - offsetof(Var, name), + +static struct ohash_info var_info = { + offsetof(Var, name), NULL, hash_alloc, hash_free, element_alloc }; -static int quick_lookup __P((const char *, const char **, u_int32_t *)); +static int quick_lookup(const char *, const char **, u_int32_t *); #define VarValue(v) Buf_Retrieve(&((v)->val)) -static Var *varfind __P((const char *, const char *, SymTable *, int, int, u_int32_t)); -static Var *VarFind_interval __P((const char *, const char *, SymTable *, int)); -#define VarFind(n, ctxt, flags) VarFind_interval(n, NULL, ctxt, flags) -static Var *VarAdd __P((const char *, const char *, GSymT *)); -static void VarDelete __P((void *)); -static void VarPrintVar __P((void *)); -static const char *context_name __P((GSymT *)); -static Var *new_var __P((const char *, const char *)); -static Var *getvar __P((GSymT *, const char *, const char *, u_int32_t)); -static Var *var_name_with_dollar __P((char *, char **, SymTable *, Boolean, char)); +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 *VarAdd(const char *, const char *, u_int32_t, const char *, GSymT *); +static void VarDelete(void *); +static void VarPrintVar(Var *); +static const char *context_name(GSymT *); +static Var *new_var(const char *, const char *, const char *); +static Var *getvar(GSymT *, const char *, const char *, u_int32_t); +static Var *create_var(const char *, const char *); +static Var *var_from_env(const char *, const char *, u_int32_t); +static void var_init_string(Var *, const char *); + +static const char *find_0(const char *); +static const char *find_rparen(const char *); +static const char *find_ket(const char *); +typedef const char * (*find_t)(const char *); +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; { - static SymTable sym_template; + static SymTable sym_template; memcpy(ctxt, &sym_template, sizeof(*ctxt)); } +#ifdef CLEANUP void SymTable_Destroy(ctxt) SymTable *ctxt; @@ -229,6 +300,7 @@ SymTable_Destroy(ctxt) if (ctxt->locals[i] != NULL) VarDelete(ctxt->locals[i]); } +#endif static int quick_lookup(name, end, pk) @@ -241,82 +313,114 @@ quick_lookup(name, end, pk) *pk = ohash_interval(name, end); len = *end - name; /* substitute short version for long local name */ - switch (*pk % MAGICSLOTS) { /* MAGICSLOTS should be the */ - case K_LONGALLSRC % MAGICSLOTS: /* smallest constant yielding */ - /* distinct case values */ + switch (*pk % MAGICSLOTS1) { /* MAGICSLOTS should be the */ + case K_LONGALLSRC % MAGICSLOTS1: /* smallest constant yielding */ + /* distinct case values */ if (*pk == K_LONGALLSRC && strncmp(name, LONGALLSRC, len) == 0 && len == strlen(LONGALLSRC)) return ALLSRC_INDEX; break; - case K_LONGARCHIVE % MAGICSLOTS: + case K_LONGARCHIVE % MAGICSLOTS1: if (*pk == K_LONGARCHIVE && strncmp(name, LONGARCHIVE, len) == 0 && len == strlen(LONGARCHIVE)) return ARCHIVE_INDEX; break; - case K_LONGIMPSRC % MAGICSLOTS: + case K_LONGIMPSRC % MAGICSLOTS1: if (*pk == K_LONGIMPSRC && strncmp(name, LONGIMPSRC, len) == 0 && len == strlen(LONGIMPSRC)) return IMPSRC_INDEX; break; - case K_LONGMEMBER % MAGICSLOTS: + case K_LONGMEMBER % MAGICSLOTS1: if (*pk == K_LONGMEMBER && strncmp(name, LONGMEMBER, len) == 0 && len == strlen(LONGMEMBER)) return MEMBER_INDEX; break; - case K_LONGOODATE % MAGICSLOTS: + case K_LONGOODATE % MAGICSLOTS1: if (*pk == K_LONGOODATE && strncmp(name, LONGOODATE, len) == 0 && len == strlen(LONGOODATE)) return OODATE_INDEX; break; - case K_LONGPREFIX % MAGICSLOTS: + case K_LONGPREFIX % MAGICSLOTS1: if (*pk == K_LONGPREFIX && strncmp(name, LONGPREFIX, len) == 0 && len == strlen(LONGPREFIX)) return PREFIX_INDEX; break; - case K_LONGTARGET % MAGICSLOTS: + case K_LONGTARGET % MAGICSLOTS1: if (*pk == K_LONGTARGET && strncmp(name, LONGTARGET, len) == 0 && len == strlen(LONGTARGET)) return TARGET_INDEX; break; - case K_TARGET % MAGICSLOTS: + case K_TARGET % MAGICSLOTS1: if (name[0] == TARGET[0] && len == 1) return TARGET_INDEX; break; - case K_OODATE % MAGICSLOTS: + case K_OODATE % MAGICSLOTS1: if (name[0] == OODATE[0] && len == 1) return OODATE_INDEX; break; - case K_ALLSRC % MAGICSLOTS: + case K_ALLSRC % MAGICSLOTS1: if (name[0] == ALLSRC[0] && len == 1) return ALLSRC_INDEX; break; - case K_IMPSRC % MAGICSLOTS: + case K_IMPSRC % MAGICSLOTS1: if (name[0] == IMPSRC[0] && len == 1) return IMPSRC_INDEX; break; - case K_PREFIX % MAGICSLOTS: + case K_PREFIX % MAGICSLOTS1: if (name[0] == PREFIX[0] && len == 1) return PREFIX_INDEX; break; - case K_ARCHIVE % MAGICSLOTS: + case K_ARCHIVE % MAGICSLOTS1: if (name[0] == ARCHIVE[0] && len == 1) return ARCHIVE_INDEX; break; - case K_MEMBER % MAGICSLOTS: + case K_MEMBER % MAGICSLOTS1: if (name[0] == MEMBER[0] && len == 1) return MEMBER_INDEX; break; + case K_FTARGET % MAGICSLOTS1: + if (name[0] == FTARGET[0] && name[1] == FTARGET[1] && len == 2) + return FTARGET_INDEX; + break; + case K_DTARGET % MAGICSLOTS1: + if (name[0] == DTARGET[0] && name[1] == DTARGET[1] && len == 2) + return DTARGET_INDEX; + break; + case K_FPREFIX % MAGICSLOTS1: + if (name[0] == FPREFIX[0] && name[1] == FPREFIX[1] && len == 2) + return FPREFIX_INDEX; + break; + case K_DPREFIX % MAGICSLOTS1: + if (name[0] == DPREFIX[0] && name[1] == DPREFIX[1] && len == 2) + return DPREFIX_INDEX; + break; + case K_FARCHIVE % MAGICSLOTS1: + if (name[0] == FARCHIVE[0] && name[1] == FARCHIVE[1] && len == 2) + return FARCHIVE_INDEX; + break; + case K_DARCHIVE % MAGICSLOTS1: + if (name[0] == DARCHIVE[0] && name[1] == DARCHIVE[1] && len == 2) + return DARCHIVE_INDEX; + break; + case K_FMEMBER % MAGICSLOTS1: + if (name[0] == FMEMBER[0] && name[1] == FMEMBER[1] && len == 2) + return FMEMBER_INDEX; + break; + case K_DMEMBER % MAGICSLOTS1: + if (name[0] == DMEMBER[0] && name[1] == DMEMBER[1] && len == 2) + return DMEMBER_INDEX; + break; default: break; } return -1; } -void +void Varq_Set(idx, val, gn) int idx; - const char *val; - GNode *gn; + const char *val; + GNode *gn; { /* We only look for a variable in the given context since anything set * here will override anything in a lower context, so there's not much @@ -324,27 +428,28 @@ Varq_Set(idx, val, gn) Var *v = gn->context.locals[idx]; if (v == NULL) { - v = new_var(varnames[idx], val); + v = new_var(varnames[idx], NULL, val); v->flags = 0; gn->context.locals[idx] = v; } else { Buf_Reset(&(v->val)); Buf_AddString(&(v->val), val); + } if (DEBUG(VAR)) printf("%s:%s = %s\n", gn->name, varnames[idx], val); } -void +void Varq_Append(idx, val, gn) - int idx; + int idx; const char *val; GNode *gn; { - Var *v = gn->context.locals[idx]; + Var *v = gn->context.locals[idx]; if (v == NULL) { - v = new_var(varnames[idx], val); + v = new_var(varnames[idx], NULL, val); v->flags = 0; gn->context.locals[idx] = v; } else { @@ -357,63 +462,109 @@ Varq_Append(idx, val, gn) char * Varq_Value(idx, gn) - int idx; + int idx; GNode *gn; { Var *v = gn->context.locals[idx]; - if (v != NULL) - return VarValue(v); - else + if (v == NULL) return NULL; + else + return VarValue(v); } -Boolean -Varq_Exists(idx, gn) - int idx; - GNode *gn; -{ - return gn->context.locals[idx] != NULL; -} - - static const char * context_name(ctxt) GSymT *ctxt; { if (ctxt == VAR_GLOBAL) - return "Global"; - else if (ctxt == VAR_CMD) - return "Command"; - else - return "Environment"; + return "Global"; + if (ctxt == VAR_CMD) + return "Command"; + return "Error"; } - -/* Create a variable, to pass to VarAdd. */ + +/* We separate var creation proper from setting of initial value: + * VAR_DUMMY corresponds to `lazy' setup, e.g., always create global + * variable at first lookup, and then fill it up when value is wanted. + * This avoids looking through the environment several times. + */ static Var * -new_var(name, val) - const char *name; - const char *val; +create_var(name, end) + const char *name; + const char *end; { + return ohash_create_entry(&var_info, name, &end); +} + +/* Set the initial value a var should have */ +static void +var_init_string(v, val) Var *v; - const char *end = NULL; + const char *val; +{ + size_t len; + + len = strlen(val); + Buf_Init(&(v->val), len+1); + Buf_AddChars(&(v->val), len, val); +} + +static Var * +new_var(name, end, val) + const char *name; + const char *end; + const char *val; +{ + Var *v; + + v = create_var(name, end); +#ifdef STATS_VAR_LOOKUP + STAT_VAR_CREATION++; +#endif + if (val != NULL) + var_init_string(v, val); + else + Buf_Init(&(v->val), 1); - v = ohash_create_entry(&var_info, name, &end); + return v; +} + +static Var * +var_from_env(name, end, k) + const char *name; + const char *end; + u_int32_t k; +{ + char *env; + Var *v; + + /* getenv requires a null-terminated name, so we create the var + * structure first. */ + v = create_var(name, end); + env = getenv(v->name); + if (env == NULL) + v->flags = VAR_DUMMY; + else { + var_init_string(v, env); + if (checkEnvFirst) + v->flags = VAR_READ_ONLY | VAR_FROM_ENV; + else + v->flags = VAR_FROM_ENV; + } - if (val != NULL) { - size_t len = strlen(val); - Buf_Init(&(v->val), len+1); - Buf_AddChars(&(v->val), len, val); - } else - Buf_Init(&(v->val), 1); +#ifdef STATS_VAR_LOOKUP + STAT_VAR_FROM_ENV++; +#endif + ohash_insert(VAR_GLOBAL, ohash_lookup_interval(VAR_GLOBAL, name, end, k), v); return v; } static Var * getvar(ctxt, name, end, k) GSymT *ctxt; - const char *name; + const char *name; const char *end; u_int32_t k; { @@ -425,28 +576,29 @@ getvar(ctxt, name, end, k) * VarFind_interval -- * 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. + * the interval name - end is concerned. * * Results: * A pointer to the structure describing the desired variable or * NULL if the variable does not exist. - * - * Side Effects: - * Caches env variables in the VAR_ENV context. *----------------------------------------------------------------------- */ static Var * VarFind_interval(name, end, ctxt, flags) - const char *name; /* name to find */ + const char *name; /* name to find */ const char *end; /* end of name */ - SymTable *ctxt; /* context in which to find it */ - int flags; /* FIND_MINE set means to look in the + SymTable *ctxt; /* context in which to find it */ + int flags; /* FIND_MINE set means to look in the * CTXT_GLOBAL and CTXT_CMD contexts also. * FIND_ENV set means to look in the * environment */ { - int idx; u_int32_t k; + int idx; + +#ifdef STATS_VAR_LOOKUP + STAT_VAR_FIND++; +#endif idx = quick_lookup(name, &end, &k); return varfind(name, end, ctxt, flags, idx, k); @@ -457,58 +609,66 @@ varfind(name, end, ctxt, flags, idx, k) const char *name; const char *end; SymTable *ctxt; - int flags; - int idx; + int flags; + int idx; u_int32_t k; { - Var *v; - - /* - * First look for the variable in the given context. If it's not there, - * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, - * depending on the FIND_* flags in 'flags' - */ - if (ctxt == NULL) - v = NULL; - else if (ctxt == CTXT_GLOBAL || ctxt == CTXT_CMD || ctxt == CTXT_ENV) - v = getvar((GSymT *)ctxt, name, end, k); - else { - if (idx == -1) - v = NULL; - else - v = ctxt->locals[idx]; - } - if (v != NULL) - return v; - - if ((flags & FIND_MINE) && ctxt != CTXT_CMD) - v = getvar(VAR_CMD, name, end, k); - if (v != NULL) - return v; - - if (!checkEnvFirst && (flags & FIND_MINE) && ctxt != CTXT_GLOBAL) - v = getvar(VAR_GLOBAL, name, end, k); - if (v != NULL) - return v; - - if ((flags & FIND_ENV)) { - char *env; - char *n; - - v = getvar(VAR_ENV, name, end, k); - if (v != NULL) - return v; - - /* getenv requires a null-terminated name */ - n = interval_dup(name, end); - env = getenv(n); - free(n); - if (env != NULL) - return VarAdd(name, env, VAR_ENV); + Var *v; + + /* Handle local variables first */ + if (idx != -1) { + if (ctxt != NULL && ctxt != CTXT_CMD && ctxt != CTXT_GLOBAL) { + if (idx < LOCAL_SIZE) + return ctxt->locals[idx]; + else + return ctxt->locals[EXTENDED2SIMPLE(idx)]; + } else + return NULL; } + /* First look for the variable in the given context. If it's not there, + look for it in CTXT_CMD, CTXT_GLOBAL and the environment, + depending on the FIND_* flags in 'flags' */ + if (ctxt == CTXT_CMD || ctxt == CTXT_GLOBAL) + v = getvar((GSymT *)ctxt, name, end, k); + else + v = NULL; - if (checkEnvFirst && (flags & FIND_MINE) && ctxt != CTXT_GLOBAL) - v = getvar(VAR_GLOBAL, name, end, k); + if (v == NULL) + switch (flags) { + case 0: + break; + case FIND_MINE: + if (ctxt != CTXT_CMD) + v = getvar(VAR_CMD, name, end, k); + if (v == NULL && ctxt != CTXT_GLOBAL) + v = getvar(VAR_GLOBAL, name, end, k); + break; + case FIND_ENV: + v = var_from_env(name, end, k); + break; + case FIND_ENV | FIND_MINE: + if (ctxt != CTXT_CMD) + v = getvar(VAR_CMD, name, end, k); + if (v == NULL) { + if (ctxt != CTXT_GLOBAL) + v = getvar(VAR_GLOBAL, name, end, k); + if (v == NULL) + v = var_from_env(name, end, k); + else if (checkEnvFirst && (v->flags & VAR_FROM_ENV) == 0) { + char *env; + + env = getenv(v->name); + if (env != NULL) { + Buf_Reset(&(v->val)); + Buf_AddString(&(v->val), env); + } + /* XXX even if no such env variable, fake it, to avoid + * further lookup */ + v->flags |= VAR_FROM_ENV; + } + } + break; + } return v; } @@ -518,7 +678,7 @@ varfind(name, end, ctxt, flags, idx, k) * Add a new variable of name name and value val to the given context * * Results: - * The added variable + * The added variable. * * Side Effects: * The new variable is placed in the given context. @@ -527,31 +687,25 @@ varfind(name, end, ctxt, flags, idx, k) *----------------------------------------------------------------------- */ static Var * -VarAdd(name, val, ctxt) +VarAdd(name, end, k, val, ctxt) const char *name; /* name of variable to add */ + const char *end; + u_int32_t k; const char *val; /* value to set it to */ GSymT *ctxt; /* context in which to set it */ { - Var *v; - const char *end = NULL; - int idx; - u_int32_t k; + Var *v; - v = new_var(name, val); + v = new_var(name, end, val); v->flags = 0; - idx = quick_lookup(name, &end, &k); - - if (idx != -1) - Parse_Error(PARSE_FATAL, "Trying to set dynamic variable %s", - v->name); - else - ohash_insert(ctxt, ohash_lookup_interval(ctxt, name, end, k), v); + ohash_insert(ctxt, ohash_lookup_interval(ctxt, name, end, k), v); + if (DEBUG(VAR)) + printf("%s:%s = %s\n", context_name(ctxt), v->name, val); return v; } - /*- *----------------------------------------------------------------------- * VarDelete -- @@ -560,11 +714,12 @@ VarAdd(name, val, ctxt) */ static void VarDelete(vp) - void *vp; + void *vp; { - Var *v = (Var *) vp; + Var *v = (Var *)vp; - Buf_Destroy(&(v->val)); + if ((v->flags & VAR_DUMMY) == 0) + Buf_Destroy(&(v->val)); free(v); } @@ -573,28 +728,35 @@ VarDelete(vp) /*- *----------------------------------------------------------------------- * Var_Delete -- - * Remove a variable from a context. + * Remove a global variable. * * Side Effects: * The Var structure is removed and freed. *----------------------------------------------------------------------- */ void -Var_Delete(name, ctxt) - const char *name; - GSymT *ctxt; +Var_Delete(name) + const char *name; { Var *v; u_int32_t k; + unsigned int slot; const char *end = NULL; + int idx; + if (DEBUG(VAR)) - printf("%s:delete %s\n", context_name(ctxt), name); - (void)quick_lookup(name, &end, &k); - v = ohash_remove(ctxt, ohash_lookup_interval(ctxt, name, end, k)); + printf("delete %s\n", name); - if (v != NULL) + idx = quick_lookup(name, &end, &k); + if (idx != -1) + Parse_Error(PARSE_FATAL, "Trying to delete dynamic variable"); + slot = ohash_lookup_interval(VAR_GLOBAL, name, end, k); + v = ohash_find(VAR_GLOBAL, slot); + if (v != NULL && (v->flags & VAR_READ_ONLY) == 0) { + ohash_remove(VAR_GLOBAL, slot); VarDelete(v); + } } /*- @@ -608,46 +770,51 @@ Var_Delete(name, ctxt) * * Notes: * The variable is searched for only in its context before being - * created in that context. I.e. if the context is VAR_GLOBAL, - * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only - * VAR_CMD->context is searched. This is done to avoid the literally - * thousands of unnecessary strcmp's that used to be done to - * set, say, $(@) or $(<). + * 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(name, val, ctxt) +Var_Set_interval(name, end, val, ctxt) const char *name; /* name of variable to set */ + const char *end; const char *val; /* value to give to the variable */ - GSymT *ctxt; /* context in which to set it */ + GSymT *ctxt; /* context in which to set it */ { Var *v; + u_int32_t k; + int idx; + + idx = quick_lookup(name, &end, &k); + if (idx != -1) + Parse_Error(PARSE_FATAL, "Trying to set dynamic variable $%s", + varnames[idx]); - /* - * We only look for a variable in the given context since anything set + /* We only look for a variable in the given context since anything set * here will override anything in a lower context, so there's not much - * point in searching them all just to save a bit of memory... - */ - v = VarFind(name, (SymTable *)ctxt, 0); + * point in searching them all just to save a bit of memory... */ + v = varfind(name, end, (SymTable *)ctxt, 0, idx, k); if (v == NULL) - (void)VarAdd(name, val, ctxt); + v = VarAdd(name, end, k, val, ctxt); else { - Buf_Reset(&(v->val)); - Buf_AddString(&(v->val), val); + if ((v->flags & VAR_READ_ONLY) == 0) { + if ((v->flags & VAR_DUMMY) == 0) { + Buf_Reset(&(v->val)); + Buf_AddString(&(v->val), val); + } else { + var_init_string(v, val); + v->flags &= ~VAR_DUMMY; + } + + } } if (DEBUG(VAR)) - printf("%s:%s = %s\n", context_name(ctxt), name, val); - /* - * Any variables given on the command line are automatically exported - * to the environment (as per POSIX standard). - * We put them into the env cache directly. - * (Note that additions to VAR_CMD occur very early, so VAR_ENV is - * actually empty at this point). - */ - if (ctxt == VAR_CMD) { - esetenv(name, val); - (void)VarAdd(name, val, VAR_ENV); - } + printf("%s:%s = %s\n", context_name(ctxt), v->name, val); + /* Any variables given on the command line are automatically exported + * to the environment (as per POSIX standard). */ + if (ctxt == VAR_CMD) + esetenv(v->name, val); } /*- @@ -660,126 +827,193 @@ Var_Set(name, val, ctxt) * If the variable doesn't exist, it is created. Else the strings * are concatenated (with a space in between). * - * Notes: - * Only if the variable is being sought in the global context is the - * environment searched. - * XXX: Knows its calling circumstances in that if called with ctxt - * an actual target, it will only search that context since only - * a local variable could be being appended to. This is actually - * a big win and must be tolerated. *----------------------------------------------------------------------- */ void -Var_Append(name, val, ctxt) +Var_Append_interval(name, end, val, ctxt) const char *name; /* Name of variable to modify */ + const char *end; const char *val; /* String to append to it */ GSymT *ctxt; /* Context in which this should occur */ { - Var *v; + Var *v; + u_int32_t k; + int idx; - v = VarFind(name, (SymTable *)ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0); + assert(ctxt == VAR_GLOBAL || ctxt == VAR_CMD); + + idx = quick_lookup(name, &end, &k); + if (idx != -1) + Parse_Error(PARSE_FATAL, "Trying to append to dynamic variable $%s", + varnames[idx]); + + v = varfind(name, end, (SymTable *)ctxt, FIND_ENV, idx, k); + + if ((v->flags & VAR_READ_ONLY) == 0) { + if ((v->flags & VAR_DUMMY) == 0) { + Buf_AddSpace(&(v->val)); + Buf_AddString(&(v->val), val); + } else { + var_init_string(v, val); + v->flags &= ~VAR_DUMMY; + } - if (v == NULL) { - v = VarAdd(name, val, ctxt); - } else { - Buf_AddSpace(&(v->val)); - Buf_AddString(&(v->val), val); } if (DEBUG(VAR)) - printf("%s:%s = %s\n", context_name(ctxt), name, VarValue(v)); + printf("%s:%s = %s\n", context_name(ctxt), v->name, VarValue(v)); } /*- *----------------------------------------------------------------------- - * Var_Exists -- - * See if the given variable exists. + * Var_Value -- + * Return the value of a global named variable * * Results: - * TRUE if it does, FALSE if it doesn't + * The value if the variable exists, NULL if it doesn't *----------------------------------------------------------------------- */ -Boolean -Var_Exists(name, ctxt) - const char *name; /* Variable to find */ - GSymT *ctxt; /* Context in which to start search */ +char * +Var_Value_interval(name, end) + const char *name; /* name to find */ + const char *end; { - Var *v; + Var *v; - v = VarFind(name, (SymTable *)ctxt, FIND_MINE|FIND_ENV); - - if (v == NULL) - return FALSE; + v = VarFind_interval(name, end, NULL, FIND_ENV | FIND_MINE); + if (v != NULL && (v->flags & VAR_DUMMY) == 0) + return VarValue(v); else - return TRUE; + return NULL; +} + +static const char * +find_0(p) + const char *p; +{ + while (*p != '$' && *p != '\0' && *p != ':') + p++; + return p; +} + +static const char * +find_rparen(p) + const char *p; +{ + while (*p != '$' && *p != '\0' && *p != ')' && *p != ':') + p++; + return p; +} + +static const char * +find_ket(p) + const char *p; +{ + while (*p != '$' && *p != '\0' && *p != '}' && *p != ':') + p++; + return p; +} + +static find_t +find_pos(c) + int c; +{ + switch(c) { + case '\0': + return find_0; + case ')': + return find_rparen; + case '}': + return find_ket; + default: + return 0; + } } /*- *----------------------------------------------------------------------- - * Var_Value -- - * Return the value of the named variable in the given context + * 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. * - * Results: - * The value if the variable exists, NULL if it doesn't + * Return value: the amount to skip *----------------------------------------------------------------------- */ -char * -Var_Value(name, ctxt) - const char *name; /* name to find */ - GSymT *ctxt; /* context in which to search for it */ +size_t +Var_ParseSkip(str, ctxt, result) + const char *str; + SymTable *ctxt; + ReturnStatus *result; { - Var *v; + const char *tstr; /* Pointer into str */ + Var *v; /* Variable in invocation */ + char endc; /* Ending character when variable in parens + * or braces */ + const char *start; + size_t length; + struct Name name; - v = VarFind(name, (SymTable *)ctxt, FIND_ENV | FIND_MINE); - if (v != NULL) - return VarValue(v); - else - return NULL; + v = NULL; + start = str; + str++; + + if (*str != '(' && *str != '{') { + name.tofree = FALSE; + tstr = str + 1; + length = 2; + endc = '\0'; + } else { + endc = *str == '(' ? ')' : '}'; + str++; + + /* Find eventual modifiers in the variable */ + tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc)); + Var_Name_Free(&name); + length = tstr+1 - start; + } + + if (result != NULL) + *result = SUCCESS; + if (*tstr == ':' && endc != '\0') + if (VarModifiers_Apply(NULL, NULL, ctxt, TRUE, NULL, tstr, endc, + &length) == var_Error) + *result = FAILURE; + return length; } -/* +/*- *----------------------------------------------------------------------- - * v = var_name_with_dollar(str, &pos, ctxt, err, endc) - * handle variable name that contains a dollar - * str points to the first letter of the variable name, - * &pos to the current position in the name (first dollar at invocation, - * end of name specification at return). - * returns the corresponding variable. + * 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...?). *----------------------------------------------------------------------- */ -static Var * -var_name_with_dollar(str, pos, ctxt, err, endc) - char *str; /* First dollar in variable name */ - char **pos; /* Current position in variable spec */ - SymTable *ctxt; /* The context for the variable */ - Boolean err; /* TRUE if undefined variables are an error */ - char endc; /* End character for spec */ +ReturnStatus +Var_ParseBuffer(buf, str, ctxt, err, lengthPtr) + Buffer buf; + const char *str; + SymTable *ctxt; + Boolean err; + size_t *lengthPtr; { - BUFFER buf; /* Store the variable name */ - size_t sublen; /* Deal with recursive expansions */ - Boolean subfree; - char *n; /* Sub name */ - Var *v; + char *result; + Boolean freeIt; - Buf_Init(&buf, MAKE_BSIZE); + result = Var_Parse(str, ctxt, err, lengthPtr, &freeIt); + if (result == var_Error) + return FAILURE; - for (;;) { - Buf_AddInterval(&buf, str, *pos); - n = Var_Parse(*pos, ctxt, err, &sublen, &subfree); - if (n != NULL) - Buf_AddString(&buf, n); - if (subfree) - free(n); - *pos += sublen; - str = *pos; - for (; **pos != '$'; (*pos)++) { - if (**pos == '\0' || **pos == endc || **pos == ':') { - Buf_AddInterval(&buf, str, *pos); - v = VarFind(Buf_Retrieve(&buf), ctxt, FIND_ENV | FIND_MINE); - Buf_Destroy(&buf); - return v; - } - } - } + Buf_AddString(buf, result); + if (freeIt) + free(result); + return SUCCESS; } /*- @@ -800,96 +1034,54 @@ var_name_with_dollar(str, pos, ctxt, err, endc) */ char * Var_Parse(str, ctxt, err, lengthPtr, freePtr) - char *str; /* The string to parse */ - SymTable *ctxt; /* The context for the variable */ - Boolean err; /* TRUE if undefined variables are an error */ + const char *str; /* The string to parse */ + SymTable *ctxt; /* The context for the variable */ + Boolean 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 */ + Boolean *freePtr; /* OUT: TRUE if caller should free result */ { - char *tstr; /* Pointer into str */ - Var *v; /* Variable in invocation */ - char endc; /* Ending character when variable in parens + const char *tstr; /* Pointer into str */ + Var *v; /* Variable in invocation */ + char endc; /* Ending character when variable in parens * or braces */ - char *start; + struct Name name; + const char *start; char *val; /* Variable value */ u_int32_t k; - int idx; + int idx; *freePtr = FALSE; start = str++; val = NULL; v = NULL; - idx = 0; + idx = -1; if (*str != '(' && *str != '{') { - tstr = str + 1; + name.s = str; + name.e = str+1; + name.tofree = FALSE; + tstr = str + 1; *lengthPtr = 2; endc = '\0'; } else { endc = *str == '(' ? ')' : '}'; - str++; + str++; /* Find eventual modifiers in the variable */ - for (tstr = str; *tstr != ':'; tstr++) { - if (*tstr == '$') { - v = var_name_with_dollar(str, &tstr, ctxt, err, endc); - if (*tstr == '\0' || *tstr == endc) - endc = '\0'; - break; - } else if (*tstr == '\0' || *tstr == endc) { - endc = '\0'; - break; - } - } + tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc)); *lengthPtr = tstr+1 - start; } - if (v == NULL) { - idx = quick_lookup(str, &tstr, &k); - v = varfind(str, tstr, ctxt, FIND_ENV | FIND_MINE, idx, k); - } - if (v == NULL) { - /* Find out about D and F forms of local variables. */ - if (idx == -1 && tstr == str+2 && (str[1] == 'D' || str[1] == 'F')) { - switch (*str) { - case '@': - idx = TARGET_INDEX; - break; - case '!': - idx = ARCHIVE_INDEX; - break; - case '*': - idx = PREFIX_INDEX; - break; - case '%': - idx = MEMBER_INDEX; - break; - default: - break; - } - /* This is a DF form, check if we can expand it now. */ - if (idx != -1 && ctxt != NULL && ctxt != CTXT_GLOBAL) { - v = varfind(str, str+1, ctxt, 0, idx, 0); - /* No need for nested expansion or anything, as we're - * the only one who sets these things and we sure don't - * do nested invocations in them... */ - if (v != NULL) { - val = VarValue(v); - if (str[1] == 'D') - val = Var_GetHead(val); - else - val = Var_GetTail(val); - *freePtr = TRUE; - } - } - } - } else { + idx = quick_lookup(name.s, &name.e, &k); + v = varfind(name.s, name.e, ctxt, FIND_ENV | FIND_MINE, idx, k); + if (v != NULL && (v->flags & VAR_DUMMY) == 0) { if (v->flags & VAR_IN_USE) Fatal("Variable %s is recursive.", v->name); /*NOTREACHED*/ else v->flags |= VAR_IN_USE; + /* Before doing any modification, we have to make sure the value * has been fully expanded. If it looks like recursion might be * necessary (there's a dollar sign somewhere in the variable's value) @@ -898,26 +1090,51 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) * been dynamically-allocated, so it will need freeing when we * return. */ val = VarValue(v); - if (strchr(val, '$') != NULL) { - val = Var_Subst(val, ctxt, err); + if (idx == -1) { + if (strchr(val, '$') != NULL) { + val = Var_Subst(val, ctxt, err); + *freePtr = TRUE; + } + } else if (idx >= LOCAL_SIZE) { + if (IS_EXTENDED_F(idx)) + val = Var_GetTail(val); + else + val = Var_GetHead(val); *freePtr = TRUE; } - v->flags &= ~VAR_IN_USE; } - if (endc != '\0') - val = VarModifiers_Apply(val, ctxt, err, freePtr, tstr+1, endc, + if (*tstr == ':' && endc != '\0') + val = VarModifiers_Apply(val, &name, ctxt, err, freePtr, tstr, endc, lengthPtr); if (val == NULL) { - /* Dynamic source that can't be expanded for now: copy the var - * specification instead. */ - if (idx != -1 && (ctxt == NULL || ctxt == CTXT_GLOBAL)) { - *freePtr = TRUE; - val = interval_dup(start, start+ *lengthPtr); - } else - val = err ? var_Error : varNoError; + val = err ? var_Error : varNoError; + /* Dynamic source */ + 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); + } else { + /* somehow, this should have been expanded already. */ + GNode *n; + + n = (GNode *)(((char *)ctxt) - offsetof(GNode, context)); + if (idx >= LOCAL_SIZE) + idx = EXTENDED2SIMPLE(idx); + switch(idx) { + case IMPSRC_INDEX: + Fatal("Using $< in a non-suffix rule context is a GNUmake idiom (line %lu of %s)", + n->lineno, n->fname); + default: + Error("Using undefined dynamic variable $%s (line %lu of %s)", + varnames[idx], n->lineno, n->fname); + break; + } + } + } } - + Var_Name_Free(&name); return val; } @@ -932,16 +1149,16 @@ Var_Parse(str, ctxt, err, lengthPtr, freePtr) * The resulting string. * * Side Effects: - * None. The old string must be freed by the caller + * The new string must be freed by the caller *----------------------------------------------------------------------- */ char * Var_Subst(str, ctxt, undefErr) - char *str; /* the string in which to substitute */ - SymTable *ctxt; /* the context wherein to find variables */ - Boolean undefErr; /* TRUE if undefineds are an error */ + 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 */ { - BUFFER buf; /* Buffer for forming things */ + BUFFER buf; /* Buffer for forming things */ static Boolean errorReported; /* Set true if an error has already * been reported to prevent a plethora * of messages when recursing */ @@ -951,8 +1168,8 @@ Var_Subst(str, ctxt, undefErr) 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 */ + size_t length; /* Length of the variable invocation */ + Boolean doFree; /* Set true if val should be freed */ const char *cp; /* copy uninteresting stuff */ @@ -977,21 +1194,20 @@ Var_Subst(str, ctxt, undefErr) * the variable and continue with the substitution. Otherwise, * store the dollar sign and advance str so we continue with * the string... */ - if (oldVars) { + if (oldVars) str += length; - } else if (undefErr) { + else if (undefErr) { /* If variable is undefined, complain and skip the * variable. The complaint will stop us from doing anything * when the file is parsed. */ - if (!errorReported) { + if (!errorReported) Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",length,str); - } str += length; errorReported = TRUE; } else { Buf_AddChar(&buf, *str); - str += 1; + str++; } } else { /* We've now got a variable structure to store in. But first, @@ -1013,25 +1229,25 @@ Var_Subst(str, ctxt, undefErr) * 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. Returns the string with substitutions. + * variable is encountered. Add the substituted string to buffer. *----------------------------------------------------------------------- */ -char * -Var_SubstVar(str, var, val, estimate) - const char *str; /* The string in which to substitute */ +void +Var_SubstVar(buf, str, var, val) + Buffer buf; + const char *str; /* The string in which to substitute */ const char *var; /* Named variable */ const char *val; /* Its value */ - size_t estimate; /* Size estimate for the result buffer */ { - BUFFER buf; /* Where to store the result */ - Buf_Init(&buf, estimate); + assert(*var != '\0'); + for (;;) { const char *start; /* Copy uninteresting stuff */ for (start = str; *str != '\0' && *str != '$'; str++) ; - Buf_AddInterval(&buf, start, str); + Buf_AddInterval(buf, start, str); start = str; if (*str++ == '\0') @@ -1039,13 +1255,13 @@ Var_SubstVar(str, var, val, estimate) str++; /* and escaped dollars */ if (start[1] == '$') { - Buf_AddInterval(&buf, start, start+2); + Buf_AddInterval(buf, start, start+2); continue; } /* Simple variable, if it's not us, copy. */ if (start[1] != '(' && start[1] != '{') { if (start[1] != *var || var[1] != '\0') { - Buf_AddChars(&buf, 2, start); + Buf_AddChars(buf, 2, start); continue; } } else { @@ -1054,52 +1270,54 @@ Var_SubstVar(str, var, val, estimate) if (start[1] == '(') endc = ')'; - else + else endc = '}'; /* Find the end of the variable specification. */ p = str; while (*p != '\0' && *p != ':' && *p != endc && *p != '$') p++; - /* A variable inside the variable. We don't know how to - * expand the external variable at this point, so we try - * again with the nested variable. */ + /* A variable inside the variable. We don't know how to + * expand the external variable at this point, so we try + * again with the nested variable. */ if (*p == '$') { - Buf_AddInterval(&buf, start, p); + Buf_AddInterval(buf, start, p); str = p; continue; } if (strncmp(var, str, p - str) != 0 || var[p - str] != '\0') { - /* Not the variable we want to expand. */ - Buf_AddInterval(&buf, start, p); + /* Not the variable we want to expand. */ + Buf_AddInterval(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 */ + size_t length; /* Length of the variable invocation */ + Boolean doFree; /* Set true if val should be freed */ char *newval; /* Value substituted for a variable */ + struct Name name; - length = p - str + 1; + length = p - str + 1; doFree = FALSE; + name.s = var; + name.e = var + (p-str); /* val won't be freed since doFree == FALSE, but * VarModifiers_Apply doesn't know that, hence the cast. */ - newval = VarModifiers_Apply((char *)val, NULL, FALSE, - &doFree, p+1, endc, &length); - Buf_AddString(&buf, newval); + newval = VarModifiers_Apply((char *)val, &name, NULL, FALSE, + &doFree, p, endc, &length); + Buf_AddString(buf, newval); if (doFree) free(newval); str += length; continue; } else - str = p+1; + str = p+1; } - Buf_AddString(&buf, val); + Buf_AddString(buf, val); } - return Buf_Retrieve(&buf); } /*- @@ -1108,23 +1326,22 @@ Var_SubstVar(str, var, val, estimate) * Initialize the module * * Side Effects: - * The VAR_CMD and VAR_GLOBAL contexts are created + * The CTXT_CMD and CTXT_GLOBAL contexts are initialized *----------------------------------------------------------------------- */ void Var_Init() { - static GSymT global_vars, cmd_vars, env_vars; + static GSymT global_vars, cmd_vars; VAR_GLOBAL = &global_vars; VAR_CMD = &cmd_vars; - VAR_ENV = &env_vars; ohash_init(VAR_GLOBAL, 10, &var_info); ohash_init(VAR_CMD, 5, &var_info); - ohash_init(VAR_ENV, 5, &var_info); CTXT_GLOBAL = (SymTable *)VAR_GLOBAL; CTXT_CMD = (SymTable *)VAR_CMD; - CTXT_ENV = (SymTable *)VAR_ENV; + + VarModifiers_Init(); } @@ -1135,49 +1352,59 @@ Var_End() Var *v; unsigned int i; - for (v = ohash_first(VAR_GLOBAL, &i); v != NULL; + for (v = ohash_first(VAR_GLOBAL, &i); v != NULL; v = ohash_next(VAR_GLOBAL, &i)) VarDelete(v); - for (v = ohash_first(VAR_CMD, &i); v != NULL; + for (v = ohash_first(VAR_CMD, &i); v != NULL; v = ohash_next(VAR_CMD, &i)) VarDelete(v); - for (v = ohash_first(VAR_ENV, &i); v != NULL; - v = ohash_next(VAR_ENV, &i)) - VarDelete(v); #endif } +static const char *interpret(int); + +static const char * +interpret(f) + int f; +{ + if (f & VAR_DUMMY) + return "(D)"; + return ""; +} + /****************** PRINT DEBUGGING INFO *****************/ static void -VarPrintVar(vp) - void *vp; +VarPrintVar(v) + Var *v; { - Var *v = (Var *)vp; - - printf("%-16s = %s\n", v->name, VarValue(v)); + printf("%-16s%s = %s\n", v->name, interpret(v->flags), + (v->flags & VAR_DUMMY) == 0 ? VarValue(v) : "(none)"); } /*- *----------------------------------------------------------------------- * Var_Dump -- - * print all variables in a context + * print all variables *----------------------------------------------------------------------- */ void -Var_Dump(ctxt) - GSymT *ctxt; +Var_Dump() { - Var *v; - unsigned int i; + Var *v; + unsigned int i; - for (v = ohash_first(ctxt, &i); v != NULL; - v = ohash_next(ctxt, &i)) - VarPrintVar(v); -} + printf("#*** Global Variables:\n"); + for (v = ohash_first(VAR_GLOBAL, &i); v != NULL; + v = ohash_next(VAR_GLOBAL, &i)) + VarPrintVar(v); + + printf("#*** Command-line Variables:\n"); -#ifdef POSIX + for (v = ohash_first(VAR_CMD, &i); v != NULL; v = ohash_next(VAR_CMD, &i)) + VarPrintVar(v); +} static const char *quotable = " \t\n\\'\""; @@ -1195,8 +1422,8 @@ Var_AddCmdline(name) Buf_Init(&buf, MAKE_BSIZE); - for (v = ohash_first(VAR_CMD, &i); v != NULL; - v = ohash_next(VAR_CMD, &i)) { + for (v = ohash_first(VAR_CMD, &i); v != NULL; + v = ohash_next(VAR_CMD, &i)) { /* We assume variable names don't need quoting */ Buf_AddString(&buf, v->name); Buf_AddChar(&buf, '='); @@ -1210,4 +1437,3 @@ Var_AddCmdline(name) Var_Append(name, Buf_Retrieve(&buf), VAR_GLOBAL); Buf_Destroy(&buf); } -#endif diff --git a/usr.bin/make/varmodifiers.c b/usr.bin/make/varmodifiers.c index 9f390f1a6c8..2605290e2f0 100644 --- a/usr.bin/make/varmodifiers.c +++ b/usr.bin/make/varmodifiers.c @@ -1,4 +1,5 @@ -/* $OpenBSD: varmodifiers.c,v 1.6 2000/09/14 13:36:46 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: varmodifiers.c,v 1.7 2001/05/03 13:41:13 espie Exp $ */ /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */ /* @@ -65,8 +66,10 @@ * SUCH DAMAGE. */ -/* VarModifiers_Apply is mostly a constituent function of Var_Parse. */ - +/* VarModifiers_Apply is mostly a constituent function of Var_Parse, it + * is also called directly by Var_SubstVar. */ + + #include <ctype.h> #ifndef MAKE_BOOTSTRAP #include <sys/types.h> @@ -79,144 +82,191 @@ /* Var*Pattern flags */ #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */ #define VAR_SUB_ONE 0x02 /* Apply substitution to one word */ -#define VAR_SUB_MATCHED 0x04 /* There was a match */ -#define VAR_MATCH_START 0x08 /* Match at start of word */ +#define VAR_SUB_MATCHED 0x04 /* There was a match */ +#define VAR_MATCH_START 0x08 /* Match at start of word */ #define VAR_MATCH_END 0x10 /* Match at end of word */ +/* Modifiers flags */ +#define VAR_EQUAL 0x20 +#define VAR_MAY_EQUAL 0x40 +#define VAR_ADD_EQUAL 0x80 +#define VAR_BANG_EQUAL 0x100 + typedef struct { - char *lhs; /* String to match */ - size_t leftLen; /* Length of string */ - char *rhs; /* Replacement string (w/ &'s removed) */ - size_t rightLen; /* Length of replacement */ - int flags; + char *lbuffer; /* left string to free */ + char *lhs; /* String to match */ + size_t leftLen; /* Length of string */ + char *rhs; /* Replacement string (w/ &'s removed) */ + size_t rightLen; /* Length of replacement */ + int flags; } VarPattern; +struct LoopStuff { + char *var; + char *expand; + SymTable *ctxt; + Boolean 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 *); + + #ifndef MAKE_BOOTSTRAP +static void VarREError(int, regex_t *, const char *); +static Boolean VarRESubstitute(struct Name *, Boolean, Buffer, void *); +static char *do_regex(const char *, const struct Name *, void *); + typedef struct { regex_t re; - int nsub; + int nsub; regmatch_t *matches; char *replace; - int flags; + int flags; } VarREPattern; #endif -static Boolean VarHead __P((const char *, Boolean, Buffer, void *)); -static Boolean VarTail __P((const char *, Boolean, Buffer, void *)); -static Boolean VarSuffix __P((const char *, Boolean, Buffer, void *)); -static Boolean VarRoot __P((const char *, Boolean, Buffer, void *)); -static Boolean VarMatch __P((const char *, Boolean, Buffer, void *)); -#ifdef SYSVVARSUB -static Boolean VarSYSVMatch __P((const char *, Boolean, Buffer, void *)); -#endif -static Boolean VarNoMatch __P((const char *, Boolean, Buffer, void *)); +static Boolean VarSubstitute(struct Name *, Boolean, 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 void *check_empty(const char **, SymTable *, Boolean, 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 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 *); +static int NameCompare(const void *, const void *); +static char *do_label(const char *, const struct Name *, void *); +static char *do_path(const char *, const struct Name *, void *); +static char *do_def(const char *, const struct Name *, void *); +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 free_stringarg(void *); +static void *get_patternarg(const char **, SymTable *, Boolean, int); +static void *get_spatternarg(const char **, SymTable *, Boolean, 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 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); + char * (*apply)(const char *, const struct Name *, void *); + Boolean (*word_apply)(struct Name *, Boolean, 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}, #ifndef MAKE_BOOTSTRAP -static void VarREError __P((int, regex_t *, const char *)); -static Boolean VarRESubstitute __P((const char *, Boolean, Buffer, void *)); + resubst_mod = {FALSE, get_patternarg, do_regex, NULL, free_patternarg}, #endif -static Boolean VarSubstitute __P((const char *, Boolean, Buffer, void *)); -static char *VarGetPattern __P((SymTable *, int, char **, int, int *, size_t *, - VarPattern *)); -static char *VarQuote __P((const char *)); -static char *VarModify __P((char *, Boolean (*)(const char *, Boolean, Buffer, void *), void *)); -static Boolean VarUppercase __P((const char *, Boolean, Buffer, void *)); -static Boolean VarLowercase __P((const char *, Boolean, Buffer, void *)); - -/*- - *----------------------------------------------------------------------- - * VarUppercase -- - * Place the Upper cased word in the given buffer. - * - * Results: - * TRUE if characters were added to the buffer (a space needs to be - * added to the buffer before the next word). - * - * Side Effects: - * The word is added to the buffer. - * - *----------------------------------------------------------------------- - */ -static Boolean -VarUppercase(word, addSpace, buf, dummy) - const char *word; /* Word to Upper Case */ - Boolean addSpace; /* True if need to add a space to the buffer - * before sticking in the head */ - Buffer buf; /* Buffer in which to store it */ - void *dummy UNUSED; + 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 +VarModifiers_Init() { - size_t len = strlen(word); - - if (addSpace) - Buf_AddSpace(buf); - while (len--) - Buf_AddChar(buf, toupper(*word++)); - return TRUE; + choose_mod['M'] = &match_mod; + choose_mod['N'] = &nomatch_mod; + choose_mod['S'] = &subst_mod; +#ifndef MAKE_BOOTSTRAP + choose_mod['C'] = &resubst_mod; +#endif + choose_mod['Q'] = "e_mod; + choose_mod['T'] = &tail_mod; + choose_mod['H'] = &head_mod; + choose_mod['E'] = &suffix_mod; + choose_mod['R'] = &root_mod; + if (FEATURES(FEATURE_UPPERLOWER)) { + choose_mod['U'] = &upper_mod; + choose_mod['L'] = &lower_mod; + } + if (FEATURES(FEATURE_SUNSHCMD)) + choose_mod['s'] = &shcmd_mod; + if (FEATURES(FEATURE_UNIQ)) + choose_mod['u'] = &uniq_mod; + if (FEATURES(FEATURE_SORT)) + choose_mod['O'] = &sort_mod; + if (FEATURES(FEATURE_ODE)) { + choose_mod['@'] = &loop_mod; + choose_mod['D'] = &def_mod; + choose_mod['U'] = &undef_mod; + choose_mod['L'] = &label_mod; + choose_mod['P'] = &path_mod; + } + if (FEATURES(FEATURE_ASSIGN)) + choose_mod[':'] = &assign_mod; + if (FEATURES(FEATURE_EXECMOD)) + choose_mod['!'] = &exec_mod; } -/*- - *----------------------------------------------------------------------- - * VarLowercase -- - * Place the Lower cased word in the given buffer. - * - * Results: - * TRUE if characters were added to the buffer (a space needs to be - * added to the buffer before the next word). - * - * Side Effects: - * The word is added to the buffer. - * - *----------------------------------------------------------------------- +/* All modifiers handle addSpace (need to add a space before placing the + * next word into the buffer) and propagate it when necessary. */ -static Boolean -VarLowercase(word, addSpace, buf, dummy) - const char *word; /* Word to Lower Case */ - Boolean addSpace; /* True if need to add a space to the buffer - * before sticking in the head */ - Buffer buf; /* Buffer in which to store it */ - void *dummy UNUSED; -{ - size_t len = strlen(word); - - if (addSpace) - Buf_AddSpace(buf); - while (len--) - Buf_AddChar(buf, tolower(*word++)); - return TRUE; -} /*- *----------------------------------------------------------------------- * VarHead -- - * Remove the tail of the given word and place the result in the given + * Remove the tail of the given word and add the result to the given * buffer. - * - * Results: - * TRUE if characters were added to the buffer (a space needs to be - * added to the buffer before the next word). - * - * Side Effects: - * The trimmed word is added to the buffer. - * *----------------------------------------------------------------------- */ static Boolean VarHead(word, addSpace, buf, dummy) - const char *word; /* Word to trim */ - Boolean addSpace; /* True if need to add a space to the buffer - * before sticking in the head */ - Buffer buf; /* Buffer in which to store it */ + struct Name *word; + Boolean addSpace; + Buffer buf; void *dummy UNUSED; { const char *slash; - slash = strrchr(word, '/'); + slash = lastchar(word->s, word->e, '/'); if (slash != NULL) { if (addSpace) Buf_AddSpace(buf); - Buf_AddInterval(buf, word, slash); - return TRUE; + Buf_AddInterval(buf, word->s, slash); } else { - /* If no directory part, give . (q.v. the POSIX standard) */ + /* If no directory part, give . (q.v. the POSIX standard). */ if (addSpace) Buf_AddString(buf, " ."); else @@ -228,67 +278,49 @@ VarHead(word, addSpace, buf, dummy) /*- *----------------------------------------------------------------------- * VarTail -- - * Remove the head of the given word and place the result in the given + * Remove the head of the given word add the result to the given * buffer. - * - * Results: - * TRUE if characters were added to the buffer (a space needs to be - * added to the buffer before the next word). - * - * Side Effects: - * The trimmed word is added to the buffer. - * *----------------------------------------------------------------------- */ static Boolean VarTail(word, addSpace, buf, dummy) - const char *word; /* Word to trim */ - Boolean addSpace; /* TRUE if need to stick a space in the - * buffer before adding the tail */ - Buffer buf; /* Buffer in which to store it */ + struct Name *word; + Boolean addSpace; + Buffer buf; void *dummy UNUSED; { const char *slash; - if (addSpace) + if (addSpace) Buf_AddSpace(buf); - slash = strrchr(word, '/'); + slash = lastchar(word->s, word->e, '/'); if (slash != NULL) - Buf_AddString(buf, slash+1); + Buf_AddInterval(buf, slash+1, word->e); else - Buf_AddString(buf, word); + Buf_AddInterval(buf, word->s, word->e); return TRUE; } /*- *----------------------------------------------------------------------- * VarSuffix -- - * Place the suffix of the given word in the given buffer. - * - * Results: - * TRUE if characters were added to the buffer (a space needs to be - * added to the buffer before the next word). - * - * Side Effects: - * The suffix from the word is placed in the buffer. - * + * Add the suffix of the given word to the given buffer. *----------------------------------------------------------------------- */ static Boolean VarSuffix(word, addSpace, buf, dummy) - const char *word; /* Word to trim */ - Boolean addSpace; /* TRUE if need to add a space before placing - * the suffix in the buffer */ - Buffer buf; /* Buffer in which to store it */ + struct Name *word; + Boolean addSpace; + Buffer buf; void *dummy UNUSED; { const char *dot; - dot = strrchr(word, '.'); + dot = lastchar(word->s, word->e, '.'); if (dot != NULL) { if (addSpace) Buf_AddSpace(buf); - Buf_AddString(buf, dot+1); + Buf_AddInterval(buf, dot+1, word->e); addSpace = TRUE; } return addSpace; @@ -297,212 +329,421 @@ VarSuffix(word, addSpace, buf, dummy) /*- *----------------------------------------------------------------------- * VarRoot -- - * Remove the suffix of the given word and place the result in the + * Remove the suffix of the given word and add the result to the * buffer. - * - * Results: - * TRUE if characters were added to the buffer (a space needs to be - * added to the buffer before the next word). - * - * Side Effects: - * The trimmed word is added to the buffer. - * *----------------------------------------------------------------------- */ static Boolean VarRoot(word, addSpace, buf, dummy) - const char *word; /* Word to trim */ - Boolean addSpace; /* TRUE if need to add a space to the buffer - * before placing the root in it */ - Buffer buf; /* Buffer in which to store it */ + struct Name *word; + Boolean addSpace; + Buffer buf; void *dummy UNUSED; { const char *dot; if (addSpace) Buf_AddSpace(buf); - - dot = strrchr(word, '.'); + dot = lastchar(word->s, word->e, '.'); if (dot != NULL) - Buf_AddInterval(buf, word, dot); + Buf_AddInterval(buf, word->s, dot); else - Buf_AddString(buf, word); + Buf_AddInterval(buf, word->s, word->e); return TRUE; } /*- *----------------------------------------------------------------------- * VarMatch -- - * Place the word in the buffer if it matches the given pattern. - * Callback function for VarModify to implement the :M modifier. - * - * Results: - * TRUE if a space should be placed in the buffer before the next - * word. - * - * Side Effects: - * The word may be copied to the buffer. - * + * Add the word to the buffer if it matches the given pattern. *----------------------------------------------------------------------- */ static Boolean VarMatch(word, addSpace, buf, pattern) - const char *word; /* Word to examine */ - Boolean addSpace; /* TRUE if need to add a space to the - * buffer before adding the word, if it - * matches */ - Buffer buf; /* Buffer in which to store it */ - void *pattern; /* Pattern the word must match */ + struct Name *word; + Boolean addSpace; + Buffer buf; + void *pattern; /* Pattern the word must match */ { - if (Str_Match(word, (char *) pattern)) { + if (Str_Match(word->s, (const char *)pattern)) { if (addSpace) Buf_AddSpace(buf); + Buf_AddInterval(buf, word->s, word->e); + return TRUE; + } else + return addSpace; +} + +/*- + *----------------------------------------------------------------------- + * VarNoMatch -- + * Add the word to the buffer if it doesn't match the given pattern. + *----------------------------------------------------------------------- + */ +static Boolean +VarNoMatch(word, addSpace, buf, pattern) + struct Name *word; + Boolean addSpace; + Buffer buf; + void *pattern; /* Pattern the word must not match */ +{ + if (!Str_Match(word->s, (const char *)pattern)) { + if (addSpace) + Buf_AddSpace(buf); + Buf_AddInterval(buf, word->s, word->e); + return TRUE; + } else + return addSpace; +} + +static Boolean +VarUniq(word, addSpace, buf, lastp) + struct Name *word; + Boolean addSpace; + Buffer buf; + void *lastp; +{ + struct Name *last = (struct Name *)lastp; + + /* does not match */ + if (last->s == NULL || last->e - last->s != word->e - word->s || + 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_AddString(buf, word); } + last->s = word->s; + last->e = word->e; return addSpace; } -#ifdef SYSVVARSUB +static Boolean +VarLoop(word, addSpace, buf, vp) + struct Name *word; + Boolean addSpace; + Buffer buf; + void *vp; +{ + struct LoopStuff *v = (struct LoopStuff *)vp; + + if (addSpace) + Buf_AddSpace(buf); + Var_SubstVar(buf, v->expand, v->var, word->s); + return TRUE; +} + +static char * +finish_loop(s, n, p) + const char *s; + const struct Name *n UNUSED; + void *p; +{ + struct LoopStuff *l = (struct LoopStuff *)p; + + return Var_Subst(s, l->ctxt, l->err); +} + +static int +NameCompare(ap, bp) + const void *ap; + const void *bp; +{ + struct Name *a, *b; + size_t n, m; + int c; + + a = (struct Name *)ap; + b = (struct Name *)bp; + n = a->e - a->s; + m = b->e - b->s; + if (n < m) { + c = strncmp(a->s, b->s, n); + if (c != 0) + return c; + else + return -1; + } else if (m < n) { + c = strncmp(a->s, b->s, m); + if (c != 0) + return c; + else + return 1; + } else + return strncmp(a->s, b->s, n); +} + +static char * +do_sort(s, dummy, arg) + const char *s; + const struct Name *dummy UNUSED; + void *arg UNUSED; +{ + struct Name *t; + unsigned long n, i, j; + const char *start, *end; + + n = 1024; /* start at 1024 words */ + t = (struct Name *)emalloc(sizeof(struct Name) * n); + start = s; + end = start; + + for (i = 0;; i++) { + if (i == n) { + n *= 2; + t = (struct Name *)erealloc(t, sizeof(struct Name) * n); + } + start = iterate_words(&end); + if (start == NULL) + break; + t[i].s = start; + t[i].e = end; + } + if (i > 0) { + BUFFER buf; + + Buf_Init(&buf, end - s); + qsort(t, i, sizeof(struct Name), NameCompare); + Buf_AddInterval(&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); + } + free(t); + return Buf_Retrieve(&buf); + } else { + free(t); + return ""; + } +} + +static char * +do_label(s, n, arg) + const char *s UNUSED; + const struct Name *n; + void *arg UNUSED; +{ + return interval_dup(n->s, n->e); +} + +static char * +do_path(s, n, arg) + const char *s UNUSED; + const struct Name *n; + void *arg UNUSED; +{ + GNode *gn; + + gn = Targ_FindNode(n->s, n->e, TARG_NOCREATE); + if (gn == NULL) + return interval_dup(n->s, n->e); + else + return strdup(gn->path); +} + +static char * +do_def(s, n, arg) + const char *s; + const struct Name *n UNUSED; + void *arg; +{ + VarPattern *v = (VarPattern *)arg; + if (s == NULL) { + free_patternarg(v); + return NULL; + } else + return v->lbuffer; +} + +static char * +do_undef(s, n, arg) + const char *s; + const struct Name *n UNUSED; + void *arg; +{ + VarPattern *v = (VarPattern *)arg; + if (s != NULL) { + free_patternarg(v); + return NULL; + } else + return v->lbuffer; +} + +static char * +do_assign(s, n, arg) + const char *s; + const struct Name *n; + void *arg; +{ + VarPattern *v = (VarPattern *)arg; + char *msg; + char *result; + + switch (v->flags) { + case VAR_EQUAL: + Var_Set_interval(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); + break; + case VAR_ADD_EQUAL: + if (s == NULL) + Var_Set_interval(n->s, n->e, v->lbuffer, VAR_GLOBAL); + else + Var_Append_interval(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); + free(result); + } else + Error(msg, v->lbuffer); + break; + + } + return NULL; +} + +static char * +do_exec(s, n, arg) + const char *s UNUSED; + const struct Name *n UNUSED; + void *arg; +{ + VarPattern *v = (VarPattern *)arg; + char *msg; + char *result; + + result = Cmd_Exec(v->lbuffer, &msg); + if (result == NULL) + Error(msg, v->lbuffer); + return result; +} + /*- *----------------------------------------------------------------------- * VarSYSVMatch -- - * Place the word in the buffer if it matches the given pattern. - * Callback function for VarModify to implement the System V % - * modifiers. - * - * Results: - * TRUE if a space should be placed in the buffer before the next - * word. - * - * Side Effects: - * The word may be copied to the buffer. - * + * Add the word to the buffer if it matches the given pattern. + * Used to implement the System V % modifiers. *----------------------------------------------------------------------- */ static Boolean VarSYSVMatch(word, addSpace, buf, patp) - const char *word; /* Word to examine */ - Boolean addSpace; /* TRUE if need to add a space to the - * buffer before adding the word, if it - * matches */ - Buffer buf; /* Buffer in which to store it */ - void *patp; /* Pattern the word must match */ + struct Name *word; + Boolean addSpace; + Buffer buf; + void *patp; /* Pattern the word must match */ { - size_t len; - const char *ptr; - VarPattern *pat = (VarPattern *) patp; + size_t len; + const char *ptr; + VarPattern *pat = (VarPattern *)patp; - if (*word) { + if (*word->s != '\0') { if (addSpace) Buf_AddSpace(buf); - - addSpace = TRUE; - - if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) + if ((ptr = Str_SYSVMatch(word->s, pat->lhs, &len)) != NULL) Str_SYSVSubst(buf, pat->rhs, ptr, len); else - Buf_AddString(buf, word); - } - return addSpace; + Buf_AddInterval(buf, word->s, word->e); + return TRUE; + } else + return addSpace; } -#endif -/*- - *----------------------------------------------------------------------- - * VarNoMatch -- - * Place the word in the buffer if it doesn't match the given pattern. - * Callback function for VarModify to implement the :N modifier. - * - * Results: - * TRUE if a space should be placed in the buffer before the next - * word. - * - * Side Effects: - * The word may be copied to the buffer. - * - *----------------------------------------------------------------------- - */ -static Boolean -VarNoMatch(word, addSpace, buf, pattern) - const char *word; /* Word to examine */ - Boolean addSpace; /* TRUE if need to add a space to the - * buffer before adding the word, if it - * matches */ - Buffer buf; /* Buffer in which to store it */ - void *pattern; /* Pattern the word must match */ +void * +get_sysvpattern(p, ctxt, err, endc) + const char **p; + SymTable *ctxt UNUSED; + Boolean err UNUSED; + int endc; { - if (!Str_Match(word, (char *) pattern)) { - if (addSpace) - Buf_AddSpace(buf); - addSpace = TRUE; - Buf_AddString(buf, word); + static VarPattern pattern; + const char *cp, *cp2; + int cnt = 0; + char startc = endc == ')' ? '(' : '}'; + + for (cp = *p;; cp++) { + if (*cp == '=' && cnt == 0) + break; + if (*cp == '\0') + return NULL; + if (*cp == startc) + cnt++; + else if (*cp == endc) { + cnt--; + if (cnt < 0) + return NULL; + } } - return(addSpace); + for (cp2 = cp+1;; cp2++) { + if ((*cp2 == ':' || *cp2 == endc) && cnt == 0) + break; + if (*cp2 == startc) + cnt++; + else if (*cp2 == endc) { + cnt--; + if (cnt < 0) + return NULL; + } + } + + pattern.lhs = interval_dup(*p, cp); + pattern.leftLen = cp - *p; + pattern.rhs = interval_dup(cp+1, cp2); + pattern.rightLen = cp2 - (cp+1); + pattern.flags = 0; + *p = cp2; + return &pattern; } /*- *----------------------------------------------------------------------- * VarSubstitute -- - * Perform a string-substitution on the given word, placing the - * result in the passed buffer. - * - * Results: - * TRUE if a space is needed before more characters are added. - * - * Side Effects: - * None. - * + * Perform a string-substitution on the given word, Adding the + * result to the given buffer. *----------------------------------------------------------------------- */ static Boolean VarSubstitute(word, addSpace, buf, patternp) - const char *word; /* Word to modify */ - Boolean addSpace; /* True if space should be added before - * other characters */ - Buffer buf; /* Buffer for result */ - void *patternp; /* Pattern for substitution */ + struct Name *word; + Boolean addSpace; + Buffer buf; + void *patternp; /* Pattern for substitution */ { - size_t wordLen; /* Length of word */ - const char *cp; /* General pointer */ - VarPattern *pattern = (VarPattern *) patternp; + size_t wordLen; /* Length of word */ + const char *cp; /* General pointer */ + VarPattern *pattern = (VarPattern *)patternp; - wordLen = strlen(word); + wordLen = word->e - word->s; if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) != (VAR_SUB_ONE|VAR_SUB_MATCHED)) { - /* - * Still substituting -- break it down into simple anchored cases - * and if none of them fits, perform the general substitution case. - */ + /* Still substituting -- break it down into simple anchored cases + * and if none of them fits, perform the general substitution case. */ if ((pattern->flags & VAR_MATCH_START) && - (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) { - /* - * Anchored at start and beginning of word matches pattern - */ + (strncmp(word->s, pattern->lhs, pattern->leftLen) == 0)) { + /* Anchored at start and beginning of word matches pattern. */ if ((pattern->flags & VAR_MATCH_END) && (wordLen == pattern->leftLen)) { - /* - * Also anchored at end and matches to the end (word + /* Also anchored at end and matches to the end (word * is same length as pattern) add space and rhs only - * if rhs is non-null. - */ + * if rhs is non-null. */ if (pattern->rightLen != 0) { if (addSpace) Buf_AddSpace(buf); addSpace = TRUE; - Buf_AddChars(buf, pattern->rightLen, pattern->rhs); + Buf_AddChars(buf, pattern->rightLen, + pattern->rhs); } pattern->flags |= VAR_SUB_MATCHED; } else if (pattern->flags & VAR_MATCH_END) { - /* - * Doesn't match to end -- copy word wholesale - */ + /* Doesn't match to end -- copy word wholesale. */ goto nosub; } else { - /* - * Matches at start but need to copy in trailing characters - */ + /* Matches at start but need to copy in + * trailing characters. */ if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){ if (addSpace) Buf_AddSpace(buf); @@ -510,124 +751,102 @@ VarSubstitute(word, addSpace, buf, patternp) } Buf_AddChars(buf, pattern->rightLen, pattern->rhs); Buf_AddChars(buf, wordLen - pattern->leftLen, - word + pattern->leftLen); + word->s + pattern->leftLen); pattern->flags |= VAR_SUB_MATCHED; } } else if (pattern->flags & VAR_MATCH_START) { - /* - * Had to match at start of word and didn't -- copy whole word. - */ + /* Had to match at start of word and didn't -- copy whole word. */ goto nosub; } else if (pattern->flags & VAR_MATCH_END) { - /* - * Anchored at end, Find only place match could occur (leftLen + /* Anchored at end, Find only place match could occur (leftLen * characters from the end of the word) and see if it does. Note * that because the $ will be left at the end of the lhs, we have - * to use strncmp. - */ - cp = word + (wordLen - pattern->leftLen); - if ((cp >= word) && - (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) { - /* - * Match found. If we will place characters in the buffer, + * to use strncmp. */ + cp = word->s + (wordLen - pattern->leftLen); + if (cp >= word->s && + strncmp(cp, pattern->lhs, pattern->leftLen) == 0) { + /* Match found. If we will place characters in the buffer, * add a space before hand as indicated by addSpace, then * stuff in the initial, unmatched part of the word followed - * by the right-hand-side. - */ - if (((cp - word) + pattern->rightLen) != 0) { + * by the right-hand-side. */ + if (((cp - word->s) + pattern->rightLen) != 0) { if (addSpace) Buf_AddSpace(buf); addSpace = TRUE; } - Buf_AddInterval(buf, word, cp); + Buf_AddInterval(buf, word->s, cp); Buf_AddChars(buf, pattern->rightLen, pattern->rhs); pattern->flags |= VAR_SUB_MATCHED; } else { - /* - * Had to match at end and didn't. Copy entire word. - */ + /* Had to match at end and didn't. Copy entire word. */ goto nosub; } } else { - /* - * Pattern is unanchored: search for the pattern in the word using - * String_FindSubstring, copying unmatched portions and the + /* Pattern is unanchored: search for the pattern in the word using + * strstr, copying unmatched portions and the * right-hand-side for each match found, handling non-global * substitutions correctly, etc. When the loop is done, any * remaining part of the word (word and wordLen are adjusted * accordingly through the loop) is copied straight into the * buffer. - * addSpace is set FALSE as soon as a space is added to the - * buffer. - */ - register Boolean done; + * addSpace is set to FALSE as soon as a space is added to the + * buffer. */ + Boolean done; size_t origSize; done = FALSE; origSize = Buf_Size(buf); while (!done) { - cp = strstr(word, pattern->lhs); - if (cp != (char *)NULL) { - if (addSpace && (((cp - word) + pattern->rightLen) != 0)){ + cp = strstr(word->s, pattern->lhs); + if (cp != NULL) { + if (addSpace && (cp - word->s) + pattern->rightLen != 0){ Buf_AddSpace(buf); addSpace = FALSE; } - Buf_AddInterval(buf, word, cp); + Buf_AddInterval(buf, word->s, cp); Buf_AddChars(buf, pattern->rightLen, pattern->rhs); - wordLen -= (cp - word) + pattern->leftLen; - word = cp + pattern->leftLen; - if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){ + wordLen -= (cp - word->s) + pattern->leftLen; + word->s = cp + pattern->leftLen; + if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0) done = TRUE; - } pattern->flags |= VAR_SUB_MATCHED; - } else { + } else done = TRUE; - } } if (wordLen != 0) { if (addSpace) Buf_AddSpace(buf); - Buf_AddChars(buf, wordLen, word); + Buf_AddChars(buf, wordLen, word->s); } - /* - * If added characters to the buffer, need to add a space + /* If added characters to the buffer, need to add a space * before we add any more. If we didn't add any, just return - * the previous value of addSpace. - */ - return (Buf_Size(buf) != origSize || addSpace); + * the previous value of addSpace. */ + return Buf_Size(buf) != origSize || addSpace; } - return (addSpace); + return addSpace; } nosub: if (addSpace) Buf_AddSpace(buf); - Buf_AddChars(buf, wordLen, word); - return(TRUE); + Buf_AddChars(buf, wordLen, word->s); + return TRUE; } - #ifndef MAKE_BOOTSTRAP /*- *----------------------------------------------------------------------- * VarREError -- * Print the error caused by a regcomp or regexec call. - * - * Results: - * None. - * - * Side Effects: - * An error gets printed. - * *----------------------------------------------------------------------- */ static void VarREError(err, pat, str) - int err; - regex_t *pat; - const char *str; + int err; + regex_t *pat; + const char *str; { - char *errbuf; - int errlen; + char *errbuf; + int errlen; errlen = regerror(err, pat, 0, 0); errbuf = emalloc(errlen); @@ -641,35 +860,28 @@ VarREError(err, pat, str) * VarRESubstitute -- * Perform a regex substitution on the given word, placing the * result in the passed buffer. - * - * Results: - * TRUE if a space is needed before more characters are added. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ static Boolean VarRESubstitute(word, addSpace, buf, patternp) - const char *word; - Boolean addSpace; - Buffer buf; - void *patternp; + struct Name *word; + Boolean addSpace; + Buffer buf; + void *patternp; { - VarREPattern *pat; - int xrv; - const char *wp; - char *rp; - int added; + VarREPattern *pat; + int xrv; + const char *wp; + char *rp; + int added; #define MAYBE_ADD_SPACE() \ - if (addSpace && !added) \ + if (addSpace && !added) \ Buf_AddSpace(buf); \ added = 1 added = 0; - wp = word; + wp = word->s; pat = patternp; if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) == @@ -689,12 +901,12 @@ VarRESubstitute(word, addSpace, buf, patternp) } for (rp = pat->replace; *rp; rp++) { - if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) { + if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) { MAYBE_ADD_SPACE(); - Buf_AddChar(buf, rp[1]); + Buf_AddChar(buf,rp[1]); rp++; } - else if ((*rp == '&') || ((*rp == '\\') && isdigit(rp[1]))) { + else if (*rp == '&' || (*rp == '\\' && isdigit(rp[1]))) { int n; const char *subbuf; int sublen; @@ -716,12 +928,12 @@ VarRESubstitute(word, addSpace, buf, patternp) Error("No subexpression %s", &errstr[0]); subbuf = ""; sublen = 0; - } else if ((pat->matches[n].rm_so == -1) && - (pat->matches[n].rm_eo == -1)) { + } else if (pat->matches[n].rm_so == -1 && + pat->matches[n].rm_eo == -1) { Error("No match for subexpression %s", &errstr[0]); subbuf = ""; sublen = 0; - } else { + } else { subbuf = wp + pat->matches[n].rm_so; sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so; } @@ -740,7 +952,7 @@ VarRESubstitute(word, addSpace, buf, patternp) goto tryagain; if (*wp) { MAYBE_ADD_SPACE(); - Buf_AddChars(buf, strlen(wp), wp); + Buf_AddString(buf, wp); } break; default: @@ -749,11 +961,11 @@ VarRESubstitute(word, addSpace, buf, patternp) case REG_NOMATCH: if (*wp) { MAYBE_ADD_SPACE(); - Buf_AddChars(buf, strlen(wp), wp); + Buf_AddString(buf, wp); } break; } - return(addSpace||added); + return addSpace||added; } #endif @@ -765,38 +977,33 @@ VarRESubstitute(word, addSpace, buf, patternp) * * Results: * A string of all the words modified appropriately. - * *----------------------------------------------------------------------- */ static char * VarModify(str, modProc, datum) - char *str; /* String whose words should be trimmed */ - /* Function to use to modify them */ - Boolean (*modProc) __P((const char *, Boolean, Buffer, void *)); - void *datum; /* Datum to pass it */ + char *str; /* String whose words should be trimmed */ + /* Function to use to modify them */ + Boolean (*modProc)(struct Name *, Boolean, 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 + BUFFER buf; /* Buffer for the new string */ + Boolean addSpace; /* TRUE if need to add a space to the * buffer before adding the trimmed * word */ - char *end; - char *word; - - if (str == NULL) - return NULL; + struct Name word; Buf_Init(&buf, 0); addSpace = FALSE; - end = str; + word.e = str; - while ((word = iterate_words(&end)) != NULL) { - char termc; + while ((word.s = iterate_words(&word.e)) != NULL) { + char termc; - termc = *end; - *end = '\0'; - addSpace = (*modProc)(word, addSpace, &buf, datum); - *end = termc; + termc = *word.e; + *((char *)(word.e)) = '\0'; + addSpace = (*modProc)(&word, addSpace, &buf, datum); + *((char *)(word.e)) = termc; } return Buf_Retrieve(&buf); } @@ -815,34 +1022,30 @@ VarModify(str, modProc, datum) * Results: * A string of all the words modified appropriately. * If length is specified, return the string length of the buffer - * If flags is specified and the last character of the pattern is a - * $ set the VAR_MATCH_END bit of flags. - * - * Side Effects: - * None. *----------------------------------------------------------------------- */ static char * -VarGetPattern(ctxt, err, tstr, delim, flags, length, pattern) - SymTable *ctxt; - int err; - char **tstr; - int delim; - int *flags; - size_t *length; - VarPattern *pattern; +VarGetPattern(ctxt, err, tstr, delim1, delim2, length, pattern) + SymTable *ctxt; + int err; + const char **tstr; + int delim1; + int delim2; + size_t *length; + VarPattern *pattern; { - char *cp; - BUFFER buf; - size_t junk; + const char *cp; + char *result; + BUFFER buf; + size_t junk; Buf_Init(&buf, 0); if (length == NULL) length = &junk; -#define IS_A_MATCH(cp, delim) \ - ((cp[0] == '\\') && ((cp[1] == delim) || \ - (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&')))) +#define IS_A_MATCH(cp, delim1, delim2) \ + (cp[0] == '\\' && (cp[1] == delim1 || cp[1] == delim2 || \ + cp[1] == '\\' || cp[1] == '$' || (pattern && cp[1] == '&'))) /* * Skim through until the matching delimiter is found; @@ -850,449 +1053,539 @@ VarGetPattern(ctxt, err, tstr, delim, flags, length, pattern) * backslashes to quote the delimiter, $, and \, but don't * touch other backslashes. */ - for (cp = *tstr; *cp && (*cp != delim); cp++) { - if (IS_A_MATCH(cp, delim)) { + for (cp = *tstr; *cp != '\0' && *cp != delim1 && *cp != delim2; cp++) { + if (IS_A_MATCH(cp, delim1, delim2)) { Buf_AddChar(&buf, cp[1]); cp++; } else if (*cp == '$') { - if (cp[1] == delim) { - if (flags == NULL) - Buf_AddChar(&buf, *cp); - else - /* - * Unescaped $ at end of pattern => anchor - * pattern at end. - */ - *flags |= VAR_MATCH_END; - } + /* Allowed at end of pattern */ + if (cp[1] == delim1 || cp[1] == delim2) + Buf_AddChar(&buf, *cp); else { - char *cp2; - size_t len; - Boolean freeIt; - - /* - * If unescaped dollar sign not before the - * delimiter, assume it's a variable - * substitution and recurse. - */ - cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); - Buf_AddString(&buf, cp2); - if (freeIt) - free(cp2); + size_t len; + + /* If unescaped dollar sign not before the delimiter, + * assume it's a variable substitution and recurse. */ + (void)Var_ParseBuffer(&buf, cp, ctxt, err, &len); cp += len - 1; } - } - else if (pattern && *cp == '&') + } else if (pattern && *cp == '&') Buf_AddChars(&buf, pattern->leftLen, pattern->lhs); else Buf_AddChar(&buf, *cp); } - if (*cp != delim) { + *length = Buf_Size(&buf); + result = Buf_Retrieve(&buf); + + if (*cp != delim1 && *cp != delim2) { *tstr = cp; *length = 0; + free(result); return NULL; } else { *tstr = ++cp; - *length = Buf_Size(&buf); - return Buf_Retrieve(&buf); + return result; } } -char * -VarModifiers_Apply(str, ctxt, err, freePtr, start, endc, lengthPtr) - char *str; - SymTable *ctxt; - Boolean err; - Boolean *freePtr; - char *start; - char endc; - size_t *lengthPtr; +/*- + *----------------------------------------------------------------------- + * VarQuote -- + * Quote shell meta-characters in the string + * + * Results: + * The quoted string + *----------------------------------------------------------------------- + */ +static char * +VarQuote(str, n, dummy) + const char *str; + const struct Name *n UNUSED; + void *dummy UNUSED; { - char *tstr; - char delim; - char *cp; - tstr = start; + BUFFER buf; + /* This should cover most shells :-( */ + static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; - /* - * Now we need to apply any modifiers the user wants applied. - * These are: - * :M<pattern> words which match the given <pattern>. - * <pattern> is of the standard file - * wildcarding form. - * :S<d><pat1><d><pat2><d>[g] - * Substitute <pat2> for <pat1> in the value - * :C<d><pat1><d><pat2><d>[g] - * Substitute <pat2> for regex <pat1> in the value - * :H Substitute the head of each word - * :T Substitute the tail of each word - * :E Substitute the extension (minus '.') of - * each word - * :R Substitute the root of each word - * (pathname minus the suffix). - * :lhs=rhs Like :S, but the rhs goes to the end of - * the invocation. - */ - while (*tstr != endc) { - char *newStr; /* New value to return */ - char termc; /* Character which terminated scan */ + Buf_Init(&buf, MAKE_BSIZE); + for (; *str; str++) { + if (strchr(meta, *str) != NULL) + Buf_AddChar(&buf, '\\'); + Buf_AddChar(&buf, *str); + } + return Buf_Retrieve(&buf); +} - if (DEBUG(VAR)) - printf("Applying :%c to \"%s\"\n", *tstr, str ? str : ""); - switch (*tstr) { - case 'N': - case 'M': - { - for (cp = tstr + 1; - *cp != '\0' && *cp != ':' && *cp != endc; - cp++) { - if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){ - cp++; - } - } - termc = *cp; - *cp = '\0'; - if (*tstr == 'M') - newStr = VarModify(str, VarMatch, tstr+1); - else - newStr = VarModify(str, VarNoMatch, tstr+1); - break; - } - case 'S': - { - VarPattern pattern; - - pattern.flags = 0; - delim = tstr[1]; - tstr += 2; - - /* If pattern begins with '^', it is anchored to the - * start of the word -- skip over it and flag pattern. */ - if (*tstr == '^') { - pattern.flags |= VAR_MATCH_START; - tstr++; - } +static void * +check_empty(p, ctxt, b, endc) + const char **p; + SymTable *ctxt UNUSED; + Boolean b UNUSED; + int endc; +{ + dummy_arg->s = NULL; + if ((*p)[1] == endc || (*p)[1] == ':') { + (*p)++; + return dummy_arg; + } else + return NULL; +} - cp = tstr; - if ((pattern.lhs = VarGetPattern(ctxt, err, &cp, delim, - &pattern.flags, &pattern.leftLen, NULL)) == NULL) - goto cleanup; - - if ((pattern.rhs = VarGetPattern(ctxt, err, &cp, delim, - NULL, &pattern.rightLen, &pattern)) == NULL) - goto cleanup; - - /* Check for global substitution. If 'g' after the final - * delimiter, substitution is global and is marked that - * way. */ - for (;; cp++) { - switch (*cp) { - case 'g': - pattern.flags |= VAR_SUB_GLOBAL; - continue; - case '1': - pattern.flags |= VAR_SUB_ONE; - continue; - } - break; - } +static void * +check_shcmd(p, ctxt, b, endc) + const char **p; + SymTable *ctxt UNUSED; + Boolean b UNUSED; + int endc; +{ + if ((*p)[1] == 'h' && ((*p)[2] == endc || (*p)[2] == ':')) { + (*p)+=2; + return dummy_arg; + } else + return NULL; +} - termc = *cp; - newStr = VarModify(str, VarSubstitute, &pattern); - /* Free the two strings. */ - free(pattern.lhs); - free(pattern.rhs); - break; - } -#ifndef MAKE_BOOTSTRAP - case 'C': - { - VarREPattern pattern; - char *re; - int error; - - pattern.flags = 0; - delim = tstr[1]; - tstr += 2; - - cp = tstr; - - if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL, - NULL, NULL)) == NULL) - goto cleanup; - - if ((pattern.replace = VarGetPattern(ctxt, err, &cp, - delim, NULL, NULL, NULL)) == NULL) { - free(re); - goto cleanup; - } +static char * +do_shcmd(s, n, arg) + const char *s; + const struct Name *n UNUSED; + void *arg UNUSED; +{ + char *err; + char *t; - for (;; cp++) { - switch (*cp) { - case 'g': - pattern.flags |= VAR_SUB_GLOBAL; - continue; - case '1': - pattern.flags |= VAR_SUB_ONE; - continue; - } - break; - } + t = Cmd_Exec(s, &err); + if (err) + Error(err, s); + return t; +} - termc = *cp; +static void * +get_stringarg(p, ctxt, b, endc) + const char **p; + SymTable *ctxt UNUSED; + Boolean b UNUSED; + int endc; +{ + const char *cp; + char *s; + + for (cp = *p + 1; *cp != ':' && *cp != endc; cp++) { + if (*cp == '\\') { + if (cp[1] == ':' || cp[1] == endc || cp[1] == '\\') + cp++; + } else if (*cp == '\0') + return NULL; + } + s = escape_dup(*p+1, cp, ":)}"); + *p = cp; + return s; +} - error = regcomp(&pattern.re, re, REG_EXTENDED); - free(re); - if (error) { - *lengthPtr = cp - start + 1; - VarREError(error, &pattern.re, "RE substitution error"); - free(pattern.replace); - return var_Error; - } +static void +free_stringarg(arg) + void *arg; +{ + free(arg); +} - pattern.nsub = pattern.re.re_nsub + 1; - if (pattern.nsub < 1) - pattern.nsub = 1; - if (pattern.nsub > 10) - pattern.nsub = 10; - pattern.matches = emalloc(pattern.nsub * - sizeof(regmatch_t)); - newStr = VarModify(str, VarRESubstitute, &pattern); - regfree(&pattern.re); - free(pattern.replace); - free(pattern.matches); - break; - } -#endif - case 'Q': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarQuote(str); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ - case 'T': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarModify(str, VarTail, NULL); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ - case 'H': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarModify(str, VarHead, NULL); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ - case 'E': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarModify(str, VarSuffix, NULL); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ - case 'R': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarModify(str, VarRoot, NULL); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ - case 'U': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarModify(str, VarUppercase, NULL); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ - case 'L': - if (tstr[1] == endc || tstr[1] == ':') { - newStr = VarModify(str, VarLowercase, NULL); - cp = tstr + 1; - termc = *cp; - break; - } - /* FALLTHROUGH */ -#ifdef SUNSHCMD - case 's': - if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) { - char *err = 0; - newStr = str ? Cmd_Exec(str, &err) : NULL; - if (err) - Error(err, str); - cp = tstr + 2; - termc = *cp; - break; - } - /* FALLTHROUGH */ -#endif - default: - { -#ifdef SYSVVARSUB - /* This can either be a bogus modifier or a System-V - * substitution command. */ - VarPattern pattern; - Boolean eqFound; - int cnt; /* Used to count brace pairs when - * variable in in parens or braces */ - char startc; - - if (endc == ')') - startc = '('; - else - startc = '{'; - - pattern.flags = 0; - eqFound = FALSE; - /* First we make a pass through the string trying - * to verify it is a SYSV-make-style translation: - * it must be: <string1>=<string2>) */ - cp = tstr; - cnt = 1; - while (*cp != '\0' && cnt) { - if (*cp == '=') { - eqFound = TRUE; - /* continue looking for endc */ - } - else if (*cp == endc) - cnt--; - else if (*cp == startc) - cnt++; - if (cnt) - cp++; +static char * +do_upper(s, n, arg) + const char *s; + const struct Name *n UNUSED; + void *arg UNUSED; +{ + size_t len, i; + char *t; + + len = strlen(s); + t = emalloc(len+1); + for (i = 0; i < len; i++) + t[i] = toupper(s[i]); + t[len] = '\0'; + return t; +} + +static char * +do_lower(s, n, arg) + const char *s; + const struct Name *n UNUSED; + void *arg UNUSED; +{ + size_t len, i; + char *t; + + len = strlen(s); + t = emalloc(len+1); + for (i = 0; i < len; i++) + t[i] = tolower(s[i]); + t[len] = '\0'; + return t; +} + +/* Extract anchors */ +static void * +get_spatternarg(p, ctxt, err, endc) + const char **p; + SymTable *ctxt; + Boolean err; + int endc; +{ + VarPattern *pattern; + + pattern = get_patternarg(p, ctxt, err, endc); + if (pattern != NULL && pattern->leftLen > 0) { + if (pattern->lhs[pattern->leftLen-1] == '$') { + pattern->leftLen--; + pattern->flags |= VAR_MATCH_END; + } + if (pattern->lhs[0] == '^') { + pattern->lhs++; + pattern->leftLen--; + pattern->flags |= VAR_MATCH_START; } - if (*cp == endc && eqFound) { - - /* Now we break this sucker into the lhs and - * rhs. We must null terminate them of course. */ - for (cp = tstr; *cp != '='; cp++) - continue; - pattern.lhs = tstr; - pattern.leftLen = cp - tstr; - *cp++ = '\0'; - - pattern.rhs = cp; - cnt = 1; - while (cnt) { - if (*cp == endc) - cnt--; - else if (*cp == startc) - cnt++; - if (cnt) - cp++; - } - pattern.rightLen = cp - pattern.rhs; - *cp = '\0'; + } + return pattern; +} - /* SYSV modifications happen through the whole - * string. Note the pattern is anchored at the end. */ - newStr = VarModify(str, VarSYSVMatch, &pattern); +static void +free_looparg(arg) + void *arg; +{ + struct LoopStuff *l = (struct LoopStuff *)arg; - /* Restore the nulled characters */ - pattern.lhs[pattern.leftLen] = '='; - pattern.rhs[pattern.rightLen] = endc; - termc = endc; - } else -#endif - { - Error ("Unknown modifier '%c'\n", *tstr); - for (cp = tstr+1; - *cp != ':' && *cp != endc && *cp != '\0';) - cp++; - termc = *cp; - newStr = var_Error; + free(l->var); + free(l->expand); +} + +static char * +LoopGrab(s) + const char **s; +{ + const char *p, *start; + + start = *s; + for (p = start; *p != '@'; p++) { + if (*p == '\\') + p++; + if (*p == 0) + return NULL; + } + *s = p+1; + return escape_dup(start, p, "@\\"); +} + +static void * +get_loop(p, ctxt, err, endc) + const char **p; + SymTable *ctxt; + Boolean err; + int endc; +{ + static struct LoopStuff loop; + const char *s; + + s = *p +1; + + loop.var = NULL; + loop.expand = NULL; + loop.ctxt =ctxt; + loop.err = err; + loop.var = LoopGrab(&s); + if (loop.var != NULL) { + loop.expand = LoopGrab(&s); + if (*s == endc || *s == ':') { + *p = s; + return &loop; + } + } + free_looparg(&loop); + return NULL; +} + +static void * +get_patternarg(p, ctxt, err, endc) + const char **p; + SymTable *ctxt; + Boolean err; + int endc; +{ + static VarPattern pattern; /* just one for the whole system */ + char delim; + const char *s; + + s = *p; + + pattern.flags = 0; + delim = s[1]; + if (delim == '\0') + return NULL; + s += 2; + + pattern.rhs = NULL; + pattern.lhs = VarGetPattern(ctxt, err, &s, delim, delim, + &pattern.leftLen, NULL); + pattern.lbuffer = pattern.lhs; + if (pattern.lhs != NULL) { + pattern.rhs = VarGetPattern(ctxt, err, &s, delim, delim, + &pattern.rightLen, &pattern); + if (pattern.rhs != NULL) { + /* Check for global substitution. If 'g' after the final + * delimiter, substitution is global and is marked that + * way. */ + for (;; s++) { + switch (*s) { + case 'g': + pattern.flags |= VAR_SUB_GLOBAL; + continue; + case '1': + pattern.flags |= VAR_SUB_ONE; + continue; } + break; + } + if (*s == endc || *s == ':') { + *p = s; + return &pattern; } } - if (DEBUG(VAR)) - printf("Result is \"%s\"\n", newStr != NULL ? newStr : ""); + } + free_patternarg(&pattern); + return NULL; +} - if (*freePtr) - free(str); - str = newStr; - if (str != var_Error && str != NULL) - *freePtr = TRUE; - else - *freePtr = FALSE; - if (termc == '\0') - Error("Unclosed variable specification"); - else if (termc == ':') - *cp++ = termc; - else - *cp = termc; - tstr = cp; +static void * +assign_get_value(p, ctxt, err, endc) + const char **p; + SymTable *ctxt; + Boolean err; + int endc; +{ + const char *s; + int flags; + VarPattern *arg; + + s = *p + 1; + if (s[0] == '=') + flags = VAR_EQUAL; + else if (s[0] == '?' && s[1] == '=') + flags = VAR_MAY_EQUAL; + else if (s[0] == '+' && s[1] == '=') + flags = VAR_ADD_EQUAL; + else if (s[0] == '!' && s[1] == '=') + flags = VAR_BANG_EQUAL; + else + return NULL; + + arg = get_value(&s, ctxt, err, endc); + if (arg != NULL) { + *p = s; + arg->flags = flags; + } + return arg; +} + +static void * +get_value(p, ctxt, err, endc) + const char **p; + SymTable *ctxt; + Boolean err; + int endc; +{ + static VarPattern pattern; + const char *s; + + s = *p + 1; + pattern.rhs = NULL; + pattern.lbuffer = VarGetPattern(ctxt, err, &s, ':', endc, + &pattern.leftLen, NULL); + if (s[-1] == endc || s[-1] == ':') { + *p = s-1; + return &pattern; } - *lengthPtr += tstr - start+1; - return str; + free_patternarg(&pattern); + return NULL; +} -cleanup: - *lengthPtr += cp - start +1; - if (*freePtr) - free(str); - Error("Unclosed substitution for (%c missing)", delim); - return var_Error; +static void * +get_cmd(p, ctxt, err, endc) + const char **p; + SymTable *ctxt; + Boolean err; + int endc UNUSED; +{ + static VarPattern pattern; + const char *s; + + s = *p + 1; + pattern.rhs = NULL; + pattern.lbuffer = VarGetPattern(ctxt, err, &s, '!', '!', + &pattern.leftLen, NULL); + if (s[-1] == '!') { + *p = s-1; + return &pattern; + } + free_patternarg(&pattern); + return NULL; } -/*- - *----------------------------------------------------------------------- - * VarQuote -- - * Quote shell meta-characters in the string - * - * Results: - * The quoted string - * - *----------------------------------------------------------------------- - */ +static void +free_patternarg(p) + void *p; +{ + VarPattern *vp = (VarPattern *)p; + free(vp->lbuffer); + free(vp->rhs); +} + +#ifndef MAKE_BOOTSTRAP static char * -VarQuote(str) - const char *str; +do_regex(s, n, arg) + const char *s; + const struct Name *n UNUSED; + void *arg; { + VarREPattern p2; + VarPattern *p = (VarPattern *)arg; + int error; + char *result; + + error = regcomp(&p2.re, p->lhs, REG_EXTENDED); + if (error) { + VarREError(error, &p2.re, "RE substitution error"); + return var_Error; + } + p2.nsub = p2.re.re_nsub + 1; + p2.replace = p->rhs; + p2.flags = p->flags; + if (p2.nsub < 1) + p2.nsub = 1; + if (p2.nsub > 10) + p2.nsub = 10; + p2.matches = emalloc(p2.nsub * sizeof(regmatch_t)); + result = VarModify((char *)s, VarRESubstitute, &p2); + regfree(&p2.re); + free(p2.matches); + return result; +} +#endif - BUFFER buf; - /* This should cover most shells :-( */ - static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; +char * +VarModifiers_Apply(str, name, ctxt, err, freePtr, start, endc, lengthPtr) + char *str; + const struct Name *name; + SymTable *ctxt; + Boolean err; + Boolean *freePtr; + const char *start; + int endc; + size_t *lengthPtr; +{ + const char *tstr; + Boolean atstart; /* Some ODE modifiers only make sense at start */ - if (str == NULL) - return NULL; + tstr = start; + /* + * Now we need to apply any modifiers the user wants applied. + * These are: + * :M<pattern> words which match the given <pattern>. + * <pattern> is of the standard file + * wildcarding form. + * :S<d><pat1><d><pat2><d>[g] + * Substitute <pat2> for <pat1> in the value + * :C<d><pat1><d><pat2><d>[g] + * Substitute <pat2> for regex <pat1> in the value + * :H Substitute the head of each word + * :T Substitute the tail of each word + * :E Substitute the extension (minus '.') of + * each word + * :R Substitute the root of each word + * (pathname minus the suffix). + * :lhs=rhs Like :S, but the rhs goes to the end of + * the invocation. + */ + + atstart = TRUE; + while (*tstr != endc && *tstr != '\0') { + struct modifier *mod; + void *arg; + char *newStr; + + tstr++; + if (DEBUG(VAR)) + printf("Applying :%c to \"%s\"\n", *tstr, str); - Buf_Init(&buf, MAKE_BSIZE); - for (; *str; str++) { - if (strchr(meta, *str) != NULL) - Buf_AddChar(&buf, '\\'); - Buf_AddChar(&buf, *str); + mod = choose_mod[*tstr]; + arg = NULL; + + if (mod != NULL && (!mod->atstart || atstart)) + arg = mod->getarg(&tstr, ctxt, err, endc); + if (FEATURES(FEATURE_SYSVVARSUB) && arg == NULL) { + mod = &sysv_mod; + arg = mod->getarg(&tstr, ctxt, err, endc); + } + atstart = FALSE; + if (arg != NULL) { + if (str != NULL || (mod->atstart && name != NULL)) { + if (mod->word_apply != NULL) { + newStr = VarModify(str, mod->word_apply, arg); + if (mod->apply != NULL) { + char *newStr2; + + newStr2 = mod->apply(newStr, name, arg); + free(newStr); + newStr = newStr2; + } + } else + newStr = mod->apply(str, name, arg); + if (*freePtr) + free(str); + str = newStr; + if (str != var_Error) + *freePtr = TRUE; + else + *freePtr = FALSE; + } + if (mod->freearg != NULL) + mod->freearg(arg); + } else { + Error("Bad modifier: %s\n", tstr); + /* Try skipping to end of var... */ + for (tstr++; *tstr != endc && *tstr != '\0';) + tstr++; + if (str != NULL && *freePtr) + free(str); + str = var_Error; + freePtr = FALSE; + break; + } + if (DEBUG(VAR)) + printf("Result is \"%s\"\n", str); } - return Buf_Retrieve(&buf); + if (*tstr == '\0') + Error("Unclosed variable specification"); + + *lengthPtr += tstr - start; + 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. - * - * Results: - * The leading components. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ char * -Var_GetHead(file) - char *file; /* Filename to manipulate */ +Var_GetHead(s) + char *s; { - return VarModify(file, VarHead, NULL); + return VarModify(s, VarHead, NULL); } /*- @@ -1300,19 +1593,11 @@ Var_GetHead(file) * Var_GetTail -- * Return the tail from each of a list of words. Used to set the * System V local variables. - * - * Results: - * The resulting string. - * - * Side Effects: - * None. - * *----------------------------------------------------------------------- */ char * -Var_GetTail(file) - char *file; /* Filename to modify */ +Var_GetTail(s) + char *s; { - return VarModify(file, VarTail, NULL); + return VarModify(s, VarTail, NULL); } - diff --git a/usr.bin/make/varmodifiers.h b/usr.bin/make/varmodifiers.h index 3b34269707a..227459ca6e8 100644 --- a/usr.bin/make/varmodifiers.h +++ b/usr.bin/make/varmodifiers.h @@ -1,4 +1,5 @@ -/* $OpenBSD: varmodifiers.h,v 1.1 2000/07/17 23:09:06 espie Exp $ */ +/* $OpenPackages$ */ +/* $OpenBSD: varmodifiers.h,v 1.2 2001/05/03 13:41:15 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie. @@ -28,8 +29,9 @@ */ #ifndef VARMODIFIERS_H #define VARMODIFIERS_H -extern char *VarModifiers_Apply __P((char *, SymTable *, Boolean, - Boolean *, char *, char, size_t *)); -extern char *Var_GetTail __P((char *)); -extern char *Var_GetHead __P((char *)); +extern char *VarModifiers_Apply(char *, const struct Name *, SymTable *, + Boolean, Boolean *, const char *, int, size_t *); +extern char *Var_GetTail(char *); +extern char *Var_GetHead(char *); +extern void VarModifiers_Init(void); #endif |