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