source: trunk/minix/commands/make/input.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 11.0 KB
RevLine 
[9]1/*************************************************************************
2 *
3 * m a k e : i n p u t . c
4 *
5 * Parse a makefile
6 *========================================================================
7 * Edition history
8 *
9 * # Date Comments By
10 * --- -------- ---------------------------------------------------- ---
11 * 1 ?? ??
12 * 2 23.08.89 new name tree structure introduced to speed up make,
13 * testname introduced to shrink the memory usage RAL
14 * 3 30.08.89 indention changed PSH,RAL
15 * 4 03.09.89 fixed LZ eliminated RAL
16 * 5 06.09.89 ; command added RAL
17 * ------------ Version 2.0 released ------------------------------- RAL
18 *
19 *************************************************************************/
20
21
22#include "h.h"
23
24
25static struct name *lastrrp;
26static struct name *freerp = (struct name *)NULL;
27
28void init()
29{
30 if( (suffparray = (struct name **) malloc( sizesuffarray *
31 sizeof(struct name *))) == (struct name **) NULL)
32 fatal("No memory for suffarray",(char *)0,0);
33 if ((*suffparray = (struct name *)malloc(sizeof (struct name)))
34 == (struct name *)0)
35 fatal("No memory for name",(char *)0,0);
36 (*suffparray)->n_next = (struct name *)0;
37
38 if ((str1 = (char *) malloc(LZ1)) == ((char *)0))
39 fatal("No memory for str1",(char *)0,0);
40 str1s.ptr = &str1;
41 str1s.len = LZ1;
42 if ((str2 = (char *) malloc(LZ2)) == (char *)0)
43 fatal("No memory for str2",(char *)0,0);
44 str2s.ptr = &str2;
45 str2s.len = LZ2;
46}
47
48void strrealloc(strs)
49struct str *strs;
50{
51 strs->len *= 2;
52 *strs->ptr = (char *) realloc(*strs->ptr, strs->len + 16);
53 if(*strs->ptr == (char *) NULL)
54 fatal("No memory for string reallocation",(char *)0,0);
55}
56
57/*
58 * Intern a name. Return a pointer to the name struct
59 */
60struct name *newname(name)
61char *name;
62{
63 register struct name *rp;
64 register struct name *rrp;
65 register char *cp;
66
67 register int i;
68 register char *suff; /* ptr. to suffix in current name */
69 register struct name **sp; /* ptr. to ptr. to chain of names */
70
71 if ( (suff = suffix(name)) != (char *)NULL) {
72 for (i = 1, sp = suffparray, sp++;
73 i <= maxsuffarray && strcmp(suff, (*sp)->n_name) != 0;
74 sp++,i++);
75 if (i > maxsuffarray) {
76 if ( i >= sizesuffarray) { /* must realloc suffarray */
77 sizesuffarray *= 2;
78 if( (suffparray = (struct name **) realloc((char *) suffparray,
79 sizesuffarray * sizeof(struct name *))) == (struct name **) NULL)
80 fatal("No memory for suffarray",(char *)0,0);
81 }
82 maxsuffarray++;
83 sp = &suffparray[i];
84 if ((*sp = (struct name *)malloc(sizeof (struct name)))
85 == (struct name *)0)
86 fatal("No memory for name",(char *)0,0);
87 (*sp)->n_next = (struct name *)0;
88 if ((cp = (char *) malloc(strlen(suff)+1)) == (char *)0)
89 fatal("No memory for name",(char *)0,0);
90 strcpy(cp, suff);
91 (*sp)->n_name = cp;
92 }
93 }
94 else
95 sp = suffparray;
96
97 for ( rp = (*sp)->n_next, rrp = *sp; rp; rp = rp->n_next, rrp = rrp->n_next )
98 if (strcmp(name, rp->n_name) == 0) return rp;
99
100 if ( freerp == (struct name *)NULL) {
101 if ((rp = (struct name *)malloc(sizeof (struct name))) == (struct name *)0)
102 fatal("No memory for name",(char *)0,0);
103 }
104 else {
105 rp = freerp;
106 freerp = (struct name *)NULL;
107 }
108 rrp->n_next = rp;
109 rp->n_next = (struct name *)0;
110 if ((cp = (char *) malloc(strlen(name)+1)) == (char *)0)
111 fatal("No memory for name",(char *)0,0);
112 strcpy(cp, name);
113 rp->n_name = cp;
114 rp->n_line = (struct line *)0;
115 rp->n_time = (time_t)0;
116 rp->n_flag = 0;
117 lastrrp = rrp;
118
119 return rp;
120}
121
122/*
123 * Test a name.
124 * If the name already exists return the ptr. to its name structure.
125 * Else if the file exists 'intern' the name and return the ptr.
126 * Otherwise don't waste memory and return a NULL pointer
127 */
128struct name *testname(name)
129char *name;
130{
131 register struct name *rp;
132
133 lastrrp = (struct name *)NULL;
134 rp = newname( name);
135 if (rp->n_line || rp->n_flag & N_EXISTS)
136 return(rp);
137 modtime(rp);
138 if (rp->n_flag & N_EXISTS)
139 return(rp);
140 if (lastrrp != (struct name *)NULL) {
141 free (rp->n_name);
142 lastrrp->n_next = (struct name *)NULL;
143 freerp = rp;
144 }
145 return((struct name *)NULL);
146}
147
148
149
150/*
151 * Add a dependant to the end of the supplied list of dependants.
152 * Return the new head pointer for that list.
153 */
154struct depend *newdep(np, dp)
155struct name *np;
156struct depend *dp;
157{
158 register struct depend *rp;
159 register struct depend *rrp;
160
161
162 if ((rp = (struct depend *)malloc(sizeof (struct depend)))
163 == (struct depend *)0)
164 fatal("No memory for dependant",(char *)0,0);
165 rp->d_next = (struct depend *)0;
166 rp->d_name = np;
167
168 if (dp == (struct depend *)0) return rp;
169
170 for (rrp = dp; rrp->d_next; rrp = rrp->d_next) ;
171
172 rrp->d_next = rp;
173
174 return dp;
175}
176
177
178/*
179 * Add a command to the end of the supplied list of commands.
180 * Return the new head pointer for that list.
181 */
182struct cmd *newcmd(str, cp)
183char *str;
184struct cmd *cp;
185{
186 register struct cmd *rp;
187 register struct cmd *rrp;
188 register char *rcp;
189
190
191 if (rcp = strrchr(str, '\n')) *rcp = '\0'; /* Loose newline */
192
193 while (isspace(*str)) str++;
194
195 if (*str == '\0') return cp; /* If nothing left, the exit */
196
197 if ((rp = (struct cmd *)malloc(sizeof (struct cmd))) == (struct cmd *)0)
198 fatal("No memory for command",(char *)0,0);
199 rp->c_next = (struct cmd *)0;
200 if ((rcp = (char *) malloc(strlen(str)+1)) == (char *)0)
201 fatal("No memory for command",(char *)0,0);
202 strcpy(rcp, str);
203 rp->c_cmd = rcp;
204
205 if (cp == (struct cmd *)0) return rp;
206
207 for (rrp = cp; rrp->c_next; rrp = rrp->c_next) ;
208
209 rrp->c_next = rp;
210
211 return cp;
212}
213
214
215/*
216 * Add a new 'line' of stuff to a target. This check to see
217 * if commands already exist for the target. If flag is set,
218 * the line is a double colon target.
219 *
220 * Kludges:
221 * i) If the new name begins with a '.', and there are no dependents,
222 * then the target must cease to be a target. This is for .SUFFIXES.
223 * ii) If the new name begins with a '.', with no dependents and has
224 * commands, then replace the current commands. This is for
225 * redefining commands for a default rule.
226 * Neither of these free the space used by dependents or commands,
227 * since they could be used by another target.
228 */
229
230void newline(np, dp, cp, flag)
231struct name *np;
232struct depend *dp;
233struct cmd *cp;
234int flag;
235{
236 bool hascmds = FALSE; /* Target has commands */
237 register struct line *rp;
238 register struct line *rrp;
239
240
241 /* Handle the .SUFFIXES case */
242 if (np->n_name[0] == '.' && !dp && !cp) {
243 for (rp = np->n_line; rp; rp = rrp) {
244 rrp = rp->l_next;
245 free(rp);
246 }
247 np->n_line = (struct line *)0;
248 np->n_flag &= ~N_TARG;
249 return;
250 }
251
252 /* This loop must happen since rrp is used later. */
253 for ( rp = np->n_line, rrp = (struct line *)0; rp; rrp = rp, rp = rp->l_next)
254 if (rp->l_cmd) hascmds = TRUE;
255
256 if (hascmds && cp && !(np->n_flag & N_DOUBLE))
257 /* Handle the implicit rules redefinition case */
258 if (np->n_name[0] == '.' && dp == (struct depend *)0) {
259 np->n_line->l_cmd = cp;
260 return;
261 }
262 else
263 error("Commands defined twice for target %s", np->n_name);
264 if (np->n_flag & N_TARG)
265 if (!(np->n_flag & N_DOUBLE) != !flag) /* like xor */
266 error("Inconsistent rules for target %s", np->n_name);
267
268 if ((rp = (struct line *)malloc(sizeof (struct line))) == (struct line *)0)
269 fatal("No memory for line",(char *)0,0);
270 rp->l_next = (struct line *)0;
271 rp->l_dep = dp;
272 rp->l_cmd = cp;
273
274 if (rrp)
275 rrp->l_next = rp;
276 else
277 np->n_line = rp;
278
279 np->n_flag |= N_TARG;
280 if (flag) np->n_flag |= N_DOUBLE;
281}
282
283
284/*
285 * Parse input from the makefile, and construct a tree structure
286 * of it.
287 */
288void input(fd)
289FILE *fd;
290{
291 char *p; /* General */
292 char *q;
293 register char *a;
294 struct name *np;
295 struct depend *dp;
296 struct cmd *cp;
297 bool dbl;
298
299
300 if (getline(&str1s, fd)) return; /* Read the first line */
301
302 for(;;) {
303 if (*str1 == TABCHAR) /* Rules without targets */
304 error("Rules not allowed here",(char *)0);
305
306 p = str1;
307
308 while (isspace(*p)) p++; /* Find first target */
309
310
311 while (((q = strchr(p, '=')) != (char *)0) &&
312 (p != q) && (q[-1] == '\\')) /* Find value */
313 {
314 a = q - 1; /* Del \ chr; move rest back */
315 p = q;
316 while(*a++ = *q++)
317 ;
318 }
319
320 if (q != (char *)0) {
321
322 *q++ = '\0'; /* Separate name and val */
323 while (isspace(*q))
324 q++;
325 if (p = strrchr(q, '\n'))
326 *p = '\0';
327
328 p = str1;
329 if ((a = gettok(&p)) == (char *)0)
330 error("No macro name",(char *)0);
331
332 setmacro(a, q);
333
334 if (getline(&str1s, fd))
335 return;
336 continue;
337 }
338
339 /* include? */
340 p = str1;
341 while (isspace(*p)) p++;
342 if (strncmp(p, "include", 7) == 0 && isspace(p[7])) {
343 char *old_makefile = makefile;
344 int old_lineno = lineno;
345 FILE *ifd;
346
347 p += 8;
348 memmove(str1, p, strlen(p)+1);
349 expand(&str1s);
350 p = str1;
351 while (isspace(*p)) p++;
352
353 if ((q = malloc(strlen(p)+1)) == (char *)0)
354 fatal("No memory for include",(char *)0,0);
355
356 strcpy(q, p);
357 p = q;
358 while ((makefile = gettok(&q)) != (char *)0) {
359 if ((ifd = fopen(makefile, "r")) == (FILE *)0)
360 fatal("Can't open %s: %s", makefile, errno);
361 lineno = 0;
362 input(ifd);
363 fclose(ifd);
364 }
365 free(p);
366 makefile = old_makefile;
367 lineno = old_lineno;
368
369 if (getline(&str1s, fd))
370 return;
371 continue;
372 }
373
374 /* Search for commands on target line --- do not expand them ! */
375 q = str1;
376 cp = (struct cmd *)0;
377 if ((a = strchr(q, ';')) != (char *)0) {
378 *a++ = '\0'; /* Separate dependents and commands */
379 if ( a) cp = newcmd(a, cp);
380 }
381
382 expand(&str1s);
383 p = str1;
384
385 while (isspace(*p)) p++;
386
387 while (((q = strchr(p, ':')) != (char *)0) &&
388 (p != q) && (q[-1] == '\\')) /* Find dependents */
389 {
390 a = q - 1; /* Del \ chr; move rest back */
391 p = q;
392 while(*a++ = *q++) ;
393 }
394
395 if (q == (char *)0)
396 error("No targets provided",(char *)0);
397
398 *q++ = '\0'; /* Separate targets and dependents */
399
400 if (*q == ':') { /* Double colon */
401 dbl = 1;
402 q++;
403 }
404 else
405 dbl = 0;
406
407 for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);)
408 /* get list of dep's */
409 {
410 np = newname(p); /* Intern name */
411 dp = newdep(np, dp); /* Add to dep list */
412 }
413
414 *((q = str1) + strlen(str1) + 1) = '\0';
415 /* Need two nulls for gettok (Remember separation) */
416
417 if (getline(&str2s, fd) == FALSE) { /* Get commands */
418 while (*str2 == TABCHAR) {
419 cp = newcmd(&str2[0], cp);
420 if (getline(&str2s, fd))
421 break;
422 }
423 }
424
425 while ((p = gettok(&q)) != (char *)0) /* Get list of targ's */
426 {
427 np = newname(p); /* Intern name */
428 newline(np, dp, cp, dbl);
429 if (!firstname && p[0] != '.')
430 firstname = np;
431 }
432
433 if (feof(fd)) /* EOF? */
434 return;
435
436 while (strlen(str2) >= str1s.len) strrealloc(&str1s);
437 strcpy(str1, str2);
438 }
439}
Note: See TracBrowser for help on using the repository browser.