Annotation of src/usr.bin/make/expandchildren.c, Revision 1.3
1.3 ! espie 1: /* $OpenBSD: expandchildren.c,v 1.2 2020/01/26 12:41: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 "defines.h"
48: #include "direxpand.h"
49: #include "engine.h"
50: #include "arch.h"
51: #include "expandchildren.h"
52: #include "var.h"
53: #include "targ.h"
54: #include "lst.h"
55: #include "gnode.h"
56: #include "suff.h"
57:
58: static void ExpandChildren(LstNode, GNode *);
59: static void ExpandVarChildren(LstNode, GNode *, GNode *);
60: static void ExpandWildChildren(LstNode, GNode *, GNode *);
61:
62: void
63: LinkParent(GNode *cgn, GNode *pgn)
64: {
65: Lst_AtEnd(&cgn->parents, pgn);
66: if (!has_been_built(cgn))
67: pgn->children_left++;
1.2 espie 68: else if ( ! (cgn->type & OP_USE)) {
1.1 espie 69: if (cgn->built_status == REBUILT)
70: pgn->child_rebuilt = true;
71: (void)Make_TimeStamp(pgn, cgn);
72: }
73: }
74:
75: static void
76: ExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
77: {
78: GNode *gn; /* New source 8) */
79: char *cp; /* Expanded value */
80: LIST members;
81:
82:
83: if (DEBUG(SUFF))
84: printf("Expanding \"%s\"...", cgn->name);
85:
86: cp = Var_Subst(cgn->name, &pgn->localvars, true);
87: if (cp == NULL) {
88: printf("Problem substituting in %s", cgn->name);
89: printf("\n");
90: return;
91: }
92:
93: Lst_Init(&members);
94:
95: if (cgn->type & OP_ARCHV) {
96: /*
97: * Node was an archive(member) target, so we want to call
98: * on the Arch module to find the nodes for us, expanding
99: * variables in the parent's context.
100: */
101: const char *sacrifice = (const char *)cp;
102:
103: (void)Arch_ParseArchive(&sacrifice, &members, &pgn->localvars);
104: } else {
105: /* Break the result into a vector of strings whose nodes
106: * we can find, then add those nodes to the members list.
107: * Unfortunately, we can't use brk_string because it
108: * doesn't understand about variable specifications with
109: * spaces in them... */
110: const char *start, *cp2;
111:
112: for (start = cp; *start == ' ' || *start == '\t'; start++)
113: continue;
114: for (cp2 = start; *cp2 != '\0';) {
115: if (ISSPACE(*cp2)) {
116: /* White-space -- terminate element, find the
117: * node, add it, skip any further spaces. */
118: gn = Targ_FindNodei(start, cp2, TARG_CREATE);
119: cp2++;
120: Lst_AtEnd(&members, gn);
121: while (ISSPACE(*cp2))
122: cp2++;
123: /* Adjust cp2 for increment at start of loop,
124: * but set start to first non-space. */
125: start = cp2;
126: } else if (*cp2 == '$')
127: /* Start of a variable spec -- contact variable
128: * module to find the end so we can skip over
129: * it. */
130: Var_ParseSkip(&cp2, &pgn->localvars);
131: else if (*cp2 == '\\' && cp2[1] != '\0')
132: /* Escaped something -- skip over it. */
133: cp2+=2;
134: else
135: cp2++;
136: }
137:
138: if (cp2 != start) {
139: /* Stuff left over -- add it to the list too. */
140: gn = Targ_FindNodei(start, cp2, TARG_CREATE);
141: Lst_AtEnd(&members, gn);
142: }
143: }
144: /* Add all elements of the members list to the parent node. */
145: while ((gn = Lst_DeQueue(&members)) != NULL) {
146: if (DEBUG(SUFF))
147: printf("%s...", gn->name);
148: if (Lst_Member(&pgn->children, gn) == NULL) {
149: Lst_Append(&pgn->children, after, gn);
150: after = Lst_Adv(after);
151: LinkParent(gn, pgn);
152: }
153: }
154: /* Free the result. */
155: free(cp);
156: if (DEBUG(SUFF))
157: printf("\n");
158: }
159:
160: static void
161: ExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
162: {
163: char *cp; /* Expanded value */
164:
165: LIST exp; /* List of expansions */
166: Lst path; /* Search path along which to expand */
167:
168: if (DEBUG(SUFF))
169: printf("Wildcard expanding \"%s\"...", cgn->name);
170:
171: /* Find a path along which to expand the word: if
172: * the word has a known suffix, use the path for that suffix,
173: * otherwise use the default path. */
174: path = find_best_path(cgn->name);
175:
176: /* Expand the word along the chosen path. */
177: Lst_Init(&exp);
178: Dir_Expand(cgn->name, path, &exp);
179:
180: /* Fetch next expansion off the list and find its GNode. */
181: while ((cp = Lst_DeQueue(&exp)) != NULL) {
182: GNode *gn; /* New source 8) */
183: if (DEBUG(SUFF))
184: printf("%s...", cp);
185: gn = Targ_FindNode(cp, TARG_CREATE);
186:
187: /* If gn isn't already a child of the parent, make it so and
188: * up the parent's count of children to build. */
189: if (Lst_Member(&pgn->children, gn) == NULL) {
190: Lst_Append(&pgn->children, after, gn);
191: after = Lst_Adv(after);
192: LinkParent(gn, pgn);
193: }
194: }
195:
196: if (DEBUG(SUFF))
197: printf("\n");
198: }
199:
200: /*-
201: *-----------------------------------------------------------------------
202: * ExpandChildren --
203: * Expand the names of any children of a given node that contain
204: * variable invocations or file wildcards into actual targets.
205: *
206: * Side Effects:
207: * The expanded node is removed from the parent's list of children,
208: * and the parent's children to build counter is decremented,
209: * but other nodes may be added.
210: *-----------------------------------------------------------------------
211: */
212: static void
213: ExpandChildren(LstNode ln, /* LstNode of child, so we can replace it */
214: GNode *pgn)
215: {
216: GNode *cgn = Lst_Datum(ln);
217:
218: /* First do variable expansion -- this takes precedence over wildcard
219: * expansion. If the result contains wildcards, they'll be gotten to
220: * later since the resulting words are tacked on to the end of the
221: * children list. */
222: if (strchr(cgn->name, '$') != NULL)
223: ExpandVarChildren(ln, cgn, pgn);
224: else if (Dir_HasWildcards(cgn->name))
225: ExpandWildChildren(ln, cgn, pgn);
226: else
227: /* Third case: nothing to expand. */
228: return;
229:
230: /* Since the source was expanded, remove it from the list of children to
231: * keep it from being processed. */
232: pgn->children_left--;
233: Lst_Remove(&pgn->children, ln);
234: }
235:
236: void
237: expand_children_from(GNode *parent, LstNode from)
238: {
239: LstNode np, ln;
240:
241: for (ln = from; ln != NULL; ln = np) {
242: np = Lst_Adv(ln);
243: ExpandChildren(ln, parent);
244: }
245: }