Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / make / parse.c
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
41 static char sccsid[] = "@(#)parse.c     8.3 (Berkeley) 3/19/94";
42 #else
43 static const char rcsid[] =
44   "$FreeBSD: src/usr.bin/make/parse.c,v 1.22.2.1 2002/12/26 14:36:38 ru 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
112 static Lst          targets;    /* targets we're working on */
113 static Lst          targCmds;   /* command lines for targets */
114 static Boolean      inLine;     /* true if currently in a dependency
115                                  * line or its commands */
116 typedef struct {
117     char *str;
118     char *ptr;
119 } PTR;
120
121 static char         *fname;     /* name of current file (for errors) */
122 static int          lineno;     /* line number in current file */
123 static FILE         *curFILE = NULL;    /* current makefile */
124
125 static PTR          *curPTR = NULL;     /* current makefile */
126
127 static int          fatals = 0;
128
129 static 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  */
135 typedef 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
142 static Lst      includes;       /* stack of IFiles generated by
143                                  * #includes */
144 Lst             parseIncPath;   /* list of directories for "..." includes */
145 Lst             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  */
153 typedef 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
184 static ParseSpecial specType;
185 static 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  */
191 static 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  */
200 static 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
241 static int ParseFindKeyword __P((char *));
242 static int ParseLinkSrc __P((ClientData, ClientData));
243 static int ParseDoOp __P((ClientData, ClientData));
244 static int ParseAddDep __P((ClientData, ClientData));
245 static void ParseDoSrc __P((int, char *, Lst));
246 static int ParseFindMain __P((ClientData, ClientData));
247 static int ParseAddDir __P((ClientData, ClientData));
248 static int ParseClearPath __P((ClientData, ClientData));
249 static void ParseDoDependency __P((char *));
250 static int ParseAddCmd __P((ClientData, ClientData));
251 static int ParseReadc __P((void));
252 static void ParseUnreadc __P((int));
253 static void ParseHasCommands __P((ClientData));
254 static void ParseDoInclude __P((char *));
255 static void ParseDoError __P((char *));
256 #ifdef SYSVINCLUDE
257 static void ParseTraditionalInclude __P((char *));
258 #endif
259 static int ParseEOF __P((int));
260 static char *ParseReadLine __P((void));
261 static char *ParseSkipLine __P((int));
262 static 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  */
276 static int
277 ParseFindKeyword (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 */
316 void
317 #ifdef __STDC__
318 Parse_Error(int type, char *fmt, ...)
319 #else
320 Parse_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  */
363 static int
364 ParseLinkSrc (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  */
396 static int
397 ParseDoOp (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  */
474 static int
475 ParseAddDep(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  */
514 static void
515 ParseDoSrc (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  */
627 static int
628 ParseFindMain(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  */
655 static int
656 ParseAddDir(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  */
677 static int
678 ParseClearPath(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  */
720 static void
721 ParseDoDependency (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 ((unsigned char) *cp) && *cp != '(';
749              cp++)
750         {
751             if (*cp == '$') {
752                 /*
753                  * Must be a dynamic source (would have been expanded
754                  * otherwise), so call the Var module to parse the puppy
755                  * so we can safely advance beyond it...There should be
756                  * no errors in this, as they would have been discovered
757                  * in the initial Var_Subst and we wouldn't be here.
758                  */
759                 int     length;
760                 Boolean freeIt;
761                 char    *result;
762
763                 result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
764
765                 if (freeIt) {
766                     free(result);
767                 }
768                 cp += length-1;
769             } else if (*cp == '!' || *cp == ':') {
770                 /*
771                  * We don't want to end a word on ':' or '!' if there is a
772                  * better match later on in the string (greedy matching).
773                  * This allows the user to have targets like:
774                  *    fie::fi:fo: fum
775                  *    foo::bar:
776                  * where "fie::fi:fo" and "foo::bar" are the targets.  In
777                  * real life this is used for perl5 library man pages where
778                  * "::" separates an object from its class.
779                  * Ie: "File::Spec::Unix".  This behaviour is also consistent
780                  * with other versions of make.
781                  */
782                 char *p = cp + 1;
783
784                 if (*cp == ':' && *p == ':')
785                     p++;
786
787                 /* Found the best match already. */
788                 if (*p == '\0' || isspace(*p))
789                     break;
790
791                 p += strcspn(p, "!:");
792
793                 /* No better match later on... */
794                 if (*p == '\0')
795                     break;
796             }
797             continue;
798         }
799         if (*cp == '(') {
800             /*
801              * Archives must be handled specially to make sure the OP_ARCHV
802              * flag is set in their 'type' field, for one thing, and because
803              * things like "archive(file1.o file2.o file3.o)" are permissible.
804              * Arch_ParseArchive will set 'line' to be the first non-blank
805              * after the archive-spec. It creates/finds nodes for the members
806              * and places them on the given list, returning SUCCESS if all
807              * went well and FAILURE if there was an error in the
808              * specification. On error, line should remain untouched.
809              */
810             if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
811                 Parse_Error (PARSE_FATAL,
812                              "Error in archive specification: \"%s\"", line);
813                 return;
814             } else {
815                 continue;
816             }
817         }
818         savec = *cp;
819
820         if (!*cp) {
821             /*
822              * Ending a dependency line without an operator is a Bozo
823              * no-no
824              */
825             Parse_Error (PARSE_FATAL, "Need an operator");
826             return;
827         }
828         *cp = '\0';
829         /*
830          * Have a word in line. See if it's a special target and set
831          * specType to match it.
832          */
833         if (*line == '.' && isupper (line[1])) {
834             /*
835              * See if the target is a special target that must have it
836              * or its sources handled specially.
837              */
838             int keywd = ParseFindKeyword(line);
839             if (keywd != -1) {
840                 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
841                     Parse_Error(PARSE_FATAL, "Mismatched special targets");
842                     return;
843                 }
844
845                 specType = parseKeywords[keywd].spec;
846                 tOp = parseKeywords[keywd].op;
847
848                 /*
849                  * Certain special targets have special semantics:
850                  *      .PATH           Have to set the dirSearchPath
851                  *                      variable too
852                  *      .MAIN           Its sources are only used if
853                  *                      nothing has been specified to
854                  *                      create.
855                  *      .DEFAULT        Need to create a node to hang
856                  *                      commands on, but we don't want
857                  *                      it in the graph, nor do we want
858                  *                      it to be the Main Target, so we
859                  *                      create it, set OP_NOTMAIN and
860                  *                      add it to the list, setting
861                  *                      DEFAULT to the new node for
862                  *                      later use. We claim the node is
863                  *                      A transformation rule to make
864                  *                      life easier later, when we'll
865                  *                      use Make_HandleUse to actually
866                  *                      apply the .DEFAULT commands.
867                  *      .PHONY          The list of targets
868                  *      .BEGIN
869                  *      .END
870                  *      .INTERRUPT      Are not to be considered the
871                  *                      main target.
872                  *      .NOTPARALLEL    Make only one target at a time.
873                  *      .SINGLESHELL    Create a shell for each command.
874                  *      .ORDER          Must set initial predecessor to NIL
875                  */
876                 switch (specType) {
877                     case ExPath:
878                         if (paths == NULL) {
879                             paths = Lst_Init(FALSE);
880                         }
881                         (void)Lst_AtEnd(paths, (ClientData)dirSearchPath);
882                         break;
883                     case Main:
884                         if (!Lst_IsEmpty(create)) {
885                             specType = Not;
886                         }
887                         break;
888                     case Begin:
889                     case End:
890                     case Interrupt:
891                         gn = Targ_FindNode(line, TARG_CREATE);
892                         gn->type |= OP_NOTMAIN;
893                         (void)Lst_AtEnd(targets, (ClientData)gn);
894                         break;
895                     case Default:
896                         gn = Targ_NewGN(".DEFAULT");
897                         gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
898                         (void)Lst_AtEnd(targets, (ClientData)gn);
899                         DEFAULT = gn;
900                         break;
901                     case NotParallel:
902                     {
903                         extern int  maxJobs;
904
905                         maxJobs = 1;
906                         break;
907                     }
908                     case SingleShell:
909                         compatMake = 1;
910                         break;
911                     case Order:
912                         predecessor = NILGNODE;
913                         break;
914                     default:
915                         break;
916                 }
917             } else if (strncmp (line, ".PATH", 5) == 0) {
918                 /*
919                  * .PATH<suffix> has to be handled specially.
920                  * Call on the suffix module to give us a path to
921                  * modify.
922                  */
923                 Lst     path;
924
925                 specType = ExPath;
926                 path = Suff_GetPath (&line[5]);
927                 if (path == NILLST) {
928                     Parse_Error (PARSE_FATAL,
929                                  "Suffix '%s' not defined (yet)",
930                                  &line[5]);
931                     return;
932                 } else {
933                     if (paths == (Lst)NULL) {
934                         paths = Lst_Init(FALSE);
935                     }
936                     (void)Lst_AtEnd(paths, (ClientData)path);
937                 }
938             }
939         }
940
941         /*
942          * Have word in line. Get or create its node and stick it at
943          * the end of the targets list
944          */
945         if ((specType == Not) && (*line != '\0')) {
946             if (Dir_HasWildcards(line)) {
947                 /*
948                  * Targets are to be sought only in the current directory,
949                  * so create an empty path for the thing. Note we need to
950                  * use Dir_Destroy in the destruction of the path as the
951                  * Dir module could have added a directory to the path...
952                  */
953                 Lst         emptyPath = Lst_Init(FALSE);
954
955                 Dir_Expand(line, emptyPath, curTargs);
956
957                 Lst_Destroy(emptyPath, Dir_Destroy);
958             } else {
959                 /*
960                  * No wildcards, but we want to avoid code duplication,
961                  * so create a list with the word on it.
962                  */
963                 (void)Lst_AtEnd(curTargs, (ClientData)line);
964             }
965
966             while(!Lst_IsEmpty(curTargs)) {
967                 char    *targName = (char *)Lst_DeQueue(curTargs);
968
969                 if (!Suff_IsTransform (targName)) {
970                     gn = Targ_FindNode (targName, TARG_CREATE);
971                 } else {
972                     gn = Suff_AddTransform (targName);
973                 }
974
975                 (void)Lst_AtEnd (targets, (ClientData)gn);
976             }
977         } else if (specType == ExPath && *line != '.' && *line != '\0') {
978             Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
979         }
980
981         *cp = savec;
982         /*
983          * If it is a special type and not .PATH, it's the only target we
984          * allow on this line...
985          */
986         if (specType != Not && specType != ExPath) {
987             Boolean warn = FALSE;
988
989             while ((*cp != '!') && (*cp != ':') && *cp) {
990                 if (*cp != ' ' && *cp != '\t') {
991                     warn = TRUE;
992                 }
993                 cp++;
994             }
995             if (warn) {
996                 Parse_Error(PARSE_WARNING, "Extra target ignored");
997             }
998         } else {
999             while (*cp && isspace (*cp)) {
1000                 cp++;
1001             }
1002         }
1003         line = cp;
1004     } while ((*line != '!') && (*line != ':') && *line);
1005
1006     /*
1007      * Don't need the list of target names anymore...
1008      */
1009     Lst_Destroy(curTargs, NOFREE);
1010
1011     if (!Lst_IsEmpty(targets)) {
1012         switch(specType) {
1013             default:
1014                 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
1015                 break;
1016             case Default:
1017             case Begin:
1018             case End:
1019             case Interrupt:
1020                 /*
1021                  * These four create nodes on which to hang commands, so
1022                  * targets shouldn't be empty...
1023                  */
1024             case Not:
1025                 /*
1026                  * Nothing special here -- targets can be empty if it wants.
1027                  */
1028                 break;
1029         }
1030     }
1031
1032     /*
1033      * Have now parsed all the target names. Must parse the operator next. The
1034      * result is left in  op .
1035      */
1036     if (*cp == '!') {
1037         op = OP_FORCE;
1038     } else if (*cp == ':') {
1039         if (cp[1] == ':') {
1040             op = OP_DOUBLEDEP;
1041             cp++;
1042         } else {
1043             op = OP_DEPENDS;
1044         }
1045     } else {
1046         Parse_Error (PARSE_FATAL, "Missing dependency operator");
1047         return;
1048     }
1049
1050     cp++;                       /* Advance beyond operator */
1051
1052     Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
1053
1054     /*
1055      * Get to the first source
1056      */
1057     while (*cp && isspace (*cp)) {
1058         cp++;
1059     }
1060     line = cp;
1061
1062     /*
1063      * Several special targets take different actions if present with no
1064      * sources:
1065      *  a .SUFFIXES line with no sources clears out all old suffixes
1066      *  a .PRECIOUS line makes all targets precious
1067      *  a .IGNORE line ignores errors for all targets
1068      *  a .SILENT line creates silence when making all targets
1069      *  a .PATH removes all directories from the search path(s).
1070      */
1071     if (!*line) {
1072         switch (specType) {
1073             case Suffixes:
1074                 Suff_ClearSuffixes ();
1075                 break;
1076             case Precious:
1077                 allPrecious = TRUE;
1078                 break;
1079             case Ignore:
1080                 ignoreErrors = TRUE;
1081                 break;
1082             case Silent:
1083                 beSilent = TRUE;
1084                 break;
1085             case ExPath:
1086                 Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
1087                 break;
1088 #ifdef POSIX
1089             case Posix:
1090                 Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1091                 break;
1092 #endif
1093             default:
1094                 break;
1095         }
1096     } else if (specType == MFlags) {
1097         /*
1098          * Call on functions in main.c to deal with these arguments and
1099          * set the initial character to a null-character so the loop to
1100          * get sources won't get anything
1101          */
1102         Main_ParseArgLine (line);
1103         *line = '\0';
1104     } else if (specType == ExShell) {
1105         if (Job_ParseShell (line) != SUCCESS) {
1106             Parse_Error (PARSE_FATAL, "improper shell specification");
1107             return;
1108         }
1109         *line = '\0';
1110     } else if ((specType == NotParallel) || (specType == SingleShell)) {
1111         *line = '\0';
1112     }
1113
1114     /*
1115      * NOW GO FOR THE SOURCES
1116      */
1117     if ((specType == Suffixes) || (specType == ExPath) ||
1118         (specType == Includes) || (specType == Libs) ||
1119         (specType == Null))
1120     {
1121         while (*line) {
1122             /*
1123              * If the target was one that doesn't take files as its sources
1124              * but takes something like suffixes, we take each
1125              * space-separated word on the line as a something and deal
1126              * with it accordingly.
1127              *
1128              * If the target was .SUFFIXES, we take each source as a
1129              * suffix and add it to the list of suffixes maintained by the
1130              * Suff module.
1131              *
1132              * If the target was a .PATH, we add the source as a directory
1133              * to search on the search path.
1134              *
1135              * If it was .INCLUDES, the source is taken to be the suffix of
1136              * files which will be #included and whose search path should
1137              * be present in the .INCLUDES variable.
1138              *
1139              * If it was .LIBS, the source is taken to be the suffix of
1140              * files which are considered libraries and whose search path
1141              * should be present in the .LIBS variable.
1142              *
1143              * If it was .NULL, the source is the suffix to use when a file
1144              * has no valid suffix.
1145              */
1146             char  savec;
1147             while (*cp && !isspace (*cp)) {
1148                 cp++;
1149             }
1150             savec = *cp;
1151             *cp = '\0';
1152             switch (specType) {
1153                 case Suffixes:
1154                     Suff_AddSuffix (line);
1155                     break;
1156                 case ExPath:
1157                     Lst_ForEach(paths, ParseAddDir, (ClientData)line);
1158                     break;
1159                 case Includes:
1160                     Suff_AddInclude (line);
1161                     break;
1162                 case Libs:
1163                     Suff_AddLib (line);
1164                     break;
1165                 case Null:
1166                     Suff_SetNull (line);
1167                     break;
1168                 default:
1169                     break;
1170             }
1171             *cp = savec;
1172             if (savec != '\0') {
1173                 cp++;
1174             }
1175             while (*cp && isspace (*cp)) {
1176                 cp++;
1177             }
1178             line = cp;
1179         }
1180         if (paths) {
1181             Lst_Destroy(paths, NOFREE);
1182         }
1183     } else {
1184         while (*line) {
1185             /*
1186              * The targets take real sources, so we must beware of archive
1187              * specifications (i.e. things with left parentheses in them)
1188              * and handle them accordingly.
1189              */
1190             while (*cp && !isspace (*cp)) {
1191                 if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
1192                     /*
1193                      * Only stop for a left parenthesis if it isn't at the
1194                      * start of a word (that'll be for variable changes
1195                      * later) and isn't preceded by a dollar sign (a dynamic
1196                      * source).
1197                      */
1198                     break;
1199                 } else {
1200                     cp++;
1201                 }
1202             }
1203
1204             if (*cp == '(') {
1205                 GNode     *gn;
1206
1207                 sources = Lst_Init (FALSE);
1208                 if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
1209                     Parse_Error (PARSE_FATAL,
1210                                  "Error in source archive spec \"%s\"", line);
1211                     return;
1212                 }
1213
1214                 while (!Lst_IsEmpty (sources)) {
1215                     gn = (GNode *) Lst_DeQueue (sources);
1216                     ParseDoSrc (tOp, gn->name, curSrcs);
1217                 }
1218                 Lst_Destroy (sources, NOFREE);
1219                 cp = line;
1220             } else {
1221                 if (*cp) {
1222                     *cp = '\0';
1223                     cp += 1;
1224                 }
1225
1226                 ParseDoSrc (tOp, line, curSrcs);
1227             }
1228             while (*cp && isspace (*cp)) {
1229                 cp++;
1230             }
1231             line = cp;
1232         }
1233     }
1234
1235     if (mainNode == NILGNODE) {
1236         /*
1237          * If we have yet to decide on a main target to make, in the
1238          * absence of any user input, we want the first target on
1239          * the first dependency line that is actually a real target
1240          * (i.e. isn't a .USE or .EXEC rule) to be made.
1241          */
1242         Lst_ForEach (targets, ParseFindMain, (ClientData)0);
1243     }
1244
1245     /*
1246      * Finally, destroy the list of sources
1247      */
1248     Lst_Destroy(curSrcs, NOFREE);
1249 }
1250
1251 /*-
1252  *---------------------------------------------------------------------
1253  * Parse_IsVar  --
1254  *      Return TRUE if the passed line is a variable assignment. A variable
1255  *      assignment consists of a single word followed by optional whitespace
1256  *      followed by either a += or an = operator.
1257  *      This function is used both by the Parse_File function and main when
1258  *      parsing the command-line arguments.
1259  *
1260  * Results:
1261  *      TRUE if it is. FALSE if it ain't
1262  *
1263  * Side Effects:
1264  *      none
1265  *---------------------------------------------------------------------
1266  */
1267 Boolean
1268 Parse_IsVar (line)
1269     register char  *line;       /* the line to check */
1270 {
1271     register Boolean wasSpace = FALSE;  /* set TRUE if found a space */
1272     register Boolean haveName = FALSE;  /* Set TRUE if have a variable name */
1273     int level = 0;
1274 #define ISEQOPERATOR(c) \
1275         (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1276
1277     /*
1278      * Skip to variable name
1279      */
1280     for (;(*line == ' ') || (*line == '\t'); line++)
1281         continue;
1282
1283     for (; *line != '=' || level != 0; line++)
1284         switch (*line) {
1285         case '\0':
1286             /*
1287              * end-of-line -- can't be a variable assignment.
1288              */
1289             return FALSE;
1290
1291         case ' ':
1292         case '\t':
1293             /*
1294              * there can be as much white space as desired so long as there is
1295              * only one word before the operator
1296              */
1297             wasSpace = TRUE;
1298             break;
1299
1300         case '(':
1301         case '{':
1302             level++;
1303             break;
1304
1305         case '}':
1306         case ')':
1307             level--;
1308             break;
1309
1310         default:
1311             if (wasSpace && haveName) {
1312                     if (ISEQOPERATOR(*line)) {
1313                         /*
1314                          * We must have a finished word
1315                          */
1316                         if (level != 0)
1317                             return FALSE;
1318
1319                         /*
1320                          * When an = operator [+?!:] is found, the next
1321                          * character must be an = or it ain't a valid
1322                          * assignment.
1323                          */
1324                         if (line[1] == '=')
1325                             return haveName;
1326 #ifdef SUNSHCMD
1327                         /*
1328                          * This is a shell command
1329                          */
1330                         if (strncmp(line, ":sh", 3) == 0)
1331                             return haveName;
1332 #endif
1333                     }
1334                     /*
1335                      * This is the start of another word, so not assignment.
1336                      */
1337                     return FALSE;
1338             }
1339             else {
1340                 haveName = TRUE;
1341                 wasSpace = FALSE;
1342             }
1343             break;
1344         }
1345
1346     return haveName;
1347 }
1348
1349 /*-
1350  *---------------------------------------------------------------------
1351  * Parse_DoVar  --
1352  *      Take the variable assignment in the passed line and do it in the
1353  *      global context.
1354  *
1355  *      Note: There is a lexical ambiguity with assignment modifier characters
1356  *      in variable names. This routine interprets the character before the =
1357  *      as a modifier. Therefore, an assignment like
1358  *          C++=/usr/bin/CC
1359  *      is interpreted as "C+ +=" instead of "C++ =".
1360  *
1361  * Results:
1362  *      none
1363  *
1364  * Side Effects:
1365  *      the variable structure of the given variable name is altered in the
1366  *      global context.
1367  *---------------------------------------------------------------------
1368  */
1369 void
1370 Parse_DoVar (line, ctxt)
1371     char            *line;      /* a line guaranteed to be a variable
1372                                  * assignment. This reduces error checks */
1373     GNode           *ctxt;      /* Context in which to do the assignment */
1374 {
1375     char           *cp; /* pointer into line */
1376     enum {
1377         VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1378     }               type;       /* Type of assignment */
1379     char            *opc;       /* ptr to operator character to
1380                                  * null-terminate the variable name */
1381     /*
1382      * Avoid clobbered variable warnings by forcing the compiler
1383      * to ``unregister'' variables
1384      */
1385 #if __GNUC__
1386     (void) &cp;
1387     (void) &line;
1388 #endif
1389
1390     /*
1391      * Skip to variable name
1392      */
1393     while ((*line == ' ') || (*line == '\t')) {
1394         line++;
1395     }
1396
1397     /*
1398      * Skip to operator character, nulling out whitespace as we go
1399      */
1400     for (cp = line + 1; *cp != '='; cp++) {
1401         if (isspace (*cp)) {
1402             *cp = '\0';
1403         }
1404     }
1405     opc = cp-1;         /* operator is the previous character */
1406     *cp++ = '\0';       /* nuke the = */
1407
1408     /*
1409      * Check operator type
1410      */
1411     switch (*opc) {
1412         case '+':
1413             type = VAR_APPEND;
1414             *opc = '\0';
1415             break;
1416
1417         case '?':
1418             /*
1419              * If the variable already has a value, we don't do anything.
1420              */
1421             *opc = '\0';
1422             if (Var_Exists(line, ctxt)) {
1423                 return;
1424             } else {
1425                 type = VAR_NORMAL;
1426             }
1427             break;
1428
1429         case ':':
1430             type = VAR_SUBST;
1431             *opc = '\0';
1432             break;
1433
1434         case '!':
1435             type = VAR_SHELL;
1436             *opc = '\0';
1437             break;
1438
1439         default:
1440 #ifdef SUNSHCMD
1441             while (*opc != ':')
1442                 if (opc == line)
1443                     break;
1444                 else
1445                     --opc;
1446
1447             if (strncmp(opc, ":sh", 3) == 0) {
1448                 type = VAR_SHELL;
1449                 *opc = '\0';
1450                 break;
1451             }
1452 #endif
1453             type = VAR_NORMAL;
1454             break;
1455     }
1456
1457     while (isspace (*cp)) {
1458         cp++;
1459     }
1460
1461     if (type == VAR_APPEND) {
1462         Var_Append (line, cp, ctxt);
1463     } else if (type == VAR_SUBST) {
1464         /*
1465          * Allow variables in the old value to be undefined, but leave their
1466          * invocation alone -- this is done by forcing oldVars to be false.
1467          * XXX: This can cause recursive variables, but that's not hard to do,
1468          * and this allows someone to do something like
1469          *
1470          *  CFLAGS = $(.INCLUDES)
1471          *  CFLAGS := -I.. $(CFLAGS)
1472          *
1473          * And not get an error.
1474          */
1475         Boolean   oldOldVars = oldVars;
1476
1477         oldVars = FALSE;
1478         cp = Var_Subst(NULL, cp, ctxt, FALSE);
1479         oldVars = oldOldVars;
1480
1481         Var_Set(line, cp, ctxt);
1482         free(cp);
1483     } else if (type == VAR_SHELL) {
1484         Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
1485                                   * if any variable expansion was performed */
1486         char *res, *err;
1487
1488         if (strchr(cp, '$') != NULL) {
1489             /*
1490              * There's a dollar sign in the command, so perform variable
1491              * expansion on the whole thing. The resulting string will need
1492              * freeing when we're done, so set freeCmd to TRUE.
1493              */
1494             cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
1495             freeCmd = TRUE;
1496         }
1497
1498         res = Cmd_Exec(cp, &err);
1499         Var_Set(line, res, ctxt);
1500         free(res);
1501
1502         if (err)
1503             Parse_Error(PARSE_WARNING, err, cp);
1504
1505         if (freeCmd)
1506             free(cp);
1507     } else {
1508         /*
1509          * Normal assignment -- just do it.
1510          */
1511         Var_Set(line, cp, ctxt);
1512     }
1513 }
1514
1515
1516 /*-
1517  * ParseAddCmd  --
1518  *      Lst_ForEach function to add a command line to all targets
1519  *
1520  * Results:
1521  *      Always 0
1522  *
1523  * Side Effects:
1524  *      A new element is added to the commands list of the node.
1525  */
1526 static int
1527 ParseAddCmd(gnp, cmd)
1528     ClientData gnp;     /* the node to which the command is to be added */
1529     ClientData cmd;     /* the command to add */
1530 {
1531     GNode *gn = (GNode *) gnp;
1532     /* if target already supplied, ignore commands */
1533     if (!(gn->type & OP_HAS_COMMANDS))
1534         (void)Lst_AtEnd(gn->commands, cmd);
1535     return(0);
1536 }
1537
1538 /*-
1539  *-----------------------------------------------------------------------
1540  * ParseHasCommands --
1541  *      Callback procedure for Parse_File when destroying the list of
1542  *      targets on the last dependency line. Marks a target as already
1543  *      having commands if it does, to keep from having shell commands
1544  *      on multiple dependency lines.
1545  *
1546  * Results:
1547  *      None
1548  *
1549  * Side Effects:
1550  *      OP_HAS_COMMANDS may be set for the target.
1551  *
1552  *-----------------------------------------------------------------------
1553  */
1554 static void
1555 ParseHasCommands(gnp)
1556     ClientData    gnp;      /* Node to examine */
1557 {
1558     GNode *gn = (GNode *) gnp;
1559     if (!Lst_IsEmpty(gn->commands)) {
1560         gn->type |= OP_HAS_COMMANDS;
1561     }
1562 }
1563
1564 /*-
1565  *-----------------------------------------------------------------------
1566  * Parse_AddIncludeDir --
1567  *      Add a directory to the path searched for included makefiles
1568  *      bracketed by double-quotes. Used by functions in main.c
1569  *
1570  * Results:
1571  *      None.
1572  *
1573  * Side Effects:
1574  *      The directory is appended to the list.
1575  *
1576  *-----------------------------------------------------------------------
1577  */
1578 void
1579 Parse_AddIncludeDir (dir)
1580     char          *dir;     /* The name of the directory to add */
1581 {
1582     Dir_AddDir (parseIncPath, dir);
1583 }
1584
1585 /*---------------------------------------------------------------------
1586  * ParseDoError  --
1587  *      Handle error directive
1588  *
1589  *      The input is the line minus the ".error".  We substitute variables,
1590  *      print the message and exit(1) or just print a warning if the ".error"
1591  *      directive is malformed.
1592  *
1593  *---------------------------------------------------------------------
1594  */
1595 static void
1596 ParseDoError(errmsg)
1597     char          *errmsg;      /* error message */
1598 {
1599         if (!isspace(*errmsg)) {
1600                 Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
1601                 return;
1602         }
1603         
1604         while (isspace(*errmsg))
1605                 errmsg++;
1606         
1607         errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
1608
1609         /* use fprintf/exit instead of Parse_Error to terminate immediately */
1610         fprintf(stderr, "\"%s\", line %d: %s\n", fname, lineno, errmsg);
1611         exit(1);
1612 }
1613
1614 /*-
1615  *---------------------------------------------------------------------
1616  * ParseDoInclude  --
1617  *      Push to another file.
1618  *
1619  *      The input is the line minus the #include. A file spec is a string
1620  *      enclosed in <> or "". The former is looked for only in sysIncPath.
1621  *      The latter in . and the directories specified by -I command line
1622  *      options
1623  *
1624  * Results:
1625  *      None
1626  *
1627  * Side Effects:
1628  *      A structure is added to the includes Lst and readProc, lineno,
1629  *      fname and curFILE are altered for the new file
1630  *---------------------------------------------------------------------
1631  */
1632 static void
1633 ParseDoInclude (file)
1634     char          *file;        /* file specification */
1635 {
1636     char          *fullname;    /* full pathname of file */
1637     IFile         *oldFile;     /* state associated with current file */
1638     char          endc;         /* the character which ends the file spec */
1639     char          *cp;          /* current position in file spec */
1640     Boolean       isSystem;     /* TRUE if makefile is a system makefile */
1641
1642     /*
1643      * Skip to delimiter character so we know where to look
1644      */
1645     while ((*file == ' ') || (*file == '\t')) {
1646         file++;
1647     }
1648
1649     if ((*file != '"') && (*file != '<')) {
1650         Parse_Error (PARSE_FATAL,
1651             ".include filename must be delimited by '\"' or '<'");
1652         return;
1653     }
1654
1655     /*
1656      * Set the search path on which to find the include file based on the
1657      * characters which bracket its name. Angle-brackets imply it's
1658      * a system Makefile while double-quotes imply it's a user makefile
1659      */
1660     if (*file == '<') {
1661         isSystem = TRUE;
1662         endc = '>';
1663     } else {
1664         isSystem = FALSE;
1665         endc = '"';
1666     }
1667
1668     /*
1669      * Skip to matching delimiter
1670      */
1671     for (cp = ++file; *cp && *cp != endc; cp++) {
1672         continue;
1673     }
1674
1675     if (*cp != endc) {
1676         Parse_Error (PARSE_FATAL,
1677                      "Unclosed %cinclude filename. '%c' expected",
1678                      '.', endc);
1679         return;
1680     }
1681     *cp = '\0';
1682
1683     /*
1684      * Substitute for any variables in the file name before trying to
1685      * find the thing.
1686      */
1687     file = Var_Subst (NULL, file, VAR_CMD, FALSE);
1688
1689     /*
1690      * Now we know the file's name and its search path, we attempt to
1691      * find the durn thing. A return of NULL indicates the file don't
1692      * exist.
1693      */
1694     if (!isSystem) {
1695         /*
1696          * Include files contained in double-quotes are first searched for
1697          * relative to the including file's location. We don't want to
1698          * cd there, of course, so we just tack on the old file's
1699          * leading path components and call Dir_FindFile to see if
1700          * we can locate the beast.
1701          */
1702         char      *prefEnd, *Fname;
1703
1704         /* Make a temporary copy of this, to be safe. */
1705         Fname = estrdup(fname);
1706
1707         prefEnd = strrchr (Fname, '/');
1708         if (prefEnd != (char *)NULL) {
1709             char        *newName;
1710
1711             *prefEnd = '\0';
1712             if (file[0] == '/')
1713                 newName = estrdup(file);
1714             else
1715                 newName = str_concat (Fname, file, STR_ADDSLASH);
1716             fullname = Dir_FindFile (newName, parseIncPath);
1717             if (fullname == (char *)NULL) {
1718                 fullname = Dir_FindFile(newName, dirSearchPath);
1719             }
1720             free (newName);
1721             *prefEnd = '/';
1722         } else {
1723             fullname = (char *)NULL;
1724         }
1725         free (Fname);
1726     } else {
1727         fullname = (char *)NULL;
1728     }
1729
1730     if (fullname == (char *)NULL) {
1731         /*
1732          * System makefile or makefile wasn't found in same directory as
1733          * included makefile. Search for it first on the -I search path,
1734          * then on the .PATH search path, if not found in a -I directory.
1735          * XXX: Suffix specific?
1736          */
1737         fullname = Dir_FindFile (file, parseIncPath);
1738         if (fullname == (char *)NULL) {
1739             fullname = Dir_FindFile(file, dirSearchPath);
1740         }
1741     }
1742
1743     if (fullname == (char *)NULL) {
1744         /*
1745          * Still haven't found the makefile. Look for it on the system
1746          * path as a last resort.
1747          */
1748         fullname = Dir_FindFile(file, sysIncPath);
1749     }
1750
1751     if (fullname == (char *) NULL) {
1752         *cp = endc;
1753         Parse_Error (PARSE_FATAL, "Could not find %s", file);
1754         return;
1755     }
1756
1757     free(file);
1758
1759     /*
1760      * Once we find the absolute path to the file, we get to save all the
1761      * state from the current file before we can start reading this
1762      * include file. The state is stored in an IFile structure which
1763      * is placed on a list with other IFile structures. The list makes
1764      * a very nice stack to track how we got here...
1765      */
1766     oldFile = (IFile *) emalloc (sizeof (IFile));
1767     oldFile->fname = fname;
1768
1769     oldFile->F = curFILE;
1770     oldFile->p = curPTR;
1771     oldFile->lineno = lineno;
1772
1773     (void) Lst_AtFront (includes, (ClientData)oldFile);
1774
1775     /*
1776      * Once the previous state has been saved, we can get down to reading
1777      * the new file. We set up the name of the file to be the absolute
1778      * name of the include file so error messages refer to the right
1779      * place. Naturally enough, we start reading at line number 0.
1780      */
1781     fname = fullname;
1782     lineno = 0;
1783
1784     curFILE = fopen (fullname, "r");
1785     curPTR = NULL;
1786     if (curFILE == (FILE * ) NULL) {
1787         Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1788         /*
1789          * Pop to previous file
1790          */
1791         (void) ParseEOF(0);
1792     }
1793 }
1794
1795
1796
1797 /*-
1798  *---------------------------------------------------------------------
1799  * Parse_FromString  --
1800  *      Start Parsing from the given string
1801  *
1802  * Results:
1803  *      None
1804  *
1805  * Side Effects:
1806  *      A structure is added to the includes Lst and readProc, lineno,
1807  *      fname and curFILE are altered for the new file
1808  *---------------------------------------------------------------------
1809  */
1810 void
1811 Parse_FromString(str)
1812     char *str;
1813 {
1814     IFile         *oldFile;     /* state associated with this file */
1815
1816     if (DEBUG(FOR))
1817         (void) fprintf(stderr, "%s\n----\n", str);
1818
1819     oldFile = (IFile *) emalloc (sizeof (IFile));
1820     oldFile->lineno = lineno;
1821     oldFile->fname = fname;
1822     oldFile->F = curFILE;
1823     oldFile->p = curPTR;
1824
1825     (void) Lst_AtFront (includes, (ClientData)oldFile);
1826
1827     curFILE = NULL;
1828     curPTR = (PTR *) emalloc (sizeof (PTR));
1829     curPTR->str = curPTR->ptr = str;
1830     lineno = 0;
1831     fname = estrdup(fname);
1832 }
1833
1834
1835 #ifdef SYSVINCLUDE
1836 /*-
1837  *---------------------------------------------------------------------
1838  * ParseTraditionalInclude  --
1839  *      Push to another file.
1840  *
1841  *      The input is the line minus the "include".  The file name is
1842  *      the string following the "include".
1843  *
1844  * Results:
1845  *      None
1846  *
1847  * Side Effects:
1848  *      A structure is added to the includes Lst and readProc, lineno,
1849  *      fname and curFILE are altered for the new file
1850  *---------------------------------------------------------------------
1851  */
1852 static void
1853 ParseTraditionalInclude (file)
1854     char          *file;        /* file specification */
1855 {
1856     char          *fullname;    /* full pathname of file */
1857     IFile         *oldFile;     /* state associated with current file */
1858     char          *cp;          /* current position in file spec */
1859     char          *prefEnd;
1860
1861     /*
1862      * Skip over whitespace
1863      */
1864     while ((*file == ' ') || (*file == '\t')) {
1865         file++;
1866     }
1867
1868     if (*file == '\0') {
1869         Parse_Error (PARSE_FATAL,
1870                      "Filename missing from \"include\"");
1871         return;
1872     }
1873
1874     /*
1875      * Skip to end of line or next whitespace
1876      */
1877     for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1878         continue;
1879     }
1880
1881     *cp = '\0';
1882
1883     /*
1884      * Substitute for any variables in the file name before trying to
1885      * find the thing.
1886      */
1887     file = Var_Subst (NULL, file, VAR_CMD, FALSE);
1888
1889     /*
1890      * Now we know the file's name, we attempt to find the durn thing.
1891      * A return of NULL indicates the file don't exist.
1892      *
1893      * Include files are first searched for relative to the including
1894      * file's location. We don't want to cd there, of course, so we
1895      * just tack on the old file's leading path components and call
1896      * Dir_FindFile to see if we can locate the beast.
1897      * XXX - this *does* search in the current directory, right?
1898      */
1899
1900     prefEnd = strrchr (fname, '/');
1901     if (prefEnd != (char *)NULL) {
1902         char    *newName;
1903
1904         *prefEnd = '\0';
1905         newName = str_concat (fname, file, STR_ADDSLASH);
1906         fullname = Dir_FindFile (newName, parseIncPath);
1907         if (fullname == (char *)NULL) {
1908             fullname = Dir_FindFile(newName, dirSearchPath);
1909         }
1910         free (newName);
1911         *prefEnd = '/';
1912     } else {
1913         fullname = (char *)NULL;
1914     }
1915
1916     if (fullname == (char *)NULL) {
1917         /*
1918          * System makefile or makefile wasn't found in same directory as
1919          * included makefile. Search for it first on the -I search path,
1920          * then on the .PATH search path, if not found in a -I directory.
1921          * XXX: Suffix specific?
1922          */
1923         fullname = Dir_FindFile (file, parseIncPath);
1924         if (fullname == (char *)NULL) {
1925             fullname = Dir_FindFile(file, dirSearchPath);
1926         }
1927     }
1928
1929     if (fullname == (char *)NULL) {
1930         /*
1931          * Still haven't found the makefile. Look for it on the system
1932          * path as a last resort.
1933          */
1934         fullname = Dir_FindFile(file, sysIncPath);
1935     }
1936
1937     if (fullname == (char *) NULL) {
1938         Parse_Error (PARSE_FATAL, "Could not find %s", file);
1939         return;
1940     }
1941
1942     /*
1943      * Once we find the absolute path to the file, we get to save all the
1944      * state from the current file before we can start reading this
1945      * include file. The state is stored in an IFile structure which
1946      * is placed on a list with other IFile structures. The list makes
1947      * a very nice stack to track how we got here...
1948      */
1949     oldFile = (IFile *) emalloc (sizeof (IFile));
1950     oldFile->fname = fname;
1951
1952     oldFile->F = curFILE;
1953     oldFile->p = curPTR;
1954     oldFile->lineno = lineno;
1955
1956     (void) Lst_AtFront (includes, (ClientData)oldFile);
1957
1958     /*
1959      * Once the previous state has been saved, we can get down to reading
1960      * the new file. We set up the name of the file to be the absolute
1961      * name of the include file so error messages refer to the right
1962      * place. Naturally enough, we start reading at line number 0.
1963      */
1964     fname = fullname;
1965     lineno = 0;
1966
1967     curFILE = fopen (fullname, "r");
1968     curPTR = NULL;
1969     if (curFILE == (FILE * ) NULL) {
1970         Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1971         /*
1972          * Pop to previous file
1973          */
1974         (void) ParseEOF(1);
1975     }
1976 }
1977 #endif
1978
1979 /*-
1980  *---------------------------------------------------------------------
1981  * ParseEOF  --
1982  *      Called when EOF is reached in the current file. If we were reading
1983  *      an include file, the includes stack is popped and things set up
1984  *      to go back to reading the previous file at the previous location.
1985  *
1986  * Results:
1987  *      CONTINUE if there's more to do. DONE if not.
1988  *
1989  * Side Effects:
1990  *      The old curFILE, is closed. The includes list is shortened.
1991  *      lineno, curFILE, and fname are changed if CONTINUE is returned.
1992  *---------------------------------------------------------------------
1993  */
1994 static int
1995 ParseEOF (opened)
1996     int opened;
1997 {
1998     IFile     *ifile;   /* the state on the top of the includes stack */
1999
2000     if (Lst_IsEmpty (includes)) {
2001         return (DONE);
2002     }
2003
2004     ifile = (IFile *) Lst_DeQueue (includes);
2005     free ((Address) fname);
2006     fname = ifile->fname;
2007     lineno = ifile->lineno;
2008     if (opened && curFILE)
2009         (void) fclose (curFILE);
2010     if (curPTR) {
2011         free((Address) curPTR->str);
2012         free((Address) curPTR);
2013     }
2014     curFILE = ifile->F;
2015     curPTR = ifile->p;
2016     free ((Address)ifile);
2017     return (CONTINUE);
2018 }
2019
2020 /*-
2021  *---------------------------------------------------------------------
2022  * ParseReadc  --
2023  *      Read a character from the current file
2024  *
2025  * Results:
2026  *      The character that was read
2027  *
2028  * Side Effects:
2029  *---------------------------------------------------------------------
2030  */
2031 static int
2032 ParseReadc()
2033 {
2034     if (curFILE)
2035         return fgetc(curFILE);
2036
2037     if (curPTR && *curPTR->ptr)
2038         return *curPTR->ptr++;
2039     return EOF;
2040 }
2041
2042
2043 /*-
2044  *---------------------------------------------------------------------
2045  * ParseUnreadc  --
2046  *      Put back a character to the current file
2047  *
2048  * Results:
2049  *      None.
2050  *
2051  * Side Effects:
2052  *---------------------------------------------------------------------
2053  */
2054 static void
2055 ParseUnreadc(c)
2056     int c;
2057 {
2058     if (curFILE) {
2059         ungetc(c, curFILE);
2060         return;
2061     }
2062     if (curPTR) {
2063         *--(curPTR->ptr) = c;
2064         return;
2065     }
2066 }
2067
2068
2069 /* ParseSkipLine():
2070  *      Grab the next line
2071  */
2072 static char *
2073 ParseSkipLine(skip)
2074     int skip;           /* Skip lines that don't start with . */
2075 {
2076     char *line;
2077     int c, lastc, lineLength = 0;
2078     Buffer buf;
2079
2080     buf = Buf_Init(MAKE_BSIZE);
2081
2082     do {
2083         Buf_Discard(buf, lineLength);
2084         lastc = '\0';
2085
2086         while (((c = ParseReadc()) != '\n' || lastc == '\\')
2087                && c != EOF) {
2088             if (c == '\n') {
2089                 Buf_ReplaceLastByte(buf, (Byte)' ');
2090                 lineno++;
2091
2092                 while ((c = ParseReadc()) == ' ' || c == '\t');
2093
2094                 if (c == EOF)
2095                     break;
2096             }
2097
2098             Buf_AddByte(buf, (Byte)c);
2099             lastc = c;
2100         }
2101
2102         if (c == EOF) {
2103             Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
2104             Buf_Destroy(buf, TRUE);
2105             return((char *)NULL);
2106         }
2107
2108         lineno++;
2109         Buf_AddByte(buf, (Byte)'\0');
2110         line = (char *)Buf_GetAll(buf, &lineLength);
2111     } while (skip == 1 && line[0] != '.');
2112
2113     Buf_Destroy(buf, FALSE);
2114     return line;
2115 }
2116
2117
2118 /*-
2119  *---------------------------------------------------------------------
2120  * ParseReadLine --
2121  *      Read an entire line from the input file. Called only by Parse_File.
2122  *      To facilitate escaped newlines and what have you, a character is
2123  *      buffered in 'lastc', which is '\0' when no characters have been
2124  *      read. When we break out of the loop, c holds the terminating
2125  *      character and lastc holds a character that should be added to
2126  *      the line (unless we don't read anything but a terminator).
2127  *
2128  * Results:
2129  *      A line w/o its newline
2130  *
2131  * Side Effects:
2132  *      Only those associated with reading a character
2133  *---------------------------------------------------------------------
2134  */
2135 static char *
2136 ParseReadLine ()
2137 {
2138     Buffer        buf;          /* Buffer for current line */
2139     register int  c;            /* the current character */
2140     register int  lastc;        /* The most-recent character */
2141     Boolean       semiNL;       /* treat semi-colons as newlines */
2142     Boolean       ignDepOp;     /* TRUE if should ignore dependency operators
2143                                  * for the purposes of setting semiNL */
2144     Boolean       ignComment;   /* TRUE if should ignore comments (in a
2145                                  * shell command */
2146     char          *line;        /* Result */
2147     char          *ep;          /* to strip trailing blanks */
2148     int           lineLength;   /* Length of result */
2149
2150     semiNL = FALSE;
2151     ignDepOp = FALSE;
2152     ignComment = FALSE;
2153
2154     /*
2155      * Handle special-characters at the beginning of the line. Either a
2156      * leading tab (shell command) or pound-sign (possible conditional)
2157      * forces us to ignore comments and dependency operators and treat
2158      * semi-colons as semi-colons (by leaving semiNL FALSE). This also
2159      * discards completely blank lines.
2160      */
2161     for (;;) {
2162         c = ParseReadc();
2163
2164         if (c == '\t') {
2165             ignComment = ignDepOp = TRUE;
2166             break;
2167         } else if (c == '\n') {
2168             lineno++;
2169         } else if (c == '#') {
2170             ParseUnreadc(c);
2171             break;
2172         } else {
2173             /*
2174              * Anything else breaks out without doing anything
2175              */
2176             break;
2177         }
2178     }
2179
2180     if (c != EOF) {
2181         lastc = c;
2182         buf = Buf_Init(MAKE_BSIZE);
2183
2184         while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
2185                (c != EOF))
2186         {
2187 test_char:
2188             switch(c) {
2189             case '\n':
2190                 /*
2191                  * Escaped newline: read characters until a non-space or an
2192                  * unescaped newline and replace them all by a single space.
2193                  * This is done by storing the space over the backslash and
2194                  * dropping through with the next nonspace. If it is a
2195                  * semi-colon and semiNL is TRUE, it will be recognized as a
2196                  * newline in the code below this...
2197                  */
2198                 lineno++;
2199                 lastc = ' ';
2200                 while ((c = ParseReadc ()) == ' ' || c == '\t') {
2201                     continue;
2202                 }
2203                 if (c == EOF || c == '\n') {
2204                     goto line_read;
2205                 } else {
2206                     /*
2207                      * Check for comments, semiNL's, etc. -- easier than
2208                      * ParseUnreadc(c); continue;
2209                      */
2210                     goto test_char;
2211                 }
2212                 /*NOTREACHED*/
2213                 break;
2214
2215             case ';':
2216                 /*
2217                  * Semi-colon: Need to see if it should be interpreted as a
2218                  * newline
2219                  */
2220                 if (semiNL) {
2221                     /*
2222                      * To make sure the command that may be following this
2223                      * semi-colon begins with a tab, we push one back into the
2224                      * input stream. This will overwrite the semi-colon in the
2225                      * buffer. If there is no command following, this does no
2226                      * harm, since the newline remains in the buffer and the
2227                      * whole line is ignored.
2228                      */
2229                     ParseUnreadc('\t');
2230                     goto line_read;
2231                 }
2232                 break;
2233             case '=':
2234                 if (!semiNL) {
2235                     /*
2236                      * Haven't seen a dependency operator before this, so this
2237                      * must be a variable assignment -- don't pay attention to
2238                      * dependency operators after this.
2239                      */
2240                     ignDepOp = TRUE;
2241                 } else if (lastc == ':' || lastc == '!') {
2242                     /*
2243                      * Well, we've seen a dependency operator already, but it
2244                      * was the previous character, so this is really just an
2245                      * expanded variable assignment. Revert semi-colons to
2246                      * being just semi-colons again and ignore any more
2247                      * dependency operators.
2248                      *
2249                      * XXX: Note that a line like "foo : a:=b" will blow up,
2250                      * but who'd write a line like that anyway?
2251                      */
2252                     ignDepOp = TRUE; semiNL = FALSE;
2253                 }
2254                 break;
2255             case '#':
2256                 if (!ignComment) {
2257                     if (
2258 #if 0
2259                     compatMake &&
2260 #endif
2261                     (lastc != '\\')) {
2262                         /*
2263                          * If the character is a hash mark and it isn't escaped
2264                          * (or we're being compatible), the thing is a comment.
2265                          * Skip to the end of the line.
2266                          */
2267                         do {
2268                             c = ParseReadc();
2269                         } while ((c != '\n') && (c != EOF));
2270                         goto line_read;
2271                     } else {
2272                         /*
2273                          * Don't add the backslash. Just let the # get copied
2274                          * over.
2275                          */
2276                         lastc = c;
2277                         continue;
2278                     }
2279                 }
2280                 break;
2281             case ':':
2282             case '!':
2283                 if (!ignDepOp && (c == ':' || c == '!')) {
2284                     /*
2285                      * A semi-colon is recognized as a newline only on
2286                      * dependency lines. Dependency lines are lines with a
2287                      * colon or an exclamation point. Ergo...
2288                      */
2289                     semiNL = TRUE;
2290                 }
2291                 break;
2292             }
2293             /*
2294              * Copy in the previous character and save this one in lastc.
2295              */
2296             Buf_AddByte (buf, (Byte)lastc);
2297             lastc = c;
2298
2299         }
2300     line_read:
2301         lineno++;
2302
2303         if (lastc != '\0') {
2304             Buf_AddByte (buf, (Byte)lastc);
2305         }
2306         Buf_AddByte (buf, (Byte)'\0');
2307         line = (char *)Buf_GetAll (buf, &lineLength);
2308         Buf_Destroy (buf, FALSE);
2309
2310         /*
2311          * Strip trailing blanks and tabs from the line.
2312          * Do not strip a blank or tab that is preceeded by
2313          * a '\'
2314          */
2315         ep = line;
2316         while (*ep)
2317             ++ep;
2318         while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2319             if (ep > line + 1 && ep[-2] == '\\')
2320                 break;
2321             --ep;
2322         }
2323         *ep = 0;
2324
2325         if (line[0] == '.') {
2326             /*
2327              * The line might be a conditional. Ask the conditional module
2328              * about it and act accordingly
2329              */
2330             switch (Cond_Eval (line)) {
2331             case COND_SKIP:
2332                 /*
2333                  * Skip to next conditional that evaluates to COND_PARSE.
2334                  */
2335                 do {
2336                     free (line);
2337                     line = ParseSkipLine(1);
2338                 } while (line && Cond_Eval(line) != COND_PARSE);
2339                 if (line == NULL)
2340                     break;
2341                 /*FALLTHRU*/
2342             case COND_PARSE:
2343                 free ((Address) line);
2344                 line = ParseReadLine();
2345                 break;
2346             case COND_INVALID:
2347                 if (For_Eval(line)) {
2348                     int ok;
2349                     free(line);
2350                     do {
2351                         /*
2352                          * Skip after the matching end
2353                          */
2354                         line = ParseSkipLine(0);
2355                         if (line == NULL) {
2356                             Parse_Error (PARSE_FATAL,
2357                                      "Unexpected end of file in for loop.\n");
2358                             break;
2359                         }
2360                         ok = For_Eval(line);
2361                         free(line);
2362                     }
2363                     while (ok);
2364                     if (line != NULL)
2365                         For_Run();
2366                     line = ParseReadLine();
2367                 }
2368                 break;
2369             }
2370         }
2371         return (line);
2372
2373     } else {
2374         /*
2375          * Hit end-of-file, so return a NULL line to indicate this.
2376          */
2377         return((char *)NULL);
2378     }
2379 }
2380
2381 /*-
2382  *-----------------------------------------------------------------------
2383  * ParseFinishLine --
2384  *      Handle the end of a dependency group.
2385  *
2386  * Results:
2387  *      Nothing.
2388  *
2389  * Side Effects:
2390  *      inLine set FALSE. 'targets' list destroyed.
2391  *
2392  *-----------------------------------------------------------------------
2393  */
2394 static void
2395 ParseFinishLine()
2396 {
2397     if (inLine) {
2398         Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL);
2399         Lst_Destroy (targets, ParseHasCommands);
2400         targets = NULL;
2401         inLine = FALSE;
2402     }
2403 }
2404
2405
2406 /*-
2407  *---------------------------------------------------------------------
2408  * Parse_File --
2409  *      Parse a file into its component parts, incorporating it into the
2410  *      current dependency graph. This is the main function and controls
2411  *      almost every other function in this module
2412  *
2413  * Results:
2414  *      None
2415  *
2416  * Side Effects:
2417  *      Loads. Nodes are added to the list of all targets, nodes and links
2418  *      are added to the dependency graph. etc. etc. etc.
2419  *---------------------------------------------------------------------
2420  */
2421 void
2422 Parse_File(name, stream)
2423     char          *name;        /* the name of the file being read */
2424     FILE *        stream;       /* Stream open to makefile to parse */
2425 {
2426     register char *cp,          /* pointer into the line */
2427                   *line;        /* the line we're working on */
2428
2429     inLine = FALSE;
2430     fname = name;
2431     curFILE = stream;
2432     lineno = 0;
2433     fatals = 0;
2434
2435     do {
2436         while ((line = ParseReadLine ()) != NULL) {
2437             if (*line == '.') {
2438                 /*
2439                  * Lines that begin with the special character are either
2440                  * include or undef directives.
2441                  */
2442                 for (cp = line + 1; isspace (*cp); cp++) {
2443                     continue;
2444                 }
2445                 if (strncmp (cp, "include", 7) == 0) {
2446                     ParseDoInclude (cp + 7);
2447                     goto nextLine;
2448                 } else if (strncmp (cp, "error", 5) == 0) {
2449                     ParseDoError(cp + 5);
2450                     goto nextLine;          
2451                 } else if (strncmp(cp, "undef", 5) == 0) {
2452                     char *cp2;
2453                     for (cp += 5; isspace((unsigned char) *cp); cp++) {
2454                         continue;
2455                     }
2456
2457                     for (cp2 = cp; !isspace((unsigned char) *cp2) &&
2458                                    (*cp2 != '\0'); cp2++) {
2459                         continue;
2460                     }
2461
2462                     *cp2 = '\0';
2463
2464                     Var_Delete(cp, VAR_GLOBAL);
2465                     goto nextLine;
2466                 }
2467             }
2468             if (*line == '#') {
2469                 /* If we're this far, the line must be a comment. */
2470                 goto nextLine;
2471             }
2472
2473             if (*line == '\t') {
2474                 /*
2475                  * If a line starts with a tab, it can only hope to be
2476                  * a creation command.
2477                  */
2478 #ifndef POSIX
2479             shellCommand:
2480 #endif
2481                 for (cp = line + 1; isspace (*cp); cp++) {
2482                     continue;
2483                 }
2484                 if (*cp) {
2485                     if (inLine) {
2486                         /*
2487                          * So long as it's not a blank line and we're actually
2488                          * in a dependency spec, add the command to the list of
2489                          * commands of all targets in the dependency spec
2490                          */
2491                         Lst_ForEach (targets, ParseAddCmd, cp);
2492                         Lst_AtEnd(targCmds, (ClientData) line);
2493                         continue;
2494                     } else {
2495                         Parse_Error (PARSE_FATAL,
2496                                      "Unassociated shell command \"%s\"",
2497                                      cp);
2498                     }
2499                 }
2500 #ifdef SYSVINCLUDE
2501             } else if (strncmp (line, "include", 7) == 0 &&
2502                        isspace((unsigned char) line[7]) &&
2503                        strchr(line, ':') == NULL) {
2504                 /*
2505                  * It's an S3/S5-style "include".
2506                  */
2507                 ParseTraditionalInclude (line + 7);
2508                 goto nextLine;
2509 #endif
2510             } else if (Parse_IsVar (line)) {
2511                 ParseFinishLine();
2512                 Parse_DoVar (line, VAR_GLOBAL);
2513             } else {
2514                 /*
2515                  * We now know it's a dependency line so it needs to have all
2516                  * variables expanded before being parsed. Tell the variable
2517                  * module to complain if some variable is undefined...
2518                  * To make life easier on novices, if the line is indented we
2519                  * first make sure the line has a dependency operator in it.
2520                  * If it doesn't have an operator and we're in a dependency
2521                  * line's script, we assume it's actually a shell command
2522                  * and add it to the current list of targets.
2523                  */
2524 #ifndef POSIX
2525                 Boolean nonSpace = FALSE;
2526 #endif
2527
2528                 cp = line;
2529                 if (isspace((unsigned char) line[0])) {
2530                     while ((*cp != '\0') && isspace((unsigned char) *cp)) {
2531                         cp++;
2532                     }
2533                     if (*cp == '\0') {
2534                         goto nextLine;
2535                     }
2536 #ifndef POSIX
2537                     while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
2538                         nonSpace = TRUE;
2539                         cp++;
2540                     }
2541 #endif
2542                 }
2543
2544 #ifndef POSIX
2545                 if (*cp == '\0') {
2546                     if (inLine) {
2547                         Parse_Error (PARSE_WARNING,
2548                                      "Shell command needs a leading tab");
2549                         goto shellCommand;
2550                     } else if (nonSpace) {
2551                         Parse_Error (PARSE_FATAL, "Missing operator");
2552                     }
2553                 } else {
2554 #endif
2555                     ParseFinishLine();
2556
2557                     cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
2558                     free (line);
2559                     line = cp;
2560
2561                     /*
2562                      * Need a non-circular list for the target nodes
2563                      */
2564                     if (targets)
2565                         Lst_Destroy(targets, NOFREE);
2566
2567                     targets = Lst_Init (FALSE);
2568                     inLine = TRUE;
2569
2570                     ParseDoDependency (line);
2571 #ifndef POSIX
2572                 }
2573 #endif
2574             }
2575
2576             nextLine:
2577
2578             free (line);
2579         }
2580         /*
2581          * Reached EOF, but it may be just EOF of an include file...
2582          */
2583     } while (ParseEOF(1) == CONTINUE);
2584
2585     /*
2586      * Make sure conditionals are clean
2587      */
2588     Cond_End();
2589
2590     if (fatals)
2591         errx(1, "fatal errors encountered -- cannot continue");
2592 }
2593
2594 /*-
2595  *---------------------------------------------------------------------
2596  * Parse_Init --
2597  *      initialize the parsing module
2598  *
2599  * Results:
2600  *      none
2601  *
2602  * Side Effects:
2603  *      the parseIncPath list is initialized...
2604  *---------------------------------------------------------------------
2605  */
2606 void
2607 Parse_Init ()
2608 {
2609     mainNode = NILGNODE;
2610     parseIncPath = Lst_Init (FALSE);
2611     sysIncPath = Lst_Init (FALSE);
2612     includes = Lst_Init (FALSE);
2613     targCmds = Lst_Init (FALSE);
2614 }
2615
2616 void
2617 Parse_End()
2618 {
2619     Lst_Destroy(targCmds, (void (*) __P((ClientData))) free);
2620     if (targets)
2621         Lst_Destroy(targets, NOFREE);
2622     Lst_Destroy(sysIncPath, Dir_Destroy);
2623     Lst_Destroy(parseIncPath, Dir_Destroy);
2624     Lst_Destroy(includes, NOFREE);      /* Should be empty now */
2625 }
2626
2627
2628 /*-
2629  *-----------------------------------------------------------------------
2630  * Parse_MainName --
2631  *      Return a Lst of the main target to create for main()'s sake. If
2632  *      no such target exists, we Punt with an obnoxious error message.
2633  *
2634  * Results:
2635  *      A Lst of the single node to create.
2636  *
2637  * Side Effects:
2638  *      None.
2639  *
2640  *-----------------------------------------------------------------------
2641  */
2642 Lst
2643 Parse_MainName()
2644 {
2645     Lst           listmain;     /* result list */
2646
2647     listmain = Lst_Init (FALSE);
2648
2649     if (mainNode == NILGNODE) {
2650         Punt ("no target to make.");
2651         /*NOTREACHED*/
2652     } else if (mainNode->type & OP_DOUBLEDEP) {
2653         (void) Lst_AtEnd (listmain, (ClientData)mainNode);
2654         Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW);
2655     }
2656     else
2657         (void) Lst_AtEnd (listmain, (ClientData)mainNode);
2658     return (listmain);
2659 }