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