diff options
Diffstat (limited to 'usr.bin/make/expandchildren.c')
-rw-r--r-- | usr.bin/make/expandchildren.c | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/usr.bin/make/expandchildren.c b/usr.bin/make/expandchildren.c new file mode 100644 index 00000000000..c16ed95691e --- /dev/null +++ b/usr.bin/make/expandchildren.c @@ -0,0 +1,246 @@ +/* $OpenBSD: expandchildren.c,v 1.1 2020/01/13 14:05:21 espie Exp $ */ +/* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + */ + +/*- + * expandchildren.c -- + * Dealing with final children expansion before building stuff + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "direxpand.h" +#include "engine.h" +#include "arch.h" +#include "expandchildren.h" +#include "var.h" +#include "targ.h" +#include "lst.h" +#include "gnode.h" +#include "suff.h" + +static void ExpandChildren(LstNode, GNode *); +static void ExpandVarChildren(LstNode, GNode *, GNode *); +static void ExpandWildChildren(LstNode, GNode *, GNode *); + +void +LinkParent(GNode *cgn, GNode *pgn) +{ + Lst_AtEnd(&cgn->parents, pgn); + if (!has_been_built(cgn)) + pgn->children_left++; + else if ( ! (cgn->type & (OP_EXEC|OP_USE))) { + if (cgn->built_status == REBUILT) + pgn->child_rebuilt = true; + (void)Make_TimeStamp(pgn, cgn); + } +} + +static void +ExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn) +{ + GNode *gn; /* New source 8) */ + char *cp; /* Expanded value */ + LIST members; + + + if (DEBUG(SUFF)) + printf("Expanding \"%s\"...", cgn->name); + + cp = Var_Subst(cgn->name, &pgn->localvars, true); + if (cp == NULL) { + printf("Problem substituting in %s", cgn->name); + printf("\n"); + return; + } + + 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. + */ + const char *sacrifice = (const char *)cp; + + (void)Arch_ParseArchive(&sacrifice, &members, &pgn->localvars); + } 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... */ + const 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_FindNodei(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. */ + Var_ParseSkip(&cp2, &pgn->localvars); + else if (*cp2 == '\\' && cp2[1] != '\0') + /* Escaped something -- skip over it. */ + cp2+=2; + else + cp2++; + } + + if (cp2 != start) { + /* Stuff left over -- add it to the list too. */ + gn = Targ_FindNodei(start, cp2, TARG_CREATE); + Lst_AtEnd(&members, gn); + } + } + /* Add all elements of the members list to the parent node. */ + while ((gn = Lst_DeQueue(&members)) != NULL) { + if (DEBUG(SUFF)) + printf("%s...", gn->name); + if (Lst_Member(&pgn->children, gn) == NULL) { + Lst_Append(&pgn->children, after, gn); + after = Lst_Adv(after); + LinkParent(gn, pgn); + } + } + /* Free the result. */ + free(cp); + if (DEBUG(SUFF)) + printf("\n"); +} + +static void +ExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn) +{ + char *cp; /* Expanded value */ + + LIST exp; /* List of expansions */ + Lst path; /* Search path along which to expand */ + + if (DEBUG(SUFF)) + printf("Wildcard expanding \"%s\"...", cgn->name); + + /* Find a path along which to expand the word: if + * the word has a known suffix, use the path for that suffix, + * otherwise use the default path. */ + path = find_best_path(cgn->name); + + /* 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 = Lst_DeQueue(&exp)) != NULL) { + GNode *gn; /* New source 8) */ + if (DEBUG(SUFF)) + printf("%s...", cp); + gn = Targ_FindNode(cp, TARG_CREATE); + + /* If gn isn't already a child of the parent, make it so and + * up the parent's count of children to build. */ + if (Lst_Member(&pgn->children, gn) == NULL) { + Lst_Append(&pgn->children, after, gn); + after = Lst_Adv(after); + LinkParent(gn, pgn); + } + } + + if (DEBUG(SUFF)) + printf("\n"); +} + +/*- + *----------------------------------------------------------------------- + * ExpandChildren -- + * 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 children to build counter is decremented, + * but other nodes may be added. + *----------------------------------------------------------------------- + */ +static void +ExpandChildren(LstNode ln, /* LstNode of child, so we can replace it */ + GNode *pgn) +{ + GNode *cgn = Lst_Datum(ln); + + /* 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) + ExpandVarChildren(ln, cgn, pgn); + else if (Dir_HasWildcards(cgn->name)) + ExpandWildChildren(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->children_left--; + Lst_Remove(&pgn->children, ln); +} + +void +expand_children_from(GNode *parent, LstNode from) +{ + LstNode np, ln; + + for (ln = from; ln != NULL; ln = np) { + np = Lst_Adv(ln); + ExpandChildren(ln, parent); + } +} |