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