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