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