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