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