source: trunk/src/kmk/parse.c@ 25

Last change on this file since 25 was 25, checked in by bird, 23 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

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