VirtualBox

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

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

kMk and porting to kLib.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.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#define KLIBFILEDEF rcsid
42#endif /* not lint */
43
44/*-
45 * for.c --
46 * Functions to handle loops in a makefile.
47 *
48 * Interface:
49 * For_Eval Evaluate the loop in the passed line.
50 * For_Run Run accumulated loop
51 *
52 */
53
54#include <ctype.h>
55#include "make.h"
56#include "hash.h"
57#include "dir.h"
58#include "buf.h"
59
60/*
61 * For statements are of the form:
62 *
63 * .for <variable> in <varlist>
64 * ...
65 * .endfor
66 *
67 * The trick is to look for the matching end inside for for loop
68 * To do that, we count the current nesting level of the for loops.
69 * and the .endfor statements, accumulating all the statements between
70 * the initial .for loop and the matching .endfor;
71 * then we evaluate the for loop for each variable in the varlist.
72 */
73
74static int forLevel = 0; /* Nesting level */
75static char *forVar; /* Iteration variable */
76static Buffer forBuf; /* Commands in loop */
77static Lst forLst; /* List of items */
78
79/*
80 * State of a for loop.
81 */
82typedef struct _For {
83 Buffer buf; /* Unexpanded buffer */
84 char* var; /* Index name */
85 Lst lst; /* List of variables */
86} For;
87
88static int ForExec __P((ClientData, ClientData));
89
90
91
92
93
94/*-
95 *-----------------------------------------------------------------------
96 * For_Eval --
97 * Evaluate the for loop in the passed line. The line
98 * looks like this:
99 * .for <variable> in <varlist>
100 *
101 * Results:
102 * TRUE: We found a for loop, or we are inside a for loop
103 * FALSE: We did not find a for loop, or we found the end of the for
104 * for loop.
105 *
106 * Side Effects:
107 * None.
108 *
109 *-----------------------------------------------------------------------
110 */
111int
112For_Eval (line)
113 char *line; /* Line to parse */
114{
115 char *ptr = line, *sub, *wrd;
116 int level; /* Level at which to report errors. */
117
118 level = PARSE_FATAL;
119
120
121 if (forLevel == 0) {
122 Buffer buf;
123 int varlen;
124
125 for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
126 continue;
127 /*
128 * If we are not in a for loop quickly determine if the statement is
129 * a for.
130 */
131 if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' ||
132 !isspace((unsigned char) ptr[3]))
133 return FALSE;
134 ptr += 3;
135
136 /*
137 * we found a for loop, and now we are going to parse it.
138 */
139 while (*ptr && isspace((unsigned char) *ptr))
140 ptr++;
141
142 /*
143 * Grab the variable
144 */
145 buf = Buf_Init(0);
146 for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++)
147 continue;
148 Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd);
149
150 forVar = (char *) Buf_GetAll(buf, &varlen);
151 if (varlen == 0) {
152 Parse_Error (level, "missing variable in for");
153 return 0;
154 }
155 Buf_Destroy(buf, FALSE);
156
157 while (*ptr && isspace((unsigned char) *ptr))
158 ptr++;
159
160 /*
161 * Grab the `in'
162 */
163 if (ptr[0] != 'i' || ptr[1] != 'n' ||
164 !isspace((unsigned char) ptr[2])) {
165 Parse_Error (level, "missing `in' in for");
166 printf("%s\n", ptr);
167 return 0;
168 }
169 ptr += 3;
170
171 while (*ptr && isspace((unsigned char) *ptr))
172 ptr++;
173
174 /*
175 * Make a list with the remaining words
176 */
177 forLst = Lst_Init(FALSE);
178 buf = Buf_Init(0);
179 sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
180
181#define ADDWORD() \
182 Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd), \
183 Buf_AddByte(buf, (Byte) '\0'), \
184 Lst_AtFront(forLst, (ClientData) Buf_GetAll(buf, &varlen)), \
185 Buf_Destroy(buf, FALSE)
186
187 for (ptr = sub; *ptr && isspace((unsigned char) *ptr); ptr++)
188 continue;
189
190 for (wrd = ptr; *ptr; ptr++)
191 if (isspace((unsigned char) *ptr)) {
192 ADDWORD();
193 buf = Buf_Init(0);
194 while (*ptr && isspace((unsigned char) *ptr))
195 ptr++;
196 wrd = ptr--;
197 }
198 if (DEBUG(FOR))
199 (void) fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);
200 if (ptr - wrd > 0)
201 ADDWORD();
202 else
203 Buf_Destroy(buf, TRUE);
204 efree((Address) sub);
205
206 forBuf = Buf_Init(0);
207 forLevel++;
208 return 1;
209 }
210 else if (*ptr == '.') {
211
212 for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
213 continue;
214
215 if (strncmp(ptr, "endfor", 6) == 0 &&
216 (isspace((unsigned char) ptr[6]) || !ptr[6])) {
217 if (DEBUG(FOR))
218 (void) fprintf(stderr, "For: end for %d\n", forLevel);
219 if (--forLevel < 0) {
220 Parse_Error (level, "for-less endfor");
221 return 0;
222 }
223 }
224 else if (strncmp(ptr, "for", 3) == 0 &&
225 isspace((unsigned char) ptr[3])) {
226 forLevel++;
227 if (DEBUG(FOR))
228 (void) fprintf(stderr, "For: new loop %d\n", forLevel);
229 }
230 }
231
232 if (forLevel != 0) {
233 Buf_AddBytes(forBuf, strlen(line), (Byte *) line);
234 Buf_AddByte(forBuf, (Byte) '\n');
235 return 1;
236 }
237 else {
238 return 0;
239 }
240}
241
242/*-
243 *-----------------------------------------------------------------------
244 * ForExec --
245 * Expand the for loop for this index and push it in the Makefile
246 *
247 * Results:
248 * None.
249 *
250 * Side Effects:
251 * None.
252 *
253 *-----------------------------------------------------------------------
254 */
255static int
256ForExec(namep, argp)
257 ClientData namep;
258 ClientData argp;
259{
260 char *name = (char *) namep;
261 For *arg = (For *) argp;
262 int len;
263 Var_Set(arg->var, name, VAR_GLOBAL);
264 if (DEBUG(FOR))
265 (void) fprintf(stderr, "--- %s = %s\n", arg->var, name);
266 Parse_FromString(Var_Subst(arg->var, (char *) Buf_GetAll(arg->buf, &len),
267 VAR_GLOBAL, FALSE));
268 Var_Delete(arg->var, VAR_GLOBAL);
269
270 return 0;
271}
272
273
274
275/*-
276 *-----------------------------------------------------------------------
277 * For_Run --
278 * Run the for loop, immitating the actions of an include file
279 *
280 * Results:
281 * None.
282 *
283 * Side Effects:
284 * None.
285 *
286 *-----------------------------------------------------------------------
287 */
288void
289For_Run()
290{
291 For arg;
292
293 if (forVar == NULL || forBuf == NULL || forLst == NULL)
294 return;
295 arg.var = forVar;
296 arg.buf = forBuf;
297 arg.lst = forLst;
298 forVar = NULL;
299 forBuf = NULL;
300 forLst = NULL;
301
302 Lst_ForEach(arg.lst, ForExec, (ClientData) &arg);
303
304 efree((Address)arg.var);
305 Lst_Destroy(arg.lst, (void (*) __P((ClientData))) efree);
306 Buf_Destroy(arg.buf, TRUE);
307}
Note: See TracBrowser for help on using the repository browser.

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