VirtualBox

source: kBuild/trunk/src/kmk/for.c@ 30

Last change on this file since 30 was 25, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 1992, The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
37#else
38static const char rcsid[] =
39 "$FreeBSD: src/usr.bin/make/for.c,v 1.10 1999/09/11 13:08:01 hoek Exp $";
40#endif
41#endif /* not lint */
42
43/*-
44 * for.c --
45 * Functions to handle loops in a makefile.
46 *
47 * Interface:
48 * For_Eval Evaluate the loop in the passed line.
49 * For_Run Run accumulated loop
50 *
51 */
52
53#include <ctype.h>
54#include "make.h"
55#include "hash.h"
56#include "dir.h"
57#include "buf.h"
58
59/*
60 * For statements are of the form:
61 *
62 * .for <variable> in <varlist>
63 * ...
64 * .endfor
65 *
66 * The trick is to look for the matching end inside for for loop
67 * To do that, we count the current nesting level of the for loops.
68 * and the .endfor statements, accumulating all the statements between
69 * the initial .for loop and the matching .endfor;
70 * then we evaluate the for loop for each variable in the varlist.
71 */
72
73static int forLevel = 0; /* Nesting level */
74static char *forVar; /* Iteration variable */
75static Buffer forBuf; /* Commands in loop */
76static Lst forLst; /* List of items */
77
78/*
79 * State of a for loop.
80 */
81typedef struct _For {
82 Buffer buf; /* Unexpanded buffer */
83 char* var; /* Index name */
84 Lst lst; /* List of variables */
85} For;
86
87static int ForExec __P((ClientData, ClientData));
88
89
90
91
92
93/*-
94 *-----------------------------------------------------------------------
95 * For_Eval --
96 * Evaluate the for loop in the passed line. The line
97 * looks like this:
98 * .for <variable> in <varlist>
99 *
100 * Results:
101 * TRUE: We found a for loop, or we are inside a for loop
102 * FALSE: We did not find a for loop, or we found the end of the for
103 * for loop.
104 *
105 * Side Effects:
106 * None.
107 *
108 *-----------------------------------------------------------------------
109 */
110int
111For_Eval (line)
112 char *line; /* Line to parse */
113{
114 char *ptr = line, *sub, *wrd;
115 int level; /* Level at which to report errors. */
116
117 level = PARSE_FATAL;
118
119
120 if (forLevel == 0) {
121 Buffer buf;
122 int varlen;
123
124 for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
125 continue;
126 /*
127 * If we are not in a for loop quickly determine if the statement is
128 * a for.
129 */
130 if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' ||
131 !isspace((unsigned char) ptr[3]))
132 return FALSE;
133 ptr += 3;
134
135 /*
136 * we found a for loop, and now we are going to parse it.
137 */
138 while (*ptr && isspace((unsigned char) *ptr))
139 ptr++;
140
141 /*
142 * Grab the variable
143 */
144 buf = Buf_Init(0);
145 for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++)
146 continue;
147 Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd);
148
149 forVar = (char *) Buf_GetAll(buf, &varlen);
150 if (varlen == 0) {
151 Parse_Error (level, "missing variable in for");
152 return 0;
153 }
154 Buf_Destroy(buf, FALSE);
155
156 while (*ptr && isspace((unsigned char) *ptr))
157 ptr++;
158
159 /*
160 * Grab the `in'
161 */
162 if (ptr[0] != 'i' || ptr[1] != 'n' ||
163 !isspace((unsigned char) ptr[2])) {
164 Parse_Error (level, "missing `in' in for");
165 printf("%s\n", ptr);
166 return 0;
167 }
168 ptr += 3;
169
170 while (*ptr && isspace((unsigned char) *ptr))
171 ptr++;
172
173 /*
174 * Make a list with the remaining words
175 */
176 forLst = Lst_Init(FALSE);
177 buf = Buf_Init(0);
178 sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
179
180#define ADDWORD() \
181 Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd), \
182 Buf_AddByte(buf, (Byte) '\0'), \
183 Lst_AtFront(forLst, (ClientData) Buf_GetAll(buf, &varlen)), \
184 Buf_Destroy(buf, FALSE)
185
186 for (ptr = sub; *ptr && isspace((unsigned char) *ptr); ptr++)
187 continue;
188
189 for (wrd = ptr; *ptr; ptr++)
190 if (isspace((unsigned char) *ptr)) {
191 ADDWORD();
192 buf = Buf_Init(0);
193 while (*ptr && isspace((unsigned char) *ptr))
194 ptr++;
195 wrd = ptr--;
196 }
197 if (DEBUG(FOR))
198 (void) fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);
199 if (ptr - wrd > 0)
200 ADDWORD();
201 else
202 Buf_Destroy(buf, TRUE);
203 free((Address) sub);
204
205 forBuf = Buf_Init(0);
206 forLevel++;
207 return 1;
208 }
209 else if (*ptr == '.') {
210
211 for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
212 continue;
213
214 if (strncmp(ptr, "endfor", 6) == 0 &&
215 (isspace((unsigned char) ptr[6]) || !ptr[6])) {
216 if (DEBUG(FOR))
217 (void) fprintf(stderr, "For: end for %d\n", forLevel);
218 if (--forLevel < 0) {
219 Parse_Error (level, "for-less endfor");
220 return 0;
221 }
222 }
223 else if (strncmp(ptr, "for", 3) == 0 &&
224 isspace((unsigned char) ptr[3])) {
225 forLevel++;
226 if (DEBUG(FOR))
227 (void) fprintf(stderr, "For: new loop %d\n", forLevel);
228 }
229 }
230
231 if (forLevel != 0) {
232 Buf_AddBytes(forBuf, strlen(line), (Byte *) line);
233 Buf_AddByte(forBuf, (Byte) '\n');
234 return 1;
235 }
236 else {
237 return 0;
238 }
239}
240
241/*-
242 *-----------------------------------------------------------------------
243 * ForExec --
244 * Expand the for loop for this index and push it in the Makefile
245 *
246 * Results:
247 * None.
248 *
249 * Side Effects:
250 * None.
251 *
252 *-----------------------------------------------------------------------
253 */
254static int
255ForExec(namep, argp)
256 ClientData namep;
257 ClientData argp;
258{
259 char *name = (char *) namep;
260 For *arg = (For *) argp;
261 int len;
262 Var_Set(arg->var, name, VAR_GLOBAL);
263 if (DEBUG(FOR))
264 (void) fprintf(stderr, "--- %s = %s\n", arg->var, name);
265 Parse_FromString(Var_Subst(arg->var, (char *) Buf_GetAll(arg->buf, &len),
266 VAR_GLOBAL, FALSE));
267 Var_Delete(arg->var, VAR_GLOBAL);
268
269 return 0;
270}
271
272
273
274/*-
275 *-----------------------------------------------------------------------
276 * For_Run --
277 * Run the for loop, immitating the actions of an include file
278 *
279 * Results:
280 * None.
281 *
282 * Side Effects:
283 * None.
284 *
285 *-----------------------------------------------------------------------
286 */
287void
288For_Run()
289{
290 For arg;
291
292 if (forVar == NULL || forBuf == NULL || forLst == NULL)
293 return;
294 arg.var = forVar;
295 arg.buf = forBuf;
296 arg.lst = forLst;
297 forVar = NULL;
298 forBuf = NULL;
299 forLst = NULL;
300
301 Lst_ForEach(arg.lst, ForExec, (ClientData) &arg);
302
303 free((Address)arg.var);
304 Lst_Destroy(arg.lst, (void (*) __P((ClientData))) free);
305 Buf_Destroy(arg.buf, TRUE);
306}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette