parse.c revision 1.19 1 /* $NetBSD: parse.c,v 1.19 1996/02/07 23:04:04 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * Copyright (c) 1988, 1989 by Adam de Boor
6 * Copyright (c) 1989 by Berkeley Softworks
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Adam de Boor.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91";
44 #else
45 static char rcsid[] = "$NetBSD: parse.c,v 1.19 1996/02/07 23:04:04 thorpej Exp $";
46 #endif
47 #endif /* not lint */
48
49 /*-
50 * parse.c --
51 * Functions to parse a makefile.
52 *
53 * One function, Parse_Init, must be called before any functions
54 * in this module are used. After that, the function Parse_File is the
55 * main entry point and controls most of the other functions in this
56 * module.
57 *
58 * Most important structures are kept in Lsts. Directories for
59 * the #include "..." function are kept in the 'parseIncPath' Lst, while
60 * those for the #include <...> are kept in the 'sysIncPath' Lst. The
61 * targets currently being defined are kept in the 'targets' Lst.
62 *
63 * The variables 'fname' and 'lineno' are used to track the name
64 * of the current file and the line number in that file so that error
65 * messages can be more meaningful.
66 *
67 * Interface:
68 * Parse_Init Initialization function which must be
69 * called before anything else in this module
70 * is used.
71 *
72 * Parse_End Cleanup the module
73 *
74 * Parse_File Function used to parse a makefile. It must
75 * be given the name of the file, which should
76 * already have been opened, and a function
77 * to call to read a character from the file.
78 *
79 * Parse_IsVar Returns TRUE if the given line is a
80 * variable assignment. Used by MainParseArgs
81 * to determine if an argument is a target
82 * or a variable assignment. Used internally
83 * for pretty much the same thing...
84 *
85 * Parse_Error Function called when an error occurs in
86 * parsing. Used by the variable and
87 * conditional modules.
88 * Parse_MainName Returns a Lst of the main target to create.
89 */
90
91 #if __STDC__
92 #include <stdarg.h>
93 #else
94 #include <varargs.h>
95 #endif
96 #include <stdio.h>
97 #include <ctype.h>
98 #include <errno.h>
99 #include <sys/wait.h>
100 #include "make.h"
101 #include "hash.h"
102 #include "dir.h"
103 #include "job.h"
104 #include "buf.h"
105 #include "pathnames.h"
106
107 /*
108 * These values are returned by ParseEOF to tell Parse_File whether to
109 * CONTINUE parsing, i.e. it had only reached the end of an include file,
110 * or if it's DONE.
111 */
112 #define CONTINUE 1
113 #define DONE 0
114 static Lst targets; /* targets we're working on */
115 static Lst targCmds; /* command lines for targets */
116 static Boolean inLine; /* true if currently in a dependency
117 * line or its commands */
118 typedef struct {
119 char *str;
120 char *ptr;
121 } PTR;
122
123 static char *fname; /* name of current file (for errors) */
124 static int lineno; /* line number in current file */
125 static FILE *curFILE = NULL; /* current makefile */
126
127 static PTR *curPTR = NULL; /* current makefile */
128
129 static int fatals = 0;
130
131 static GNode *mainNode; /* The main target to create. This is the
132 * first target on the first dependency
133 * line in the first makefile */
134 /*
135 * Definitions for handling #include specifications
136 */
137 typedef struct IFile {
138 char *fname; /* name of previous file */
139 int lineno; /* saved line number */
140 FILE * F; /* the open stream */
141 PTR * p; /* the char pointer */
142 } IFile;
143
144 static Lst includes; /* stack of IFiles generated by
145 * #includes */
146 Lst parseIncPath; /* list of directories for "..." includes */
147 Lst sysIncPath; /* list of directories for <...> includes */
148
149 /*-
150 * specType contains the SPECial TYPE of the current target. It is
151 * Not if the target is unspecial. If it *is* special, however, the children
152 * are linked as children of the parent but not vice versa. This variable is
153 * set in ParseDoDependency
154 */
155 typedef enum {
156 Begin, /* .BEGIN */
157 Default, /* .DEFAULT */
158 End, /* .END */
159 Ignore, /* .IGNORE */
160 Includes, /* .INCLUDES */
161 Interrupt, /* .INTERRUPT */
162 Libs, /* .LIBS */
163 MFlags, /* .MFLAGS or .MAKEFLAGS */
164 Main, /* .MAIN and we don't have anything user-specified to
165 * make */
166 NoExport, /* .NOEXPORT */
167 Not, /* Not special */
168 NotParallel, /* .NOTPARALELL */
169 Null, /* .NULL */
170 Order, /* .ORDER */
171 Parallel, /* .PARALLEL */
172 ExPath, /* .PATH */
173 Precious, /* .PRECIOUS */
174 ExShell, /* .SHELL */
175 Silent, /* .SILENT */
176 SingleShell, /* .SINGLESHELL */
177 Suffixes, /* .SUFFIXES */
178 Wait, /* .WAIT */
179 Attribute /* Generic attribute */
180 } ParseSpecial;
181
182 static ParseSpecial specType;
183 static int waiting;
184
185 /*
186 * Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER
187 * seen, then set to each successive source on the line.
188 */
189 static GNode *predecessor;
190
191 /*
192 * The parseKeywords table is searched using binary search when deciding
193 * if a target or source is special. The 'spec' field is the ParseSpecial
194 * type of the keyword ("Not" if the keyword isn't special as a target) while
195 * the 'op' field is the operator to apply to the list of targets if the
196 * keyword is used as a source ("0" if the keyword isn't special as a source)
197 */
198 static struct {
199 char *name; /* Name of keyword */
200 ParseSpecial spec; /* Type when used as a target */
201 int op; /* Operator when used as a source */
202 } parseKeywords[] = {
203 { ".BEGIN", Begin, 0 },
204 { ".DEFAULT", Default, 0 },
205 { ".END", End, 0 },
206 { ".EXEC", Attribute, OP_EXEC },
207 { ".IGNORE", Ignore, OP_IGNORE },
208 { ".INCLUDES", Includes, 0 },
209 { ".INTERRUPT", Interrupt, 0 },
210 { ".INVISIBLE", Attribute, OP_INVISIBLE },
211 { ".JOIN", Attribute, OP_JOIN },
212 { ".LIBS", Libs, 0 },
213 { ".MAIN", Main, 0 },
214 { ".MAKE", Attribute, OP_MAKE },
215 { ".MAKEFLAGS", MFlags, 0 },
216 { ".MFLAGS", MFlags, 0 },
217 { ".NOTMAIN", Attribute, OP_NOTMAIN },
218 { ".NOTPARALLEL", NotParallel, 0 },
219 { ".NO_PARALLEL", NotParallel, 0 },
220 { ".NULL", Null, 0 },
221 { ".OPTIONAL", Attribute, OP_OPTIONAL },
222 { ".ORDER", Order, 0 },
223 { ".PARALLEL", Parallel, 0 },
224 { ".PATH", ExPath, 0 },
225 { ".PRECIOUS", Precious, OP_PRECIOUS },
226 { ".RECURSIVE", Attribute, OP_MAKE },
227 { ".SHELL", ExShell, 0 },
228 { ".SILENT", Silent, OP_SILENT },
229 { ".SINGLESHELL", SingleShell, 0 },
230 { ".SUFFIXES", Suffixes, 0 },
231 { ".USE", Attribute, OP_USE },
232 { ".WAIT", Wait, 0 },
233 };
234
235 static int ParseFindKeyword __P((char *));
236 static int ParseLinkSrc __P((ClientData, ClientData));
237 static int ParseDoOp __P((ClientData, ClientData));
238 static int ParseAddDep __P((ClientData, ClientData));
239 static void ParseDoSrc __P((int, char *, Lst));
240 static int ParseFindMain __P((ClientData, ClientData));
241 static int ParseAddDir __P((ClientData, ClientData));
242 static int ParseClearPath __P((ClientData, ClientData));
243 static void ParseDoDependency __P((char *));
244 static int ParseAddCmd __P((ClientData, ClientData));
245 static int ParseReadc __P((void));
246 static void ParseUnreadc __P((int));
247 static void ParseHasCommands __P((ClientData));
248 static void ParseDoInclude __P((char *));
249 #ifdef SYSVINCLUDE
250 static void ParseTraditionalInclude __P((char *));
251 #endif
252 static int ParseEOF __P((int));
253 static char *ParseReadLine __P((void));
254 static char *ParseSkipLine __P((int));
255 static void ParseFinishLine __P((void));
256
257 /*-
258 *----------------------------------------------------------------------
259 * ParseFindKeyword --
260 * Look in the table of keywords for one matching the given string.
261 *
262 * Results:
263 * The index of the keyword, or -1 if it isn't there.
264 *
265 * Side Effects:
266 * None
267 *----------------------------------------------------------------------
268 */
269 static int
270 ParseFindKeyword (str)
271 char *str; /* String to find */
272 {
273 register int start,
274 end,
275 cur;
276 register int diff;
277
278 start = 0;
279 end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
280
281 do {
282 cur = start + ((end - start) / 2);
283 diff = strcmp (str, parseKeywords[cur].name);
284
285 if (diff == 0) {
286 return (cur);
287 } else if (diff < 0) {
288 end = cur - 1;
289 } else {
290 start = cur + 1;
291 }
292 } while (start <= end);
293 return (-1);
294 }
295
296 /*-
297 * Parse_Error --
298 * Error message abort function for parsing. Prints out the context
299 * of the error (line number and file) as well as the message with
300 * two optional arguments.
301 *
302 * Results:
303 * None
304 *
305 * Side Effects:
306 * "fatals" is incremented if the level is PARSE_FATAL.
307 */
308 /* VARARGS */
309 void
310 #if __STDC__
311 Parse_Error(int type, char *fmt, ...)
312 #else
313 Parse_Error(va_alist)
314 va_dcl
315 #endif
316 {
317 va_list ap;
318 #if __STDC__
319 va_start(ap, fmt);
320 #else
321 int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */
322 char *fmt;
323
324 va_start(ap);
325 type = va_arg(ap, int);
326 fmt = va_arg(ap, char *);
327 #endif
328
329 (void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
330 if (type == PARSE_WARNING)
331 (void)fprintf(stderr, "warning: ");
332 (void)vfprintf(stderr, fmt, ap);
333 va_end(ap);
334 (void)fprintf(stderr, "\n");
335 (void)fflush(stderr);
336 if (type == PARSE_FATAL)
337 fatals += 1;
338 }
339
340 /*-
341 *---------------------------------------------------------------------
342 * ParseLinkSrc --
343 * Link the parent node to its new child. Used in a Lst_ForEach by
344 * ParseDoDependency. If the specType isn't 'Not', the parent
345 * isn't linked as a parent of the child.
346 *
347 * Results:
348 * Always = 0
349 *
350 * Side Effects:
351 * New elements are added to the parents list of cgn and the
352 * children list of cgn. the unmade field of pgn is updated
353 * to reflect the additional child.
354 *---------------------------------------------------------------------
355 */
356 static int
357 ParseLinkSrc (pgnp, cgnp)
358 ClientData pgnp; /* The parent node */
359 ClientData cgnp; /* The child node */
360 {
361 GNode *pgn = (GNode *) pgnp;
362 GNode *cgn = (GNode *) cgnp;
363 if (Lst_Member (pgn->children, (ClientData)cgn) == NILLNODE) {
364 (void)Lst_AtEnd (pgn->children, (ClientData)cgn);
365 if (specType == Not) {
366 (void)Lst_AtEnd (cgn->parents, (ClientData)pgn);
367 }
368 pgn->unmade += 1;
369 }
370 return (0);
371 }
372
373 /*-
374 *---------------------------------------------------------------------
375 * ParseDoOp --
376 * Apply the parsed operator to the given target node. Used in a
377 * Lst_ForEach call by ParseDoDependency once all targets have
378 * been found and their operator parsed. If the previous and new
379 * operators are incompatible, a major error is taken.
380 *
381 * Results:
382 * Always 0
383 *
384 * Side Effects:
385 * The type field of the node is altered to reflect any new bits in
386 * the op.
387 *---------------------------------------------------------------------
388 */
389 static int
390 ParseDoOp (gnp, opp)
391 ClientData gnp; /* The node to which the operator is to be
392 * applied */
393 ClientData opp; /* The operator to apply */
394 {
395 GNode *gn = (GNode *) gnp;
396 int op = *(int *) opp;
397 /*
398 * If the dependency mask of the operator and the node don't match and
399 * the node has actually had an operator applied to it before, and
400 * the operator actually has some dependency information in it, complain.
401 */
402 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
403 !OP_NOP(gn->type) && !OP_NOP(op))
404 {
405 Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name);
406 return (1);
407 }
408
409 if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
410 /*
411 * If the node was the object of a :: operator, we need to create a
412 * new instance of it for the children and commands on this dependency
413 * line. The new instance is placed on the 'cohorts' list of the
414 * initial one (note the initial one is not on its own cohorts list)
415 * and the new instance is linked to all parents of the initial
416 * instance.
417 */
418 register GNode *cohort;
419 LstNode ln;
420
421 cohort = Targ_NewGN(gn->name);
422 /*
423 * Duplicate links to parents so graph traversal is simple. Perhaps
424 * some type bits should be duplicated?
425 *
426 * Make the cohort invisible as well to avoid duplicating it into
427 * other variables. True, parents of this target won't tend to do
428 * anything with their local variables, but better safe than
429 * sorry.
430 */
431 Lst_ForEach(gn->parents, ParseLinkSrc, (ClientData)cohort);
432 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
433 (void)Lst_AtEnd(gn->cohorts, (ClientData)cohort);
434
435 /*
436 * Replace the node in the targets list with the new copy
437 */
438 ln = Lst_Member(targets, (ClientData)gn);
439 Lst_Replace(ln, (ClientData)cohort);
440 gn = cohort;
441 }
442 /*
443 * We don't want to nuke any previous flags (whatever they were) so we
444 * just OR the new operator into the old
445 */
446 gn->type |= op;
447
448 return (0);
449 }
450
451 /*-
452 *---------------------------------------------------------------------
453 * ParseAddDep --
454 * Check if the pair of GNodes given needs to be synchronized.
455 * This has to be when two nodes are on different sides of a
456 * .WAIT directive.
457 *
458 * Results:
459 * Returns 1 if the two targets need to be ordered, 0 otherwise.
460 * If it returns 1, the search can stop
461 *
462 * Side Effects:
463 * A dependency can be added between the two nodes.
464 *
465 *---------------------------------------------------------------------
466 */
467 int
468 ParseAddDep(pp, sp)
469 ClientData pp;
470 ClientData sp;
471 {
472 GNode *p = (GNode *) pp;
473 GNode *s = (GNode *) sp;
474
475 if (p->order < s->order) {
476 /*
477 * XXX: This can cause loops, and loops can cause unmade targets,
478 * but checking is tedious, and the debugging output can show the
479 * problem
480 */
481 (void)Lst_AtEnd(p->successors, (ClientData)s);
482 (void)Lst_AtEnd(s->preds, (ClientData)p);
483 return 0;
484 }
485 else
486 return 1;
487 }
488
489
490 /*-
491 *---------------------------------------------------------------------
492 * ParseDoSrc --
493 * Given the name of a source, figure out if it is an attribute
494 * and apply it to the targets if it is. Else decide if there is
495 * some attribute which should be applied *to* the source because
496 * of some special target and apply it if so. Otherwise, make the
497 * source be a child of the targets in the list 'targets'
498 *
499 * Results:
500 * None
501 *
502 * Side Effects:
503 * Operator bits may be added to the list of targets or to the source.
504 * The targets may have a new source added to their lists of children.
505 *---------------------------------------------------------------------
506 */
507 static void
508 ParseDoSrc (tOp, src, allsrc)
509 int tOp; /* operator (if any) from special targets */
510 char *src; /* name of the source to handle */
511 Lst allsrc; /* List of all sources to wait for */
512
513 {
514 GNode *gn = NULL;
515
516 if (*src == '.' && isupper (src[1])) {
517 int keywd = ParseFindKeyword(src);
518 if (keywd != -1) {
519 int op = parseKeywords[keywd].op;
520 if (op != 0) {
521 Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
522 return;
523 }
524 if (parseKeywords[keywd].spec == Wait) {
525 waiting++;
526 return;
527 }
528 }
529 }
530
531 switch (specType) {
532 case Main:
533 /*
534 * If we have noted the existence of a .MAIN, it means we need
535 * to add the sources of said target to the list of things
536 * to create. The string 'src' is likely to be free, so we
537 * must make a new copy of it. Note that this will only be
538 * invoked if the user didn't specify a target on the command
539 * line. This is to allow #ifmake's to succeed, or something...
540 */
541 (void) Lst_AtEnd (create, (ClientData)strdup(src));
542 /*
543 * Add the name to the .TARGETS variable as well, so the user cna
544 * employ that, if desired.
545 */
546 Var_Append(".TARGETS", src, VAR_GLOBAL);
547 return;
548
549 case Order:
550 /*
551 * Create proper predecessor/successor links between the previous
552 * source and the current one.
553 */
554 gn = Targ_FindNode(src, TARG_CREATE);
555 if (predecessor != NILGNODE) {
556 (void)Lst_AtEnd(predecessor->successors, (ClientData)gn);
557 (void)Lst_AtEnd(gn->preds, (ClientData)predecessor);
558 }
559 /*
560 * The current source now becomes the predecessor for the next one.
561 */
562 predecessor = gn;
563 break;
564
565 default:
566 /*
567 * If the source is not an attribute, we need to find/create
568 * a node for it. After that we can apply any operator to it
569 * from a special target or link it to its parents, as
570 * appropriate.
571 *
572 * In the case of a source that was the object of a :: operator,
573 * the attribute is applied to all of its instances (as kept in
574 * the 'cohorts' list of the node) or all the cohorts are linked
575 * to all the targets.
576 */
577 gn = Targ_FindNode (src, TARG_CREATE);
578 if (tOp) {
579 gn->type |= tOp;
580 } else {
581 Lst_ForEach (targets, ParseLinkSrc, (ClientData)gn);
582 }
583 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
584 register GNode *cohort;
585 register LstNode ln;
586
587 for (ln=Lst_First(gn->cohorts); ln != NILLNODE; ln = Lst_Succ(ln)){
588 cohort = (GNode *)Lst_Datum(ln);
589 if (tOp) {
590 cohort->type |= tOp;
591 } else {
592 Lst_ForEach(targets, ParseLinkSrc, (ClientData)cohort);
593 }
594 }
595 }
596 break;
597 }
598
599 gn->order = waiting;
600 (void)Lst_AtEnd(allsrc, (ClientData)gn);
601 if (waiting) {
602 Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn);
603 }
604 }
605
606 /*-
607 *-----------------------------------------------------------------------
608 * ParseFindMain --
609 * Find a real target in the list and set it to be the main one.
610 * Called by ParseDoDependency when a main target hasn't been found
611 * yet.
612 *
613 * Results:
614 * 0 if main not found yet, 1 if it is.
615 *
616 * Side Effects:
617 * mainNode is changed and Targ_SetMain is called.
618 *
619 *-----------------------------------------------------------------------
620 */
621 static int
622 ParseFindMain(gnp, dummy)
623 ClientData gnp; /* Node to examine */
624 ClientData dummy;
625 {
626 GNode *gn = (GNode *) gnp;
627 if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) {
628 mainNode = gn;
629 Targ_SetMain(gn);
630 return (dummy ? 1 : 1);
631 } else {
632 return (dummy ? 0 : 0);
633 }
634 }
635
636 /*-
637 *-----------------------------------------------------------------------
638 * ParseAddDir --
639 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
640 *
641 * Results:
642 * === 0
643 *
644 * Side Effects:
645 * See Dir_AddDir.
646 *
647 *-----------------------------------------------------------------------
648 */
649 static int
650 ParseAddDir(path, name)
651 ClientData path;
652 ClientData name;
653 {
654 Dir_AddDir((Lst) path, (char *) name);
655 return(0);
656 }
657
658 /*-
659 *-----------------------------------------------------------------------
660 * ParseClearPath --
661 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
662 *
663 * Results:
664 * === 0
665 *
666 * Side Effects:
667 * See Dir_ClearPath
668 *
669 *-----------------------------------------------------------------------
670 */
671 static int
672 ParseClearPath(path, dummy)
673 ClientData path;
674 ClientData dummy;
675 {
676 Dir_ClearPath((Lst) path);
677 return(dummy ? 0 : 0);
678 }
679
680 /*-
681 *---------------------------------------------------------------------
682 * ParseDoDependency --
683 * Parse the dependency line in line.
684 *
685 * Results:
686 * None
687 *
688 * Side Effects:
689 * The nodes of the sources are linked as children to the nodes of the
690 * targets. Some nodes may be created.
691 *
692 * We parse a dependency line by first extracting words from the line and
693 * finding nodes in the list of all targets with that name. This is done
694 * until a character is encountered which is an operator character. Currently
695 * these are only ! and :. At this point the operator is parsed and the
696 * pointer into the line advanced until the first source is encountered.
697 * The parsed operator is applied to each node in the 'targets' list,
698 * which is where the nodes found for the targets are kept, by means of
699 * the ParseDoOp function.
700 * The sources are read in much the same way as the targets were except
701 * that now they are expanded using the wildcarding scheme of the C-Shell
702 * and all instances of the resulting words in the list of all targets
703 * are found. Each of the resulting nodes is then linked to each of the
704 * targets as one of its children.
705 * Certain targets are handled specially. These are the ones detailed
706 * by the specType variable.
707 * The storing of transformation rules is also taken care of here.
708 * A target is recognized as a transformation rule by calling
709 * Suff_IsTransform. If it is a transformation rule, its node is gotten
710 * from the suffix module via Suff_AddTransform rather than the standard
711 * Targ_FindNode in the target module.
712 *---------------------------------------------------------------------
713 */
714 static void
715 ParseDoDependency (line)
716 char *line; /* the line to parse */
717 {
718 char *cp; /* our current position */
719 GNode *gn; /* a general purpose temporary node */
720 int op; /* the operator on the line */
721 char savec; /* a place to save a character */
722 Lst paths; /* List of search paths to alter when parsing
723 * a list of .PATH targets */
724 int tOp; /* operator from special target */
725 Lst sources; /* list of archive source names after
726 * expansion */
727 Lst curTargs; /* list of target names to be found and added
728 * to the targets list */
729 Lst curSrcs; /* list of sources in order */
730
731 tOp = 0;
732
733 specType = Not;
734 waiting = 0;
735 paths = (Lst)NULL;
736
737 curTargs = Lst_Init(FALSE);
738 curSrcs = Lst_Init(FALSE);
739
740 do {
741 for (cp = line;
742 *cp && !isspace (*cp) &&
743 (*cp != '!') && (*cp != ':') && (*cp != '(');
744 cp++)
745 {
746 if (*cp == '$') {
747 /*
748 * Must be a dynamic source (would have been expanded
749 * otherwise), so call the Var module to parse the puppy
750 * so we can safely advance beyond it...There should be
751 * no errors in this, as they would have been discovered
752 * in the initial Var_Subst and we wouldn't be here.
753 */
754 int length;
755 Boolean freeIt;
756 char *result;
757
758 result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
759
760 if (freeIt) {
761 free(result);
762 }
763 cp += length-1;
764 }
765 continue;
766 }
767 if (*cp == '(') {
768 /*
769 * Archives must be handled specially to make sure the OP_ARCHV
770 * flag is set in their 'type' field, for one thing, and because
771 * things like "archive(file1.o file2.o file3.o)" are permissible.
772 * Arch_ParseArchive will set 'line' to be the first non-blank
773 * after the archive-spec. It creates/finds nodes for the members
774 * and places them on the given list, returning SUCCESS if all
775 * went well and FAILURE if there was an error in the
776 * specification. On error, line should remain untouched.
777 */
778 if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
779 Parse_Error (PARSE_FATAL,
780 "Error in archive specification: \"%s\"", line);
781 return;
782 } else {
783 continue;
784 }
785 }
786 savec = *cp;
787
788 if (!*cp) {
789 /*
790 * Ending a dependency line without an operator is a Bozo
791 * no-no
792 */
793 Parse_Error (PARSE_FATAL, "Need an operator");
794 return;
795 }
796 *cp = '\0';
797 /*
798 * Have a word in line. See if it's a special target and set
799 * specType to match it.
800 */
801 if (*line == '.' && isupper (line[1])) {
802 /*
803 * See if the target is a special target that must have it
804 * or its sources handled specially.
805 */
806 int keywd = ParseFindKeyword(line);
807 if (keywd != -1) {
808 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
809 Parse_Error(PARSE_FATAL, "Mismatched special targets");
810 return;
811 }
812
813 specType = parseKeywords[keywd].spec;
814 tOp = parseKeywords[keywd].op;
815
816 /*
817 * Certain special targets have special semantics:
818 * .PATH Have to set the dirSearchPath
819 * variable too
820 * .MAIN Its sources are only used if
821 * nothing has been specified to
822 * create.
823 * .DEFAULT Need to create a node to hang
824 * commands on, but we don't want
825 * it in the graph, nor do we want
826 * it to be the Main Target, so we
827 * create it, set OP_NOTMAIN and
828 * add it to the list, setting
829 * DEFAULT to the new node for
830 * later use. We claim the node is
831 * A transformation rule to make
832 * life easier later, when we'll
833 * use Make_HandleUse to actually
834 * apply the .DEFAULT commands.
835 * .BEGIN
836 * .END
837 * .INTERRUPT Are not to be considered the
838 * main target.
839 * .NOTPARALLEL Make only one target at a time.
840 * .SINGLESHELL Create a shell for each command.
841 * .ORDER Must set initial predecessor to NIL
842 */
843 switch (specType) {
844 case ExPath:
845 if (paths == NULL) {
846 paths = Lst_Init(FALSE);
847 }
848 (void)Lst_AtEnd(paths, (ClientData)dirSearchPath);
849 break;
850 case Main:
851 if (!Lst_IsEmpty(create)) {
852 specType = Not;
853 }
854 break;
855 case Begin:
856 case End:
857 case Interrupt:
858 gn = Targ_FindNode(line, TARG_CREATE);
859 gn->type |= OP_NOTMAIN;
860 (void)Lst_AtEnd(targets, (ClientData)gn);
861 break;
862 case Default:
863 gn = Targ_NewGN(".DEFAULT");
864 gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
865 (void)Lst_AtEnd(targets, (ClientData)gn);
866 DEFAULT = gn;
867 break;
868 case NotParallel:
869 {
870 extern int maxJobs;
871
872 maxJobs = 1;
873 break;
874 }
875 case SingleShell:
876 compatMake = 1;
877 break;
878 case Order:
879 predecessor = NILGNODE;
880 break;
881 default:
882 break;
883 }
884 } else if (strncmp (line, ".PATH", 5) == 0) {
885 /*
886 * .PATH<suffix> has to be handled specially.
887 * Call on the suffix module to give us a path to
888 * modify.
889 */
890 Lst path;
891
892 specType = ExPath;
893 path = Suff_GetPath (&line[5]);
894 if (path == NILLST) {
895 Parse_Error (PARSE_FATAL,
896 "Suffix '%s' not defined (yet)",
897 &line[5]);
898 return;
899 } else {
900 if (paths == (Lst)NULL) {
901 paths = Lst_Init(FALSE);
902 }
903 (void)Lst_AtEnd(paths, (ClientData)path);
904 }
905 }
906 }
907
908 /*
909 * Have word in line. Get or create its node and stick it at
910 * the end of the targets list
911 */
912 if ((specType == Not) && (*line != '\0')) {
913 if (Dir_HasWildcards(line)) {
914 /*
915 * Targets are to be sought only in the current directory,
916 * so create an empty path for the thing. Note we need to
917 * use Dir_Destroy in the destruction of the path as the
918 * Dir module could have added a directory to the path...
919 */
920 Lst emptyPath = Lst_Init(FALSE);
921
922 Dir_Expand(line, emptyPath, curTargs);
923
924 Lst_Destroy(emptyPath, Dir_Destroy);
925 } else {
926 /*
927 * No wildcards, but we want to avoid code duplication,
928 * so create a list with the word on it.
929 */
930 (void)Lst_AtEnd(curTargs, (ClientData)line);
931 }
932
933 while(!Lst_IsEmpty(curTargs)) {
934 char *targName = (char *)Lst_DeQueue(curTargs);
935
936 if (!Suff_IsTransform (targName)) {
937 gn = Targ_FindNode (targName, TARG_CREATE);
938 } else {
939 gn = Suff_AddTransform (targName);
940 }
941
942 (void)Lst_AtEnd (targets, (ClientData)gn);
943 }
944 } else if (specType == ExPath && *line != '.' && *line != '\0') {
945 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
946 }
947
948 *cp = savec;
949 /*
950 * If it is a special type and not .PATH, it's the only target we
951 * allow on this line...
952 */
953 if (specType != Not && specType != ExPath) {
954 Boolean warn = FALSE;
955
956 while ((*cp != '!') && (*cp != ':') && *cp) {
957 if (*cp != ' ' && *cp != '\t') {
958 warn = TRUE;
959 }
960 cp++;
961 }
962 if (warn) {
963 Parse_Error(PARSE_WARNING, "Extra target ignored");
964 }
965 } else {
966 while (*cp && isspace (*cp)) {
967 cp++;
968 }
969 }
970 line = cp;
971 } while ((*line != '!') && (*line != ':') && *line);
972
973 /*
974 * Don't need the list of target names anymore...
975 */
976 Lst_Destroy(curTargs, NOFREE);
977
978 if (!Lst_IsEmpty(targets)) {
979 switch(specType) {
980 default:
981 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
982 break;
983 case Default:
984 case Begin:
985 case End:
986 case Interrupt:
987 /*
988 * These four create nodes on which to hang commands, so
989 * targets shouldn't be empty...
990 */
991 case Not:
992 /*
993 * Nothing special here -- targets can be empty if it wants.
994 */
995 break;
996 }
997 }
998
999 /*
1000 * Have now parsed all the target names. Must parse the operator next. The
1001 * result is left in op .
1002 */
1003 if (*cp == '!') {
1004 op = OP_FORCE;
1005 } else if (*cp == ':') {
1006 if (cp[1] == ':') {
1007 op = OP_DOUBLEDEP;
1008 cp++;
1009 } else {
1010 op = OP_DEPENDS;
1011 }
1012 } else {
1013 Parse_Error (PARSE_FATAL, "Missing dependency operator");
1014 return;
1015 }
1016
1017 cp++; /* Advance beyond operator */
1018
1019 Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
1020
1021 /*
1022 * Get to the first source
1023 */
1024 while (*cp && isspace (*cp)) {
1025 cp++;
1026 }
1027 line = cp;
1028
1029 /*
1030 * Several special targets take different actions if present with no
1031 * sources:
1032 * a .SUFFIXES line with no sources clears out all old suffixes
1033 * a .PRECIOUS line makes all targets precious
1034 * a .IGNORE line ignores errors for all targets
1035 * a .SILENT line creates silence when making all targets
1036 * a .PATH removes all directories from the search path(s).
1037 */
1038 if (!*line) {
1039 switch (specType) {
1040 case Suffixes:
1041 Suff_ClearSuffixes ();
1042 break;
1043 case Precious:
1044 allPrecious = TRUE;
1045 break;
1046 case Ignore:
1047 ignoreErrors = TRUE;
1048 break;
1049 case Silent:
1050 beSilent = TRUE;
1051 break;
1052 case ExPath:
1053 Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
1054 break;
1055 default:
1056 break;
1057 }
1058 } else if (specType == MFlags) {
1059 /*
1060 * Call on functions in main.c to deal with these arguments and
1061 * set the initial character to a null-character so the loop to
1062 * get sources won't get anything
1063 */
1064 Main_ParseArgLine (line);
1065 *line = '\0';
1066 } else if (specType == ExShell) {
1067 if (Job_ParseShell (line) != SUCCESS) {
1068 Parse_Error (PARSE_FATAL, "improper shell specification");
1069 return;
1070 }
1071 *line = '\0';
1072 } else if ((specType == NotParallel) || (specType == SingleShell)) {
1073 *line = '\0';
1074 }
1075
1076 /*
1077 * NOW GO FOR THE SOURCES
1078 */
1079 if ((specType == Suffixes) || (specType == ExPath) ||
1080 (specType == Includes) || (specType == Libs) ||
1081 (specType == Null))
1082 {
1083 while (*line) {
1084 /*
1085 * If the target was one that doesn't take files as its sources
1086 * but takes something like suffixes, we take each
1087 * space-separated word on the line as a something and deal
1088 * with it accordingly.
1089 *
1090 * If the target was .SUFFIXES, we take each source as a
1091 * suffix and add it to the list of suffixes maintained by the
1092 * Suff module.
1093 *
1094 * If the target was a .PATH, we add the source as a directory
1095 * to search on the search path.
1096 *
1097 * If it was .INCLUDES, the source is taken to be the suffix of
1098 * files which will be #included and whose search path should
1099 * be present in the .INCLUDES variable.
1100 *
1101 * If it was .LIBS, the source is taken to be the suffix of
1102 * files which are considered libraries and whose search path
1103 * should be present in the .LIBS variable.
1104 *
1105 * If it was .NULL, the source is the suffix to use when a file
1106 * has no valid suffix.
1107 */
1108 char savec;
1109 while (*cp && !isspace (*cp)) {
1110 cp++;
1111 }
1112 savec = *cp;
1113 *cp = '\0';
1114 switch (specType) {
1115 case Suffixes:
1116 Suff_AddSuffix (line);
1117 break;
1118 case ExPath:
1119 Lst_ForEach(paths, ParseAddDir, (ClientData)line);
1120 break;
1121 case Includes:
1122 Suff_AddInclude (line);
1123 break;
1124 case Libs:
1125 Suff_AddLib (line);
1126 break;
1127 case Null:
1128 Suff_SetNull (line);
1129 break;
1130 default:
1131 break;
1132 }
1133 *cp = savec;
1134 if (savec != '\0') {
1135 cp++;
1136 }
1137 while (*cp && isspace (*cp)) {
1138 cp++;
1139 }
1140 line = cp;
1141 }
1142 if (paths) {
1143 Lst_Destroy(paths, NOFREE);
1144 }
1145 } else {
1146 while (*line) {
1147 /*
1148 * The targets take real sources, so we must beware of archive
1149 * specifications (i.e. things with left parentheses in them)
1150 * and handle them accordingly.
1151 */
1152 while (*cp && !isspace (*cp)) {
1153 if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
1154 /*
1155 * Only stop for a left parenthesis if it isn't at the
1156 * start of a word (that'll be for variable changes
1157 * later) and isn't preceded by a dollar sign (a dynamic
1158 * source).
1159 */
1160 break;
1161 } else {
1162 cp++;
1163 }
1164 }
1165
1166 if (*cp == '(') {
1167 GNode *gn;
1168
1169 sources = Lst_Init (FALSE);
1170 if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
1171 Parse_Error (PARSE_FATAL,
1172 "Error in source archive spec \"%s\"", line);
1173 return;
1174 }
1175
1176 while (!Lst_IsEmpty (sources)) {
1177 gn = (GNode *) Lst_DeQueue (sources);
1178 ParseDoSrc (tOp, gn->name, curSrcs);
1179 }
1180 Lst_Destroy (sources, NOFREE);
1181 cp = line;
1182 } else {
1183 if (*cp) {
1184 *cp = '\0';
1185 cp += 1;
1186 }
1187
1188 ParseDoSrc (tOp, line, curSrcs);
1189 }
1190 while (*cp && isspace (*cp)) {
1191 cp++;
1192 }
1193 line = cp;
1194 }
1195 }
1196
1197 if (mainNode == NILGNODE) {
1198 /*
1199 * If we have yet to decide on a main target to make, in the
1200 * absence of any user input, we want the first target on
1201 * the first dependency line that is actually a real target
1202 * (i.e. isn't a .USE or .EXEC rule) to be made.
1203 */
1204 Lst_ForEach (targets, ParseFindMain, (ClientData)0);
1205 }
1206
1207 /*
1208 * Finally, destroy the list of sources
1209 */
1210 Lst_Destroy(curSrcs, NOFREE);
1211 }
1212
1213 /*-
1214 *---------------------------------------------------------------------
1215 * Parse_IsVar --
1216 * Return TRUE if the passed line is a variable assignment. A variable
1217 * assignment consists of a single word followed by optional whitespace
1218 * followed by either a += or an = operator.
1219 * This function is used both by the Parse_File function and main when
1220 * parsing the command-line arguments.
1221 *
1222 * Results:
1223 * TRUE if it is. FALSE if it ain't
1224 *
1225 * Side Effects:
1226 * none
1227 *---------------------------------------------------------------------
1228 */
1229 Boolean
1230 Parse_IsVar (line)
1231 register char *line; /* the line to check */
1232 {
1233 register Boolean wasSpace = FALSE; /* set TRUE if found a space */
1234 register Boolean haveName = FALSE; /* Set TRUE if have a variable name */
1235 int level = 0;
1236 #define ISEQOPERATOR(c) \
1237 (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1238
1239 /*
1240 * Skip to variable name
1241 */
1242 for (;(*line == ' ') || (*line == '\t'); line++)
1243 continue;
1244
1245 for (; *line != '=' || level != 0; line++)
1246 switch (*line) {
1247 case '\0':
1248 /*
1249 * end-of-line -- can't be a variable assignment.
1250 */
1251 return FALSE;
1252
1253 case ' ':
1254 case '\t':
1255 /*
1256 * there can be as much white space as desired so long as there is
1257 * only one word before the operator
1258 */
1259 wasSpace = TRUE;
1260 break;
1261
1262 case '(':
1263 case '{':
1264 level++;
1265 break;
1266
1267 case '}':
1268 case ')':
1269 level--;
1270 break;
1271
1272 default:
1273 if (wasSpace && haveName) {
1274 if (ISEQOPERATOR(*line)) {
1275 /*
1276 * When an = operator [+?!:] is found, the next
1277 * character * must be an = or it ain't a valid
1278 * assignment.
1279 */
1280 if (line[1] != '=' && level == 0)
1281 return FALSE;
1282 else
1283 return haveName;
1284 }
1285 else {
1286 /*
1287 * This is the start of another word, so not assignment.
1288 */
1289 return FALSE;
1290 }
1291 }
1292 else {
1293 haveName = TRUE;
1294 wasSpace = FALSE;
1295 }
1296 break;
1297 }
1298
1299 return haveName;
1300 }
1301
1302 /*-
1303 *---------------------------------------------------------------------
1304 * Parse_DoVar --
1305 * Take the variable assignment in the passed line and do it in the
1306 * global context.
1307 *
1308 * Note: There is a lexical ambiguity with assignment modifier characters
1309 * in variable names. This routine interprets the character before the =
1310 * as a modifier. Therefore, an assignment like
1311 * C++=/usr/bin/CC
1312 * is interpreted as "C+ +=" instead of "C++ =".
1313 *
1314 * Results:
1315 * none
1316 *
1317 * Side Effects:
1318 * the variable structure of the given variable name is altered in the
1319 * global context.
1320 *---------------------------------------------------------------------
1321 */
1322 void
1323 Parse_DoVar (line, ctxt)
1324 char *line; /* a line guaranteed to be a variable
1325 * assignment. This reduces error checks */
1326 GNode *ctxt; /* Context in which to do the assignment */
1327 {
1328 char *cp; /* pointer into line */
1329 enum {
1330 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1331 } type; /* Type of assignment */
1332 char *opc; /* ptr to operator character to
1333 * null-terminate the variable name */
1334 /*
1335 * Avoid clobbered variable warnings by forcing the compiler
1336 * to ``unregister'' variables
1337 */
1338 #if __GNUC__
1339 (void) &cp;
1340 (void) &line;
1341 #endif
1342
1343 /*
1344 * Skip to variable name
1345 */
1346 while ((*line == ' ') || (*line == '\t')) {
1347 line++;
1348 }
1349
1350 /*
1351 * Skip to operator character, nulling out whitespace as we go
1352 */
1353 for (cp = line + 1; *cp != '='; cp++) {
1354 if (isspace (*cp)) {
1355 *cp = '\0';
1356 }
1357 }
1358 opc = cp-1; /* operator is the previous character */
1359 *cp++ = '\0'; /* nuke the = */
1360
1361 /*
1362 * Check operator type
1363 */
1364 switch (*opc) {
1365 case '+':
1366 type = VAR_APPEND;
1367 *opc = '\0';
1368 break;
1369
1370 case '?':
1371 /*
1372 * If the variable already has a value, we don't do anything.
1373 */
1374 *opc = '\0';
1375 if (Var_Exists(line, ctxt)) {
1376 return;
1377 } else {
1378 type = VAR_NORMAL;
1379 }
1380 break;
1381
1382 case ':':
1383 type = VAR_SUBST;
1384 *opc = '\0';
1385 break;
1386
1387 case '!':
1388 type = VAR_SHELL;
1389 *opc = '\0';
1390 break;
1391
1392 default:
1393 type = VAR_NORMAL;
1394 break;
1395 }
1396
1397 while (isspace (*cp)) {
1398 cp++;
1399 }
1400
1401 if (type == VAR_APPEND) {
1402 Var_Append (line, cp, ctxt);
1403 } else if (type == VAR_SUBST) {
1404 /*
1405 * Allow variables in the old value to be undefined, but leave their
1406 * invocation alone -- this is done by forcing oldVars to be false.
1407 * XXX: This can cause recursive variables, but that's not hard to do,
1408 * and this allows someone to do something like
1409 *
1410 * CFLAGS = $(.INCLUDES)
1411 * CFLAGS := -I.. $(CFLAGS)
1412 *
1413 * And not get an error.
1414 */
1415 Boolean oldOldVars = oldVars;
1416
1417 oldVars = FALSE;
1418 cp = Var_Subst(NULL, cp, ctxt, FALSE);
1419 oldVars = oldOldVars;
1420
1421 Var_Set(line, cp, ctxt);
1422 free(cp);
1423 } else if (type == VAR_SHELL) {
1424 char *args[4]; /* Args for invoking the shell */
1425 int fds[2]; /* Pipe streams */
1426 int cpid; /* Child PID */
1427 int pid; /* PID from wait() */
1428 Boolean freeCmd; /* TRUE if the command needs to be freed, i.e.
1429 * if any variable expansion was performed */
1430
1431 /*
1432 * Avoid clobbered variable warnings by forcing the compiler
1433 * to ``unregister'' variables
1434 */
1435 #if __GNUC__
1436 (void) &freeCmd;
1437 #endif
1438
1439 /*
1440 * Set up arguments for shell
1441 */
1442 args[0] = "sh";
1443 args[1] = "-c";
1444 if (strchr(cp, '$') != (char *)NULL) {
1445 /*
1446 * There's a dollar sign in the command, so perform variable
1447 * expansion on the whole thing. The resulting string will need
1448 * freeing when we're done, so set freeCmd to TRUE.
1449 */
1450 args[2] = Var_Subst(NULL, cp, VAR_CMD, TRUE);
1451 freeCmd = TRUE;
1452 } else {
1453 args[2] = cp;
1454 freeCmd = FALSE;
1455 }
1456 args[3] = (char *)NULL;
1457
1458 /*
1459 * Open a pipe for fetching its output
1460 */
1461 pipe(fds);
1462
1463 /*
1464 * Fork
1465 */
1466 cpid = vfork();
1467 if (cpid == 0) {
1468 /*
1469 * Close input side of pipe
1470 */
1471 close(fds[0]);
1472
1473 /*
1474 * Duplicate the output stream to the shell's output, then
1475 * shut the extra thing down. Note we don't fetch the error
1476 * stream...why not? Why?
1477 */
1478 dup2(fds[1], 1);
1479 close(fds[1]);
1480
1481 execv("/bin/sh", args);
1482 _exit(1);
1483 } else if (cpid < 0) {
1484 /*
1485 * Couldn't fork -- tell the user and make the variable null
1486 */
1487 Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp);
1488 Var_Set(line, "", ctxt);
1489 } else {
1490 int status;
1491 int cc;
1492 Buffer buf;
1493 char *res;
1494
1495 /*
1496 * No need for the writing half
1497 */
1498 close(fds[1]);
1499
1500 buf = Buf_Init (MAKE_BSIZE);
1501
1502 do {
1503 char result[BUFSIZ];
1504 cc = read(fds[0], result, sizeof(result));
1505 if (cc > 0)
1506 Buf_AddBytes(buf, cc, (Byte *) result);
1507 }
1508 while (cc > 0 || (cc == -1 && errno == EINTR));
1509
1510 /*
1511 * Close the input side of the pipe.
1512 */
1513 close(fds[0]);
1514
1515 /*
1516 * Wait for the process to exit.
1517 */
1518 while(((pid = wait(&status)) != cpid) && (pid >= 0))
1519 continue;
1520
1521 res = (char *)Buf_GetAll (buf, &cc);
1522 Buf_Destroy (buf, FALSE);
1523
1524 if (cc == 0) {
1525 /*
1526 * Couldn't read the child's output -- tell the user and
1527 * set the variable to null
1528 */
1529 Parse_Error(PARSE_WARNING, "Couldn't read shell's output");
1530 }
1531
1532 if (status) {
1533 /*
1534 * Child returned an error -- tell the user but still use
1535 * the result.
1536 */
1537 Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
1538 }
1539
1540 /*
1541 * Null-terminate the result, convert newlines to spaces and
1542 * install it in the variable.
1543 */
1544 res[cc] = '\0';
1545 cp = &res[cc] - 1;
1546
1547 if (*cp == '\n') {
1548 /*
1549 * A final newline is just stripped
1550 */
1551 *cp-- = '\0';
1552 }
1553 while (cp >= res) {
1554 if (*cp == '\n') {
1555 *cp = ' ';
1556 }
1557 cp--;
1558 }
1559 Var_Set(line, res, ctxt);
1560 free(res);
1561
1562 }
1563 if (freeCmd) {
1564 free(args[2]);
1565 }
1566 } else {
1567 /*
1568 * Normal assignment -- just do it.
1569 */
1570 Var_Set (line, cp, ctxt);
1571 }
1572 }
1573
1574 /*-
1575 * ParseAddCmd --
1576 * Lst_ForEach function to add a command line to all targets
1577 *
1578 * Results:
1579 * Always 0
1580 *
1581 * Side Effects:
1582 * A new element is added to the commands list of the node.
1583 */
1584 static int
1585 ParseAddCmd(gnp, cmd)
1586 ClientData gnp; /* the node to which the command is to be added */
1587 ClientData cmd; /* the command to add */
1588 {
1589 GNode *gn = (GNode *) gnp;
1590 /* if target already supplied, ignore commands */
1591 if (!(gn->type & OP_HAS_COMMANDS))
1592 (void)Lst_AtEnd(gn->commands, cmd);
1593 return(0);
1594 }
1595
1596 /*-
1597 *-----------------------------------------------------------------------
1598 * ParseHasCommands --
1599 * Callback procedure for Parse_File when destroying the list of
1600 * targets on the last dependency line. Marks a target as already
1601 * having commands if it does, to keep from having shell commands
1602 * on multiple dependency lines.
1603 *
1604 * Results:
1605 * None
1606 *
1607 * Side Effects:
1608 * OP_HAS_COMMANDS may be set for the target.
1609 *
1610 *-----------------------------------------------------------------------
1611 */
1612 static void
1613 ParseHasCommands(gnp)
1614 ClientData gnp; /* Node to examine */
1615 {
1616 GNode *gn = (GNode *) gnp;
1617 if (!Lst_IsEmpty(gn->commands)) {
1618 gn->type |= OP_HAS_COMMANDS;
1619 }
1620 }
1621
1622 /*-
1623 *-----------------------------------------------------------------------
1624 * Parse_AddIncludeDir --
1625 * Add a directory to the path searched for included makefiles
1626 * bracketed by double-quotes. Used by functions in main.c
1627 *
1628 * Results:
1629 * None.
1630 *
1631 * Side Effects:
1632 * The directory is appended to the list.
1633 *
1634 *-----------------------------------------------------------------------
1635 */
1636 void
1637 Parse_AddIncludeDir (dir)
1638 char *dir; /* The name of the directory to add */
1639 {
1640 Dir_AddDir (parseIncPath, dir);
1641 }
1642
1643 /*-
1644 *---------------------------------------------------------------------
1645 * ParseDoInclude --
1646 * Push to another file.
1647 *
1648 * The input is the line minus the #include. A file spec is a string
1649 * enclosed in <> or "". The former is looked for only in sysIncPath.
1650 * The latter in . and the directories specified by -I command line
1651 * options
1652 *
1653 * Results:
1654 * None
1655 *
1656 * Side Effects:
1657 * A structure is added to the includes Lst and readProc, lineno,
1658 * fname and curFILE are altered for the new file
1659 *---------------------------------------------------------------------
1660 */
1661 static void
1662 ParseDoInclude (file)
1663 char *file; /* file specification */
1664 {
1665 char *fullname; /* full pathname of file */
1666 IFile *oldFile; /* state associated with current file */
1667 char endc; /* the character which ends the file spec */
1668 char *cp; /* current position in file spec */
1669 Boolean isSystem; /* TRUE if makefile is a system makefile */
1670
1671 /*
1672 * Skip to delimiter character so we know where to look
1673 */
1674 while ((*file == ' ') || (*file == '\t')) {
1675 file++;
1676 }
1677
1678 if ((*file != '"') && (*file != '<')) {
1679 Parse_Error (PARSE_FATAL,
1680 ".include filename must be delimited by '\"' or '<'");
1681 return;
1682 }
1683
1684 /*
1685 * Set the search path on which to find the include file based on the
1686 * characters which bracket its name. Angle-brackets imply it's
1687 * a system Makefile while double-quotes imply it's a user makefile
1688 */
1689 if (*file == '<') {
1690 isSystem = TRUE;
1691 endc = '>';
1692 } else {
1693 isSystem = FALSE;
1694 endc = '"';
1695 }
1696
1697 /*
1698 * Skip to matching delimiter
1699 */
1700 for (cp = ++file; *cp && *cp != endc; cp++) {
1701 continue;
1702 }
1703
1704 if (*cp != endc) {
1705 Parse_Error (PARSE_FATAL,
1706 "Unclosed %cinclude filename. '%c' expected",
1707 '.', endc);
1708 return;
1709 }
1710 *cp = '\0';
1711
1712 /*
1713 * Substitute for any variables in the file name before trying to
1714 * find the thing.
1715 */
1716 file = Var_Subst (NULL, file, VAR_CMD, FALSE);
1717
1718 /*
1719 * Now we know the file's name and its search path, we attempt to
1720 * find the durn thing. A return of NULL indicates the file don't
1721 * exist.
1722 */
1723 if (!isSystem) {
1724 /*
1725 * Include files contained in double-quotes are first searched for
1726 * relative to the including file's location. We don't want to
1727 * cd there, of course, so we just tack on the old file's
1728 * leading path components and call Dir_FindFile to see if
1729 * we can locate the beast.
1730 */
1731 char *prefEnd, *Fname;
1732
1733 /* Make a temporary copy of this, to be safe. */
1734 Fname = strdup(fname);
1735
1736 prefEnd = strrchr (Fname, '/');
1737 if (prefEnd != (char *)NULL) {
1738 char *newName;
1739
1740 *prefEnd = '\0';
1741 if (file[0] == '/')
1742 newName = strdup(file);
1743 else
1744 newName = str_concat (Fname, file, STR_ADDSLASH);
1745 fullname = Dir_FindFile (newName, parseIncPath);
1746 if (fullname == (char *)NULL) {
1747 fullname = Dir_FindFile(newName, dirSearchPath);
1748 }
1749 free (newName);
1750 *prefEnd = '/';
1751 } else {
1752 fullname = (char *)NULL;
1753 }
1754 free (Fname);
1755 } else {
1756 fullname = (char *)NULL;
1757 }
1758
1759 if (fullname == (char *)NULL) {
1760 /*
1761 * System makefile or makefile wasn't found in same directory as
1762 * included makefile. Search for it first on the -I search path,
1763 * then on the .PATH search path, if not found in a -I directory.
1764 * XXX: Suffix specific?
1765 */
1766 fullname = Dir_FindFile (file, parseIncPath);
1767 if (fullname == (char *)NULL) {
1768 fullname = Dir_FindFile(file, dirSearchPath);
1769 }
1770 }
1771
1772 if (fullname == (char *)NULL) {
1773 /*
1774 * Still haven't found the makefile. Look for it on the system
1775 * path as a last resort.
1776 */
1777 fullname = Dir_FindFile(file, sysIncPath);
1778 }
1779
1780 if (fullname == (char *) NULL) {
1781 *cp = endc;
1782 Parse_Error (PARSE_FATAL, "Could not find %s", file);
1783 return;
1784 }
1785
1786 free(file);
1787
1788 /*
1789 * Once we find the absolute path to the file, we get to save all the
1790 * state from the current file before we can start reading this
1791 * include file. The state is stored in an IFile structure which
1792 * is placed on a list with other IFile structures. The list makes
1793 * a very nice stack to track how we got here...
1794 */
1795 oldFile = (IFile *) emalloc (sizeof (IFile));
1796 oldFile->fname = fname;
1797
1798 oldFile->F = curFILE;
1799 oldFile->p = curPTR;
1800 oldFile->lineno = lineno;
1801
1802 (void) Lst_AtFront (includes, (ClientData)oldFile);
1803
1804 /*
1805 * Once the previous state has been saved, we can get down to reading
1806 * the new file. We set up the name of the file to be the absolute
1807 * name of the include file so error messages refer to the right
1808 * place. Naturally enough, we start reading at line number 0.
1809 */
1810 fname = fullname;
1811 lineno = 0;
1812
1813 curFILE = fopen (fullname, "r");
1814 curPTR = NULL;
1815 if (curFILE == (FILE * ) NULL) {
1816 Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1817 /*
1818 * Pop to previous file
1819 */
1820 (void) ParseEOF(0);
1821 }
1822 }
1823
1824
1825 /*-
1826 *---------------------------------------------------------------------
1827 * Parse_FromString --
1828 * Start Parsing from the given string
1829 *
1830 * Results:
1831 * None
1832 *
1833 * Side Effects:
1834 * A structure is added to the includes Lst and readProc, lineno,
1835 * fname and curFILE are altered for the new file
1836 *---------------------------------------------------------------------
1837 */
1838 void
1839 Parse_FromString(str)
1840 char *str;
1841 {
1842 IFile *oldFile; /* state associated with this file */
1843
1844 if (DEBUG(FOR))
1845 (void) fprintf(stderr, "%s\n----\n", str);
1846
1847 oldFile = (IFile *) emalloc (sizeof (IFile));
1848 oldFile->lineno = lineno;
1849 oldFile->fname = fname;
1850 oldFile->F = curFILE;
1851 oldFile->p = curPTR;
1852
1853 (void) Lst_AtFront (includes, (ClientData)oldFile);
1854
1855 curFILE = NULL;
1856 curPTR = (PTR *) emalloc (sizeof (PTR));
1857 curPTR->str = curPTR->ptr = str;
1858 lineno = 0;
1859 fname = strdup(fname);
1860 }
1861
1862
1863 #ifdef SYSVINCLUDE
1864 /*-
1865 *---------------------------------------------------------------------
1866 * ParseTraditionalInclude --
1867 * Push to another file.
1868 *
1869 * The input is the line minus the "include". The file name is
1870 * the string following the "include".
1871 *
1872 * Results:
1873 * None
1874 *
1875 * Side Effects:
1876 * A structure is added to the includes Lst and readProc, lineno,
1877 * fname and curFILE are altered for the new file
1878 *---------------------------------------------------------------------
1879 */
1880 static void
1881 ParseTraditionalInclude (file)
1882 char *file; /* file specification */
1883 {
1884 char *fullname; /* full pathname of file */
1885 IFile *oldFile; /* state associated with current file */
1886 char *cp; /* current position in file spec */
1887 char *prefEnd;
1888
1889 /*
1890 * Skip over whitespace
1891 */
1892 while ((*file == ' ') || (*file == '\t')) {
1893 file++;
1894 }
1895
1896 if (*file == '\0') {
1897 Parse_Error (PARSE_FATAL,
1898 "Filename missing from \"include\"");
1899 return;
1900 }
1901
1902 /*
1903 * Skip to end of line or next whitespace
1904 */
1905 for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1906 continue;
1907 }
1908
1909 *cp = '\0';
1910
1911 /*
1912 * Substitute for any variables in the file name before trying to
1913 * find the thing.
1914 */
1915 file = Var_Subst (NULL, file, VAR_CMD, FALSE);
1916
1917 /*
1918 * Now we know the file's name, we attempt to find the durn thing.
1919 * A return of NULL indicates the file don't exist.
1920 *
1921 * Include files are first searched for relative to the including
1922 * file's location. We don't want to cd there, of course, so we
1923 * just tack on the old file's leading path components and call
1924 * Dir_FindFile to see if we can locate the beast.
1925 * XXX - this *does* search in the current directory, right?
1926 */
1927
1928 prefEnd = strrchr (fname, '/');
1929 if (prefEnd != (char *)NULL) {
1930 char *newName;
1931
1932 *prefEnd = '\0';
1933 newName = str_concat (fname, file, STR_ADDSLASH);
1934 fullname = Dir_FindFile (newName, parseIncPath);
1935 if (fullname == (char *)NULL) {
1936 fullname = Dir_FindFile(newName, dirSearchPath);
1937 }
1938 free (newName);
1939 *prefEnd = '/';
1940 } else {
1941 fullname = (char *)NULL;
1942 }
1943
1944 if (fullname == (char *)NULL) {
1945 /*
1946 * System makefile or makefile wasn't found in same directory as
1947 * included makefile. Search for it first on the -I search path,
1948 * then on the .PATH search path, if not found in a -I directory.
1949 * XXX: Suffix specific?
1950 */
1951 fullname = Dir_FindFile (file, parseIncPath);
1952 if (fullname == (char *)NULL) {
1953 fullname = Dir_FindFile(file, dirSearchPath);
1954 }
1955 }
1956
1957 if (fullname == (char *)NULL) {
1958 /*
1959 * Still haven't found the makefile. Look for it on the system
1960 * path as a last resort.
1961 */
1962 fullname = Dir_FindFile(file, sysIncPath);
1963 }
1964
1965 if (fullname == (char *) NULL) {
1966 Parse_Error (PARSE_FATAL, "Could not find %s", file);
1967 return;
1968 }
1969
1970 /*
1971 * Once we find the absolute path to the file, we get to save all the
1972 * state from the current file before we can start reading this
1973 * include file. The state is stored in an IFile structure which
1974 * is placed on a list with other IFile structures. The list makes
1975 * a very nice stack to track how we got here...
1976 */
1977 oldFile = (IFile *) emalloc (sizeof (IFile));
1978 oldFile->fname = fname;
1979
1980 oldFile->F = curFILE;
1981 oldFile->p = curPTR;
1982 oldFile->lineno = lineno;
1983
1984 (void) Lst_AtFront (includes, (ClientData)oldFile);
1985
1986 /*
1987 * Once the previous state has been saved, we can get down to reading
1988 * the new file. We set up the name of the file to be the absolute
1989 * name of the include file so error messages refer to the right
1990 * place. Naturally enough, we start reading at line number 0.
1991 */
1992 fname = fullname;
1993 lineno = 0;
1994
1995 curFILE = fopen (fullname, "r");
1996 curPTR = NULL;
1997 if (curFILE == (FILE * ) NULL) {
1998 Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1999 /*
2000 * Pop to previous file
2001 */
2002 (void) ParseEOF(1);
2003 }
2004 }
2005 #endif
2006
2007 /*-
2008 *---------------------------------------------------------------------
2009 * ParseEOF --
2010 * Called when EOF is reached in the current file. If we were reading
2011 * an include file, the includes stack is popped and things set up
2012 * to go back to reading the previous file at the previous location.
2013 *
2014 * Results:
2015 * CONTINUE if there's more to do. DONE if not.
2016 *
2017 * Side Effects:
2018 * The old curFILE, is closed. The includes list is shortened.
2019 * lineno, curFILE, and fname are changed if CONTINUE is returned.
2020 *---------------------------------------------------------------------
2021 */
2022 static int
2023 ParseEOF (opened)
2024 int opened;
2025 {
2026 IFile *ifile; /* the state on the top of the includes stack */
2027
2028 if (Lst_IsEmpty (includes)) {
2029 return (DONE);
2030 }
2031
2032 ifile = (IFile *) Lst_DeQueue (includes);
2033 free ((Address) fname);
2034 fname = ifile->fname;
2035 lineno = ifile->lineno;
2036 if (opened && curFILE)
2037 (void) fclose (curFILE);
2038 if (curPTR) {
2039 free((Address) curPTR->str);
2040 free((Address) curPTR);
2041 }
2042 curFILE = ifile->F;
2043 curPTR = ifile->p;
2044 free ((Address)ifile);
2045 return (CONTINUE);
2046 }
2047
2048 /*-
2049 *---------------------------------------------------------------------
2050 * ParseReadc --
2051 * Read a character from the current file
2052 *
2053 * Results:
2054 * The character that was read
2055 *
2056 * Side Effects:
2057 *---------------------------------------------------------------------
2058 */
2059 static int
2060 ParseReadc()
2061 {
2062 if (curFILE)
2063 return fgetc(curFILE);
2064
2065 if (curPTR && *curPTR->ptr)
2066 return *curPTR->ptr++;
2067 return EOF;
2068 }
2069
2070
2071 /*-
2072 *---------------------------------------------------------------------
2073 * ParseUnreadc --
2074 * Put back a character to the current file
2075 *
2076 * Results:
2077 * None.
2078 *
2079 * Side Effects:
2080 *---------------------------------------------------------------------
2081 */
2082 static void
2083 ParseUnreadc(c)
2084 int c;
2085 {
2086 if (curFILE) {
2087 ungetc(c, curFILE);
2088 return;
2089 }
2090 if (curPTR) {
2091 *--(curPTR->ptr) = c;
2092 return;
2093 }
2094 }
2095
2096
2097 /* ParseSkipLine():
2098 * Grab the next line
2099 */
2100 static char *
2101 ParseSkipLine(skip)
2102 int skip; /* Skip lines that don't start with . */
2103 {
2104 char *line;
2105 int c, lastc = '\0', lineLength;
2106 Buffer buf;
2107
2108 c = ParseReadc();
2109
2110 if (skip) {
2111 /*
2112 * Skip lines until get to one that begins with a
2113 * special char.
2114 */
2115 while ((c != '.') && (c != EOF)) {
2116 while (((c != '\n') || (lastc == '\\')) && (c != EOF))
2117 {
2118 /*
2119 * Advance to next unescaped newline
2120 */
2121 if ((lastc = c) == '\n') {
2122 lineno++;
2123 }
2124 c = ParseReadc();
2125 }
2126 lineno++;
2127
2128 lastc = c;
2129 c = ParseReadc ();
2130 }
2131 }
2132
2133 if (c == EOF) {
2134 Parse_Error (PARSE_FATAL, "Unclosed conditional/for loop");
2135 return ((char *)NULL);
2136 }
2137
2138 /*
2139 * Read the entire line into buf
2140 */
2141 buf = Buf_Init (MAKE_BSIZE);
2142 if (c != '\n') {
2143 do {
2144 Buf_AddByte (buf, (Byte)c);
2145 c = ParseReadc();
2146 } while ((c != '\n') && (c != EOF));
2147 }
2148 lineno++;
2149
2150 Buf_AddByte (buf, (Byte)'\0');
2151 line = (char *)Buf_GetAll (buf, &lineLength);
2152 Buf_Destroy (buf, FALSE);
2153 return line;
2154 }
2155
2156
2157 /*-
2158 *---------------------------------------------------------------------
2159 * ParseReadLine --
2160 * Read an entire line from the input file. Called only by Parse_File.
2161 * To facilitate escaped newlines and what have you, a character is
2162 * buffered in 'lastc', which is '\0' when no characters have been
2163 * read. When we break out of the loop, c holds the terminating
2164 * character and lastc holds a character that should be added to
2165 * the line (unless we don't read anything but a terminator).
2166 *
2167 * Results:
2168 * A line w/o its newline
2169 *
2170 * Side Effects:
2171 * Only those associated with reading a character
2172 *---------------------------------------------------------------------
2173 */
2174 static char *
2175 ParseReadLine ()
2176 {
2177 Buffer buf; /* Buffer for current line */
2178 register int c; /* the current character */
2179 register int lastc; /* The most-recent character */
2180 Boolean semiNL; /* treat semi-colons as newlines */
2181 Boolean ignDepOp; /* TRUE if should ignore dependency operators
2182 * for the purposes of setting semiNL */
2183 Boolean ignComment; /* TRUE if should ignore comments (in a
2184 * shell command */
2185 char *line; /* Result */
2186 char *ep; /* to strip trailing blanks */
2187 int lineLength; /* Length of result */
2188
2189 semiNL = FALSE;
2190 ignDepOp = FALSE;
2191 ignComment = FALSE;
2192
2193 /*
2194 * Handle special-characters at the beginning of the line. Either a
2195 * leading tab (shell command) or pound-sign (possible conditional)
2196 * forces us to ignore comments and dependency operators and treat
2197 * semi-colons as semi-colons (by leaving semiNL FALSE). This also
2198 * discards completely blank lines.
2199 */
2200 for (;;) {
2201 c = ParseReadc();
2202
2203 if (c == '\t') {
2204 ignComment = ignDepOp = TRUE;
2205 break;
2206 } else if (c == '\n') {
2207 lineno++;
2208 } else if (c == '#') {
2209 ParseUnreadc(c);
2210 break;
2211 } else {
2212 /*
2213 * Anything else breaks out without doing anything
2214 */
2215 break;
2216 }
2217 }
2218
2219 if (c != EOF) {
2220 lastc = c;
2221 buf = Buf_Init(MAKE_BSIZE);
2222
2223 while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
2224 (c != EOF))
2225 {
2226 test_char:
2227 switch(c) {
2228 case '\n':
2229 /*
2230 * Escaped newline: read characters until a non-space or an
2231 * unescaped newline and replace them all by a single space.
2232 * This is done by storing the space over the backslash and
2233 * dropping through with the next nonspace. If it is a
2234 * semi-colon and semiNL is TRUE, it will be recognized as a
2235 * newline in the code below this...
2236 */
2237 lineno++;
2238 lastc = ' ';
2239 while ((c = ParseReadc ()) == ' ' || c == '\t') {
2240 continue;
2241 }
2242 if (c == EOF || c == '\n') {
2243 goto line_read;
2244 } else {
2245 /*
2246 * Check for comments, semiNL's, etc. -- easier than
2247 * ParseUnreadc(c); continue;
2248 */
2249 goto test_char;
2250 }
2251 /*NOTREACHED*/
2252 break;
2253
2254 case ';':
2255 /*
2256 * Semi-colon: Need to see if it should be interpreted as a
2257 * newline
2258 */
2259 if (semiNL) {
2260 /*
2261 * To make sure the command that may be following this
2262 * semi-colon begins with a tab, we push one back into the
2263 * input stream. This will overwrite the semi-colon in the
2264 * buffer. If there is no command following, this does no
2265 * harm, since the newline remains in the buffer and the
2266 * whole line is ignored.
2267 */
2268 ParseUnreadc('\t');
2269 goto line_read;
2270 }
2271 break;
2272 case '=':
2273 if (!semiNL) {
2274 /*
2275 * Haven't seen a dependency operator before this, so this
2276 * must be a variable assignment -- don't pay attention to
2277 * dependency operators after this.
2278 */
2279 ignDepOp = TRUE;
2280 } else if (lastc == ':' || lastc == '!') {
2281 /*
2282 * Well, we've seen a dependency operator already, but it
2283 * was the previous character, so this is really just an
2284 * expanded variable assignment. Revert semi-colons to
2285 * being just semi-colons again and ignore any more
2286 * dependency operators.
2287 *
2288 * XXX: Note that a line like "foo : a:=b" will blow up,
2289 * but who'd write a line like that anyway?
2290 */
2291 ignDepOp = TRUE; semiNL = FALSE;
2292 }
2293 break;
2294 case '#':
2295 if (!ignComment) {
2296 if (
2297 #if 0
2298 compatMake &&
2299 #endif
2300 (lastc != '\\')) {
2301 /*
2302 * If the character is a hash mark and it isn't escaped
2303 * (or we're being compatible), the thing is a comment.
2304 * Skip to the end of the line.
2305 */
2306 do {
2307 c = ParseReadc();
2308 } while ((c != '\n') && (c != EOF));
2309 goto line_read;
2310 } else {
2311 /*
2312 * Don't add the backslash. Just let the # get copied
2313 * over.
2314 */
2315 lastc = c;
2316 continue;
2317 }
2318 }
2319 break;
2320 case ':':
2321 case '!':
2322 if (!ignDepOp && (c == ':' || c == '!')) {
2323 /*
2324 * A semi-colon is recognized as a newline only on
2325 * dependency lines. Dependency lines are lines with a
2326 * colon or an exclamation point. Ergo...
2327 */
2328 semiNL = TRUE;
2329 }
2330 break;
2331 }
2332 /*
2333 * Copy in the previous character and save this one in lastc.
2334 */
2335 Buf_AddByte (buf, (Byte)lastc);
2336 lastc = c;
2337
2338 }
2339 line_read:
2340 lineno++;
2341
2342 if (lastc != '\0') {
2343 Buf_AddByte (buf, (Byte)lastc);
2344 }
2345 Buf_AddByte (buf, (Byte)'\0');
2346 line = (char *)Buf_GetAll (buf, &lineLength);
2347 Buf_Destroy (buf, FALSE);
2348
2349 /*
2350 * Strip trailing blanks and tabs from the line.
2351 * Do not strip a blank or tab that is preceeded by
2352 * a '\'
2353 */
2354 ep = line;
2355 while (*ep)
2356 ++ep;
2357 while (ep > line && (ep[-1] == ' ' || ep[-1] == '\t')) {
2358 if (ep > line + 1 && ep[-2] == '\\')
2359 break;
2360 --ep;
2361 }
2362 *ep = 0;
2363
2364 if (line[0] == '.') {
2365 /*
2366 * The line might be a conditional. Ask the conditional module
2367 * about it and act accordingly
2368 */
2369 switch (Cond_Eval (line)) {
2370 case COND_SKIP:
2371 /*
2372 * Skip to next conditional that evaluates to COND_PARSE.
2373 */
2374 do {
2375 free (line);
2376 line = ParseSkipLine(1);
2377 } while (line && Cond_Eval(line) != COND_PARSE);
2378 if (line == NULL)
2379 break;
2380 /*FALLTHRU*/
2381 case COND_PARSE:
2382 free ((Address) line);
2383 line = ParseReadLine();
2384 break;
2385 case COND_INVALID:
2386 if (For_Eval(line)) {
2387 int ok;
2388 free(line);
2389 do {
2390 /*
2391 * Skip after the matching end
2392 */
2393 line = ParseSkipLine(0);
2394 if (line == NULL) {
2395 Parse_Error (PARSE_FATAL,
2396 "Unexpected end of file in for loop.\n");
2397 break;
2398 }
2399 ok = For_Eval(line);
2400 free(line);
2401 }
2402 while (ok);
2403 if (line != NULL)
2404 For_Run();
2405 line = ParseReadLine();
2406 }
2407 break;
2408 }
2409 }
2410 return (line);
2411
2412 } else {
2413 /*
2414 * Hit end-of-file, so return a NULL line to indicate this.
2415 */
2416 return((char *)NULL);
2417 }
2418 }
2419
2420 /*-
2421 *-----------------------------------------------------------------------
2422 * ParseFinishLine --
2423 * Handle the end of a dependency group.
2424 *
2425 * Results:
2426 * Nothing.
2427 *
2428 * Side Effects:
2429 * inLine set FALSE. 'targets' list destroyed.
2430 *
2431 *-----------------------------------------------------------------------
2432 */
2433 static void
2434 ParseFinishLine()
2435 {
2436 if (inLine) {
2437 Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL);
2438 Lst_Destroy (targets, ParseHasCommands);
2439 targets = NULL;
2440 inLine = FALSE;
2441 }
2442 }
2443
2444
2445 /*-
2446 *---------------------------------------------------------------------
2447 * Parse_File --
2448 * Parse a file into its component parts, incorporating it into the
2449 * current dependency graph. This is the main function and controls
2450 * almost every other function in this module
2451 *
2452 * Results:
2453 * None
2454 *
2455 * Side Effects:
2456 * Loads. Nodes are added to the list of all targets, nodes and links
2457 * are added to the dependency graph. etc. etc. etc.
2458 *---------------------------------------------------------------------
2459 */
2460 void
2461 Parse_File(name, stream)
2462 char *name; /* the name of the file being read */
2463 FILE * stream; /* Stream open to makefile to parse */
2464 {
2465 register char *cp, /* pointer into the line */
2466 *line; /* the line we're working on */
2467
2468 inLine = FALSE;
2469 fname = name;
2470 curFILE = stream;
2471 lineno = 0;
2472 fatals = 0;
2473
2474 do {
2475 while ((line = ParseReadLine ()) != NULL) {
2476 if (*line == '.') {
2477 /*
2478 * Lines that begin with the special character are either
2479 * include or undef directives.
2480 */
2481 for (cp = line + 1; isspace (*cp); cp++) {
2482 continue;
2483 }
2484 if (strncmp (cp, "include", 7) == 0) {
2485 ParseDoInclude (cp + 7);
2486 goto nextLine;
2487 } else if (strncmp(cp, "undef", 5) == 0) {
2488 char *cp2;
2489 for (cp += 5; isspace((unsigned char) *cp); cp++) {
2490 continue;
2491 }
2492
2493 for (cp2 = cp; !isspace((unsigned char) *cp2) &&
2494 (*cp2 != '\0'); cp2++) {
2495 continue;
2496 }
2497
2498 *cp2 = '\0';
2499
2500 Var_Delete(cp, VAR_GLOBAL);
2501 goto nextLine;
2502 }
2503 }
2504 if (*line == '#' || *line == '\0') {
2505 /* If we're this far, the line must be a comment.
2506 (Empty lines are ignored as well) */
2507 goto nextLine;
2508 }
2509
2510 if (*line == '\t') {
2511 /*
2512 * If a line starts with a tab, it can only hope to be
2513 * a creation command.
2514 */
2515 #ifndef POSIX
2516 shellCommand:
2517 #endif
2518 for (cp = line + 1; isspace (*cp); cp++) {
2519 continue;
2520 }
2521 if (*cp) {
2522 if (inLine) {
2523 /*
2524 * So long as it's not a blank line and we're actually
2525 * in a dependency spec, add the command to the list of
2526 * commands of all targets in the dependency spec
2527 */
2528 Lst_ForEach (targets, ParseAddCmd, cp);
2529 Lst_AtEnd(targCmds, (ClientData) line);
2530 continue;
2531 } else {
2532 Parse_Error (PARSE_FATAL,
2533 "Unassociated shell command \"%.20s\"",
2534 cp);
2535 }
2536 }
2537 #ifdef SYSVINCLUDE
2538 } else if (strncmp (line, "include", 7) == 0 &&
2539 strchr(line, ':') == NULL) {
2540 /*
2541 * It's an S3/S5-style "include".
2542 */
2543 ParseTraditionalInclude (line + 7);
2544 goto nextLine;
2545 #endif
2546 } else if (Parse_IsVar (line)) {
2547 ParseFinishLine();
2548 Parse_DoVar (line, VAR_GLOBAL);
2549 } else {
2550 /*
2551 * We now know it's a dependency line so it needs to have all
2552 * variables expanded before being parsed. Tell the variable
2553 * module to complain if some variable is undefined...
2554 * To make life easier on novices, if the line is indented we
2555 * first make sure the line has a dependency operator in it.
2556 * If it doesn't have an operator and we're in a dependency
2557 * line's script, we assume it's actually a shell command
2558 * and add it to the current list of targets.
2559 */
2560 #ifndef POSIX
2561 Boolean nonSpace = FALSE;
2562 #endif
2563
2564 cp = line;
2565 if (isspace((unsigned char) line[0])) {
2566 while ((*cp != '\0') && isspace((unsigned char) *cp)) {
2567 cp++;
2568 }
2569 if (*cp == '\0') {
2570 goto nextLine;
2571 }
2572 #ifndef POSIX
2573 while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
2574 nonSpace = TRUE;
2575 cp++;
2576 }
2577 #endif
2578 }
2579
2580 #ifndef POSIX
2581 if (*cp == '\0') {
2582 if (inLine) {
2583 Parse_Error (PARSE_WARNING,
2584 "Shell command needs a leading tab");
2585 goto shellCommand;
2586 } else if (nonSpace) {
2587 Parse_Error (PARSE_FATAL, "Missing operator");
2588 }
2589 } else {
2590 #endif
2591 ParseFinishLine();
2592
2593 cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
2594 free (line);
2595 line = cp;
2596
2597 /*
2598 * Need a non-circular list for the target nodes
2599 */
2600 if (targets)
2601 Lst_Destroy(targets, NOFREE);
2602
2603 targets = Lst_Init (FALSE);
2604 inLine = TRUE;
2605
2606 ParseDoDependency (line);
2607 #ifndef POSIX
2608 }
2609 #endif
2610 }
2611
2612 nextLine:
2613
2614 free (line);
2615 }
2616 /*
2617 * Reached EOF, but it may be just EOF of an include file...
2618 */
2619 } while (ParseEOF(1) == CONTINUE);
2620
2621 /*
2622 * Make sure conditionals are clean
2623 */
2624 Cond_End();
2625
2626 if (fatals) {
2627 fprintf (stderr, "Fatal errors encountered -- cannot continue\n");
2628 exit (1);
2629 }
2630 }
2631
2632 /*-
2633 *---------------------------------------------------------------------
2634 * Parse_Init --
2635 * initialize the parsing module
2636 *
2637 * Results:
2638 * none
2639 *
2640 * Side Effects:
2641 * the parseIncPath list is initialized...
2642 *---------------------------------------------------------------------
2643 */
2644 void
2645 Parse_Init ()
2646 {
2647 char *cp = NULL, *start;
2648 /* avoid faults on read-only strings */
2649 static char syspath[] = _PATH_DEFSYSPATH;
2650
2651 mainNode = NILGNODE;
2652 parseIncPath = Lst_Init (FALSE);
2653 sysIncPath = Lst_Init (FALSE);
2654 includes = Lst_Init (FALSE);
2655 targCmds = Lst_Init (FALSE);
2656
2657 /*
2658 * Add the directories from the DEFSYSPATH (more than one may be given
2659 * as dir1:...:dirn) to the system include path.
2660 */
2661 for (start = syspath; *start != '\0'; start = cp) {
2662 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
2663 continue;
2664 if (*cp == '\0') {
2665 Dir_AddDir(sysIncPath, start);
2666 } else {
2667 *cp++ = '\0';
2668 Dir_AddDir(sysIncPath, start);
2669 }
2670 }
2671 }
2672
2673 void
2674 Parse_End()
2675 {
2676 Lst_Destroy(targCmds, (void (*) __P((ClientData))) free);
2677 if (targets)
2678 Lst_Destroy(targets, NOFREE);
2679 Lst_Destroy(sysIncPath, Dir_Destroy);
2680 Lst_Destroy(parseIncPath, Dir_Destroy);
2681 Lst_Destroy(includes, NOFREE); /* Should be empty now */
2682 }
2683
2684
2685 /*-
2686 *-----------------------------------------------------------------------
2687 * Parse_MainName --
2688 * Return a Lst of the main target to create for main()'s sake. If
2689 * no such target exists, we Punt with an obnoxious error message.
2690 *
2691 * Results:
2692 * A Lst of the single node to create.
2693 *
2694 * Side Effects:
2695 * None.
2696 *
2697 *-----------------------------------------------------------------------
2698 */
2699 Lst
2700 Parse_MainName()
2701 {
2702 Lst main; /* result list */
2703
2704 main = Lst_Init (FALSE);
2705
2706 if (mainNode == NILGNODE) {
2707 Punt ("make: no target to make.\n");
2708 /*NOTREACHED*/
2709 } else if (mainNode->type & OP_DOUBLEDEP) {
2710 (void) Lst_AtEnd (main, (ClientData)mainNode);
2711 Lst_Concat(main, mainNode->cohorts, LST_CONCNEW);
2712 }
2713 else
2714 (void) Lst_AtEnd (main, (ClientData)mainNode);
2715 return (main);
2716 }
2717