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