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