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