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