Annotation of src/usr.bin/make/parse.c, Revision 1.295
1.295 ! rillig 1: /* $NetBSD: parse.c,v 1.294 2020/09/12 18:19:50 rillig 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.295 ! rillig 72: static char rcsid[] = "$NetBSD: parse.c,v 1.294 2020/09/12 18:19:50 rillig 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.295 ! rillig 79: __RCSID("$NetBSD: parse.c,v 1.294 2020/09/12 18:19:50 rillig 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.170 dholland 126: #include <sys/types.h>
127: #include <sys/mman.h>
1.171 dholland 128: #include <sys/stat.h>
1.84 wiz 129: #include <errno.h>
1.5 cgd 130: #include <stdarg.h>
131: #include <stdio.h>
1.225 maya 132: #include <stdint.h>
1.84 wiz 133:
1.177 nakayama 134: #ifndef MAP_FILE
135: #define MAP_FILE 0
136: #endif
1.170 dholland 137: #ifndef MAP_COPY
138: #define MAP_COPY MAP_PRIVATE
139: #endif
140:
1.1 cgd 141: #include "make.h"
1.5 cgd 142: #include "dir.h"
143: #include "job.h"
1.1 cgd 144: #include "pathnames.h"
145:
1.248 rillig 146: /* types and constants */
1.166 dholland 147:
1.1 cgd 148: /*
1.166 dholland 149: * Structure for a file being read ("included file")
1.1 cgd 150: */
151: typedef struct IFile {
1.189 sjg 152: char *fname; /* name of file */
1.281 rillig 153: Boolean fromForLoop; /* simulated .include by the .for loop */
1.155 dsl 154: int lineno; /* current line number in file */
155: int first_lineno; /* line number of start of text */
156: int cond_depth; /* 'if' nesting when file opened */
1.210 sjg 157: Boolean depending; /* state of doing_depend on EOF */
1.123 dsl 158: char *P_str; /* point to base of string buffer */
159: char *P_ptr; /* point to next char of string buffer */
1.125 dsl 160: char *P_end; /* point to the end of string buffer */
1.170 dholland 161: char *(*nextbuf)(void *, size_t *); /* Function to get more data */
1.155 dsl 162: void *nextbuf_arg; /* Opaque arg for nextbuf() */
1.170 dholland 163: struct loadedfile *lf; /* loadedfile object, if any */
1.5 cgd 164: } IFile;
1.1 cgd 165:
1.82 reinoud 166:
167: /*
1.166 dholland 168: * These values are returned by ParseEOF to tell Parse_File whether to
169: * CONTINUE parsing, i.e. it had only reached the end of an include file,
170: * or if it's DONE.
1.82 reinoud 171: */
1.166 dholland 172: #define CONTINUE 1
173: #define DONE 0
1.82 reinoud 174:
1.166 dholland 175: /*
176: * Tokens for target attributes
1.1 cgd 177: */
178: typedef enum {
179: Begin, /* .BEGIN */
180: Default, /* .DEFAULT */
1.215 dholland 181: DeleteOnError, /* .DELETE_ON_ERROR */
1.1 cgd 182: End, /* .END */
1.162 sjg 183: dotError, /* .ERROR */
1.1 cgd 184: Ignore, /* .IGNORE */
185: Includes, /* .INCLUDES */
186: Interrupt, /* .INTERRUPT */
187: Libs, /* .LIBS */
1.165 sjg 188: Meta, /* .META */
1.1 cgd 189: MFlags, /* .MFLAGS or .MAKEFLAGS */
190: Main, /* .MAIN and we don't have anything user-specified to
191: * make */
1.5 cgd 192: NoExport, /* .NOEXPORT */
1.165 sjg 193: NoMeta, /* .NOMETA */
194: NoMetaCmp, /* .NOMETA_CMP */
1.32 gwr 195: NoPath, /* .NOPATH */
1.1 cgd 196: Not, /* Not special */
1.75 tv 197: NotParallel, /* .NOTPARALLEL */
1.1 cgd 198: Null, /* .NULL */
1.75 tv 199: ExObjdir, /* .OBJDIR */
1.1 cgd 200: Order, /* .ORDER */
1.18 christos 201: Parallel, /* .PARALLEL */
1.5 cgd 202: ExPath, /* .PATH */
1.22 christos 203: Phony, /* .PHONY */
1.48 sjg 204: #ifdef POSIX
205: Posix, /* .POSIX */
206: #endif
1.1 cgd 207: Precious, /* .PRECIOUS */
1.5 cgd 208: ExShell, /* .SHELL */
1.1 cgd 209: Silent, /* .SILENT */
210: SingleShell, /* .SINGLESHELL */
1.187 christos 211: Stale, /* .STALE */
1.1 cgd 212: Suffixes, /* .SUFFIXES */
1.18 christos 213: Wait, /* .WAIT */
1.5 cgd 214: Attribute /* Generic attribute */
1.1 cgd 215: } ParseSpecial;
216:
1.166 dholland 217: /*
218: * Other tokens
219: */
220: #define LPAREN '('
221: #define RPAREN ')'
222:
223:
1.248 rillig 224: /* result data */
1.166 dholland 225:
226: /*
227: * The main target to create. This is the first target on the first
228: * dependency line in the first makefile.
229: */
230: static GNode *mainNode;
231:
1.248 rillig 232: /* eval state */
1.166 dholland 233:
234: /* targets we're working on */
235: static Lst targets;
236:
237: #ifdef CLEANUP
238: /* command lines for targets */
239: static Lst targCmds;
240: #endif
241:
242: /*
243: * specType contains the SPECial TYPE of the current target. It is
244: * Not if the target is unspecial. If it *is* special, however, the children
245: * are linked as children of the parent but not vice versa. This variable is
246: * set in ParseDoDependency
247: */
1.5 cgd 248: static ParseSpecial specType;
1.1 cgd 249:
250: /*
1.152 dsl 251: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 cgd 252: * seen, then set to each successive source on the line.
253: */
254: static GNode *predecessor;
255:
1.248 rillig 256: /* parser state */
1.166 dholland 257:
258: /* true if currently in a dependency line or its commands */
259: static Boolean inLine;
260:
261: /* number of fatal errors */
262: static int fatals = 0;
263:
264: /*
265: * Variables for doing includes
266: */
267:
268: /* current file being read */
269: static IFile *curFile;
270:
1.276 rillig 271: /* The current file from the command line (at the bottom of the stack) and
272: * further up all the files that are currently being read due to nested
1.281 rillig 273: * .include or .for directives. */
1.276 rillig 274: static Stack /* of *IFile */ includes;
1.166 dholland 275:
276: /* include paths (lists of directories) */
277: Lst parseIncPath; /* dirs for "..." includes */
278: Lst sysIncPath; /* dirs for <...> includes */
279: Lst defIncPath; /* default for sysIncPath */
280:
1.248 rillig 281: /* parser tables */
1.166 dholland 282:
1.1 cgd 283: /*
284: * The parseKeywords table is searched using binary search when deciding
285: * if a target or source is special. The 'spec' field is the ParseSpecial
286: * type of the keyword ("Not" if the keyword isn't special as a target) while
287: * the 'op' field is the operator to apply to the list of targets if the
288: * keyword is used as a source ("0" if the keyword isn't special as a source)
289: */
1.168 dholland 290: static const struct {
1.93 christos 291: const char *name; /* Name of keyword */
1.1 cgd 292: ParseSpecial spec; /* Type when used as a target */
293: int op; /* Operator when used as a source */
294: } parseKeywords[] = {
295: { ".BEGIN", Begin, 0 },
296: { ".DEFAULT", Default, 0 },
1.215 dholland 297: { ".DELETE_ON_ERROR", DeleteOnError, 0 },
1.1 cgd 298: { ".END", End, 0 },
1.162 sjg 299: { ".ERROR", dotError, 0 },
1.1 cgd 300: { ".EXEC", Attribute, OP_EXEC },
301: { ".IGNORE", Ignore, OP_IGNORE },
302: { ".INCLUDES", Includes, 0 },
303: { ".INTERRUPT", Interrupt, 0 },
304: { ".INVISIBLE", Attribute, OP_INVISIBLE },
305: { ".JOIN", Attribute, OP_JOIN },
306: { ".LIBS", Libs, 0 },
1.29 christos 307: { ".MADE", Attribute, OP_MADE },
1.1 cgd 308: { ".MAIN", Main, 0 },
309: { ".MAKE", Attribute, OP_MAKE },
310: { ".MAKEFLAGS", MFlags, 0 },
1.165 sjg 311: { ".META", Meta, OP_META },
1.1 cgd 312: { ".MFLAGS", MFlags, 0 },
1.165 sjg 313: { ".NOMETA", NoMeta, OP_NOMETA },
314: { ".NOMETA_CMP", NoMetaCmp, OP_NOMETA_CMP },
1.32 gwr 315: { ".NOPATH", NoPath, OP_NOPATH },
1.1 cgd 316: { ".NOTMAIN", Attribute, OP_NOTMAIN },
317: { ".NOTPARALLEL", NotParallel, 0 },
1.18 christos 318: { ".NO_PARALLEL", NotParallel, 0 },
1.1 cgd 319: { ".NULL", Null, 0 },
1.75 tv 320: { ".OBJDIR", ExObjdir, 0 },
1.14 ws 321: { ".OPTIONAL", Attribute, OP_OPTIONAL },
1.1 cgd 322: { ".ORDER", Order, 0 },
1.18 christos 323: { ".PARALLEL", Parallel, 0 },
1.5 cgd 324: { ".PATH", ExPath, 0 },
1.22 christos 325: { ".PHONY", Phony, OP_PHONY },
1.48 sjg 326: #ifdef POSIX
327: { ".POSIX", Posix, 0 },
328: #endif
1.1 cgd 329: { ".PRECIOUS", Precious, OP_PRECIOUS },
330: { ".RECURSIVE", Attribute, OP_MAKE },
1.5 cgd 331: { ".SHELL", ExShell, 0 },
1.1 cgd 332: { ".SILENT", Silent, OP_SILENT },
333: { ".SINGLESHELL", SingleShell, 0 },
1.187 christos 334: { ".STALE", Stale, 0 },
1.1 cgd 335: { ".SUFFIXES", Suffixes, 0 },
336: { ".USE", Attribute, OP_USE },
1.71 christos 337: { ".USEBEFORE", Attribute, OP_USEBEFORE },
1.18 christos 338: { ".WAIT", Wait, 0 },
1.1 cgd 339: };
340:
1.248 rillig 341: /* file loader */
1.170 dholland 342:
343: struct loadedfile {
344: const char *path; /* name, for error reports */
345: char *buf; /* contents buffer */
346: size_t len; /* length of contents */
347: size_t maplen; /* length of mmap area, or 0 */
348: Boolean used; /* XXX: have we used the data yet */
349: };
350:
351: static struct loadedfile *
352: loadedfile_create(const char *path)
353: {
354: struct loadedfile *lf;
355:
356: lf = bmake_malloc(sizeof(*lf));
1.242 rillig 357: lf->path = path == NULL ? "(stdin)" : path;
1.170 dholland 358: lf->buf = NULL;
359: lf->len = 0;
360: lf->maplen = 0;
361: lf->used = FALSE;
362: return lf;
363: }
364:
365: static void
366: loadedfile_destroy(struct loadedfile *lf)
367: {
368: if (lf->buf != NULL) {
369: if (lf->maplen > 0) {
370: munmap(lf->buf, lf->maplen);
371: } else {
372: free(lf->buf);
373: }
374: }
375: free(lf);
376: }
377:
378: /*
379: * nextbuf() operation for loadedfile, as needed by the weird and twisted
380: * logic below. Once that's cleaned up, we can get rid of lf->used...
381: */
382: static char *
383: loadedfile_nextbuf(void *x, size_t *len)
384: {
385: struct loadedfile *lf = x;
386:
387: if (lf->used) {
388: return NULL;
389: }
390: lf->used = TRUE;
391: *len = lf->len;
392: return lf->buf;
393: }
394:
395: /*
396: * Try to get the size of a file.
397: */
1.272 rillig 398: static Boolean
1.170 dholland 399: load_getsize(int fd, size_t *ret)
400: {
401: struct stat st;
402:
403: if (fstat(fd, &st) < 0) {
1.272 rillig 404: return FALSE;
1.170 dholland 405: }
406:
407: if (!S_ISREG(st.st_mode)) {
1.272 rillig 408: return FALSE;
1.170 dholland 409: }
410:
411: /*
412: * st_size is an off_t, which is 64 bits signed; *ret is
413: * size_t, which might be 32 bits unsigned or 64 bits
414: * unsigned. Rather than being elaborate, just punt on
415: * files that are more than 2^31 bytes. We should never
416: * see a makefile that size in practice...
417: *
418: * While we're at it reject negative sizes too, just in case.
419: */
420: if (st.st_size < 0 || st.st_size > 0x7fffffff) {
1.272 rillig 421: return FALSE;
1.170 dholland 422: }
423:
424: *ret = (size_t) st.st_size;
1.272 rillig 425: return TRUE;
1.170 dholland 426: }
427:
428: /*
429: * Read in a file.
430: *
431: * Until the path search logic can be moved under here instead of
432: * being in the caller in another source file, we need to have the fd
433: * passed in already open. Bleh.
434: *
435: * If the path is NULL use stdin and (to insure against fd leaks)
436: * assert that the caller passed in -1.
437: */
438: static struct loadedfile *
439: loadfile(const char *path, int fd)
440: {
441: struct loadedfile *lf;
1.227 sjg 442: static long pagesize = 0;
1.170 dholland 443: ssize_t result;
444: size_t bufpos;
445:
446: lf = loadedfile_create(path);
447:
448: if (path == NULL) {
449: assert(fd == -1);
450: fd = STDIN_FILENO;
451: } else {
452: #if 0 /* notyet */
453: fd = open(path, O_RDONLY);
454: if (fd < 0) {
455: ...
456: Error("%s: %s", path, strerror(errno));
457: exit(1);
458: }
459: #endif
460: }
461:
1.272 rillig 462: if (load_getsize(fd, &lf->len)) {
1.170 dholland 463: /* found a size, try mmap */
1.227 sjg 464: if (pagesize == 0)
465: pagesize = sysconf(_SC_PAGESIZE);
1.170 dholland 466: if (pagesize <= 0) {
467: pagesize = 0x1000;
468: }
469: /* round size up to a page */
470: lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize);
471:
472: /*
473: * XXX hack for dealing with empty files; remove when
474: * we're no longer limited by interfacing to the old
475: * logic elsewhere in this file.
476: */
477: if (lf->maplen == 0) {
478: lf->maplen = pagesize;
479: }
480:
481: /*
482: * FUTURE: remove PROT_WRITE when the parser no longer
483: * needs to scribble on the input.
484: */
485: lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
486: MAP_FILE|MAP_COPY, fd, 0);
487: if (lf->buf != MAP_FAILED) {
488: /* succeeded */
1.178 dsl 489: if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
1.220 maya 490: char *b = bmake_malloc(lf->len + 1);
1.178 dsl 491: b[lf->len] = '\n';
492: memcpy(b, lf->buf, lf->len++);
493: munmap(lf->buf, lf->maplen);
494: lf->maplen = 0;
495: lf->buf = b;
496: }
1.170 dholland 497: goto done;
498: }
499: }
500:
501: /* cannot mmap; load the traditional way */
502:
503: lf->maplen = 0;
504: lf->len = 1024;
505: lf->buf = bmake_malloc(lf->len);
506:
507: bufpos = 0;
508: while (1) {
509: assert(bufpos <= lf->len);
510: if (bufpos == lf->len) {
1.221 riastrad 511: if (lf->len > SIZE_MAX/2) {
512: errno = EFBIG;
513: Error("%s: file too large", path);
514: exit(1);
515: }
1.170 dholland 516: lf->len *= 2;
517: lf->buf = bmake_realloc(lf->buf, lf->len);
518: }
1.221 riastrad 519: assert(bufpos < lf->len);
1.170 dholland 520: result = read(fd, lf->buf + bufpos, lf->len - bufpos);
521: if (result < 0) {
522: Error("%s: read error: %s", path, strerror(errno));
523: exit(1);
524: }
525: if (result == 0) {
526: break;
527: }
528: bufpos += result;
529: }
530: assert(bufpos <= lf->len);
1.173 dholland 531: lf->len = bufpos;
1.170 dholland 532:
533: /* truncate malloc region to actual length (maybe not useful) */
1.172 dholland 534: if (lf->len > 0) {
1.218 sjg 535: /* as for mmap case, ensure trailing \n */
536: if (lf->buf[lf->len - 1] != '\n')
537: lf->len++;
1.172 dholland 538: lf->buf = bmake_realloc(lf->buf, lf->len);
1.218 sjg 539: lf->buf[lf->len - 1] = '\n';
1.172 dholland 540: }
1.170 dholland 541:
542: done:
543: if (path != NULL) {
544: close(fd);
545: }
546: return lf;
547: }
548:
1.248 rillig 549: /* old code */
1.77 christos 550:
1.279 rillig 551: /* Check if the current character is escaped on the current line. */
552: static Boolean
1.84 wiz 553: ParseIsEscaped(const char *line, const char *c)
1.77 christos 554: {
1.280 rillig 555: Boolean active = FALSE;
1.77 christos 556: for (;;) {
557: if (line == c)
558: return active;
559: if (*--c != '\\')
560: return active;
561: active = !active;
562: }
563: }
564:
1.278 rillig 565: /* Add the filename and lineno to the GNode so that we remember where it
566: * was first defined. */
567: static void
568: ParseMark(GNode *gn)
569: {
570: gn->fname = curFile->fname;
571: gn->lineno = curFile->lineno;
572: }
573:
1.1 cgd 574: /*-
575: *----------------------------------------------------------------------
576: * ParseFindKeyword --
577: * Look in the table of keywords for one matching the given string.
578: *
1.84 wiz 579: * Input:
580: * str String to find
581: *
1.1 cgd 582: * Results:
583: * The index of the keyword, or -1 if it isn't there.
584: *
585: * Side Effects:
586: * None
587: *----------------------------------------------------------------------
588: */
589: static int
1.120 dsl 590: ParseFindKeyword(const char *str)
1.1 cgd 591: {
1.84 wiz 592: int start, end, cur;
593: int diff;
1.27 christos 594:
1.1 cgd 595: start = 0;
596: end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
597:
598: do {
599: cur = start + ((end - start) / 2);
1.103 christos 600: diff = strcmp(str, parseKeywords[cur].name);
1.1 cgd 601:
602: if (diff == 0) {
1.235 rillig 603: return cur;
1.1 cgd 604: } else if (diff < 0) {
605: end = cur - 1;
606: } else {
607: start = cur + 1;
608: }
609: } while (start <= end);
1.235 rillig 610: return -1;
1.1 cgd 611: }
612:
1.291 rillig 613: static void
614: PrintLocation(FILE *f, const char *cfname, size_t clineno)
615: {
616: char dirbuf[MAXPATHLEN+1];
617:
618: (void)fprintf(f, "\"");
619: if (*cfname != '/' && strcmp(cfname, "(stdin)") != 0) {
620: char *cp, *cp2;
621: const char *dir, *fname;
622:
623: /*
624: * Nothing is more annoying than not knowing
625: * which Makefile is the culprit; we try ${.PARSEDIR}
626: * and apply realpath(3) if not absolute.
627: */
628: dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp);
629: if (dir == NULL)
630: dir = ".";
631: if (*dir != '/') {
632: dir = realpath(dir, dirbuf);
633: }
634: fname = Var_Value(".PARSEFILE", VAR_GLOBAL, &cp2);
635: if (fname == NULL) {
636: if ((fname = strrchr(cfname, '/')))
637: fname++;
638: else
639: fname = cfname;
640: }
641: (void)fprintf(f, "%s/%s", dir, fname);
642: bmake_free(cp2);
643: bmake_free(cp);
644: } else
645: (void)fprintf(f, "%s", cfname);
646:
647: (void)fprintf(f, "\" line %d: ", (int)clineno);
648: }
649:
1.1 cgd 650: /*-
1.38 christos 651: * ParseVErrorInternal --
1.1 cgd 652: * Error message abort function for parsing. Prints out the context
653: * of the error (line number and file) as well as the message with
654: * two optional arguments.
655: *
656: * Results:
657: * None
658: *
659: * Side Effects:
660: * "fatals" is incremented if the level is PARSE_FATAL.
661: */
662: /* VARARGS */
1.38 christos 663: static void
1.127 dsl 664: ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type,
1.122 dsl 665: const char *fmt, va_list ap)
1.38 christos 666: {
1.56 christos 667: static Boolean fatal_warning_error_printed = FALSE;
668:
1.148 sjg 669: (void)fprintf(f, "%s: ", progname);
1.63 christos 670:
1.291 rillig 671: if (cfname != NULL)
672: PrintLocation(f, cfname, clineno);
1.38 christos 673: if (type == PARSE_WARNING)
1.127 dsl 674: (void)fprintf(f, "warning: ");
675: (void)vfprintf(f, fmt, ap);
676: (void)fprintf(f, "\n");
677: (void)fflush(f);
1.226 sjg 678: if (type == PARSE_INFO)
679: return;
1.56 christos 680: if (type == PARSE_FATAL || parseWarnFatal)
1.38 christos 681: fatals += 1;
1.56 christos 682: if (parseWarnFatal && !fatal_warning_error_printed) {
683: Error("parsing warnings being treated as errors");
684: fatal_warning_error_printed = TRUE;
685: }
1.38 christos 686: }
687:
688: /*-
1.203 joerg 689: * ParseErrorInternal --
690: * Error function
691: *
692: * Results:
693: * None
694: *
695: * Side Effects:
696: * None
697: */
698: /* VARARGS */
699: static void
700: ParseErrorInternal(const char *cfname, size_t clineno, int type,
701: const char *fmt, ...)
702: {
703: va_list ap;
704:
705: va_start(ap, fmt);
706: (void)fflush(stdout);
707: ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap);
708: va_end(ap);
709:
710: if (debug_file != stderr && debug_file != stdout) {
711: va_start(ap, fmt);
712: ParseVErrorInternal(debug_file, cfname, clineno, type, fmt, ap);
713: va_end(ap);
714: }
715: }
716:
1.289 rillig 717: /* External interface to ParseErrorInternal; uses the default filename and
718: * line number.
1.38 christos 719: *
1.289 rillig 720: * Fmt is given without a trailing newline. */
1.38 christos 721: /* VARARGS */
1.1 cgd 722: void
1.93 christos 723: Parse_Error(int type, const char *fmt, ...)
1.1 cgd 724: {
725: va_list ap;
1.156 dsl 726: const char *fname;
727: size_t lineno;
1.84 wiz 728:
1.152 dsl 729: if (curFile == NULL) {
1.156 dsl 730: fname = NULL;
731: lineno = 0;
732: } else {
733: fname = curFile->fname;
734: lineno = curFile->lineno;
1.148 sjg 735: }
1.156 dsl 736:
737: va_start(ap, fmt);
1.163 sjg 738: (void)fflush(stdout);
1.156 dsl 739: ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
1.1 cgd 740: va_end(ap);
1.127 dsl 741:
1.131 dsl 742: if (debug_file != stderr && debug_file != stdout) {
1.127 dsl 743: va_start(ap, fmt);
1.156 dsl 744: ParseVErrorInternal(debug_file, fname, lineno, type, fmt, ap);
1.127 dsl 745: va_end(ap);
746: }
1.1 cgd 747: }
748:
1.161 sjg 749:
750: /*
751: * ParseMessage
752: * Parse a .info .warning or .error directive
753: *
754: * The input is the line minus the ".". We substitute
755: * variables, print the message and exit(1) (for .error) or just print
756: * a warning if the directive is malformed.
757: */
1.164 sjg 758: static Boolean
1.161 sjg 759: ParseMessage(char *line)
760: {
761: int mtype;
1.164 sjg 762:
1.161 sjg 763: switch(*line) {
764: case 'i':
1.226 sjg 765: mtype = PARSE_INFO;
1.161 sjg 766: break;
767: case 'w':
768: mtype = PARSE_WARNING;
769: break;
770: case 'e':
771: mtype = PARSE_FATAL;
772: break;
773: default:
774: Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line);
1.164 sjg 775: return FALSE;
1.161 sjg 776: }
777:
1.290 rillig 778: while (ch_isalpha(*line))
1.161 sjg 779: line++;
1.290 rillig 780: if (!ch_isspace(*line))
1.164 sjg 781: return FALSE; /* not for us */
1.290 rillig 782: while (ch_isspace(*line))
1.161 sjg 783: line++;
784:
1.239 rillig 785: line = Var_Subst(line, VAR_CMD, VARE_WANTRES);
1.161 sjg 786: Parse_Error(mtype, "%s", line);
787: free(line);
788:
789: if (mtype == PARSE_FATAL) {
790: /* Terminate immediately. */
791: exit(1);
792: }
1.164 sjg 793: return TRUE;
1.161 sjg 794: }
795:
1.1 cgd 796: /*-
797: *---------------------------------------------------------------------
798: * ParseLinkSrc --
799: * Link the parent node to its new child. Used in a Lst_ForEach by
800: * ParseDoDependency. If the specType isn't 'Not', the parent
801: * isn't linked as a parent of the child.
802: *
1.84 wiz 803: * Input:
804: * pgnp The parent node
805: * cgpn The child node
806: *
1.1 cgd 807: * Results:
808: * Always = 0
809: *
810: * Side Effects:
811: * New elements are added to the parents list of cgn and the
812: * children list of cgn. the unmade field of pgn is updated
813: * to reflect the additional child.
814: *---------------------------------------------------------------------
815: */
816: static int
1.157 dsl 817: ParseLinkSrc(void *pgnp, void *cgnp)
1.1 cgd 818: {
1.105 christos 819: GNode *pgn = (GNode *)pgnp;
820: GNode *cgn = (GNode *)cgnp;
1.52 mycroft 821:
1.268 rillig 822: if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(pgn->cohorts))
1.274 rillig 823: pgn = LstNode_Datum(Lst_Last(pgn->cohorts));
1.268 rillig 824: Lst_Append(pgn->children, cgn);
1.52 mycroft 825: if (specType == Not)
1.268 rillig 826: Lst_Append(cgn->parents, pgn);
1.52 mycroft 827: pgn->unmade += 1;
1.109 dsl 828: if (DEBUG(PARSE)) {
1.193 christos 829: fprintf(debug_file, "# %s: added child %s - %s\n", __func__,
830: pgn->name, cgn->name);
1.109 dsl 831: Targ_PrintNode(pgn, 0);
832: Targ_PrintNode(cgn, 0);
833: }
1.235 rillig 834: return 0;
1.1 cgd 835: }
836:
837: /*-
838: *---------------------------------------------------------------------
839: * ParseDoOp --
840: * Apply the parsed operator to the given target node. Used in a
841: * Lst_ForEach call by ParseDoDependency once all targets have
842: * been found and their operator parsed. If the previous and new
843: * operators are incompatible, a major error is taken.
844: *
1.84 wiz 845: * Input:
846: * gnp The node to which the operator is to be applied
847: * opp The operator to apply
848: *
1.1 cgd 849: * Results:
850: * Always 0
851: *
852: * Side Effects:
853: * The type field of the node is altered to reflect any new bits in
854: * the op.
855: *---------------------------------------------------------------------
856: */
857: static int
1.157 dsl 858: ParseDoOp(void *gnp, void *opp)
1.1 cgd 859: {
1.105 christos 860: GNode *gn = (GNode *)gnp;
861: int op = *(int *)opp;
1.1 cgd 862: /*
863: * If the dependency mask of the operator and the node don't match and
864: * the node has actually had an operator applied to it before, and
1.27 christos 865: * the operator actually has some dependency information in it, complain.
1.1 cgd 866: */
867: if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
868: !OP_NOP(gn->type) && !OP_NOP(op))
869: {
1.97 christos 870: Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
1.235 rillig 871: return 1;
1.1 cgd 872: }
873:
1.242 rillig 874: if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
1.1 cgd 875: /*
876: * If the node was the object of a :: operator, we need to create a
877: * new instance of it for the children and commands on this dependency
878: * line. The new instance is placed on the 'cohorts' list of the
879: * initial one (note the initial one is not on its own cohorts list)
880: * and the new instance is linked to all parents of the initial
881: * instance.
882: */
1.84 wiz 883: GNode *cohort;
1.27 christos 884:
1.33 mycroft 885: /*
1.46 mycroft 886: * Propagate copied bits to the initial node. They'll be propagated
887: * back to the rest of the cohorts later.
1.33 mycroft 888: */
1.46 mycroft 889: gn->type |= op & ~OP_OPMASK;
1.33 mycroft 890:
1.120 dsl 891: cohort = Targ_FindNode(gn->name, TARG_NOHASH);
1.186 christos 892: if (doing_depend)
893: ParseMark(cohort);
1.1 cgd 894: /*
895: * Make the cohort invisible as well to avoid duplicating it into
896: * other variables. True, parents of this target won't tend to do
897: * anything with their local variables, but better safe than
1.46 mycroft 898: * sorry. (I think this is pointless now, since the relevant list
899: * traversals will no longer see this node anyway. -mycroft)
1.1 cgd 900: */
1.46 mycroft 901: cohort->type = op | OP_INVISIBLE;
1.268 rillig 902: Lst_Append(gn->cohorts, cohort);
1.83 pk 903: cohort->centurion = gn;
904: gn->unmade_cohorts += 1;
1.120 dsl 905: snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
906: gn->unmade_cohorts);
1.46 mycroft 907: } else {
1.1 cgd 908: /*
1.46 mycroft 909: * We don't want to nuke any previous flags (whatever they were) so we
910: * just OR the new operator into the old
1.1 cgd 911: */
1.46 mycroft 912: gn->type |= op;
1.1 cgd 913: }
1.33 mycroft 914:
1.235 rillig 915: return 0;
1.1 cgd 916: }
917:
1.27 christos 918: /*-
1.18 christos 919: *---------------------------------------------------------------------
1.1 cgd 920: * ParseDoSrc --
921: * Given the name of a source, figure out if it is an attribute
922: * and apply it to the targets if it is. Else decide if there is
923: * some attribute which should be applied *to* the source because
924: * of some special target and apply it if so. Otherwise, make the
925: * source be a child of the targets in the list 'targets'
926: *
1.84 wiz 927: * Input:
928: * tOp operator (if any) from special targets
929: * src name of the source to handle
930: *
1.1 cgd 931: * Results:
932: * None
933: *
934: * Side Effects:
935: * Operator bits may be added to the list of targets or to the source.
936: * The targets may have a new source added to their lists of children.
937: *---------------------------------------------------------------------
938: */
939: static void
1.120 dsl 940: ParseDoSrc(int tOp, const char *src)
1.1 cgd 941: {
1.18 christos 942: GNode *gn = NULL;
1.120 dsl 943: static int wait_number = 0;
944: char wait_src[16];
1.1 cgd 945:
1.290 rillig 946: if (*src == '.' && ch_isupper(src[1])) {
1.1 cgd 947: int keywd = ParseFindKeyword(src);
948: if (keywd != -1) {
1.18 christos 949: int op = parseKeywords[keywd].op;
950: if (op != 0) {
1.265 rillig 951: if (targets != NULL)
1.268 rillig 952: Lst_ForEach(targets, ParseDoOp, &op);
1.18 christos 953: return;
954: }
955: if (parseKeywords[keywd].spec == Wait) {
1.120 dsl 956: /*
957: * We add a .WAIT node in the dependency list.
958: * After any dynamic dependencies (and filename globbing)
959: * have happened, it is given a dependency on the each
960: * previous child back to and previous .WAIT node.
961: * The next child won't be scheduled until the .WAIT node
962: * is built.
963: * We give each .WAIT node a unique name (mainly for diag).
964: */
965: snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
966: gn = Targ_FindNode(wait_src, TARG_NOHASH);
1.186 christos 967: if (doing_depend)
968: ParseMark(gn);
1.120 dsl 969: gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
1.265 rillig 970: if (targets != NULL)
1.268 rillig 971: Lst_ForEach(targets, ParseLinkSrc, gn);
1.18 christos 972: return;
973: }
1.1 cgd 974: }
975: }
1.18 christos 976:
977: switch (specType) {
978: case Main:
1.1 cgd 979: /*
980: * If we have noted the existence of a .MAIN, it means we need
981: * to add the sources of said target to the list of things
982: * to create. The string 'src' is likely to be free, so we
983: * must make a new copy of it. Note that this will only be
984: * invoked if the user didn't specify a target on the command
985: * line. This is to allow #ifmake's to succeed, or something...
986: */
1.268 rillig 987: Lst_Append(create, bmake_strdup(src));
1.1 cgd 988: /*
1.118 dsl 989: * Add the name to the .TARGETS variable as well, so the user can
1.1 cgd 990: * employ that, if desired.
991: */
992: Var_Append(".TARGETS", src, VAR_GLOBAL);
1.18 christos 993: return;
994:
995: case Order:
1.1 cgd 996: /*
997: * Create proper predecessor/successor links between the previous
998: * source and the current one.
999: */
1000: gn = Targ_FindNode(src, TARG_CREATE);
1.186 christos 1001: if (doing_depend)
1002: ParseMark(gn);
1.152 dsl 1003: if (predecessor != NULL) {
1.268 rillig 1004: Lst_Append(predecessor->order_succ, gn);
1005: Lst_Append(gn->order_pred, predecessor);
1.109 dsl 1006: if (DEBUG(PARSE)) {
1.193 christos 1007: fprintf(debug_file, "# %s: added Order dependency %s - %s\n",
1008: __func__, predecessor->name, gn->name);
1.109 dsl 1009: Targ_PrintNode(predecessor, 0);
1010: Targ_PrintNode(gn, 0);
1011: }
1.1 cgd 1012: }
1013: /*
1014: * The current source now becomes the predecessor for the next one.
1015: */
1016: predecessor = gn;
1.18 christos 1017: break;
1018:
1019: default:
1.1 cgd 1020: /*
1021: * If the source is not an attribute, we need to find/create
1022: * a node for it. After that we can apply any operator to it
1023: * from a special target or link it to its parents, as
1024: * appropriate.
1025: *
1026: * In the case of a source that was the object of a :: operator,
1027: * the attribute is applied to all of its instances (as kept in
1028: * the 'cohorts' list of the node) or all the cohorts are linked
1029: * to all the targets.
1030: */
1.118 dsl 1031:
1032: /* Find/create the 'src' node and attach to all targets */
1.97 christos 1033: gn = Targ_FindNode(src, TARG_CREATE);
1.186 christos 1034: if (doing_depend)
1035: ParseMark(gn);
1.1 cgd 1036: if (tOp) {
1037: gn->type |= tOp;
1038: } else {
1.265 rillig 1039: if (targets != NULL)
1.268 rillig 1040: Lst_ForEach(targets, ParseLinkSrc, gn);
1.1 cgd 1041: }
1.18 christos 1042: break;
1043: }
1.1 cgd 1044: }
1045:
1046: /*-
1047: *-----------------------------------------------------------------------
1048: * ParseFindMain --
1049: * Find a real target in the list and set it to be the main one.
1050: * Called by ParseDoDependency when a main target hasn't been found
1051: * yet.
1052: *
1.84 wiz 1053: * Input:
1054: * gnp Node to examine
1055: *
1.1 cgd 1056: * Results:
1057: * 0 if main not found yet, 1 if it is.
1058: *
1059: * Side Effects:
1060: * mainNode is changed and Targ_SetMain is called.
1061: *
1062: *-----------------------------------------------------------------------
1063: */
1064: static int
1.219 riastrad 1065: ParseFindMain(void *gnp, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 1066: {
1.105 christos 1067: GNode *gn = (GNode *)gnp;
1.242 rillig 1068: if (!(gn->type & OP_NOTARGET)) {
1.1 cgd 1069: mainNode = gn;
1070: Targ_SetMain(gn);
1.219 riastrad 1071: return 1;
1.1 cgd 1072: } else {
1.219 riastrad 1073: return 0;
1.1 cgd 1074: }
1075: }
1076:
1077: /*-
1078: *-----------------------------------------------------------------------
1079: * ParseAddDir --
1080: * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
1081: *
1082: * Results:
1083: * === 0
1084: *
1085: * Side Effects:
1086: * See Dir_AddDir.
1087: *
1088: *-----------------------------------------------------------------------
1089: */
1090: static int
1.157 dsl 1091: ParseAddDir(void *path, void *name)
1.1 cgd 1092: {
1.105 christos 1093: (void)Dir_AddDir((Lst) path, (char *)name);
1.235 rillig 1094: return 0;
1.1 cgd 1095: }
1096:
1097: /*-
1098: *-----------------------------------------------------------------------
1099: * ParseClearPath --
1100: * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
1101: *
1102: * Results:
1103: * === 0
1104: *
1105: * Side Effects:
1106: * See Dir_ClearPath
1107: *
1108: *-----------------------------------------------------------------------
1109: */
1110: static int
1.219 riastrad 1111: ParseClearPath(void *path, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 1112: {
1.9 jtc 1113: Dir_ClearPath((Lst) path);
1.219 riastrad 1114: return 0;
1.1 cgd 1115: }
1116:
1117: /*-
1118: *---------------------------------------------------------------------
1119: * ParseDoDependency --
1120: * Parse the dependency line in line.
1121: *
1.84 wiz 1122: * Input:
1123: * line the line to parse
1124: *
1.1 cgd 1125: * Results:
1126: * None
1127: *
1128: * Side Effects:
1129: * The nodes of the sources are linked as children to the nodes of the
1130: * targets. Some nodes may be created.
1131: *
1132: * We parse a dependency line by first extracting words from the line and
1133: * finding nodes in the list of all targets with that name. This is done
1134: * until a character is encountered which is an operator character. Currently
1135: * these are only ! and :. At this point the operator is parsed and the
1136: * pointer into the line advanced until the first source is encountered.
1137: * The parsed operator is applied to each node in the 'targets' list,
1138: * which is where the nodes found for the targets are kept, by means of
1139: * the ParseDoOp function.
1140: * The sources are read in much the same way as the targets were except
1141: * that now they are expanded using the wildcarding scheme of the C-Shell
1142: * and all instances of the resulting words in the list of all targets
1143: * are found. Each of the resulting nodes is then linked to each of the
1144: * targets as one of its children.
1145: * Certain targets are handled specially. These are the ones detailed
1146: * by the specType variable.
1147: * The storing of transformation rules is also taken care of here.
1148: * A target is recognized as a transformation rule by calling
1149: * Suff_IsTransform. If it is a transformation rule, its node is gotten
1150: * from the suffix module via Suff_AddTransform rather than the standard
1151: * Targ_FindNode in the target module.
1152: *---------------------------------------------------------------------
1153: */
1154: static void
1.84 wiz 1155: ParseDoDependency(char *line)
1.1 cgd 1156: {
1.9 jtc 1157: char *cp; /* our current position */
1.98 christos 1158: GNode *gn = NULL; /* a general purpose temporary node */
1.9 jtc 1159: int op; /* the operator on the line */
1.1 cgd 1160: char savec; /* a place to save a character */
1161: Lst paths; /* List of search paths to alter when parsing
1162: * a list of .PATH targets */
1163: int tOp; /* operator from special target */
1.18 christos 1164: Lst sources; /* list of archive source names after
1165: * expansion */
1.1 cgd 1166: Lst curTargs; /* list of target names to be found and added
1167: * to the targets list */
1.77 christos 1168: char *lstart = line;
1.1 cgd 1169:
1.120 dsl 1170: if (DEBUG(PARSE))
1171: fprintf(debug_file, "ParseDoDependency(%s)\n", line);
1.1 cgd 1172: tOp = 0;
1173:
1174: specType = Not;
1.179 plunky 1175: paths = NULL;
1.1 cgd 1176:
1.252 rillig 1177: curTargs = Lst_Init();
1.27 christos 1178:
1.204 dholland 1179: /*
1180: * First, grind through the targets.
1181: */
1182:
1.1 cgd 1183: do {
1.204 dholland 1184: /*
1185: * Here LINE points to the beginning of the next word, and
1186: * LSTART points to the actual beginning of the line.
1187: */
1188:
1189: /* Find the end of the next word. */
1.203 joerg 1190: for (cp = line; *cp && (ParseIsEscaped(lstart, cp) ||
1.290 rillig 1191: !(ch_isspace(*cp) ||
1.287 rillig 1192: *cp == '!' || *cp == ':' || *cp == LPAREN));) {
1.1 cgd 1193: if (*cp == '$') {
1194: /*
1195: * Must be a dynamic source (would have been expanded
1196: * otherwise), so call the Var module to parse the puppy
1197: * so we can safely advance beyond it...There should be
1198: * no errors in this, as they would have been discovered
1199: * in the initial Var_Subst and we wouldn't be here.
1200: */
1.287 rillig 1201: const char *nested_p = cp;
1.114 christos 1202: void *freeIt;
1.1 cgd 1203:
1.294 rillig 1204: (void)Var_Parse(&nested_p, VAR_CMD,
1205: VARE_UNDEFERR|VARE_WANTRES, &freeIt);
1.209 christos 1206: free(freeIt);
1.287 rillig 1207: cp += nested_p - cp;
1208: } else
1.292 rillig 1209: cp++;
1.1 cgd 1210: }
1.121 dsl 1211:
1.204 dholland 1212: /*
1213: * If the word is followed by a left parenthesis, it's the
1214: * name of an object file inside an archive (ar file).
1215: */
1.77 christos 1216: if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) {
1.1 cgd 1217: /*
1.203 joerg 1218: * Archives must be handled specially to make sure the OP_ARCHV
1219: * flag is set in their 'type' field, for one thing, and because
1220: * things like "archive(file1.o file2.o file3.o)" are permissible.
1221: * Arch_ParseArchive will set 'line' to be the first non-blank
1222: * after the archive-spec. It creates/finds nodes for the members
1.272 rillig 1223: * and places them on the given list, returning TRUE if all
1224: * went well and FALSE if there was an error in the
1.203 joerg 1225: * specification. On error, line should remain untouched.
1.1 cgd 1226: */
1.264 rillig 1227: if (!Arch_ParseArchive(&line, targets, VAR_CMD)) {
1.97 christos 1228: Parse_Error(PARSE_FATAL,
1.203 joerg 1229: "Error in archive specification: \"%s\"", line);
1.112 christos 1230: goto out;
1.203 joerg 1231: } else {
1.204 dholland 1232: /* Done with this word; on to the next. */
1.213 matthias 1233: cp = line;
1.1 cgd 1234: continue;
1.203 joerg 1235: }
1.1 cgd 1236: }
1.27 christos 1237:
1.1 cgd 1238: if (!*cp) {
1239: /*
1.204 dholland 1240: * We got to the end of the line while we were still
1241: * looking at targets.
1242: *
1.1 cgd 1243: * Ending a dependency line without an operator is a Bozo
1.65 sommerfe 1244: * no-no. As a heuristic, this is also often triggered by
1245: * undetected conflicts from cvs/rcs merges.
1.1 cgd 1246: */
1.65 sommerfe 1247: if ((strncmp(line, "<<<<<<", 6) == 0) ||
1248: (strncmp(line, "======", 6) == 0) ||
1249: (strncmp(line, ">>>>>>", 6) == 0))
1.97 christos 1250: Parse_Error(PARSE_FATAL,
1.67 sommerfe 1251: "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
1.240 rillig 1252: else if (lstart[0] == '.') {
1253: const char *dirstart = lstart + 1;
1.247 rillig 1254: const char *dirend;
1.290 rillig 1255: while (ch_isspace(*dirstart))
1.240 rillig 1256: dirstart++;
1.247 rillig 1257: dirend = dirstart;
1.290 rillig 1258: while (ch_isalnum(*dirend) || *dirend == '-')
1.240 rillig 1259: dirend++;
1260: Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
1261: (int)(dirend - dirstart), dirstart);
1262: } else
1.241 rillig 1263: Parse_Error(PARSE_FATAL, "Need an operator");
1.112 christos 1264: goto out;
1.1 cgd 1265: }
1.204 dholland 1266:
1267: /* Insert a null terminator. */
1268: savec = *cp;
1.1 cgd 1269: *cp = '\0';
1.118 dsl 1270:
1.1 cgd 1271: /*
1.204 dholland 1272: * Got the word. See if it's a special target and if so set
1.1 cgd 1273: * specType to match it.
1274: */
1.290 rillig 1275: if (*line == '.' && ch_isupper(line[1])) {
1.1 cgd 1276: /*
1277: * See if the target is a special target that must have it
1.27 christos 1278: * or its sources handled specially.
1.1 cgd 1279: */
1280: int keywd = ParseFindKeyword(line);
1281: if (keywd != -1) {
1.5 cgd 1282: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
1.1 cgd 1283: Parse_Error(PARSE_FATAL, "Mismatched special targets");
1.112 christos 1284: goto out;
1.1 cgd 1285: }
1.27 christos 1286:
1.1 cgd 1287: specType = parseKeywords[keywd].spec;
1288: tOp = parseKeywords[keywd].op;
1289:
1290: /*
1291: * Certain special targets have special semantics:
1292: * .PATH Have to set the dirSearchPath
1293: * variable too
1294: * .MAIN Its sources are only used if
1295: * nothing has been specified to
1296: * create.
1297: * .DEFAULT Need to create a node to hang
1298: * commands on, but we don't want
1299: * it in the graph, nor do we want
1300: * it to be the Main Target, so we
1301: * create it, set OP_NOTMAIN and
1302: * add it to the list, setting
1303: * DEFAULT to the new node for
1304: * later use. We claim the node is
1305: * A transformation rule to make
1306: * life easier later, when we'll
1307: * use Make_HandleUse to actually
1308: * apply the .DEFAULT commands.
1.22 christos 1309: * .PHONY The list of targets
1.32 gwr 1310: * .NOPATH Don't search for file in the path
1.187 christos 1311: * .STALE
1.1 cgd 1312: * .BEGIN
1313: * .END
1.162 sjg 1314: * .ERROR
1.215 dholland 1315: * .DELETE_ON_ERROR
1.1 cgd 1316: * .INTERRUPT Are not to be considered the
1317: * main target.
1318: * .NOTPARALLEL Make only one target at a time.
1319: * .SINGLESHELL Create a shell for each command.
1.152 dsl 1320: * .ORDER Must set initial predecessor to NULL
1.1 cgd 1321: */
1322: switch (specType) {
1.187 christos 1323: case ExPath:
1324: if (paths == NULL) {
1.252 rillig 1325: paths = Lst_Init();
1.187 christos 1326: }
1.268 rillig 1327: Lst_Append(paths, dirSearchPath);
1.187 christos 1328: break;
1329: case Main:
1.268 rillig 1330: if (!Lst_IsEmpty(create)) {
1.187 christos 1331: specType = Not;
1332: }
1333: break;
1334: case Begin:
1335: case End:
1336: case Stale:
1337: case dotError:
1338: case Interrupt:
1339: gn = Targ_FindNode(line, TARG_CREATE);
1340: if (doing_depend)
1341: ParseMark(gn);
1342: gn->type |= OP_NOTMAIN|OP_SPECIAL;
1.268 rillig 1343: Lst_Append(targets, gn);
1.187 christos 1344: break;
1345: case Default:
1346: gn = Targ_NewGN(".DEFAULT");
1347: gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
1.268 rillig 1348: Lst_Append(targets, gn);
1.187 christos 1349: DEFAULT = gn;
1350: break;
1.215 dholland 1351: case DeleteOnError:
1352: deleteOnError = TRUE;
1353: break;
1.187 christos 1354: case NotParallel:
1355: maxJobs = 1;
1356: break;
1357: case SingleShell:
1358: compatMake = TRUE;
1359: break;
1360: case Order:
1361: predecessor = NULL;
1362: break;
1363: default:
1364: break;
1.1 cgd 1365: }
1.103 christos 1366: } else if (strncmp(line, ".PATH", 5) == 0) {
1.1 cgd 1367: /*
1368: * .PATH<suffix> has to be handled specially.
1369: * Call on the suffix module to give us a path to
1370: * modify.
1371: */
1372: Lst path;
1.27 christos 1373:
1.5 cgd 1374: specType = ExPath;
1.97 christos 1375: path = Suff_GetPath(&line[5]);
1.152 dsl 1376: if (path == NULL) {
1.97 christos 1377: Parse_Error(PARSE_FATAL,
1.1 cgd 1378: "Suffix '%s' not defined (yet)",
1379: &line[5]);
1.112 christos 1380: goto out;
1.1 cgd 1381: } else {
1.179 plunky 1382: if (paths == NULL) {
1.252 rillig 1383: paths = Lst_Init();
1.1 cgd 1384: }
1.268 rillig 1385: Lst_Append(paths, path);
1.1 cgd 1386: }
1387: }
1388: }
1.27 christos 1389:
1.1 cgd 1390: /*
1391: * Have word in line. Get or create its node and stick it at
1.27 christos 1392: * the end of the targets list
1.1 cgd 1393: */
1.242 rillig 1394: if (specType == Not && *line != '\0') {
1.1 cgd 1395: if (Dir_HasWildcards(line)) {
1396: /*
1397: * Targets are to be sought only in the current directory,
1398: * so create an empty path for the thing. Note we need to
1399: * use Dir_Destroy in the destruction of the path as the
1400: * Dir module could have added a directory to the path...
1401: */
1.252 rillig 1402: Lst emptyPath = Lst_Init();
1.27 christos 1403:
1.1 cgd 1404: Dir_Expand(line, emptyPath, curTargs);
1.27 christos 1405:
1.268 rillig 1406: Lst_Destroy(emptyPath, Dir_Destroy);
1.1 cgd 1407: } else {
1408: /*
1409: * No wildcards, but we want to avoid code duplication,
1410: * so create a list with the word on it.
1411: */
1.268 rillig 1412: Lst_Append(curTargs, line);
1.1 cgd 1413: }
1.27 christos 1414:
1.204 dholland 1415: /* Apply the targets. */
1416:
1.268 rillig 1417: while(!Lst_IsEmpty(curTargs)) {
1418: char *targName = Lst_Dequeue(curTargs);
1.27 christos 1419:
1.203 joerg 1420: if (!Suff_IsTransform (targName)) {
1.97 christos 1421: gn = Targ_FindNode(targName, TARG_CREATE);
1.1 cgd 1422: } else {
1.203 joerg 1423: gn = Suff_AddTransform(targName);
1.1 cgd 1424: }
1.186 christos 1425: if (doing_depend)
1426: ParseMark(gn);
1.27 christos 1427:
1.268 rillig 1428: Lst_Append(targets, gn);
1.1 cgd 1429: }
1.5 cgd 1430: } else if (specType == ExPath && *line != '.' && *line != '\0') {
1.1 cgd 1431: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1432: }
1.27 christos 1433:
1.204 dholland 1434: /* Don't need the inserted null terminator any more. */
1.1 cgd 1435: *cp = savec;
1.204 dholland 1436:
1.1 cgd 1437: /*
1438: * If it is a special type and not .PATH, it's the only target we
1439: * allow on this line...
1440: */
1.5 cgd 1441: if (specType != Not && specType != ExPath) {
1.115 christos 1442: Boolean warning = FALSE;
1.27 christos 1443:
1.77 christos 1444: while (*cp && (ParseIsEscaped(lstart, cp) ||
1.242 rillig 1445: (*cp != '!' && *cp != ':'))) {
1.77 christos 1446: if (ParseIsEscaped(lstart, cp) ||
1447: (*cp != ' ' && *cp != '\t')) {
1.115 christos 1448: warning = TRUE;
1.1 cgd 1449: }
1450: cp++;
1451: }
1.115 christos 1452: if (warning) {
1.1 cgd 1453: Parse_Error(PARSE_WARNING, "Extra target ignored");
1454: }
1455: } else {
1.290 rillig 1456: while (*cp && ch_isspace(*cp)) {
1.1 cgd 1457: cp++;
1458: }
1459: }
1.203 joerg 1460: line = cp;
1461: } while (*line && (ParseIsEscaped(lstart, line) ||
1.242 rillig 1462: (*line != '!' && *line != ':')));
1.1 cgd 1463:
1464: /*
1465: * Don't need the list of target names anymore...
1466: */
1.268 rillig 1467: Lst_Free(curTargs);
1.112 christos 1468: curTargs = NULL;
1.1 cgd 1469:
1.268 rillig 1470: if (targets != NULL && !Lst_IsEmpty(targets)) {
1.1 cgd 1471: switch(specType) {
1472: default:
1473: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
1474: break;
1475: case Default:
1.187 christos 1476: case Stale:
1.1 cgd 1477: case Begin:
1478: case End:
1.162 sjg 1479: case dotError:
1.1 cgd 1480: case Interrupt:
1481: /*
1482: * These four create nodes on which to hang commands, so
1483: * targets shouldn't be empty...
1484: */
1485: case Not:
1486: /*
1487: * Nothing special here -- targets can be empty if it wants.
1488: */
1489: break;
1490: }
1491: }
1492:
1493: /*
1494: * Have now parsed all the target names. Must parse the operator next. The
1495: * result is left in op .
1496: */
1497: if (*cp == '!') {
1498: op = OP_FORCE;
1499: } else if (*cp == ':') {
1500: if (cp[1] == ':') {
1501: op = OP_DOUBLEDEP;
1502: cp++;
1503: } else {
1504: op = OP_DEPENDS;
1505: }
1506: } else {
1.159 dsl 1507: Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive"
1508: : "Missing dependency operator");
1.112 christos 1509: goto out;
1.1 cgd 1510: }
1511:
1.204 dholland 1512: /* Advance beyond the operator */
1513: cp++;
1.1 cgd 1514:
1.204 dholland 1515: /*
1516: * Apply the operator to the target. This is how we remember which
1517: * operator a target was defined with. It fails if the operator
1518: * used isn't consistent across all references.
1519: */
1.265 rillig 1520: if (targets != NULL)
1.268 rillig 1521: Lst_ForEach(targets, ParseDoOp, &op);
1.1 cgd 1522:
1523: /*
1.204 dholland 1524: * Onward to the sources.
1525: *
1526: * LINE will now point to the first source word, if any, or the
1527: * end of the string if not.
1.1 cgd 1528: */
1.290 rillig 1529: while (*cp && ch_isspace(*cp)) {
1.1 cgd 1530: cp++;
1531: }
1532: line = cp;
1533:
1534: /*
1535: * Several special targets take different actions if present with no
1536: * sources:
1537: * a .SUFFIXES line with no sources clears out all old suffixes
1538: * a .PRECIOUS line makes all targets precious
1539: * a .IGNORE line ignores errors for all targets
1540: * a .SILENT line creates silence when making all targets
1541: * a .PATH removes all directories from the search path(s).
1542: */
1543: if (!*line) {
1544: switch (specType) {
1545: case Suffixes:
1.97 christos 1546: Suff_ClearSuffixes();
1.1 cgd 1547: break;
1548: case Precious:
1549: allPrecious = TRUE;
1550: break;
1551: case Ignore:
1552: ignoreErrors = TRUE;
1553: break;
1554: case Silent:
1555: beSilent = TRUE;
1556: break;
1.5 cgd 1557: case ExPath:
1.265 rillig 1558: if (paths != NULL)
1.268 rillig 1559: Lst_ForEach(paths, ParseClearPath, NULL);
1.85 sjg 1560: Dir_SetPATH();
1.1 cgd 1561: break;
1.48 sjg 1562: #ifdef POSIX
1.246 rillig 1563: case Posix:
1564: Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1565: break;
1.48 sjg 1566: #endif
1.5 cgd 1567: default:
1568: break;
1.1 cgd 1569: }
1570: } else if (specType == MFlags) {
1571: /*
1572: * Call on functions in main.c to deal with these arguments and
1573: * set the initial character to a null-character so the loop to
1574: * get sources won't get anything
1575: */
1.97 christos 1576: Main_ParseArgLine(line);
1.1 cgd 1577: *line = '\0';
1.5 cgd 1578: } else if (specType == ExShell) {
1.272 rillig 1579: if (!Job_ParseShell(line)) {
1.97 christos 1580: Parse_Error(PARSE_FATAL, "improper shell specification");
1.112 christos 1581: goto out;
1.1 cgd 1582: }
1583: *line = '\0';
1.242 rillig 1584: } else if (specType == NotParallel || specType == SingleShell ||
1585: specType == DeleteOnError) {
1.1 cgd 1586: *line = '\0';
1587: }
1.27 christos 1588:
1.1 cgd 1589: /*
1.27 christos 1590: * NOW GO FOR THE SOURCES
1.1 cgd 1591: */
1.242 rillig 1592: if (specType == Suffixes || specType == ExPath ||
1593: specType == Includes || specType == Libs ||
1594: specType == Null || specType == ExObjdir)
1.1 cgd 1595: {
1.203 joerg 1596: while (*line) {
1.1 cgd 1597: /*
1598: * If the target was one that doesn't take files as its sources
1599: * but takes something like suffixes, we take each
1600: * space-separated word on the line as a something and deal
1601: * with it accordingly.
1602: *
1603: * If the target was .SUFFIXES, we take each source as a
1604: * suffix and add it to the list of suffixes maintained by the
1.203 joerg 1605: * Suff module.
1.1 cgd 1606: *
1607: * If the target was a .PATH, we add the source as a directory
1608: * to search on the search path.
1609: *
1610: * If it was .INCLUDES, the source is taken to be the suffix of
1611: * files which will be #included and whose search path should
1612: * be present in the .INCLUDES variable.
1613: *
1614: * If it was .LIBS, the source is taken to be the suffix of
1615: * files which are considered libraries and whose search path
1616: * should be present in the .LIBS variable.
1617: *
1618: * If it was .NULL, the source is the suffix to use when a file
1619: * has no valid suffix.
1.75 tv 1620: *
1621: * If it was .OBJDIR, the source is a new definition for .OBJDIR,
1622: * and will cause make to do a new chdir to that path.
1.1 cgd 1623: */
1.290 rillig 1624: while (*cp && !ch_isspace(*cp)) {
1.1 cgd 1625: cp++;
1.203 joerg 1626: }
1.1 cgd 1627: savec = *cp;
1628: *cp = '\0';
1629: switch (specType) {
1630: case Suffixes:
1.203 joerg 1631: Suff_AddSuffix(line, &mainNode);
1.1 cgd 1632: break;
1.5 cgd 1633: case ExPath:
1.265 rillig 1634: if (paths != NULL)
1.268 rillig 1635: Lst_ForEach(paths, ParseAddDir, line);
1.1 cgd 1636: break;
1637: case Includes:
1.97 christos 1638: Suff_AddInclude(line);
1.1 cgd 1639: break;
1640: case Libs:
1.97 christos 1641: Suff_AddLib(line);
1.1 cgd 1642: break;
1643: case Null:
1.97 christos 1644: Suff_SetNull(line);
1.75 tv 1645: break;
1646: case ExObjdir:
1.216 christos 1647: Main_SetObjdir("%s", line);
1.1 cgd 1648: break;
1.5 cgd 1649: default:
1650: break;
1.1 cgd 1651: }
1652: *cp = savec;
1.203 joerg 1653: if (savec != '\0') {
1654: cp++;
1655: }
1.290 rillig 1656: while (*cp && ch_isspace(*cp)) {
1.1 cgd 1657: cp++;
1.203 joerg 1658: }
1659: line = cp;
1.1 cgd 1660: }
1661: if (paths) {
1.268 rillig 1662: Lst_Free(paths);
1.222 riastrad 1663: paths = NULL;
1.1 cgd 1664: }
1.85 sjg 1665: if (specType == ExPath)
1666: Dir_SetPATH();
1.1 cgd 1667: } else {
1.222 riastrad 1668: assert(paths == NULL);
1.1 cgd 1669: while (*line) {
1670: /*
1671: * The targets take real sources, so we must beware of archive
1672: * specifications (i.e. things with left parentheses in them)
1673: * and handle them accordingly.
1674: */
1.290 rillig 1675: for (; *cp && !ch_isspace(*cp); cp++) {
1.242 rillig 1676: if (*cp == LPAREN && cp > line && cp[-1] != '$') {
1.1 cgd 1677: /*
1678: * Only stop for a left parenthesis if it isn't at the
1679: * start of a word (that'll be for variable changes
1680: * later) and isn't preceded by a dollar sign (a dynamic
1681: * source).
1682: */
1683: break;
1684: }
1685: }
1686:
1.77 christos 1687: if (*cp == LPAREN) {
1.252 rillig 1688: sources = Lst_Init();
1.264 rillig 1689: if (!Arch_ParseArchive(&line, sources, VAR_CMD)) {
1.97 christos 1690: Parse_Error(PARSE_FATAL,
1.1 cgd 1691: "Error in source archive spec \"%s\"", line);
1.112 christos 1692: goto out;
1.1 cgd 1693: }
1694:
1.268 rillig 1695: while (!Lst_IsEmpty(sources)) {
1696: gn = Lst_Dequeue(sources);
1.120 dsl 1697: ParseDoSrc(tOp, gn->name);
1.1 cgd 1698: }
1.268 rillig 1699: Lst_Free(sources);
1.1 cgd 1700: cp = line;
1701: } else {
1702: if (*cp) {
1703: *cp = '\0';
1704: cp += 1;
1705: }
1706:
1.120 dsl 1707: ParseDoSrc(tOp, line);
1.1 cgd 1708: }
1.290 rillig 1709: while (*cp && ch_isspace(*cp)) {
1.1 cgd 1710: cp++;
1711: }
1712: line = cp;
1713: }
1714: }
1.27 christos 1715:
1.265 rillig 1716: if (mainNode == NULL && targets != NULL) {
1.1 cgd 1717: /*
1718: * If we have yet to decide on a main target to make, in the
1719: * absence of any user input, we want the first target on
1720: * the first dependency line that is actually a real target
1721: * (i.e. isn't a .USE or .EXEC rule) to be made.
1722: */
1.268 rillig 1723: Lst_ForEach(targets, ParseFindMain, NULL);
1.1 cgd 1724: }
1725:
1.112 christos 1726: out:
1.263 rillig 1727: if (paths != NULL)
1.268 rillig 1728: Lst_Free(paths);
1.263 rillig 1729: if (curTargs != NULL)
1.268 rillig 1730: Lst_Free(curTargs);
1.1 cgd 1731: }
1732:
1733: /*-
1734: *---------------------------------------------------------------------
1735: * Parse_IsVar --
1736: * Return TRUE if the passed line is a variable assignment. A variable
1737: * assignment consists of a single word followed by optional whitespace
1738: * followed by either a += or an = operator.
1739: * This function is used both by the Parse_File function and main when
1740: * parsing the command-line arguments.
1741: *
1.84 wiz 1742: * Input:
1743: * line the line to check
1744: *
1.1 cgd 1745: * Results:
1746: * TRUE if it is. FALSE if it ain't
1747: *
1748: * Side Effects:
1749: * none
1750: *---------------------------------------------------------------------
1751: */
1752: Boolean
1.286 rillig 1753: Parse_IsVar(const char *line)
1.1 cgd 1754: {
1.84 wiz 1755: Boolean wasSpace = FALSE; /* set TRUE if found a space */
1.154 dsl 1756: char ch;
1.16 christos 1757: int level = 0;
1758: #define ISEQOPERATOR(c) \
1759: (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1.1 cgd 1760:
1761: /*
1762: * Skip to variable name
1763: */
1.242 rillig 1764: while (*line == ' ' || *line == '\t')
1765: line++;
1.1 cgd 1766:
1.154 dsl 1767: /* Scan for one of the assignment operators outside a variable expansion */
1768: while ((ch = *line++) != 0) {
1769: if (ch == '(' || ch == '{') {
1.16 christos 1770: level++;
1.154 dsl 1771: continue;
1772: }
1773: if (ch == ')' || ch == '}') {
1.16 christos 1774: level--;
1.154 dsl 1775: continue;
1776: }
1777: if (level != 0)
1778: continue;
1779: while (ch == ' ' || ch == '\t') {
1780: ch = *line++;
1781: wasSpace = TRUE;
1.1 cgd 1782: }
1.191 sjg 1783: #ifdef SUNSHCMD
1784: if (ch == ':' && strncmp(line, "sh", 2) == 0) {
1785: line += 2;
1786: continue;
1787: }
1788: #endif
1.154 dsl 1789: if (ch == '=')
1790: return TRUE;
1791: if (*line == '=' && ISEQOPERATOR(ch))
1792: return TRUE;
1793: if (wasSpace)
1794: return FALSE;
1795: }
1.1 cgd 1796:
1.154 dsl 1797: return FALSE;
1.1 cgd 1798: }
1799:
1800: /*-
1801: *---------------------------------------------------------------------
1802: * Parse_DoVar --
1803: * Take the variable assignment in the passed line and do it in the
1804: * global context.
1805: *
1806: * Note: There is a lexical ambiguity with assignment modifier characters
1807: * in variable names. This routine interprets the character before the =
1808: * as a modifier. Therefore, an assignment like
1809: * C++=/usr/bin/CC
1810: * is interpreted as "C+ +=" instead of "C++ =".
1811: *
1.84 wiz 1812: * Input:
1813: * line a line guaranteed to be a variable assignment.
1814: * This reduces error checks
1815: * ctxt Context in which to do the assignment
1816: *
1.1 cgd 1817: * Results:
1818: * none
1819: *
1820: * Side Effects:
1821: * the variable structure of the given variable name is altered in the
1822: * global context.
1823: *---------------------------------------------------------------------
1824: */
1825: void
1.84 wiz 1826: Parse_DoVar(char *line, GNode *ctxt)
1.1 cgd 1827: {
1.7 cgd 1828: char *cp; /* pointer into line */
1.1 cgd 1829: enum {
1830: VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1831: } type; /* Type of assignment */
1.27 christos 1832: char *opc; /* ptr to operator character to
1.1 cgd 1833: * null-terminate the variable name */
1.86 sjg 1834: Boolean freeCp = FALSE; /* TRUE if cp needs to be freed,
1835: * i.e. if any variable expansion was
1836: * performed */
1.153 dsl 1837: int depth;
1.1 cgd 1838:
1839: /*
1840: * Skip to variable name
1841: */
1.242 rillig 1842: while (*line == ' ' || *line == '\t')
1.1 cgd 1843: line++;
1844:
1845: /*
1846: * Skip to operator character, nulling out whitespace as we go
1.153 dsl 1847: * XXX Rather than counting () and {} we should look for $ and
1848: * then expand the variable.
1.1 cgd 1849: */
1.259 rillig 1850: for (depth = 0, cp = line; depth > 0 || *cp != '='; cp++) {
1.153 dsl 1851: if (*cp == '(' || *cp == '{') {
1852: depth++;
1853: continue;
1854: }
1855: if (*cp == ')' || *cp == '}') {
1856: depth--;
1857: continue;
1858: }
1.290 rillig 1859: if (depth == 0 && ch_isspace(*cp)) {
1.1 cgd 1860: *cp = '\0';
1861: }
1862: }
1863: opc = cp-1; /* operator is the previous character */
1864: *cp++ = '\0'; /* nuke the = */
1865:
1866: /*
1867: * Check operator type
1868: */
1869: switch (*opc) {
1870: case '+':
1871: type = VAR_APPEND;
1872: *opc = '\0';
1873: break;
1874:
1875: case '?':
1876: /*
1877: * If the variable already has a value, we don't do anything.
1878: */
1879: *opc = '\0';
1880: if (Var_Exists(line, ctxt)) {
1881: return;
1882: } else {
1883: type = VAR_NORMAL;
1884: }
1885: break;
1886:
1887: case ':':
1888: type = VAR_SUBST;
1889: *opc = '\0';
1890: break;
1891:
1892: case '!':
1893: type = VAR_SHELL;
1894: *opc = '\0';
1895: break;
1896:
1897: default:
1.23 christos 1898: #ifdef SUNSHCMD
1.39 christos 1899: while (opc > line && *opc != ':')
1900: opc--;
1.23 christos 1901:
1902: if (strncmp(opc, ":sh", 3) == 0) {
1903: type = VAR_SHELL;
1904: *opc = '\0';
1905: break;
1906: }
1907: #endif
1.1 cgd 1908: type = VAR_NORMAL;
1909: break;
1910: }
1911:
1.290 rillig 1912: while (ch_isspace(*cp))
1.1 cgd 1913: cp++;
1914:
1.243 sjg 1915: if (DEBUG(LINT)) {
1916: if (type != VAR_SUBST && strchr(cp, '$') != NULL) {
1917: /* sanity check now */
1918: char *cp2;
1919:
1.249 sjg 1920: cp2 = Var_Subst(cp, ctxt, VARE_ASSIGN);
1.243 sjg 1921: free(cp2);
1922: }
1923: }
1924:
1.1 cgd 1925: if (type == VAR_APPEND) {
1.97 christos 1926: Var_Append(line, cp, ctxt);
1.1 cgd 1927: } else if (type == VAR_SUBST) {
1928: /*
1929: * Allow variables in the old value to be undefined, but leave their
1.295 ! rillig 1930: * expressions alone -- this is done by forcing oldVars to be false.
1.1 cgd 1931: * XXX: This can cause recursive variables, but that's not hard to do,
1932: * and this allows someone to do something like
1933: *
1934: * CFLAGS = $(.INCLUDES)
1935: * CFLAGS := -I.. $(CFLAGS)
1936: *
1937: * And not get an error.
1938: */
1939: Boolean oldOldVars = oldVars;
1940:
1941: oldVars = FALSE;
1.42 christos 1942:
1943: /*
1944: * make sure that we set the variable the first time to nothing
1945: * so that it gets substituted!
1946: */
1947: if (!Var_Exists(line, ctxt))
1.234 rillig 1948: Var_Set(line, "", ctxt);
1.42 christos 1949:
1.239 rillig 1950: cp = Var_Subst(cp, ctxt, VARE_WANTRES|VARE_ASSIGN);
1.1 cgd 1951: oldVars = oldOldVars;
1.86 sjg 1952: freeCp = TRUE;
1.1 cgd 1953:
1.234 rillig 1954: Var_Set(line, cp, ctxt);
1.1 cgd 1955: } else if (type == VAR_SHELL) {
1.93 christos 1956: char *res;
1.115 christos 1957: const char *error;
1.5 cgd 1958:
1.23 christos 1959: if (strchr(cp, '$') != NULL) {
1.1 cgd 1960: /*
1961: * There's a dollar sign in the command, so perform variable
1962: * expansion on the whole thing. The resulting string will need
1.238 rillig 1963: * freeing when we're done.
1.1 cgd 1964: */
1.239 rillig 1965: cp = Var_Subst(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES);
1.86 sjg 1966: freeCp = TRUE;
1.1 cgd 1967: }
1968:
1.115 christos 1969: res = Cmd_Exec(cp, &error);
1.234 rillig 1970: Var_Set(line, res, ctxt);
1.23 christos 1971: free(res);
1.1 cgd 1972:
1.115 christos 1973: if (error)
1974: Parse_Error(PARSE_WARNING, error, cp);
1.1 cgd 1975: } else {
1976: /*
1977: * Normal assignment -- just do it.
1978: */
1.234 rillig 1979: Var_Set(line, cp, ctxt);
1.1 cgd 1980: }
1.69 sjg 1981: if (strcmp(line, MAKEOVERRIDES) == 0)
1.74 tv 1982: Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */
1.85 sjg 1983: else if (strcmp(line, ".CURDIR") == 0) {
1984: /*
1985: * Somone is being (too?) clever...
1986: * Let's pretend they know what they are doing and
1987: * re-initialize the 'cur' Path.
1988: */
1989: Dir_InitCur(cp);
1990: Dir_SetPATH();
1.136 sjg 1991: } else if (strcmp(line, MAKE_JOB_PREFIX) == 0) {
1.135 sjg 1992: Job_SetPrefix();
1.136 sjg 1993: } else if (strcmp(line, MAKE_EXPORTED) == 0) {
1.250 rillig 1994: Var_Export(cp, FALSE);
1.85 sjg 1995: }
1.86 sjg 1996: if (freeCp)
1997: free(cp);
1.1 cgd 1998: }
1.23 christos 1999:
1.200 christos 2000:
1.203 joerg 2001: /*
1.195 christos 2002: * ParseMaybeSubMake --
2003: * Scan the command string to see if it a possible submake node
2004: * Input:
2005: * cmd the command to scan
2006: * Results:
2007: * TRUE if the command is possibly a submake, FALSE if not.
2008: */
2009: static Boolean
2010: ParseMaybeSubMake(const char *cmd)
2011: {
1.197 justin 2012: size_t i;
1.195 christos 2013: static struct {
2014: const char *name;
2015: size_t len;
2016: } vals[] = {
2017: #define MKV(A) { A, sizeof(A) - 1 }
2018: MKV("${MAKE}"),
2019: MKV("${.MAKE}"),
2020: MKV("$(MAKE)"),
2021: MKV("$(.MAKE)"),
2022: MKV("make"),
2023: };
1.198 justin 2024: for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {
1.195 christos 2025: char *ptr;
2026: if ((ptr = strstr(cmd, vals[i].name)) == NULL)
2027: continue;
1.290 rillig 2028: if ((ptr == cmd || !ch_isalnum(ptr[-1]))
2029: && !ch_isalnum(ptr[vals[i].len]))
1.195 christos 2030: return TRUE;
2031: }
2032: return FALSE;
2033: }
2034:
1.1 cgd 2035: /*-
2036: * ParseAddCmd --
2037: * Lst_ForEach function to add a command line to all targets
2038: *
1.84 wiz 2039: * Input:
2040: * gnp the node to which the command is to be added
2041: * cmd the command to add
2042: *
1.1 cgd 2043: * Results:
2044: * Always 0
2045: *
2046: * Side Effects:
1.195 christos 2047: * A new element is added to the commands list of the node,
2048: * and the node can be marked as a submake node if the command is
2049: * determined to be that.
1.1 cgd 2050: */
1.5 cgd 2051: static int
1.157 dsl 2052: ParseAddCmd(void *gnp, void *cmd)
1.9 jtc 2053: {
1.105 christos 2054: GNode *gn = (GNode *)gnp;
1.120 dsl 2055:
2056: /* Add to last (ie current) cohort for :: targets */
1.268 rillig 2057: if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts))
1.274 rillig 2058: gn = LstNode_Datum(Lst_Last(gn->cohorts));
1.120 dsl 2059:
1.203 joerg 2060: /* if target already supplied, ignore commands */
2061: if (!(gn->type & OP_HAS_COMMANDS)) {
1.268 rillig 2062: Lst_Append(gn->commands, cmd);
1.203 joerg 2063: if (ParseMaybeSubMake(cmd))
2064: gn->type |= OP_SUBMAKE;
2065: ParseMark(gn);
2066: } else {
2067: #ifdef notyet
2068: /* XXX: We cannot do this until we fix the tree */
1.268 rillig 2069: Lst_Append(gn->commands, cmd);
1.203 joerg 2070: Parse_Error(PARSE_WARNING,
2071: "overriding commands for target \"%s\"; "
2072: "previous commands defined at %s: %d ignored",
2073: gn->name, gn->fname, gn->lineno);
2074: #else
2075: Parse_Error(PARSE_WARNING,
2076: "duplicate script for target \"%s\" ignored",
2077: gn->name);
2078: ParseErrorInternal(gn->fname, gn->lineno, PARSE_WARNING,
2079: "using previous script for \"%s\" defined here",
2080: gn->name);
2081: #endif
1.200 christos 2082: }
1.235 rillig 2083: return 0;
1.1 cgd 2084: }
2085:
1.284 rillig 2086: /* Callback procedure for Parse_File when destroying the list of targets on
2087: * the last dependency line. Marks a target as already having commands if it
2088: * does, to keep from having shell commands on multiple dependency lines. */
1.9 jtc 2089: static void
1.157 dsl 2090: ParseHasCommands(void *gnp)
1.1 cgd 2091: {
1.105 christos 2092: GNode *gn = (GNode *)gnp;
1.268 rillig 2093: if (!Lst_IsEmpty(gn->commands)) {
1.1 cgd 2094: gn->type |= OP_HAS_COMMANDS;
2095: }
2096: }
2097:
1.284 rillig 2098: /* Add a directory to the path searched for included makefiles bracketed
2099: * by double-quotes. */
1.1 cgd 2100: void
1.84 wiz 2101: Parse_AddIncludeDir(char *dir)
1.1 cgd 2102: {
1.103 christos 2103: (void)Dir_AddDir(parseIncPath, dir);
1.1 cgd 2104: }
2105:
1.284 rillig 2106: /* Push to another file.
1.1 cgd 2107: *
1.284 rillig 2108: * The input is the line minus the '.'. A file spec is a string enclosed in
2109: * <> or "". The <> file is looked for only in sysIncPath. The "" file is
2110: * first searched in the parsedir and then in the directories specified by
2111: * the -I command line options.
1.1 cgd 2112: */
2113: static void
1.210 sjg 2114: Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent)
1.1 cgd 2115: {
1.170 dholland 2116: struct loadedfile *lf;
1.1 cgd 2117: char *fullname; /* full pathname of file */
1.140 dsl 2118: char *newName;
2119: char *prefEnd, *incdir;
1.125 dsl 2120: int fd;
1.140 dsl 2121: int i;
1.1 cgd 2122:
2123: /*
2124: * Now we know the file's name and its search path, we attempt to
2125: * find the durn thing. A return of NULL indicates the file don't
2126: * exist.
2127: */
1.147 joerg 2128: fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
1.76 reinoud 2129:
1.140 dsl 2130: if (fullname == NULL && !isSystem) {
1.1 cgd 2131: /*
2132: * Include files contained in double-quotes are first searched for
2133: * relative to the including file's location. We don't want to
2134: * cd there, of course, so we just tack on the old file's
2135: * leading path components and call Dir_FindFile to see if
2136: * we can locate the beast.
2137: */
2138:
1.147 joerg 2139: incdir = bmake_strdup(curFile->fname);
1.140 dsl 2140: prefEnd = strrchr(incdir, '/');
1.105 christos 2141: if (prefEnd != NULL) {
1.1 cgd 2142: *prefEnd = '\0';
1.140 dsl 2143: /* Now do lexical processing of leading "../" on the filename */
2144: for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
2145: prefEnd = strrchr(incdir + 1, '/');
2146: if (prefEnd == NULL || strcmp(prefEnd, "/..") == 0)
2147: break;
2148: *prefEnd = '\0';
2149: }
1.251 rillig 2150: newName = str_concat3(incdir, "/", file + i);
1.97 christos 2151: fullname = Dir_FindFile(newName, parseIncPath);
1.140 dsl 2152: if (fullname == NULL)
1.1 cgd 2153: fullname = Dir_FindFile(newName, dirSearchPath);
1.103 christos 2154: free(newName);
1.1 cgd 2155: }
1.140 dsl 2156: free(incdir);
2157:
1.142 sjg 2158: if (fullname == NULL) {
1.76 reinoud 2159: /*
1.246 rillig 2160: * Makefile wasn't found in same directory as included makefile.
1.76 reinoud 2161: * Search for it first on the -I search path,
2162: * then on the .PATH search path, if not found in a -I directory.
1.142 sjg 2163: * If we have a suffix specific path we should use that.
1.76 reinoud 2164: */
1.142 sjg 2165: char *suff;
1.152 dsl 2166: Lst suffPath = NULL;
1.142 sjg 2167:
1.145 christos 2168: if ((suff = strrchr(file, '.'))) {
1.142 sjg 2169: suffPath = Suff_GetPath(suff);
1.152 dsl 2170: if (suffPath != NULL) {
1.142 sjg 2171: fullname = Dir_FindFile(file, suffPath);
2172: }
2173: }
1.105 christos 2174: if (fullname == NULL) {
1.142 sjg 2175: fullname = Dir_FindFile(file, parseIncPath);
2176: if (fullname == NULL) {
2177: fullname = Dir_FindFile(file, dirSearchPath);
2178: }
1.76 reinoud 2179: }
1.142 sjg 2180: }
1.1 cgd 2181: }
2182:
1.76 reinoud 2183: /* Looking for a system file or file still not found */
1.105 christos 2184: if (fullname == NULL) {
1.1 cgd 2185: /*
1.76 reinoud 2186: * Look for it on the system path
1.1 cgd 2187: */
1.123 dsl 2188: fullname = Dir_FindFile(file,
1.268 rillig 2189: Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1.1 cgd 2190: }
2191:
1.105 christos 2192: if (fullname == NULL) {
1.38 christos 2193: if (!silent)
1.97 christos 2194: Parse_Error(PARSE_FATAL, "Could not find %s", file);
1.1 cgd 2195: return;
2196: }
2197:
1.125 dsl 2198: /* Actually open the file... */
2199: fd = open(fullname, O_RDONLY);
2200: if (fd == -1) {
1.38 christos 2201: if (!silent)
1.97 christos 2202: Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1.140 dsl 2203: free(fullname);
1.125 dsl 2204: return;
1.123 dsl 2205: }
1.125 dsl 2206:
1.170 dholland 2207: /* load it */
2208: lf = loadfile(fullname, fd);
2209:
1.125 dsl 2210: /* Start reading from this file next */
1.170 dholland 2211: Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
2212: curFile->lf = lf;
1.210 sjg 2213: if (depinc)
2214: doing_depend = depinc; /* only turn it on */
1.123 dsl 2215: }
2216:
2217: static void
2218: ParseDoInclude(char *line)
2219: {
2220: char endc; /* the character which ends the file spec */
2221: char *cp; /* current position in file spec */
1.242 rillig 2222: int silent = *line != 'i';
1.123 dsl 2223: char *file = &line[7 + silent];
2224:
2225: /* Skip to delimiter character so we know where to look */
2226: while (*file == ' ' || *file == '\t')
2227: file++;
2228:
2229: if (*file != '"' && *file != '<') {
2230: Parse_Error(PARSE_FATAL,
2231: ".include filename must be delimited by '\"' or '<'");
2232: return;
2233: }
2234:
2235: /*
2236: * Set the search path on which to find the include file based on the
2237: * characters which bracket its name. Angle-brackets imply it's
2238: * a system Makefile while double-quotes imply it's a user makefile
2239: */
2240: if (*file == '<') {
2241: endc = '>';
2242: } else {
2243: endc = '"';
2244: }
2245:
2246: /* Skip to matching delimiter */
2247: for (cp = ++file; *cp && *cp != endc; cp++)
2248: continue;
2249:
2250: if (*cp != endc) {
2251: Parse_Error(PARSE_FATAL,
2252: "Unclosed %cinclude filename. '%c' expected",
2253: '.', endc);
2254: return;
1.1 cgd 2255: }
1.123 dsl 2256: *cp = '\0';
2257:
2258: /*
2259: * Substitute for any variables in the file name before trying to
2260: * find the thing.
2261: */
1.239 rillig 2262: file = Var_Subst(file, VAR_CMD, VARE_WANTRES);
1.123 dsl 2263:
1.242 rillig 2264: Parse_include_file(file, endc == '>', *line == 'd', silent);
1.123 dsl 2265: free(file);
1.1 cgd 2266: }
2267:
1.281 rillig 2268: /* Split filename into dirname + basename, then assign these to the
2269: * given variables. */
1.193 christos 2270: static void
1.281 rillig 2271: SetFilenameVars(const char *filename, const char *dirvar, const char *filevar)
1.193 christos 2272: {
1.281 rillig 2273: const char *slash, *dirname, *basename;
2274: void *freeIt;
2275:
2276: slash = strrchr(filename, '/');
2277: if (slash == NULL) {
2278: dirname = curdir;
2279: basename = filename;
2280: freeIt = NULL;
2281: } else {
2282: dirname = freeIt = bmake_strsedup(filename, slash);
2283: basename = slash + 1;
2284: }
1.193 christos 2285:
1.281 rillig 2286: Var_Set(dirvar, dirname, VAR_GLOBAL);
2287: Var_Set(filevar, basename, VAR_GLOBAL);
1.193 christos 2288:
2289: if (DEBUG(PARSE))
1.281 rillig 2290: fprintf(debug_file, "%s: ${%s} = `%s' ${%s} = `%s'\n",
2291: __func__, dirvar, dirname, filevar, basename);
2292: free(freeIt);
2293: }
2294:
2295: /* Return the immediately including file.
2296: *
2297: * This is made complicated since the .for loop is implemented as a special
2298: * kind of .include; see For_Run. */
2299: static const char *
2300: GetActuallyIncludingFile(void)
2301: {
2302: size_t i;
1.193 christos 2303:
1.281 rillig 2304: /* XXX: Stack was supposed to be an opaque data structure. */
1.282 rillig 2305: for (i = includes.len; i > 0; i--) {
2306: IFile *parent = includes.items[i - 1];
1.284 rillig 2307: IFile *child = i < includes.len ? includes.items[i] : curFile;
1.281 rillig 2308: if (!child->fromForLoop)
1.282 rillig 2309: return parent->fname;
1.281 rillig 2310: }
1.282 rillig 2311: return NULL;
1.193 christos 2312: }
1.281 rillig 2313:
1.285 rillig 2314: /* Set .PARSEDIR, .PARSEFILE, .INCLUDEDFROMDIR and .INCLUDEDFROMFILE. */
1.44 aidan 2315: static void
1.122 dsl 2316: ParseSetParseFile(const char *filename)
1.44 aidan 2317: {
1.281 rillig 2318: const char *including;
1.44 aidan 2319:
1.281 rillig 2320: SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE");
2321:
2322: including = GetActuallyIncludingFile();
2323: if (including != NULL) {
2324: SetFilenameVars(including,
2325: ".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE");
1.44 aidan 2326: } else {
1.281 rillig 2327: Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
2328: Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
1.44 aidan 2329: }
2330: }
2331:
1.284 rillig 2332: /* Track the makefiles we read - so makefiles can set dependencies on them.
2333: * Avoid adding anything more than once. */
1.184 sjg 2334: static void
2335: ParseTrackInput(const char *name)
2336: {
2337: char *fp = NULL;
1.236 rillig 2338:
1.244 rillig 2339: const char *old = Var_Value(MAKE_MAKEFILES, VAR_GLOBAL, &fp);
1.184 sjg 2340: if (old) {
1.244 rillig 2341: size_t name_len = strlen(name);
2342: const char *ep = old + strlen(old) - name_len;
1.184 sjg 2343: /* does it contain name? */
2344: for (; old != NULL; old = strchr(old, ' ')) {
2345: if (*old == ' ')
2346: old++;
1.206 sjg 2347: if (old >= ep)
2348: break; /* cannot contain name */
1.184 sjg 2349: if (memcmp(old, name, name_len) == 0
2350: && (old[name_len] == 0 || old[name_len] == ' '))
2351: goto cleanup;
2352: }
2353: }
2354: Var_Append (MAKE_MAKEFILES, name, VAR_GLOBAL);
2355: cleanup:
1.245 rillig 2356: bmake_free(fp);
1.184 sjg 2357: }
1.137 sjg 2358:
1.44 aidan 2359:
1.276 rillig 2360: /* Start Parsing from the given source.
1.5 cgd 2361: *
1.276 rillig 2362: * The given file is added to the includes stack. */
1.5 cgd 2363: void
1.170 dholland 2364: Parse_SetInput(const char *name, int line, int fd,
2365: char *(*nextbuf)(void *, size_t *), void *arg)
1.5 cgd 2366: {
1.155 dsl 2367: char *buf;
1.170 dholland 2368: size_t len;
1.281 rillig 2369: Boolean fromForLoop = name == NULL;
1.155 dsl 2370:
1.281 rillig 2371: if (fromForLoop)
1.127 dsl 2372: name = curFile->fname;
1.139 dsl 2373: else
1.184 sjg 2374: ParseTrackInput(name);
1.127 dsl 2375:
2376: if (DEBUG(PARSE))
1.288 rillig 2377: fprintf(debug_file, "%s: file %s, line %d, fd %d, nextbuf %s, arg %p\n",
2378: __func__, name, line, fd,
2379: nextbuf == loadedfile_nextbuf ? "loadedfile" : "other", arg);
1.127 dsl 2380:
1.155 dsl 2381: if (fd == -1 && nextbuf == NULL)
1.125 dsl 2382: /* sanity */
2383: return;
2384:
1.132 dsl 2385: if (curFile != NULL)
1.281 rillig 2386: /* Save existing file info */
1.276 rillig 2387: Stack_Push(&includes, curFile);
1.5 cgd 2388:
1.125 dsl 2389: /* Allocate and fill in new structure */
1.147 joerg 2390: curFile = bmake_malloc(sizeof *curFile);
1.125 dsl 2391:
2392: /*
2393: * Once the previous state has been saved, we can get down to reading
2394: * the new file. We set up the name of the file to be the absolute
2395: * name of the include file so error messages refer to the right
2396: * place.
2397: */
1.189 sjg 2398: curFile->fname = bmake_strdup(name);
1.281 rillig 2399: curFile->fromForLoop = fromForLoop;
1.125 dsl 2400: curFile->lineno = line;
1.155 dsl 2401: curFile->first_lineno = line;
2402: curFile->nextbuf = nextbuf;
2403: curFile->nextbuf_arg = arg;
1.170 dholland 2404: curFile->lf = NULL;
1.212 sjg 2405: curFile->depending = doing_depend; /* restore this on EOF */
1.170 dholland 2406:
2407: assert(nextbuf != NULL);
1.125 dsl 2408:
1.170 dholland 2409: /* Get first block of input data */
2410: buf = curFile->nextbuf(curFile->nextbuf_arg, &len);
2411: if (buf == NULL) {
1.246 rillig 2412: /* Was all a waste of time ... */
1.189 sjg 2413: if (curFile->fname)
2414: free(curFile->fname);
1.170 dholland 2415: free(curFile);
2416: return;
1.125 dsl 2417: }
1.170 dholland 2418: curFile->P_str = buf;
2419: curFile->P_ptr = buf;
2420: curFile->P_end = buf+len;
1.5 cgd 2421:
1.155 dsl 2422: curFile->cond_depth = Cond_save_depth();
2423: ParseSetParseFile(name);
1.5 cgd 2424: }
2425:
1.284 rillig 2426: /* Check if the line is an include directive. */
1.228 christos 2427: static Boolean
2428: IsInclude(const char *line, Boolean sysv)
2429: {
2430: static const char inc[] = "include";
2431: static const size_t inclen = sizeof(inc) - 1;
2432:
1.248 rillig 2433: /* 'd' is not valid for sysv */
1.269 rillig 2434: int o = strchr(sysv ? "s-" : "ds-", *line) != NULL;
1.228 christos 2435:
2436: if (strncmp(line + o, inc, inclen) != 0)
2437: return FALSE;
2438:
1.248 rillig 2439: /* Space is not mandatory for BSD .include */
1.290 rillig 2440: return !sysv || ch_isspace(line[inclen + o]);
1.228 christos 2441: }
2442:
2443:
1.5 cgd 2444: #ifdef SYSVINCLUDE
1.284 rillig 2445: /* Check if the line is a SYSV include directive. */
1.228 christos 2446: static Boolean
2447: IsSysVInclude(const char *line)
2448: {
2449: const char *p;
2450:
2451: if (!IsInclude(line, TRUE))
2452: return FALSE;
2453:
2454: /* Avoid interpeting a dependency line as an include */
2455: for (p = line; (p = strchr(p, ':')) != NULL;) {
2456: if (*++p == '\0') {
2457: /* end of line -> dependency */
2458: return FALSE;
2459: }
1.290 rillig 2460: if (*p == ':' || ch_isspace(*p)) {
1.228 christos 2461: /* :: operator or ': ' -> dependency */
2462: return FALSE;
2463: }
2464: }
2465: return TRUE;
2466: }
2467:
1.284 rillig 2468: /* Push to another file. The line points to the word "include". */
1.5 cgd 2469: static void
1.84 wiz 2470: ParseTraditionalInclude(char *line)
1.5 cgd 2471: {
2472: char *cp; /* current position in file spec */
1.38 christos 2473: int done = 0;
1.242 rillig 2474: int silent = line[0] != 'i';
1.38 christos 2475: char *file = &line[silent + 7];
1.123 dsl 2476: char *all_files;
1.5 cgd 2477:
1.284 rillig 2478: if (DEBUG(PARSE))
2479: fprintf(debug_file, "%s: %s\n", __func__, file);
1.111 ginsbach 2480:
1.5 cgd 2481: /*
2482: * Skip over whitespace
2483: */
1.290 rillig 2484: while (ch_isspace(*file))
1.5 cgd 2485: file++;
2486:
1.111 ginsbach 2487: /*
2488: * Substitute for any variables in the file name before trying to
2489: * find the thing.
2490: */
1.239 rillig 2491: all_files = Var_Subst(file, VAR_CMD, VARE_WANTRES);
1.111 ginsbach 2492:
1.5 cgd 2493: if (*file == '\0') {
1.97 christos 2494: Parse_Error(PARSE_FATAL,
1.5 cgd 2495: "Filename missing from \"include\"");
1.224 riastrad 2496: goto out;
1.5 cgd 2497: }
2498:
1.123 dsl 2499: for (file = all_files; !done; file = cp + 1) {
2500: /* Skip to end of line or next whitespace */
1.290 rillig 2501: for (cp = file; *cp && !ch_isspace(*cp); cp++)
1.38 christos 2502: continue;
2503:
2504: if (*cp)
2505: *cp = '\0';
2506: else
2507: done = 1;
2508:
1.210 sjg 2509: Parse_include_file(file, FALSE, FALSE, silent);
1.5 cgd 2510: }
1.224 riastrad 2511: out:
1.123 dsl 2512: free(all_files);
1.5 cgd 2513: }
2514: #endif
2515:
1.183 sjg 2516: #ifdef GMAKEEXPORT
1.284 rillig 2517: /* Parse export <variable>=<value>, and actually export it. */
1.182 christos 2518: static void
2519: ParseGmakeExport(char *line)
2520: {
2521: char *variable = &line[6];
2522: char *value;
2523:
1.284 rillig 2524: if (DEBUG(PARSE))
2525: fprintf(debug_file, "%s: %s\n", __func__, variable);
1.182 christos 2526:
2527: /*
2528: * Skip over whitespace
2529: */
1.290 rillig 2530: while (ch_isspace(*variable))
1.182 christos 2531: variable++;
2532:
2533: for (value = variable; *value && *value != '='; value++)
2534: continue;
2535:
2536: if (*value != '=') {
2537: Parse_Error(PARSE_FATAL,
1.284 rillig 2538: "Variable/Value missing from \"export\"");
1.182 christos 2539: return;
2540: }
1.188 sjg 2541: *value++ = '\0'; /* terminate variable */
1.182 christos 2542:
2543: /*
1.183 sjg 2544: * Expand the value before putting it in the environment.
1.182 christos 2545: */
1.239 rillig 2546: value = Var_Subst(value, VAR_CMD, VARE_WANTRES);
1.182 christos 2547: setenv(variable, value, 1);
1.223 riastrad 2548: free(value);
1.182 christos 2549: }
2550: #endif
2551:
1.284 rillig 2552: /* Called when EOF is reached in the current file. If we were reading an
2553: * include file, the includes stack is popped and things set up to go back
2554: * to reading the previous file at the previous location.
1.1 cgd 2555: *
2556: * Results:
2557: * CONTINUE if there's more to do. DONE if not.
2558: */
2559: static int
1.123 dsl 2560: ParseEOF(void)
1.1 cgd 2561: {
1.155 dsl 2562: char *ptr;
1.170 dholland 2563: size_t len;
2564:
2565: assert(curFile->nextbuf != NULL);
1.155 dsl 2566:
1.210 sjg 2567: doing_depend = curFile->depending; /* restore this */
1.170 dholland 2568: /* get next input buffer, if any */
2569: ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
2570: curFile->P_ptr = ptr;
2571: curFile->P_str = ptr;
2572: curFile->P_end = ptr + len;
2573: curFile->lineno = curFile->first_lineno;
2574: if (ptr != NULL) {
2575: /* Iterate again */
2576: return CONTINUE;
1.155 dsl 2577: }
2578:
1.132 dsl 2579: /* Ensure the makefile (or loop) didn't have mismatched conditionals */
2580: Cond_restore_depth(curFile->cond_depth);
1.131 dsl 2581:
1.170 dholland 2582: if (curFile->lf != NULL) {
2583: loadedfile_destroy(curFile->lf);
2584: curFile->lf = NULL;
2585: }
2586:
1.125 dsl 2587: /* Dispose of curFile info */
2588: /* Leak curFile->fname because all the gnodes have pointers to it */
2589: free(curFile->P_str);
2590: free(curFile);
2591:
1.276 rillig 2592: if (Stack_IsEmpty(&includes)) {
1.258 rillig 2593: curFile = NULL;
1.125 dsl 2594: /* We've run out of input */
1.44 aidan 2595: Var_Delete(".PARSEDIR", VAR_GLOBAL);
2596: Var_Delete(".PARSEFILE", VAR_GLOBAL);
1.194 christos 2597: Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
2598: Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
1.125 dsl 2599: return DONE;
1.1 cgd 2600: }
2601:
1.276 rillig 2602: curFile = Stack_Pop(&includes);
1.127 dsl 2603: if (DEBUG(PARSE))
1.170 dholland 2604: fprintf(debug_file, "ParseEOF: returning to file %s, line %d\n",
2605: curFile->fname, curFile->lineno);
1.127 dsl 2606:
1.125 dsl 2607: ParseSetParseFile(curFile->fname);
1.235 rillig 2608: return CONTINUE;
1.1 cgd 2609: }
2610:
1.127 dsl 2611: #define PARSE_RAW 1
2612: #define PARSE_SKIP 2
2613:
2614: static char *
2615: ParseGetLine(int flags, int *length)
1.5 cgd 2616: {
1.125 dsl 2617: IFile *cf = curFile;
1.127 dsl 2618: char *ptr;
1.125 dsl 2619: char ch;
1.127 dsl 2620: char *line;
2621: char *line_end;
2622: char *escaped;
2623: char *comment;
2624: char *tp;
1.125 dsl 2625:
1.127 dsl 2626: /* Loop through blank lines and comment lines */
1.125 dsl 2627: for (;;) {
1.127 dsl 2628: cf->lineno++;
2629: line = cf->P_ptr;
2630: ptr = line;
2631: line_end = line;
2632: escaped = NULL;
2633: comment = NULL;
2634: for (;;) {
1.170 dholland 2635: if (cf->P_end != NULL && ptr == cf->P_end) {
2636: /* end of buffer */
2637: ch = 0;
2638: break;
2639: }
1.127 dsl 2640: ch = *ptr;
2641: if (ch == 0 || (ch == '\\' && ptr[1] == 0)) {
2642: if (cf->P_end == NULL)
2643: /* End of string (aka for loop) data */
2644: break;
1.190 sjg 2645: /* see if there is more we can parse */
2646: while (ptr++ < cf->P_end) {
2647: if ((ch = *ptr) == '\n') {
2648: if (ptr > line && ptr[-1] == '\\')
2649: continue;
2650: Parse_Error(PARSE_WARNING,
2651: "Zero byte read from file, skipping rest of line.");
2652: break;
2653: }
2654: }
1.170 dholland 2655: if (cf->nextbuf != NULL) {
2656: /*
2657: * End of this buffer; return EOF and outer logic
2658: * will get the next one. (eww)
2659: */
1.127 dsl 2660: break;
2661: }
1.170 dholland 2662: Parse_Error(PARSE_FATAL, "Zero byte read from file");
2663: return NULL;
1.127 dsl 2664: }
2665:
2666: if (ch == '\\') {
2667: /* Don't treat next character as special, remember first one */
2668: if (escaped == NULL)
2669: escaped = ptr;
2670: if (ptr[1] == '\n')
2671: cf->lineno++;
2672: ptr += 2;
2673: line_end = ptr;
2674: continue;
2675: }
2676: if (ch == '#' && comment == NULL) {
2677: /* Remember first '#' for comment stripping */
1.181 sjg 2678: /* Unless previous char was '[', as in modifier :[#] */
2679: if (!(ptr > line && ptr[-1] == '['))
2680: comment = line_end;
1.127 dsl 2681: }
2682: ptr++;
1.125 dsl 2683: if (ch == '\n')
1.127 dsl 2684: break;
1.290 rillig 2685: if (!ch_isspace(ch))
1.127 dsl 2686: /* We are not interested in trailing whitespace */
2687: line_end = ptr;
2688: }
1.125 dsl 2689:
1.127 dsl 2690: /* Save next 'to be processed' location */
2691: cf->P_ptr = ptr;
2692:
2693: /* Check we have a non-comment, non-blank line */
2694: if (line_end == line || comment == line) {
2695: if (ch == 0)
2696: /* At end of file */
2697: return NULL;
2698: /* Parse another line */
1.125 dsl 2699: continue;
1.127 dsl 2700: }
1.125 dsl 2701:
1.127 dsl 2702: /* We now have a line of data */
2703: *line_end = 0;
1.27 christos 2704:
1.127 dsl 2705: if (flags & PARSE_RAW) {
2706: /* Leave '\' (etc) in line buffer (eg 'for' lines) */
2707: *length = line_end - line;
2708: return line;
2709: }
1.5 cgd 2710:
1.127 dsl 2711: if (flags & PARSE_SKIP) {
2712: /* Completely ignore non-directives */
2713: if (line[0] != '.')
2714: continue;
2715: /* We could do more of the .else/.elif/.endif checks here */
2716: }
2717: break;
2718: }
1.5 cgd 2719:
1.127 dsl 2720: /* Brutally ignore anything after a non-escaped '#' in non-commands */
2721: if (comment != NULL && line[0] != '\t') {
2722: line_end = comment;
2723: *line_end = 0;
2724: }
1.5 cgd 2725:
1.127 dsl 2726: /* If we didn't see a '\\' then the in-situ data is fine */
2727: if (escaped == NULL) {
2728: *length = line_end - line;
2729: return line;
2730: }
1.5 cgd 2731:
1.127 dsl 2732: /* Remove escapes from '\n' and '#' */
2733: tp = ptr = escaped;
2734: escaped = line;
2735: for (; ; *tp++ = ch) {
2736: ch = *ptr++;
2737: if (ch != '\\') {
2738: if (ch == 0)
2739: break;
2740: continue;
2741: }
1.5 cgd 2742:
1.127 dsl 2743: ch = *ptr++;
2744: if (ch == 0) {
2745: /* Delete '\\' at end of buffer */
2746: tp--;
2747: break;
2748: }
1.27 christos 2749:
1.130 dsl 2750: if (ch == '#' && line[0] != '\t')
2751: /* Delete '\\' from before '#' on non-command lines */
1.127 dsl 2752: continue;
1.27 christos 2753:
1.127 dsl 2754: if (ch != '\n') {
2755: /* Leave '\\' in buffer for later */
2756: *tp++ = '\\';
2757: /* Make sure we don't delete an escaped ' ' from the line end */
2758: escaped = tp + 1;
2759: continue;
2760: }
1.27 christos 2761:
1.203 joerg 2762: /* Escaped '\n' replace following whitespace with a single ' ' */
2763: while (ptr[0] == ' ' || ptr[0] == '\t')
2764: ptr++;
2765: ch = ' ';
1.127 dsl 2766: }
1.27 christos 2767:
1.127 dsl 2768: /* Delete any trailing spaces - eg from empty continuations */
1.290 rillig 2769: while (tp > escaped && ch_isspace(tp[-1]))
1.127 dsl 2770: tp--;
1.27 christos 2771:
1.127 dsl 2772: *tp = 0;
2773: *length = tp - line;
1.5 cgd 2774: return line;
2775: }
1.1 cgd 2776:
1.284 rillig 2777: /* Read an entire line from the input file. Called only by Parse_File.
1.1 cgd 2778: *
2779: * Results:
1.284 rillig 2780: * A line without its newline.
1.1 cgd 2781: *
2782: * Side Effects:
2783: * Only those associated with reading a character
2784: */
2785: static char *
1.84 wiz 2786: ParseReadLine(void)
1.1 cgd 2787: {
1.9 jtc 2788: char *line; /* Result */
1.1 cgd 2789: int lineLength; /* Length of result */
1.95 enami 2790: int lineno; /* Saved line # */
1.151 dsl 2791: int rval;
1.1 cgd 2792:
1.5 cgd 2793: for (;;) {
1.127 dsl 2794: line = ParseGetLine(0, &lineLength);
2795: if (line == NULL)
2796: return NULL;
1.1 cgd 2797:
1.127 dsl 2798: if (line[0] != '.')
2799: return line;
1.121 dsl 2800:
2801: /*
1.127 dsl 2802: * The line might be a conditional. Ask the conditional module
2803: * about it and act accordingly
1.121 dsl 2804: */
1.127 dsl 2805: switch (Cond_Eval(line)) {
2806: case COND_SKIP:
2807: /* Skip to next conditional that evaluates to COND_PARSE. */
2808: do {
2809: line = ParseGetLine(PARSE_SKIP, &lineLength);
2810: } while (line && Cond_Eval(line) != COND_PARSE);
2811: if (line == NULL)
1.121 dsl 2812: break;
1.127 dsl 2813: continue;
2814: case COND_PARSE:
2815: continue;
2816: case COND_INVALID: /* Not a conditional line */
1.151 dsl 2817: /* Check for .for loops */
2818: rval = For_Eval(line);
2819: if (rval == 0)
2820: /* Not a .for line */
1.1 cgd 2821: break;
1.151 dsl 2822: if (rval < 0)
2823: /* Syntax error - error printed, ignore line */
2824: continue;
2825: /* Start of a .for loop */
1.127 dsl 2826: lineno = curFile->lineno;
1.151 dsl 2827: /* Accumulate loop lines until matching .endfor */
1.121 dsl 2828: do {
1.127 dsl 2829: line = ParseGetLine(PARSE_RAW, &lineLength);
1.121 dsl 2830: if (line == NULL) {
2831: Parse_Error(PARSE_FATAL,
1.174 dholland 2832: "Unexpected end of file in for loop.");
1.5 cgd 2833: break;
1.121 dsl 2834: }
1.151 dsl 2835: } while (For_Accum(line));
1.127 dsl 2836: /* Stash each iteration as a new 'input file' */
2837: For_Run(lineno);
2838: /* Read next line from for-loop buffer */
2839: continue;
1.1 cgd 2840: }
1.235 rillig 2841: return line;
1.1 cgd 2842: }
2843: }
2844:
1.293 rillig 2845: static int
2846: SuffEndTransform(void *target, void *unused MAKE_ATTR_UNUSED)
2847: {
2848: Suff_EndTransform(target);
2849: return 0;
2850: }
2851:
1.1 cgd 2852: /*-
2853: *-----------------------------------------------------------------------
2854: * ParseFinishLine --
2855: * Handle the end of a dependency group.
2856: *
2857: * Results:
2858: * Nothing.
2859: *
2860: * Side Effects:
2861: * inLine set FALSE. 'targets' list destroyed.
2862: *
2863: *-----------------------------------------------------------------------
2864: */
2865: static void
1.84 wiz 2866: ParseFinishLine(void)
1.1 cgd 2867: {
2868: if (inLine) {
1.292 rillig 2869: if (targets != NULL) {
1.293 rillig 2870: Lst_ForEach(targets, SuffEndTransform, NULL);
1.268 rillig 2871: Lst_Destroy(targets, ParseHasCommands);
1.263 rillig 2872: }
1.9 jtc 2873: targets = NULL;
1.1 cgd 2874: inLine = FALSE;
2875: }
2876: }
1.27 christos 2877:
1.1 cgd 2878:
2879: /*-
2880: *---------------------------------------------------------------------
2881: * Parse_File --
2882: * Parse a file into its component parts, incorporating it into the
2883: * current dependency graph. This is the main function and controls
2884: * almost every other function in this module
2885: *
1.84 wiz 2886: * Input:
2887: * name the name of the file being read
1.125 dsl 2888: * fd Open file to makefile to parse
1.84 wiz 2889: *
1.1 cgd 2890: * Results:
2891: * None
2892: *
2893: * Side Effects:
1.125 dsl 2894: * closes fd.
1.1 cgd 2895: * Loads. Nodes are added to the list of all targets, nodes and links
2896: * are added to the dependency graph. etc. etc. etc.
2897: *---------------------------------------------------------------------
2898: */
2899: void
1.125 dsl 2900: Parse_File(const char *name, int fd)
1.1 cgd 2901: {
1.117 dsl 2902: char *cp; /* pointer into the line */
2903: char *line; /* the line we're working on */
1.170 dholland 2904: struct loadedfile *lf;
2905:
2906: lf = loadfile(name, fd);
1.1 cgd 2907:
2908: inLine = FALSE;
2909: fatals = 0;
1.44 aidan 2910:
1.242 rillig 2911: if (name == NULL)
2912: name = "(stdin)";
1.170 dholland 2913:
2914: Parse_SetInput(name, 0, -1, loadedfile_nextbuf, lf);
2915: curFile->lf = lf;
1.1 cgd 2916:
2917: do {
1.127 dsl 2918: for (; (line = ParseReadLine()) != NULL; ) {
1.120 dsl 2919: if (DEBUG(PARSE))
1.145 christos 2920: fprintf(debug_file, "ParseReadLine (%d): '%s'\n",
2921: curFile->lineno, line);
1.1 cgd 2922: if (*line == '.') {
2923: /*
1.159 dsl 2924: * Lines that begin with the special character may be
1.1 cgd 2925: * include or undef directives.
1.159 dsl 2926: * On the other hand they can be suffix rules (.c.o: ...)
2927: * or just dependencies for filenames that start '.'.
1.1 cgd 2928: */
1.290 rillig 2929: for (cp = line + 1; ch_isspace(*cp); cp++) {
1.1 cgd 2930: continue;
2931: }
1.228 christos 2932: if (IsInclude(cp, FALSE)) {
1.97 christos 2933: ParseDoInclude(cp);
1.117 dsl 2934: continue;
2935: }
2936: if (strncmp(cp, "undef", 5) == 0) {
1.1 cgd 2937: char *cp2;
1.290 rillig 2938: for (cp += 5; ch_isspace(*cp); cp++)
1.1 cgd 2939: continue;
1.290 rillig 2940: for (cp2 = cp; !ch_isspace(*cp2) && *cp2 != '\0'; cp2++)
1.1 cgd 2941: continue;
2942: *cp2 = '\0';
2943: Var_Delete(cp, VAR_GLOBAL);
1.117 dsl 2944: continue;
1.136 sjg 2945: } else if (strncmp(cp, "export", 6) == 0) {
1.290 rillig 2946: for (cp += 6; ch_isspace(*cp); cp++)
1.136 sjg 2947: continue;
1.250 rillig 2948: Var_Export(cp, TRUE);
1.136 sjg 2949: continue;
1.160 sjg 2950: } else if (strncmp(cp, "unexport", 8) == 0) {
2951: Var_UnExport(cp);
2952: continue;
1.161 sjg 2953: } else if (strncmp(cp, "info", 4) == 0 ||
2954: strncmp(cp, "error", 5) == 0 ||
2955: strncmp(cp, "warning", 7) == 0) {
1.164 sjg 2956: if (ParseMessage(cp))
2957: continue;
1.236 rillig 2958: }
1.1 cgd 2959: }
1.27 christos 2960:
1.6 jtc 2961: if (*line == '\t') {
1.1 cgd 2962: /*
1.6 jtc 2963: * If a line starts with a tab, it can only hope to be
2964: * a creation command.
1.1 cgd 2965: */
1.133 dsl 2966: cp = line + 1;
1.127 dsl 2967: shellCommand:
1.290 rillig 2968: for (; ch_isspace(*cp); cp++) {
1.1 cgd 2969: continue;
2970: }
2971: if (*cp) {
1.117 dsl 2972: if (!inLine)
1.97 christos 2973: Parse_Error(PARSE_FATAL,
1.25 christos 2974: "Unassociated shell command \"%s\"",
1.1 cgd 2975: cp);
1.117 dsl 2976: /*
2977: * So long as it's not a blank line and we're actually
2978: * in a dependency spec, add the command to the list of
2979: * commands of all targets in the dependency spec
2980: */
1.129 christos 2981: if (targets) {
1.147 joerg 2982: cp = bmake_strdup(cp);
1.268 rillig 2983: Lst_ForEach(targets, ParseAddCmd, cp);
1.117 dsl 2984: #ifdef CLEANUP
1.268 rillig 2985: Lst_Append(targCmds, cp);
1.117 dsl 2986: #endif
1.129 christos 2987: }
1.1 cgd 2988: }
1.117 dsl 2989: continue;
2990: }
2991:
1.5 cgd 2992: #ifdef SYSVINCLUDE
1.228 christos 2993: if (IsSysVInclude(line)) {
1.5 cgd 2994: /*
2995: * It's an S3/S5-style "include".
2996: */
1.97 christos 2997: ParseTraditionalInclude(line);
1.117 dsl 2998: continue;
2999: }
1.5 cgd 3000: #endif
1.182 christos 3001: #ifdef GMAKEEXPORT
1.290 rillig 3002: if (strncmp(line, "export", 6) == 0 && ch_isspace(line[6]) &&
1.182 christos 3003: strchr(line, ':') == NULL) {
3004: /*
1.183 sjg 3005: * It's a Gmake "export".
1.182 christos 3006: */
3007: ParseGmakeExport(line);
3008: continue;
3009: }
3010: #endif
1.117 dsl 3011: if (Parse_IsVar(line)) {
1.1 cgd 3012: ParseFinishLine();
1.97 christos 3013: Parse_DoVar(line, VAR_GLOBAL);
1.117 dsl 3014: continue;
3015: }
3016:
1.127 dsl 3017: #ifndef POSIX
1.117 dsl 3018: /*
3019: * To make life easier on novices, if the line is indented we
3020: * first make sure the line has a dependency operator in it.
3021: * If it doesn't have an operator and we're in a dependency
3022: * line's script, we assume it's actually a shell command
3023: * and add it to the current list of targets.
3024: */
3025: cp = line;
1.290 rillig 3026: if (ch_isspace(line[0])) {
3027: while (ch_isspace(*cp))
1.117 dsl 3028: cp++;
3029: while (*cp && (ParseIsEscaped(line, cp) ||
1.242 rillig 3030: *cp != ':' && *cp != '!')) {
1.117 dsl 3031: cp++;
3032: }
1.127 dsl 3033: if (*cp == '\0') {
3034: if (inLine) {
3035: Parse_Error(PARSE_WARNING,
3036: "Shell command needs a leading tab");
3037: goto shellCommand;
3038: }
3039: }
3040: }
1.11 mycroft 3041: #endif
1.127 dsl 3042: ParseFinishLine();
1.27 christos 3043:
1.127 dsl 3044: /*
3045: * For some reason - probably to make the parser impossible -
3046: * a ';' can be used to separate commands from dependencies.
1.158 sjg 3047: * Attempt to avoid ';' inside substitution patterns.
1.127 dsl 3048: */
1.158 sjg 3049: {
3050: int level = 0;
3051:
3052: for (cp = line; *cp != 0; cp++) {
3053: if (*cp == '\\' && cp[1] != 0) {
3054: cp++;
3055: continue;
3056: }
3057: if (*cp == '$' &&
3058: (cp[1] == '(' || cp[1] == '{')) {
3059: level++;
3060: continue;
3061: }
3062: if (level > 0) {
3063: if (*cp == ')' || *cp == '}') {
3064: level--;
3065: continue;
3066: }
3067: } else if (*cp == ';') {
3068: break;
3069: }
1.117 dsl 3070: }
3071: }
1.127 dsl 3072: if (*cp != 0)
3073: /* Terminate the dependency list at the ';' */
1.133 dsl 3074: *cp++ = 0;
1.127 dsl 3075: else
3076: cp = NULL;
1.1 cgd 3077:
1.127 dsl 3078: /*
3079: * We now know it's a dependency line so it needs to have all
3080: * variables expanded before being parsed. Tell the variable
3081: * module to complain if some variable is undefined...
3082: */
1.239 rillig 3083: line = Var_Subst(line, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES);
1.27 christos 3084:
1.117 dsl 3085: /*
3086: * Need a non-circular list for the target nodes
3087: */
1.263 rillig 3088: if (targets != NULL)
1.268 rillig 3089: Lst_Free(targets);
1.9 jtc 3090:
1.252 rillig 3091: targets = Lst_Init();
1.117 dsl 3092: inLine = TRUE;
1.27 christos 3093:
1.117 dsl 3094: ParseDoDependency(line);
1.127 dsl 3095: free(line);
3096:
3097: /* If there were commands after a ';', add them now */
3098: if (cp != NULL) {
3099: goto shellCommand;
3100: }
1.1 cgd 3101: }
3102: /*
1.27 christos 3103: * Reached EOF, but it may be just EOF of an include file...
1.1 cgd 3104: */
1.123 dsl 3105: } while (ParseEOF() == CONTINUE);
1.1 cgd 3106:
3107: if (fatals) {
1.163 sjg 3108: (void)fflush(stdout);
1.63 christos 3109: (void)fprintf(stderr,
1.175 dholland 3110: "%s: Fatal errors encountered -- cannot continue",
1.63 christos 3111: progname);
1.161 sjg 3112: PrintOnError(NULL, NULL);
1.103 christos 3113: exit(1);
1.1 cgd 3114: }
3115: }
3116:
3117: /*-
3118: *---------------------------------------------------------------------
3119: * Parse_Init --
3120: * initialize the parsing module
3121: *
3122: * Results:
3123: * none
3124: *
3125: * Side Effects:
3126: * the parseIncPath list is initialized...
3127: *---------------------------------------------------------------------
3128: */
1.5 cgd 3129: void
1.84 wiz 3130: Parse_Init(void)
1.1 cgd 3131: {
1.152 dsl 3132: mainNode = NULL;
1.252 rillig 3133: parseIncPath = Lst_Init();
3134: sysIncPath = Lst_Init();
3135: defIncPath = Lst_Init();
1.276 rillig 3136: Stack_Init(&includes);
1.45 mycroft 3137: #ifdef CLEANUP
1.252 rillig 3138: targCmds = Lst_Init();
1.45 mycroft 3139: #endif
1.1 cgd 3140: }
1.9 jtc 3141:
3142: void
1.84 wiz 3143: Parse_End(void)
1.9 jtc 3144: {
1.45 mycroft 3145: #ifdef CLEANUP
1.268 rillig 3146: Lst_Destroy(targCmds, free);
1.9 jtc 3147: if (targets)
1.268 rillig 3148: Lst_Free(targets);
3149: Lst_Destroy(defIncPath, Dir_Destroy);
3150: Lst_Destroy(sysIncPath, Dir_Destroy);
3151: Lst_Destroy(parseIncPath, Dir_Destroy);
1.276 rillig 3152: assert(Stack_IsEmpty(&includes));
3153: Stack_Done(&includes);
1.45 mycroft 3154: #endif
1.9 jtc 3155: }
1.27 christos 3156:
1.1 cgd 3157:
3158: /*-
3159: *-----------------------------------------------------------------------
3160: * Parse_MainName --
3161: * Return a Lst of the main target to create for main()'s sake. If
3162: * no such target exists, we Punt with an obnoxious error message.
3163: *
3164: * Results:
3165: * A Lst of the single node to create.
3166: *
3167: * Side Effects:
3168: * None.
3169: *
3170: *-----------------------------------------------------------------------
3171: */
3172: Lst
1.84 wiz 3173: Parse_MainName(void)
1.1 cgd 3174: {
1.37 fair 3175: Lst mainList; /* result list */
1.1 cgd 3176:
1.252 rillig 3177: mainList = Lst_Init();
1.1 cgd 3178:
1.152 dsl 3179: if (mainNode == NULL) {
1.97 christos 3180: Punt("no target to make.");
1.246 rillig 3181: /*NOTREACHED*/
1.1 cgd 3182: } else if (mainNode->type & OP_DOUBLEDEP) {
1.268 rillig 3183: Lst_Append(mainList, mainNode);
3184: Lst_AppendAll(mainList, mainNode->cohorts);
1.1 cgd 3185: }
1.5 cgd 3186: else
1.268 rillig 3187: Lst_Append(mainList, mainNode);
1.81 pk 3188: Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL);
1.235 rillig 3189: return mainList;
1.59 christos 3190: }
CVSweb <webmaster@jp.NetBSD.org>