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