VirtualBox

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

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

emx is kind of working again...

  • 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 efree((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 efree((Address)arg.var);
304 Lst_Destroy(arg.lst, (void (*) __P((ClientData))) efree);
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