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