Annotation of src/usr.bin/make/expandchildren.c, Revision 1.2
1.2 ! espie 1: /* $OpenBSD: expandchildren.c,v 1.1 2020/01/13 14:05:21 espie Exp $ */
1.1 espie 2: /* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1988, 1989, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
7: * Copyright (c) 1989 by Berkeley Softworks
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Adam de Boor.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: */
37:
38: /*-
39: * expandchildren.c --
40: * Dealing with final children expansion before building stuff
41: */
42:
43: #include <ctype.h>
44: #include <stdio.h>
45: #include <stdlib.h>
46: #include <string.h>
47: #include "config.h"
48: #include "defines.h"
49: #include "direxpand.h"
50: #include "engine.h"
51: #include "arch.h"
52: #include "expandchildren.h"
53: #include "var.h"
54: #include "targ.h"
55: #include "lst.h"
56: #include "gnode.h"
57: #include "suff.h"
58:
59: static void ExpandChildren(LstNode, GNode *);
60: static void ExpandVarChildren(LstNode, GNode *, GNode *);
61: static void ExpandWildChildren(LstNode, GNode *, GNode *);
62:
63: void
64: LinkParent(GNode *cgn, GNode *pgn)
65: {
66: Lst_AtEnd(&cgn->parents, pgn);
67: if (!has_been_built(cgn))
68: pgn->children_left++;
1.2 ! espie 69: else if ( ! (cgn->type & OP_USE)) {
1.1 espie 70: if (cgn->built_status == REBUILT)
71: pgn->child_rebuilt = true;
72: (void)Make_TimeStamp(pgn, cgn);
73: }
74: }
75:
76: static void
77: ExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
78: {
79: GNode *gn; /* New source 8) */
80: char *cp; /* Expanded value */
81: LIST members;
82:
83:
84: if (DEBUG(SUFF))
85: printf("Expanding \"%s\"...", cgn->name);
86:
87: cp = Var_Subst(cgn->name, &pgn->localvars, true);
88: if (cp == NULL) {
89: printf("Problem substituting in %s", cgn->name);
90: printf("\n");
91: return;
92: }
93:
94: Lst_Init(&members);
95:
96: if (cgn->type & OP_ARCHV) {
97: /*
98: * Node was an archive(member) target, so we want to call
99: * on the Arch module to find the nodes for us, expanding
100: * variables in the parent's context.
101: */
102: const char *sacrifice = (const char *)cp;
103:
104: (void)Arch_ParseArchive(&sacrifice, &members, &pgn->localvars);
105: } else {
106: /* Break the result into a vector of strings whose nodes
107: * we can find, then add those nodes to the members list.
108: * Unfortunately, we can't use brk_string because it
109: * doesn't understand about variable specifications with
110: * spaces in them... */
111: const char *start, *cp2;
112:
113: for (start = cp; *start == ' ' || *start == '\t'; start++)
114: continue;
115: for (cp2 = start; *cp2 != '\0';) {
116: if (ISSPACE(*cp2)) {
117: /* White-space -- terminate element, find the
118: * node, add it, skip any further spaces. */
119: gn = Targ_FindNodei(start, cp2, TARG_CREATE);
120: cp2++;
121: Lst_AtEnd(&members, gn);
122: while (ISSPACE(*cp2))
123: cp2++;
124: /* Adjust cp2 for increment at start of loop,
125: * but set start to first non-space. */
126: start = cp2;
127: } else if (*cp2 == '$')
128: /* Start of a variable spec -- contact variable
129: * module to find the end so we can skip over
130: * it. */
131: Var_ParseSkip(&cp2, &pgn->localvars);
132: else if (*cp2 == '\\' && cp2[1] != '\0')
133: /* Escaped something -- skip over it. */
134: cp2+=2;
135: else
136: cp2++;
137: }
138:
139: if (cp2 != start) {
140: /* Stuff left over -- add it to the list too. */
141: gn = Targ_FindNodei(start, cp2, TARG_CREATE);
142: Lst_AtEnd(&members, gn);
143: }
144: }
145: /* Add all elements of the members list to the parent node. */
146: while ((gn = Lst_DeQueue(&members)) != NULL) {
147: if (DEBUG(SUFF))
148: printf("%s...", gn->name);
149: if (Lst_Member(&pgn->children, gn) == NULL) {
150: Lst_Append(&pgn->children, after, gn);
151: after = Lst_Adv(after);
152: LinkParent(gn, pgn);
153: }
154: }
155: /* Free the result. */
156: free(cp);
157: if (DEBUG(SUFF))
158: printf("\n");
159: }
160:
161: static void
162: ExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
163: {
164: char *cp; /* Expanded value */
165:
166: LIST exp; /* List of expansions */
167: Lst path; /* Search path along which to expand */
168:
169: if (DEBUG(SUFF))
170: printf("Wildcard expanding \"%s\"...", cgn->name);
171:
172: /* Find a path along which to expand the word: if
173: * the word has a known suffix, use the path for that suffix,
174: * otherwise use the default path. */
175: path = find_best_path(cgn->name);
176:
177: /* Expand the word along the chosen path. */
178: Lst_Init(&exp);
179: Dir_Expand(cgn->name, path, &exp);
180:
181: /* Fetch next expansion off the list and find its GNode. */
182: while ((cp = Lst_DeQueue(&exp)) != NULL) {
183: GNode *gn; /* New source 8) */
184: if (DEBUG(SUFF))
185: printf("%s...", cp);
186: gn = Targ_FindNode(cp, TARG_CREATE);
187:
188: /* If gn isn't already a child of the parent, make it so and
189: * up the parent's count of children to build. */
190: if (Lst_Member(&pgn->children, gn) == NULL) {
191: Lst_Append(&pgn->children, after, gn);
192: after = Lst_Adv(after);
193: LinkParent(gn, pgn);
194: }
195: }
196:
197: if (DEBUG(SUFF))
198: printf("\n");
199: }
200:
201: /*-
202: *-----------------------------------------------------------------------
203: * ExpandChildren --
204: * Expand the names of any children of a given node that contain
205: * variable invocations or file wildcards into actual targets.
206: *
207: * Side Effects:
208: * The expanded node is removed from the parent's list of children,
209: * and the parent's children to build counter is decremented,
210: * but other nodes may be added.
211: *-----------------------------------------------------------------------
212: */
213: static void
214: ExpandChildren(LstNode ln, /* LstNode of child, so we can replace it */
215: GNode *pgn)
216: {
217: GNode *cgn = Lst_Datum(ln);
218:
219: /* First do variable expansion -- this takes precedence over wildcard
220: * expansion. If the result contains wildcards, they'll be gotten to
221: * later since the resulting words are tacked on to the end of the
222: * children list. */
223: if (strchr(cgn->name, '$') != NULL)
224: ExpandVarChildren(ln, cgn, pgn);
225: else if (Dir_HasWildcards(cgn->name))
226: ExpandWildChildren(ln, cgn, pgn);
227: else
228: /* Third case: nothing to expand. */
229: return;
230:
231: /* Since the source was expanded, remove it from the list of children to
232: * keep it from being processed. */
233: pgn->children_left--;
234: Lst_Remove(&pgn->children, ln);
235: }
236:
237: void
238: expand_children_from(GNode *parent, LstNode from)
239: {
240: LstNode np, ln;
241:
242: for (ln = from; ln != NULL; ln = np) {
243: np = Lst_Adv(ln);
244: ExpandChildren(ln, parent);
245: }
246: }