Annotation of src/usr.bin/make/parse.c, Revision 1.507
1.507 ! rillig 1: /* $NetBSD: parse.c,v 1.506 2020/12/20 14:48:35 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.402 rillig 71: /*
72: * Parsing of makefiles.
73: *
74: * Parse_File is the main entry point and controls most of the other
75: * functions in this module.
1.1 cgd 76: *
1.402 rillig 77: * The directories for the .include "..." directive are kept in
78: * 'parseIncPath', while those for .include <...> are kept in 'sysIncPath'.
79: * The targets currently being defined are kept in 'targets'.
1.1 cgd 80: *
81: * Interface:
1.402 rillig 82: * Parse_Init Initialize the module
1.338 rillig 83: *
1.383 rillig 84: * Parse_End Clean up the module
1.338 rillig 85: *
1.402 rillig 86: * Parse_File Parse a top-level makefile. Included files are
87: * handled by Parse_include_file though.
88: *
89: * Parse_IsVar Return TRUE if the given line is a variable
90: * assignment. Used by MainParseArgs to determine if
91: * an argument is a target or a variable assignment.
92: * Used internally for pretty much the same thing.
93: *
94: * Parse_Error Report a parse error, a warning or an informational
95: * message.
1.338 rillig 96: *
1.402 rillig 97: * Parse_MainName Returns a list of the main target to create.
1.1 cgd 98: */
99:
1.170 dholland 100: #include <sys/types.h>
101: #include <sys/mman.h>
1.171 dholland 102: #include <sys/stat.h>
1.84 wiz 103: #include <errno.h>
1.5 cgd 104: #include <stdarg.h>
1.225 maya 105: #include <stdint.h>
1.84 wiz 106:
1.177 nakayama 107: #ifndef MAP_FILE
108: #define MAP_FILE 0
109: #endif
1.170 dholland 110: #ifndef MAP_COPY
111: #define MAP_COPY MAP_PRIVATE
112: #endif
113:
1.1 cgd 114: #include "make.h"
1.5 cgd 115: #include "dir.h"
116: #include "job.h"
1.1 cgd 117: #include "pathnames.h"
118:
1.303 rillig 119: /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
1.507 ! rillig 120: MAKE_RCSID("$NetBSD: parse.c,v 1.506 2020/12/20 14:48:35 rillig Exp $");
1.303 rillig 121:
1.248 rillig 122: /* types and constants */
1.166 dholland 123:
1.1 cgd 124: /*
1.166 dholland 125: * Structure for a file being read ("included file")
1.1 cgd 126: */
127: typedef struct IFile {
1.469 rillig 128: char *fname; /* name of file (relative? absolute?) */
129: Boolean fromForLoop; /* simulated .include by the .for loop */
130: int lineno; /* current line number in file */
131: int first_lineno; /* line number of start of text */
132: unsigned int cond_depth; /* 'if' nesting when file opened */
133: Boolean depending; /* state of doing_depend on EOF */
134:
135: /* The buffer from which the file's content is read. */
136: char *buf_freeIt;
137: char *buf_ptr; /* next char to be read */
138: char *buf_end;
139:
1.471 rillig 140: /* Function to read more data, with a single opaque argument. */
141: ReadMoreProc readMore;
142: void *readMoreArg;
143:
1.469 rillig 144: struct loadedfile *lf; /* loadedfile object, if any */
1.5 cgd 145: } IFile;
1.1 cgd 146:
1.166 dholland 147: /*
148: * Tokens for target attributes
1.1 cgd 149: */
1.386 rillig 150: typedef enum ParseSpecial {
1.469 rillig 151: SP_ATTRIBUTE, /* Generic attribute */
152: SP_BEGIN, /* .BEGIN */
153: SP_DEFAULT, /* .DEFAULT */
154: SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */
155: SP_END, /* .END */
156: SP_ERROR, /* .ERROR */
157: SP_IGNORE, /* .IGNORE */
158: SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */
159: SP_INTERRUPT, /* .INTERRUPT */
160: SP_LIBS, /* .LIBS; not mentioned in the manual page */
161: /* .MAIN and we don't have anything user-specified to make */
162: SP_MAIN,
163: SP_META, /* .META */
164: SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */
165: SP_NOMETA, /* .NOMETA */
166: SP_NOMETA_CMP, /* .NOMETA_CMP */
167: SP_NOPATH, /* .NOPATH */
168: SP_NOT, /* Not special */
169: SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */
170: SP_NULL, /* .NULL; not mentioned in the manual page */
171: SP_OBJDIR, /* .OBJDIR */
172: SP_ORDER, /* .ORDER */
173: SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */
174: SP_PATH, /* .PATH or .PATH.suffix */
175: SP_PHONY, /* .PHONY */
1.48 sjg 176: #ifdef POSIX
1.469 rillig 177: SP_POSIX, /* .POSIX; not mentioned in the manual page */
1.48 sjg 178: #endif
1.469 rillig 179: SP_PRECIOUS, /* .PRECIOUS */
180: SP_SHELL, /* .SHELL */
181: SP_SILENT, /* .SILENT */
182: SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */
183: SP_STALE, /* .STALE */
184: SP_SUFFIXES, /* .SUFFIXES */
185: SP_WAIT /* .WAIT */
1.1 cgd 186: } ParseSpecial;
187:
1.368 rillig 188: typedef List SearchPathList;
1.392 rillig 189: typedef ListNode SearchPathListNode;
1.368 rillig 190:
1.248 rillig 191: /* result data */
1.166 dholland 192:
193: /*
194: * The main target to create. This is the first target on the first
195: * dependency line in the first makefile.
196: */
197: static GNode *mainNode;
198:
1.248 rillig 199: /* eval state */
1.166 dholland 200:
1.415 rillig 201: /* During parsing, the targets from the left-hand side of the currently
202: * active dependency line, or NULL if the current line does not belong to a
203: * dependency line, for example because it is a variable assignment.
1.318 rillig 204: *
205: * See unit-tests/deptgt.mk, keyword "parse.c:targets". */
1.322 rillig 206: static GNodeList *targets;
1.166 dholland 207:
208: #ifdef CLEANUP
1.372 rillig 209: /* All shell commands for all targets, in no particular order and possibly
210: * with duplicates. Kept in a separate list since the commands from .USE or
211: * .USEBEFORE nodes are shared with other GNodes, thereby giving up the
212: * easily understandable ownership over the allocated strings. */
1.461 rillig 213: static StringList targCmds = LST_INIT;
1.166 dholland 214: #endif
215:
216: /*
1.152 dsl 217: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 cgd 218: * seen, then set to each successive source on the line.
219: */
1.407 rillig 220: static GNode *order_pred;
1.1 cgd 221:
1.248 rillig 222: /* parser state */
1.166 dholland 223:
224: /* number of fatal errors */
225: static int fatals = 0;
226:
227: /*
228: * Variables for doing includes
229: */
230:
1.408 rillig 231: /* The include chain of makefiles. At the bottom is the top-level makefile
232: * from the command line, and on top of that, there are the included files or
233: * .for loops, up to and including the current file.
1.319 rillig 234: *
235: * This data could be used to print stack traces on parse errors. As of
236: * 2020-09-14, this is not done though. It seems quite simple to print the
237: * tuples (fname:lineno:fromForLoop), from top to bottom. This simple idea is
238: * made complicated by the fact that the .for loops also use this stack for
239: * storing information.
240: *
241: * The lineno fields of the IFiles with fromForLoop == TRUE look confusing,
242: * which is demonstrated by the test 'include-main.mk'. They seem sorted
243: * backwards since they tell the number of completely parsed lines, which for
244: * a .for loop is right after the terminating .endfor. To compensate for this
245: * confusion, there is another field first_lineno pointing at the start of the
246: * .for loop, 1-based for human consumption.
247: *
248: * To make the stack trace intuitive, the entry below the first .for loop must
249: * be ignored completely since neither its lineno nor its first_lineno is
1.408 rillig 250: * useful. Instead, the topmost of each chain of .for loop needs to be
251: * printed twice, once with its first_lineno and once with its lineno.
1.319 rillig 252: *
1.408 rillig 253: * As of 2020-10-28, using the above rules, the stack trace for the .info line
1.319 rillig 254: * in include-subsub.mk would be:
255: *
1.408 rillig 256: * includes[5]: include-subsub.mk:4
1.319 rillig 257: * (lineno, from an .include)
258: * includes[4]: include-sub.mk:32
259: * (lineno, from a .for loop below an .include)
260: * includes[4]: include-sub.mk:31
261: * (first_lineno, from a .for loop, lineno == 32)
262: * includes[3]: include-sub.mk:30
263: * (first_lineno, from a .for loop, lineno == 33)
264: * includes[2]: include-sub.mk:29
265: * (first_lineno, from a .for loop, lineno == 34)
266: * includes[1]: include-sub.mk:35
267: * (not printed since it is below a .for loop)
268: * includes[0]: include-main.mk:27
269: */
1.408 rillig 270: static Vector /* of IFile */ includes;
1.400 rillig 271:
272: static IFile *
273: GetInclude(size_t i)
274: {
1.469 rillig 275: return Vector_Get(&includes, i);
1.408 rillig 276: }
277:
278: /* The file that is currently being read. */
279: static IFile *
280: CurFile(void)
281: {
1.469 rillig 282: return GetInclude(includes.len - 1);
1.400 rillig 283: }
1.166 dholland 284:
1.409 rillig 285: /* include paths */
1.322 rillig 286: SearchPath *parseIncPath; /* dirs for "..." includes */
287: SearchPath *sysIncPath; /* dirs for <...> includes */
1.414 rillig 288: SearchPath *defSysIncPath; /* default for sysIncPath */
1.166 dholland 289:
1.248 rillig 290: /* parser tables */
1.166 dholland 291:
1.1 cgd 292: /*
293: * The parseKeywords table is searched using binary search when deciding
294: * if a target or source is special. The 'spec' field is the ParseSpecial
1.404 rillig 295: * type of the keyword (SP_NOT if the keyword isn't special as a target) while
1.1 cgd 296: * the 'op' field is the operator to apply to the list of targets if the
297: * keyword is used as a source ("0" if the keyword isn't special as a source)
298: */
1.168 dholland 299: static const struct {
1.469 rillig 300: const char *name; /* Name of keyword */
301: ParseSpecial spec; /* Type when used as a target */
302: GNodeType op; /* Operator when used as a source */
1.1 cgd 303: } parseKeywords[] = {
1.466 rillig 304: { ".BEGIN", SP_BEGIN, OP_NONE },
305: { ".DEFAULT", SP_DEFAULT, OP_NONE },
306: { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, OP_NONE },
307: { ".END", SP_END, OP_NONE },
308: { ".ERROR", SP_ERROR, OP_NONE },
1.404 rillig 309: { ".EXEC", SP_ATTRIBUTE, OP_EXEC },
310: { ".IGNORE", SP_IGNORE, OP_IGNORE },
1.466 rillig 311: { ".INCLUDES", SP_INCLUDES, OP_NONE },
312: { ".INTERRUPT", SP_INTERRUPT, OP_NONE },
1.404 rillig 313: { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE },
314: { ".JOIN", SP_ATTRIBUTE, OP_JOIN },
1.466 rillig 315: { ".LIBS", SP_LIBS, OP_NONE },
1.404 rillig 316: { ".MADE", SP_ATTRIBUTE, OP_MADE },
1.466 rillig 317: { ".MAIN", SP_MAIN, OP_NONE },
1.404 rillig 318: { ".MAKE", SP_ATTRIBUTE, OP_MAKE },
1.466 rillig 319: { ".MAKEFLAGS", SP_MFLAGS, OP_NONE },
1.404 rillig 320: { ".META", SP_META, OP_META },
1.466 rillig 321: { ".MFLAGS", SP_MFLAGS, OP_NONE },
1.404 rillig 322: { ".NOMETA", SP_NOMETA, OP_NOMETA },
323: { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP },
324: { ".NOPATH", SP_NOPATH, OP_NOPATH },
325: { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN },
1.466 rillig 326: { ".NOTPARALLEL", SP_NOTPARALLEL, OP_NONE },
327: { ".NO_PARALLEL", SP_NOTPARALLEL, OP_NONE },
328: { ".NULL", SP_NULL, OP_NONE },
329: { ".OBJDIR", SP_OBJDIR, OP_NONE },
1.404 rillig 330: { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL },
1.466 rillig 331: { ".ORDER", SP_ORDER, OP_NONE },
332: { ".PARALLEL", SP_PARALLEL, OP_NONE },
333: { ".PATH", SP_PATH, OP_NONE },
1.404 rillig 334: { ".PHONY", SP_PHONY, OP_PHONY },
1.48 sjg 335: #ifdef POSIX
1.466 rillig 336: { ".POSIX", SP_POSIX, OP_NONE },
1.48 sjg 337: #endif
1.404 rillig 338: { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS },
339: { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE },
1.466 rillig 340: { ".SHELL", SP_SHELL, OP_NONE },
1.404 rillig 341: { ".SILENT", SP_SILENT, OP_SILENT },
1.466 rillig 342: { ".SINGLESHELL", SP_SINGLESHELL, OP_NONE },
343: { ".STALE", SP_STALE, OP_NONE },
344: { ".SUFFIXES", SP_SUFFIXES, OP_NONE },
1.404 rillig 345: { ".USE", SP_ATTRIBUTE, OP_USE },
346: { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE },
1.466 rillig 347: { ".WAIT", SP_WAIT, OP_NONE },
1.1 cgd 348: };
349:
1.248 rillig 350: /* file loader */
1.170 dholland 351:
352: struct loadedfile {
1.441 rillig 353: /* XXX: What is the lifetime of this path? Who manages the memory? */
1.469 rillig 354: const char *path; /* name, for error reports */
355: char *buf; /* contents buffer */
356: size_t len; /* length of contents */
357: size_t maplen; /* length of mmap area, or 0 */
358: Boolean used; /* XXX: have we used the data yet */
1.170 dholland 359: };
360:
1.441 rillig 361: /* XXX: What is the lifetime of the path? Who manages the memory? */
1.170 dholland 362: static struct loadedfile *
363: loadedfile_create(const char *path)
364: {
365: struct loadedfile *lf;
366:
1.427 rillig 367: lf = bmake_malloc(sizeof *lf);
1.242 rillig 368: lf->path = path == NULL ? "(stdin)" : path;
1.170 dholland 369: lf->buf = NULL;
370: lf->len = 0;
371: lf->maplen = 0;
372: lf->used = FALSE;
373: return lf;
374: }
375:
376: static void
377: loadedfile_destroy(struct loadedfile *lf)
378: {
379: if (lf->buf != NULL) {
1.430 rillig 380: if (lf->maplen > 0)
1.170 dholland 381: munmap(lf->buf, lf->maplen);
1.430 rillig 382: else
1.170 dholland 383: free(lf->buf);
384: }
385: free(lf);
386: }
387:
388: /*
1.471 rillig 389: * readMore() operation for loadedfile, as needed by the weird and twisted
390: * logic below. Once that's cleaned up, we can get rid of lf->used.
1.170 dholland 391: */
392: static char *
1.471 rillig 393: loadedfile_readMore(void *x, size_t *len)
1.170 dholland 394: {
395: struct loadedfile *lf = x;
396:
1.430 rillig 397: if (lf->used)
1.170 dholland 398: return NULL;
1.430 rillig 399:
1.170 dholland 400: lf->used = TRUE;
401: *len = lf->len;
402: return lf->buf;
403: }
404:
405: /*
406: * Try to get the size of a file.
407: */
1.272 rillig 408: static Boolean
1.170 dholland 409: load_getsize(int fd, size_t *ret)
410: {
411: struct stat st;
412:
1.430 rillig 413: if (fstat(fd, &st) < 0)
1.272 rillig 414: return FALSE;
1.170 dholland 415:
1.430 rillig 416: if (!S_ISREG(st.st_mode))
1.272 rillig 417: return FALSE;
1.170 dholland 418:
419: /*
420: * st_size is an off_t, which is 64 bits signed; *ret is
421: * size_t, which might be 32 bits unsigned or 64 bits
422: * unsigned. Rather than being elaborate, just punt on
423: * files that are more than 2^31 bytes. We should never
424: * see a makefile that size in practice...
425: *
426: * While we're at it reject negative sizes too, just in case.
427: */
1.430 rillig 428: if (st.st_size < 0 || st.st_size > 0x7fffffff)
1.272 rillig 429: return FALSE;
1.170 dholland 430:
1.396 rillig 431: *ret = (size_t)st.st_size;
1.272 rillig 432: return TRUE;
1.170 dholland 433: }
434:
1.414 rillig 435: static Boolean
436: loadedfile_mmap(struct loadedfile *lf, int fd)
1.170 dholland 437: {
1.369 rillig 438: static unsigned long pagesize = 0;
1.170 dholland 439:
1.430 rillig 440: if (!load_getsize(fd, &lf->len))
441: return FALSE;
442:
443: /* found a size, try mmap */
444: if (pagesize == 0)
445: pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
446: if (pagesize == 0 || pagesize == (unsigned long)-1)
447: pagesize = 0x1000;
448:
449: /* round size up to a page */
450: lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize);
1.170 dholland 451:
1.430 rillig 452: /*
453: * XXX hack for dealing with empty files; remove when
454: * we're no longer limited by interfacing to the old
455: * logic elsewhere in this file.
456: */
457: if (lf->maplen == 0)
458: lf->maplen = pagesize;
1.170 dholland 459:
1.430 rillig 460: /*
461: * FUTURE: remove PROT_WRITE when the parser no longer
462: * needs to scribble on the input.
463: */
1.469 rillig 464: lf->buf = mmap(NULL, lf->maplen, PROT_READ | PROT_WRITE,
465: MAP_FILE | MAP_COPY, fd, 0);
1.430 rillig 466: if (lf->buf == MAP_FAILED)
467: return FALSE;
1.170 dholland 468:
1.430 rillig 469: if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
470: char *b = bmake_malloc(lf->len + 1);
471: b[lf->len] = '\n';
472: memcpy(b, lf->buf, lf->len++);
473: munmap(lf->buf, lf->maplen);
474: lf->maplen = 0;
475: lf->buf = b;
1.170 dholland 476: }
1.430 rillig 477:
478: return TRUE;
1.414 rillig 479: }
480:
481: /*
482: * Read in a file.
483: *
484: * Until the path search logic can be moved under here instead of
485: * being in the caller in another source file, we need to have the fd
486: * passed in already open. Bleh.
487: *
1.430 rillig 488: * If the path is NULL, use stdin.
1.414 rillig 489: */
490: static struct loadedfile *
491: loadfile(const char *path, int fd)
492: {
493: struct loadedfile *lf;
494: ssize_t result;
495: size_t bufpos;
496:
497: lf = loadedfile_create(path);
498:
499: if (path == NULL) {
500: assert(fd == -1);
501: fd = STDIN_FILENO;
502: } else {
503: #if 0 /* notyet */
504: fd = open(path, O_RDONLY);
505: if (fd < 0) {
506: ...
507: Error("%s: %s", path, strerror(errno));
508: exit(1);
509: }
510: #endif
511: }
512:
513: if (loadedfile_mmap(lf, fd))
514: goto done;
1.170 dholland 515:
516: /* cannot mmap; load the traditional way */
517:
518: lf->maplen = 0;
519: lf->len = 1024;
520: lf->buf = bmake_malloc(lf->len);
521:
522: bufpos = 0;
1.428 rillig 523: for (;;) {
1.170 dholland 524: assert(bufpos <= lf->len);
525: if (bufpos == lf->len) {
1.469 rillig 526: if (lf->len > SIZE_MAX / 2) {
1.221 riastrad 527: errno = EFBIG;
528: Error("%s: file too large", path);
529: exit(1);
530: }
1.170 dholland 531: lf->len *= 2;
532: lf->buf = bmake_realloc(lf->buf, lf->len);
533: }
1.221 riastrad 534: assert(bufpos < lf->len);
1.170 dholland 535: result = read(fd, lf->buf + bufpos, lf->len - bufpos);
536: if (result < 0) {
537: Error("%s: read error: %s", path, strerror(errno));
538: exit(1);
539: }
1.430 rillig 540: if (result == 0)
1.170 dholland 541: break;
1.430 rillig 542:
1.369 rillig 543: bufpos += (size_t)result;
1.170 dholland 544: }
545: assert(bufpos <= lf->len);
1.173 dholland 546: lf->len = bufpos;
1.170 dholland 547:
548: /* truncate malloc region to actual length (maybe not useful) */
1.172 dholland 549: if (lf->len > 0) {
1.218 sjg 550: /* as for mmap case, ensure trailing \n */
551: if (lf->buf[lf->len - 1] != '\n')
552: lf->len++;
1.172 dholland 553: lf->buf = bmake_realloc(lf->buf, lf->len);
1.218 sjg 554: lf->buf[lf->len - 1] = '\n';
1.172 dholland 555: }
1.170 dholland 556:
557: done:
1.430 rillig 558: if (path != NULL)
1.170 dholland 559: close(fd);
1.430 rillig 560:
1.170 dholland 561: return lf;
562: }
563:
1.248 rillig 564: /* old code */
1.77 christos 565:
1.279 rillig 566: /* Check if the current character is escaped on the current line. */
567: static Boolean
1.84 wiz 568: ParseIsEscaped(const char *line, const char *c)
1.77 christos 569: {
1.469 rillig 570: Boolean active = FALSE;
571: for (;;) {
572: if (line == c)
573: return active;
574: if (*--c != '\\')
575: return active;
576: active = !active;
577: }
1.77 christos 578: }
579:
1.278 rillig 580: /* Add the filename and lineno to the GNode so that we remember where it
581: * was first defined. */
582: static void
583: ParseMark(GNode *gn)
584: {
1.469 rillig 585: IFile *curFile = CurFile();
586: gn->fname = curFile->fname;
587: gn->lineno = curFile->lineno;
1.278 rillig 588: }
589:
1.368 rillig 590: /* Look in the table of keywords for one matching the given string.
591: * Return the index of the keyword, or -1 if it isn't there. */
1.1 cgd 592: static int
1.120 dsl 593: ParseFindKeyword(const char *str)
1.1 cgd 594: {
1.469 rillig 595: int start = 0;
596: int end = sizeof parseKeywords / sizeof parseKeywords[0] - 1;
1.1 cgd 597:
1.469 rillig 598: do {
599: int curr = start + (end - start) / 2;
600: int diff = strcmp(str, parseKeywords[curr].name);
601:
602: if (diff == 0)
603: return curr;
604: if (diff < 0)
605: end = curr - 1;
606: else
607: start = curr + 1;
608: } while (start <= end);
1.430 rillig 609:
1.469 rillig 610: return -1;
1.1 cgd 611: }
612:
1.291 rillig 613: static void
1.441 rillig 614: PrintLocation(FILE *f, const char *fname, size_t lineno)
1.291 rillig 615: {
1.469 rillig 616: char dirbuf[MAXPATHLEN + 1];
1.505 rillig 617: FStr dir, base;
1.291 rillig 618:
1.441 rillig 619: if (*fname == '/' || strcmp(fname, "(stdin)") == 0) {
1.481 rillig 620: (void)fprintf(f, "\"%s\" line %u: ", fname, (unsigned)lineno);
1.299 rillig 621: return;
622: }
1.291 rillig 623:
1.299 rillig 624: /* Find out which makefile is the culprit.
625: * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */
1.291 rillig 626:
1.505 rillig 627: dir = Var_Value(".PARSEDIR", VAR_GLOBAL);
628: if (dir.str == NULL)
629: dir.str = ".";
630: if (dir.str[0] != '/')
631: dir.str = realpath(dir.str, dirbuf);
632:
633: base = Var_Value(".PARSEFILE", VAR_GLOBAL);
634: if (base.str == NULL)
635: base.str = str_basename(fname);
636:
637: (void)fprintf(f, "\"%s/%s\" line %u: ",
638: dir.str, base.str, (unsigned)lineno);
639:
640: FStr_Done(&base);
641: FStr_Done(&dir);
1.291 rillig 642: }
643:
1.38 christos 644: static void
1.441 rillig 645: ParseVErrorInternal(FILE *f, const char *fname, size_t lineno,
1.398 rillig 646: ParseErrorLevel type, const char *fmt, va_list ap)
1.38 christos 647: {
1.56 christos 648: static Boolean fatal_warning_error_printed = FALSE;
649:
1.148 sjg 650: (void)fprintf(f, "%s: ", progname);
1.63 christos 651:
1.441 rillig 652: if (fname != NULL)
653: PrintLocation(f, fname, lineno);
1.38 christos 654: if (type == PARSE_WARNING)
1.127 dsl 655: (void)fprintf(f, "warning: ");
656: (void)vfprintf(f, fmt, ap);
657: (void)fprintf(f, "\n");
658: (void)fflush(f);
1.300 rillig 659:
1.226 sjg 660: if (type == PARSE_INFO)
661: return;
1.401 rillig 662: if (type == PARSE_FATAL || opts.parseWarnFatal)
1.300 rillig 663: fatals++;
1.401 rillig 664: if (opts.parseWarnFatal && !fatal_warning_error_printed) {
1.56 christos 665: Error("parsing warnings being treated as errors");
666: fatal_warning_error_printed = TRUE;
667: }
1.38 christos 668: }
669:
1.203 joerg 670: static void
1.441 rillig 671: ParseErrorInternal(const char *fname, size_t lineno,
672: ParseErrorLevel type, const char *fmt, ...)
1.203 joerg 673: {
674: va_list ap;
675:
1.441 rillig 676: (void)fflush(stdout);
1.203 joerg 677: va_start(ap, fmt);
1.441 rillig 678: ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
1.203 joerg 679: va_end(ap);
680:
1.401 rillig 681: if (opts.debug_file != stderr && opts.debug_file != stdout) {
1.203 joerg 682: va_start(ap, fmt);
1.441 rillig 683: ParseVErrorInternal(opts.debug_file, fname, lineno, type,
1.469 rillig 684: fmt, ap);
1.203 joerg 685: va_end(ap);
686: }
687: }
688:
1.441 rillig 689: /* Print a parse error message, including location information.
690: *
691: * If the level is PARSE_FATAL, continue parsing until the end of the
692: * current top-level makefile, then exit (see Parse_File).
1.38 christos 693: *
1.289 rillig 694: * Fmt is given without a trailing newline. */
1.1 cgd 695: void
1.398 rillig 696: Parse_Error(ParseErrorLevel type, const char *fmt, ...)
1.1 cgd 697: {
698: va_list ap;
1.156 dsl 699: const char *fname;
700: size_t lineno;
1.84 wiz 701:
1.408 rillig 702: if (includes.len == 0) {
1.156 dsl 703: fname = NULL;
704: lineno = 0;
705: } else {
1.408 rillig 706: IFile *curFile = CurFile();
1.156 dsl 707: fname = curFile->fname;
1.369 rillig 708: lineno = (size_t)curFile->lineno;
1.148 sjg 709: }
1.156 dsl 710:
711: va_start(ap, fmt);
1.163 sjg 712: (void)fflush(stdout);
1.156 dsl 713: ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
1.1 cgd 714: va_end(ap);
1.127 dsl 715:
1.401 rillig 716: if (opts.debug_file != stderr && opts.debug_file != stdout) {
1.127 dsl 717: va_start(ap, fmt);
1.401 rillig 718: ParseVErrorInternal(opts.debug_file, fname, lineno, type,
1.469 rillig 719: fmt, ap);
1.127 dsl 720: va_end(ap);
721: }
1.1 cgd 722: }
723:
1.161 sjg 724:
1.441 rillig 725: /* Parse and handle a .info, .warning or .error directive.
726: * For an .error directive, immediately exit. */
1.503 rillig 727: static void
728: ParseMessage(ParseErrorLevel level, const char *levelName, const char *umsg)
1.161 sjg 729: {
1.475 rillig 730: char *xmsg;
1.469 rillig 731:
1.503 rillig 732: if (umsg[0] == '\0') {
733: Parse_Error(PARSE_FATAL, "Missing argument for \".%s\"",
734: levelName);
735: return;
736: }
1.469 rillig 737:
1.475 rillig 738: (void)Var_Subst(umsg, VAR_CMDLINE, VARE_WANTRES, &xmsg);
1.469 rillig 739: /* TODO: handle errors */
740:
1.475 rillig 741: Parse_Error(level, "%s", xmsg);
742: free(xmsg);
1.469 rillig 743:
1.475 rillig 744: if (level == PARSE_FATAL) {
1.469 rillig 745: PrintOnError(NULL, NULL);
746: exit(1);
747: }
1.161 sjg 748: }
749:
1.316 rillig 750: /* Add the child to the parent's children.
1.1 cgd 751: *
1.382 rillig 752: * Additionally, add the parent to the child's parents, but only if the
753: * target is not special. An example for such a special target is .END,
754: * which does not need to be informed once the child target has been made. */
755: static void
756: LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial)
757: {
1.469 rillig 758: if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(&pgn->cohorts))
759: pgn = pgn->cohorts.last->datum;
1.316 rillig 760:
1.469 rillig 761: Lst_Append(&pgn->children, cgn);
762: pgn->unmade++;
1.316 rillig 763:
1.469 rillig 764: /* Special targets like .END don't need any children. */
765: if (!isSpecial)
766: Lst_Append(&cgn->parents, pgn);
767:
768: if (DEBUG(PARSE)) {
769: debug_printf("# %s: added child %s - %s\n",
770: __func__, pgn->name, cgn->name);
771: Targ_PrintNode(pgn, 0);
772: Targ_PrintNode(cgn, 0);
773: }
1.1 cgd 774: }
775:
1.382 rillig 776: /* Add the node to each target from the current dependency group. */
777: static void
778: LinkToTargets(GNode *gn, Boolean isSpecial)
779: {
1.469 rillig 780: GNodeListNode *ln;
781:
782: for (ln = targets->first; ln != NULL; ln = ln->next)
783: LinkSource(ln->datum, gn, isSpecial);
1.382 rillig 784: }
785:
1.337 rillig 786: static Boolean
787: TryApplyDependencyOperator(GNode *gn, GNodeType op)
1.1 cgd 788: {
789: /*
1.469 rillig 790: * If the node occurred on the left-hand side of a dependency and the
791: * operator also defines a dependency, they must match.
1.1 cgd 792: */
1.469 rillig 793: if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) &&
794: ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) {
795: Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
796: gn->name);
797: return FALSE;
798: }
799:
800: if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
801: /*
802: * If the node was of the left-hand side of a '::' operator,
803: * we need to create a new instance of it for the children
804: * and commands on this dependency line since each of these
805: * dependency groups has its own attributes and commands,
806: * separate from the others.
807: *
808: * The new instance is placed on the 'cohorts' list of the
809: * initial one (note the initial one is not on its own
810: * cohorts list) and the new instance is linked to all
811: * parents of the initial instance.
812: */
813: GNode *cohort;
1.27 christos 814:
1.469 rillig 815: /*
816: * Propagate copied bits to the initial node. They'll be
817: * propagated back to the rest of the cohorts later.
818: */
819: gn->type |= op & ~OP_OPMASK;
1.33 mycroft 820:
1.469 rillig 821: cohort = Targ_NewInternalNode(gn->name);
822: if (doing_depend)
823: ParseMark(cohort);
824: /*
825: * Make the cohort invisible as well to avoid duplicating it
826: * into other variables. True, parents of this target won't
827: * tend to do anything with their local variables, but better
828: * safe than sorry.
829: *
830: * (I think this is pointless now, since the relevant list
831: * traversals will no longer see this node anyway. -mycroft)
832: */
833: cohort->type = op | OP_INVISIBLE;
834: Lst_Append(&gn->cohorts, cohort);
835: cohort->centurion = gn;
836: gn->unmade_cohorts++;
837: snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
838: (unsigned int)gn->unmade_cohorts % 1000000);
839: } else {
840: /*
841: * We don't want to nuke any previous flags (whatever they
842: * were) so we just OR the new operator into the old.
843: */
844: gn->type |= op;
845: }
1.33 mycroft 846:
1.469 rillig 847: return TRUE;
1.337 rillig 848: }
849:
850: static void
851: ApplyDependencyOperator(GNodeType op)
852: {
1.469 rillig 853: GNodeListNode *ln;
854:
855: for (ln = targets->first; ln != NULL; ln = ln->next)
856: if (!TryApplyDependencyOperator(ln->datum, op))
857: break;
1.1 cgd 858: }
859:
1.467 rillig 860: /*
861: * We add a .WAIT node in the dependency list. After any dynamic dependencies
862: * (and filename globbing) have happened, it is given a dependency on each
863: * previous child, back until the previous .WAIT node. The next child won't
864: * be scheduled until the .WAIT node is built.
865: *
866: * We give each .WAIT node a unique name (mainly for diagnostics).
867: */
868: static void
869: ParseDependencySourceWait(Boolean isSpecial)
870: {
871: static int wait_number = 0;
872: char wait_src[16];
873: GNode *gn;
874:
875: snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
876: gn = Targ_NewInternalNode(wait_src);
877: if (doing_depend)
878: ParseMark(gn);
879: gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
880: LinkToTargets(gn, isSpecial);
881:
882: }
883:
1.368 rillig 884: static Boolean
1.464 rillig 885: ParseDependencySourceKeyword(const char *src, ParseSpecial specType)
1.1 cgd 886: {
1.468 rillig 887: int keywd;
888: GNodeType op;
1.1 cgd 889:
1.468 rillig 890: if (*src != '.' || !ch_isupper(src[1]))
891: return FALSE;
892:
893: keywd = ParseFindKeyword(src);
894: if (keywd == -1)
895: return FALSE;
896:
897: op = parseKeywords[keywd].op;
898: if (op != OP_NONE) {
1.337 rillig 899: ApplyDependencyOperator(op);
1.368 rillig 900: return TRUE;
1.468 rillig 901: }
902: if (parseKeywords[keywd].spec == SP_WAIT) {
903: ParseDependencySourceWait(specType != SP_NOT);
1.368 rillig 904: return TRUE;
1.1 cgd 905: }
1.468 rillig 906: return FALSE;
1.368 rillig 907: }
1.18 christos 908:
1.368 rillig 909: static void
1.464 rillig 910: ParseDependencySourceMain(const char *src)
1.368 rillig 911: {
1.469 rillig 912: /*
913: * In a line like ".MAIN: source1 source2", it means we need to add
914: * the sources of said target to the list of things to create.
915: *
916: * Note that this will only be invoked if the user didn't specify a
917: * target on the command line and the .MAIN occurs for the first time.
918: *
919: * See ParseDoDependencyTargetSpecial, branch SP_MAIN.
920: * See unit-tests/cond-func-make-main.mk.
921: */
922: Lst_Append(&opts.create, bmake_strdup(src));
923: /*
924: * Add the name to the .TARGETS variable as well, so the user can
925: * employ that, if desired.
926: */
927: Var_Append(".TARGETS", src, VAR_GLOBAL);
1.368 rillig 928: }
1.18 christos 929:
1.368 rillig 930: static void
1.464 rillig 931: ParseDependencySourceOrder(const char *src)
1.368 rillig 932: {
1.469 rillig 933: GNode *gn;
934: /*
935: * Create proper predecessor/successor links between the previous
936: * source and the current one.
937: */
938: gn = Targ_GetNode(src);
939: if (doing_depend)
940: ParseMark(gn);
941: if (order_pred != NULL) {
942: Lst_Append(&order_pred->order_succ, gn);
943: Lst_Append(&gn->order_pred, order_pred);
944: if (DEBUG(PARSE)) {
945: debug_printf("# %s: added Order dependency %s - %s\n",
946: __func__, order_pred->name, gn->name);
947: Targ_PrintNode(order_pred, 0);
948: Targ_PrintNode(gn, 0);
949: }
950: }
951: /*
952: * The current source now becomes the predecessor for the next one.
953: */
954: order_pred = gn;
1.368 rillig 955: }
956:
957: static void
1.464 rillig 958: ParseDependencySourceOther(const char *src, GNodeType tOp,
959: ParseSpecial specType)
1.368 rillig 960: {
1.469 rillig 961: GNode *gn;
962:
963: /*
964: * If the source is not an attribute, we need to find/create
965: * a node for it. After that we can apply any operator to it
966: * from a special target or link it to its parents, as
967: * appropriate.
968: *
969: * In the case of a source that was the object of a :: operator,
970: * the attribute is applied to all of its instances (as kept in
971: * the 'cohorts' list of the node) or all the cohorts are linked
972: * to all the targets.
973: */
1.363 rillig 974:
1.469 rillig 975: /* Find/create the 'src' node and attach to all targets */
976: gn = Targ_GetNode(src);
977: if (doing_depend)
978: ParseMark(gn);
979: if (tOp != OP_NONE)
980: gn->type |= tOp;
981: else
982: LinkToTargets(gn, specType != SP_NOT);
1.1 cgd 983: }
984:
1.469 rillig 985: /*
986: * Given the name of a source in a dependency line, figure out if it is an
1.368 rillig 987: * attribute (such as .SILENT) and apply it to the targets if it is. Else
988: * decide if there is some attribute which should be applied *to* the source
989: * because of some special target (such as .PHONY) and apply it if so.
990: * Otherwise, make the source a child of the targets in the list 'targets'.
991: *
992: * Input:
993: * tOp operator (if any) from special targets
994: * src name of the source to handle
995: */
996: static void
1.464 rillig 997: ParseDependencySource(GNodeType tOp, const char *src, ParseSpecial specType)
1.368 rillig 998: {
1.469 rillig 999: if (ParseDependencySourceKeyword(src, specType))
1000: return;
1.368 rillig 1001:
1.469 rillig 1002: if (specType == SP_MAIN)
1003: ParseDependencySourceMain(src);
1004: else if (specType == SP_ORDER)
1005: ParseDependencySourceOrder(src);
1006: else
1007: ParseDependencySourceOther(src, tOp, specType);
1.368 rillig 1008: }
1009:
1.469 rillig 1010: /*
1011: * If we have yet to decide on a main target to make, in the absence of any
1.335 rillig 1012: * user input, we want the first target on the first dependency line that is
1.469 rillig 1013: * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made.
1014: */
1.335 rillig 1015: static void
1016: FindMainTarget(void)
1.1 cgd 1017: {
1.469 rillig 1018: GNodeListNode *ln;
1.335 rillig 1019:
1.469 rillig 1020: if (mainNode != NULL)
1021: return;
1.335 rillig 1022:
1.469 rillig 1023: for (ln = targets->first; ln != NULL; ln = ln->next) {
1024: GNode *gn = ln->datum;
1025: if (!(gn->type & OP_NOTARGET)) {
1026: DEBUG1(MAKE, "Setting main node to \"%s\"\n", gn->name);
1027: mainNode = gn;
1028: Targ_SetMain(gn);
1029: return;
1030: }
1.335 rillig 1031: }
1.1 cgd 1032: }
1033:
1.311 rillig 1034: /*
1035: * We got to the end of the line while we were still looking at targets.
1036: *
1037: * Ending a dependency line without an operator is a Bozo no-no. As a
1038: * heuristic, this is also often triggered by undetected conflicts from
1039: * cvs/rcs merges.
1040: */
1041: static void
1.395 rillig 1042: ParseErrorNoDependency(const char *lstart)
1.311 rillig 1043: {
1.469 rillig 1044: if ((strncmp(lstart, "<<<<<<", 6) == 0) ||
1045: (strncmp(lstart, "======", 6) == 0) ||
1046: (strncmp(lstart, ">>>>>>", 6) == 0))
1047: Parse_Error(PARSE_FATAL,
1.311 rillig 1048: "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
1.469 rillig 1049: else if (lstart[0] == '.') {
1050: const char *dirstart = lstart + 1;
1051: const char *dirend;
1052: cpp_skip_whitespace(&dirstart);
1053: dirend = dirstart;
1054: while (ch_isalnum(*dirend) || *dirend == '-')
1055: dirend++;
1056: Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
1.311 rillig 1057: (int)(dirend - dirstart), dirstart);
1.469 rillig 1058: } else
1059: Parse_Error(PARSE_FATAL, "Need an operator");
1.311 rillig 1060: }
1061:
1.314 rillig 1062: static void
1.445 rillig 1063: ParseDependencyTargetWord(const char **pp, const char *lstart)
1.314 rillig 1064: {
1.469 rillig 1065: const char *cp = *pp;
1066:
1067: while (*cp != '\0') {
1068: if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' ||
1069: *cp == '(') &&
1070: !ParseIsEscaped(lstart, cp))
1071: break;
1.314 rillig 1072:
1.469 rillig 1073: if (*cp == '$') {
1074: /*
1075: * Must be a dynamic source (would have been expanded
1076: * otherwise), so call the Var module to parse the
1077: * puppy so we can safely advance beyond it.
1078: *
1079: * There should be no errors in this, as they would
1080: * have been discovered in the initial Var_Subst and
1081: * we wouldn't be here.
1082: */
1083: const char *nested_p = cp;
1.504 rillig 1084: FStr nested_val;
1.314 rillig 1085:
1.469 rillig 1086: /* XXX: Why VARE_WANTRES? */
1087: (void)Var_Parse(&nested_p, VAR_CMDLINE,
1.504 rillig 1088: VARE_WANTRES | VARE_UNDEFERR, &nested_val);
1.469 rillig 1089: /* TODO: handle errors */
1.504 rillig 1090: FStr_Done(&nested_val);
1.469 rillig 1091: cp += nested_p - cp;
1092: } else
1093: cp++;
1094: }
1.314 rillig 1095:
1.469 rillig 1096: *pp = cp;
1.314 rillig 1097: }
1098:
1.440 rillig 1099: /* Handle special targets like .PATH, .DEFAULT, .BEGIN, .ORDER. */
1.368 rillig 1100: static void
1.395 rillig 1101: ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType,
1.478 rillig 1102: const char *line, /* XXX: bad name */
1.395 rillig 1103: SearchPathList **inout_paths)
1.368 rillig 1104: {
1.469 rillig 1105: switch (*inout_specType) {
1106: case SP_PATH:
1107: if (*inout_paths == NULL)
1108: *inout_paths = Lst_New();
1109: Lst_Append(*inout_paths, &dirSearchPath);
1110: break;
1111: case SP_MAIN:
1112: /*
1113: * Allow targets from the command line to override the
1114: * .MAIN node.
1115: */
1116: if (!Lst_IsEmpty(&opts.create))
1117: *inout_specType = SP_NOT;
1118: break;
1119: case SP_BEGIN:
1120: case SP_END:
1121: case SP_STALE:
1122: case SP_ERROR:
1123: case SP_INTERRUPT: {
1124: GNode *gn = Targ_GetNode(line);
1125: if (doing_depend)
1126: ParseMark(gn);
1127: gn->type |= OP_NOTMAIN | OP_SPECIAL;
1128: Lst_Append(targets, gn);
1129: break;
1130: }
1131: case SP_DEFAULT: {
1132: /*
1133: * Need to create a node to hang commands on, but we don't
1134: * want it in the graph, nor do we want it to be the Main
1135: * Target. We claim the node is a transformation rule to make
1136: * life easier later, when we'll use Make_HandleUse to
1137: * actually apply the .DEFAULT commands.
1138: */
1139: GNode *gn = GNode_New(".DEFAULT");
1140: gn->type |= OP_NOTMAIN | OP_TRANSFORM;
1141: Lst_Append(targets, gn);
1142: defaultNode = gn;
1143: break;
1144: }
1145: case SP_DELETE_ON_ERROR:
1146: deleteOnError = TRUE;
1147: break;
1148: case SP_NOTPARALLEL:
1149: opts.maxJobs = 1;
1150: break;
1151: case SP_SINGLESHELL:
1152: opts.compatMake = TRUE;
1153: break;
1154: case SP_ORDER:
1155: order_pred = NULL;
1156: break;
1157: default:
1158: break;
1159: }
1.368 rillig 1160: }
1161:
1162: /*
1163: * .PATH<suffix> has to be handled specially.
1164: * Call on the suffix module to give us a path to modify.
1165: */
1166: static Boolean
1.478 rillig 1167: ParseDoDependencyTargetPath(const char *line, /* XXX: bad name */
1168: SearchPathList **inout_paths)
1.368 rillig 1169: {
1.469 rillig 1170: SearchPath *path;
1.368 rillig 1171:
1.469 rillig 1172: path = Suff_GetPath(&line[5]);
1173: if (path == NULL) {
1174: Parse_Error(PARSE_FATAL,
1175: "Suffix '%s' not defined (yet)", &line[5]);
1176: return FALSE;
1177: }
1.430 rillig 1178:
1.469 rillig 1179: if (*inout_paths == NULL)
1180: *inout_paths = Lst_New();
1181: Lst_Append(*inout_paths, path);
1.430 rillig 1182:
1.469 rillig 1183: return TRUE;
1.368 rillig 1184: }
1185:
1186: /*
1187: * See if it's a special target and if so set specType to match it.
1.364 rillig 1188: */
1.368 rillig 1189: static Boolean
1.478 rillig 1190: ParseDoDependencyTarget(const char *line, /* XXX: bad name */
1191: ParseSpecial *inout_specType,
1.395 rillig 1192: GNodeType *out_tOp, SearchPathList **inout_paths)
1.364 rillig 1193: {
1.469 rillig 1194: int keywd;
1195:
1.478 rillig 1196: if (!(line[0] == '.' && ch_isupper(line[1])))
1.469 rillig 1197: return TRUE;
1198:
1199: /*
1200: * See if the target is a special target that must have it
1201: * or its sources handled specially.
1202: */
1203: keywd = ParseFindKeyword(line);
1204: if (keywd != -1) {
1205: if (*inout_specType == SP_PATH &&
1206: parseKeywords[keywd].spec != SP_PATH) {
1207: Parse_Error(PARSE_FATAL, "Mismatched special targets");
1208: return FALSE;
1209: }
1210:
1211: *inout_specType = parseKeywords[keywd].spec;
1212: *out_tOp = parseKeywords[keywd].op;
1213:
1214: ParseDoDependencyTargetSpecial(inout_specType, line,
1215: inout_paths);
1.364 rillig 1216:
1.469 rillig 1217: } else if (strncmp(line, ".PATH", 5) == 0) {
1218: *inout_specType = SP_PATH;
1219: if (!ParseDoDependencyTargetPath(line, inout_paths))
1220: return FALSE;
1221: }
1.368 rillig 1222: return TRUE;
1223: }
1224:
1225: static void
1.478 rillig 1226: ParseDoDependencyTargetMundane(char *line, /* XXX: bad name */
1227: StringList *curTargs)
1.368 rillig 1228: {
1.469 rillig 1229: if (Dir_HasWildcards(line)) {
1230: /*
1231: * Targets are to be sought only in the current directory,
1232: * so create an empty path for the thing. Note we need to
1233: * use Dir_Destroy in the destruction of the path as the
1234: * Dir module could have added a directory to the path...
1235: */
1236: SearchPath *emptyPath = SearchPath_New();
1.368 rillig 1237:
1.469 rillig 1238: Dir_Expand(line, emptyPath, curTargs);
1.368 rillig 1239:
1.469 rillig 1240: SearchPath_Free(emptyPath);
1241: } else {
1242: /*
1243: * No wildcards, but we want to avoid code duplication,
1244: * so create a list with the word on it.
1245: */
1246: Lst_Append(curTargs, line);
1247: }
1.368 rillig 1248:
1.469 rillig 1249: /* Apply the targets. */
1.368 rillig 1250:
1.469 rillig 1251: while (!Lst_IsEmpty(curTargs)) {
1252: char *targName = Lst_Dequeue(curTargs);
1253: GNode *gn = Suff_IsTransform(targName)
1.368 rillig 1254: ? Suff_AddTransform(targName)
1255: : Targ_GetNode(targName);
1.469 rillig 1256: if (doing_depend)
1257: ParseMark(gn);
1.368 rillig 1258:
1.469 rillig 1259: Lst_Append(targets, gn);
1260: }
1.368 rillig 1261: }
1262:
1263: static void
1264: ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart)
1265: {
1.469 rillig 1266: Boolean warning = FALSE;
1267: char *cp = *pp;
1.368 rillig 1268:
1.469 rillig 1269: while (*cp != '\0') {
1270: if (!ParseIsEscaped(lstart, cp) && (*cp == '!' || *cp == ':'))
1271: break;
1272: if (ParseIsEscaped(lstart, cp) || (*cp != ' ' && *cp != '\t'))
1273: warning = TRUE;
1274: cp++;
1275: }
1276: if (warning)
1277: Parse_Error(PARSE_WARNING, "Extra target ignored");
1.430 rillig 1278:
1.469 rillig 1279: *pp = cp;
1.368 rillig 1280: }
1281:
1282: static void
1.395 rillig 1283: ParseDoDependencyCheckSpec(ParseSpecial specType)
1.368 rillig 1284: {
1.469 rillig 1285: switch (specType) {
1286: default:
1287: Parse_Error(PARSE_WARNING,
1.441 rillig 1288: "Special and mundane targets don't mix. "
1289: "Mundane ones ignored");
1.469 rillig 1290: break;
1291: case SP_DEFAULT:
1292: case SP_STALE:
1293: case SP_BEGIN:
1294: case SP_END:
1295: case SP_ERROR:
1296: case SP_INTERRUPT:
1297: /*
1298: * These create nodes on which to hang commands, so targets
1299: * shouldn't be empty.
1300: */
1301: case SP_NOT:
1302: /* Nothing special here -- targets can be empty if it wants. */
1303: break;
1304: }
1.368 rillig 1305: }
1306:
1307: static Boolean
1.395 rillig 1308: ParseDoDependencyParseOp(char **pp, const char *lstart, GNodeType *out_op)
1.368 rillig 1309: {
1.469 rillig 1310: const char *cp = *pp;
1.368 rillig 1311:
1.469 rillig 1312: if (*cp == '!') {
1313: *out_op = OP_FORCE;
1314: (*pp)++;
1315: return TRUE;
1316: }
1.368 rillig 1317:
1.469 rillig 1318: if (*cp == ':') {
1319: if (cp[1] == ':') {
1320: *out_op = OP_DOUBLEDEP;
1321: (*pp) += 2;
1322: } else {
1323: *out_op = OP_DEPENDS;
1324: (*pp)++;
1325: }
1326: return TRUE;
1.368 rillig 1327: }
1.364 rillig 1328:
1.469 rillig 1329: {
1330: const char *msg = lstart[0] == '.'
1331: ? "Unknown directive" : "Missing dependency operator";
1332: Parse_Error(PARSE_FATAL, "%s", msg);
1333: return FALSE;
1334: }
1.368 rillig 1335: }
1.364 rillig 1336:
1.368 rillig 1337: static void
1.392 rillig 1338: ClearPaths(SearchPathList *paths)
1339: {
1.469 rillig 1340: if (paths != NULL) {
1341: SearchPathListNode *ln;
1342: for (ln = paths->first; ln != NULL; ln = ln->next)
1343: SearchPath_Clear(ln->datum);
1344: }
1.392 rillig 1345:
1.469 rillig 1346: Dir_SetPATH();
1.392 rillig 1347: }
1348:
1349: static void
1.395 rillig 1350: ParseDoDependencySourcesEmpty(ParseSpecial specType, SearchPathList *paths)
1.368 rillig 1351: {
1.469 rillig 1352: switch (specType) {
1353: case SP_SUFFIXES:
1354: Suff_ClearSuffixes();
1355: break;
1356: case SP_PRECIOUS:
1357: allPrecious = TRUE;
1358: break;
1359: case SP_IGNORE:
1360: opts.ignoreErrors = TRUE;
1361: break;
1362: case SP_SILENT:
1363: opts.beSilent = TRUE;
1364: break;
1365: case SP_PATH:
1366: ClearPaths(paths);
1367: break;
1.368 rillig 1368: #ifdef POSIX
1.469 rillig 1369: case SP_POSIX:
1370: Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1371: break;
1.368 rillig 1372: #endif
1.469 rillig 1373: default:
1374: break;
1375: }
1.368 rillig 1376: }
1.364 rillig 1377:
1.393 rillig 1378: static void
1379: AddToPaths(const char *dir, SearchPathList *paths)
1380: {
1.469 rillig 1381: if (paths != NULL) {
1382: SearchPathListNode *ln;
1383: for (ln = paths->first; ln != NULL; ln = ln->next)
1384: (void)Dir_AddDir(ln->datum, dir);
1385: }
1.393 rillig 1386: }
1387:
1.368 rillig 1388: /*
1389: * If the target was one that doesn't take files as its sources
1390: * but takes something like suffixes, we take each
1391: * space-separated word on the line as a something and deal
1392: * with it accordingly.
1393: *
1394: * If the target was .SUFFIXES, we take each source as a
1395: * suffix and add it to the list of suffixes maintained by the
1396: * Suff module.
1397: *
1398: * If the target was a .PATH, we add the source as a directory
1399: * to search on the search path.
1400: *
1401: * If it was .INCLUDES, the source is taken to be the suffix of
1402: * files which will be #included and whose search path should
1403: * be present in the .INCLUDES variable.
1404: *
1405: * If it was .LIBS, the source is taken to be the suffix of
1406: * files which are considered libraries and whose search path
1407: * should be present in the .LIBS variable.
1408: *
1409: * If it was .NULL, the source is the suffix to use when a file
1410: * has no valid suffix.
1411: *
1412: * If it was .OBJDIR, the source is a new definition for .OBJDIR,
1413: * and will cause make to do a new chdir to that path.
1414: */
1415: static void
1.395 rillig 1416: ParseDoDependencySourceSpecial(ParseSpecial specType, char *word,
1417: SearchPathList *paths)
1.368 rillig 1418: {
1.469 rillig 1419: switch (specType) {
1420: case SP_SUFFIXES:
1421: Suff_AddSuffix(word, &mainNode);
1422: break;
1423: case SP_PATH:
1424: AddToPaths(word, paths);
1425: break;
1426: case SP_INCLUDES:
1427: Suff_AddInclude(word);
1428: break;
1429: case SP_LIBS:
1430: Suff_AddLib(word);
1431: break;
1432: case SP_NULL:
1433: Suff_SetNull(word);
1434: break;
1435: case SP_OBJDIR:
1436: Main_SetObjdir(FALSE, "%s", word);
1437: break;
1438: default:
1439: break;
1440: }
1.368 rillig 1441: }
1.364 rillig 1442:
1.368 rillig 1443: static Boolean
1.395 rillig 1444: ParseDoDependencyTargets(char **inout_cp,
1445: char **inout_line,
1446: const char *lstart,
1447: ParseSpecial *inout_specType,
1448: GNodeType *inout_tOp,
1449: SearchPathList **inout_paths,
1450: StringList *curTargs)
1.368 rillig 1451: {
1.469 rillig 1452: char *cp;
1453: char *tgt = *inout_line;
1454: char savec;
1455: const char *p;
1456:
1457: for (;;) {
1458: /*
1459: * Here LINE points to the beginning of the next word, and
1460: * LSTART points to the actual beginning of the line.
1461: */
1462:
1463: /* Find the end of the next word. */
1464: cp = tgt;
1465: p = cp;
1466: ParseDependencyTargetWord(&p, lstart);
1467: cp += p - cp;
1468:
1469: /*
1470: * If the word is followed by a left parenthesis, it's the
1471: * name of an object file inside an archive (ar file).
1472: */
1473: if (!ParseIsEscaped(lstart, cp) && *cp == '(') {
1474: /*
1475: * Archives must be handled specially to make sure the
1476: * OP_ARCHV flag is set in their 'type' field, for one
1477: * thing, and because things like "archive(file1.o
1478: * file2.o file3.o)" are permissible.
1479: *
1480: * Arch_ParseArchive will set 'line' to be the first
1481: * non-blank after the archive-spec. It creates/finds
1482: * nodes for the members and places them on the given
1483: * list, returning TRUE if all went well and FALSE if
1484: * there was an error in the specification. On error,
1485: * line should remain untouched.
1486: */
1487: if (!Arch_ParseArchive(&tgt, targets, VAR_CMDLINE)) {
1488: Parse_Error(PARSE_FATAL,
1489: "Error in archive specification: \"%s\"",
1490: tgt);
1491: return FALSE;
1492: }
1493:
1494: cp = tgt;
1495: continue;
1496: }
1.444 rillig 1497:
1.469 rillig 1498: if (*cp == '\0') {
1499: ParseErrorNoDependency(lstart);
1500: return FALSE;
1501: }
1.27 christos 1502:
1.469 rillig 1503: /* Insert a null terminator. */
1504: savec = *cp;
1505: *cp = '\0';
1.204 dholland 1506:
1.469 rillig 1507: if (!ParseDoDependencyTarget(tgt, inout_specType, inout_tOp,
1508: inout_paths))
1509: return FALSE;
1.118 dsl 1510:
1.469 rillig 1511: /*
1512: * Have word in line. Get or create its node and stick it at
1513: * the end of the targets list
1514: */
1515: if (*inout_specType == SP_NOT && *tgt != '\0')
1516: ParseDoDependencyTargetMundane(tgt, curTargs);
1517: else if (*inout_specType == SP_PATH && *tgt != '.' &&
1518: *tgt != '\0')
1519: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
1520: tgt);
1.368 rillig 1521:
1.469 rillig 1522: /* Don't need the inserted null terminator any more. */
1523: *cp = savec;
1.368 rillig 1524:
1.469 rillig 1525: /*
1526: * If it is a special type and not .PATH, it's the only target
1527: * we allow on this line.
1528: */
1529: if (*inout_specType != SP_NOT && *inout_specType != SP_PATH)
1530: ParseDoDependencyTargetExtraWarn(&cp, lstart);
1531: else
1532: pp_skip_whitespace(&cp);
1.368 rillig 1533:
1.469 rillig 1534: tgt = cp;
1535: if (*tgt == '\0')
1536: break;
1537: if ((*tgt == '!' || *tgt == ':') &&
1538: !ParseIsEscaped(lstart, tgt))
1539: break;
1540: }
1.430 rillig 1541:
1.469 rillig 1542: *inout_cp = cp;
1543: *inout_line = tgt;
1544: return TRUE;
1.368 rillig 1545: }
1.27 christos 1546:
1.368 rillig 1547: static void
1.395 rillig 1548: ParseDoDependencySourcesSpecial(char *start, char *end,
1.368 rillig 1549: ParseSpecial specType, SearchPathList *paths)
1550: {
1.469 rillig 1551: char savec;
1.204 dholland 1552:
1.469 rillig 1553: while (*start != '\0') {
1554: while (*end != '\0' && !ch_isspace(*end))
1555: end++;
1556: savec = *end;
1557: *end = '\0';
1558: ParseDoDependencySourceSpecial(specType, start, paths);
1559: *end = savec;
1560: if (savec != '\0')
1561: end++;
1562: pp_skip_whitespace(&end);
1563: start = end;
1564: }
1.368 rillig 1565: }
1566:
1567: static Boolean
1.395 rillig 1568: ParseDoDependencySourcesMundane(char *start, char *end,
1.374 rillig 1569: ParseSpecial specType, GNodeType tOp)
1.368 rillig 1570: {
1.469 rillig 1571: while (*start != '\0') {
1.367 rillig 1572: /*
1.469 rillig 1573: * The targets take real sources, so we must beware of archive
1574: * specifications (i.e. things with left parentheses in them)
1575: * and handle them accordingly.
1.367 rillig 1576: */
1.469 rillig 1577: for (; *end != '\0' && !ch_isspace(*end); end++) {
1578: if (*end == '(' && end > start && end[-1] != '$') {
1579: /*
1580: * Only stop for a left parenthesis if it
1581: * isn't at the start of a word (that'll be
1582: * for variable changes later) and isn't
1583: * preceded by a dollar sign (a dynamic
1584: * source).
1585: */
1586: break;
1587: }
1588: }
1.368 rillig 1589:
1.469 rillig 1590: if (*end == '(') {
1591: GNodeList sources = LST_INIT;
1592: if (!Arch_ParseArchive(&start, &sources, VAR_CMDLINE)) {
1593: Parse_Error(PARSE_FATAL,
1594: "Error in source archive spec \"%s\"",
1595: start);
1596: return FALSE;
1597: }
1.368 rillig 1598:
1.469 rillig 1599: while (!Lst_IsEmpty(&sources)) {
1600: GNode *gn = Lst_Dequeue(&sources);
1601: ParseDependencySource(tOp, gn->name, specType);
1602: }
1603: Lst_Done(&sources);
1604: end = start;
1605: } else {
1606: if (*end != '\0') {
1607: *end = '\0';
1608: end++;
1609: }
1.368 rillig 1610:
1.469 rillig 1611: ParseDependencySource(tOp, start, specType);
1612: }
1613: pp_skip_whitespace(&end);
1614: start = end;
1.368 rillig 1615: }
1.469 rillig 1616: return TRUE;
1.368 rillig 1617: }
1.1 cgd 1618:
1.368 rillig 1619: /* Parse a dependency line consisting of targets, followed by a dependency
1620: * operator, optionally followed by sources.
1621: *
1622: * The nodes of the sources are linked as children to the nodes of the
1623: * targets. Nodes are created as necessary.
1624: *
1625: * The operator is applied to each node in the global 'targets' list,
1626: * which is where the nodes found for the targets are kept, by means of
1627: * the ParseDoOp function.
1628: *
1629: * The sources are parsed in much the same way as the targets, except
1630: * that they are expanded using the wildcarding scheme of the C-Shell,
1.441 rillig 1631: * and a target is created for each expanded word. Each of the resulting
1632: * nodes is then linked to each of the targets as one of its children.
1.368 rillig 1633: *
1634: * Certain targets and sources such as .PHONY or .PRECIOUS are handled
1635: * specially. These are the ones detailed by the specType variable.
1636: *
1637: * The storing of transformation rules such as '.c.o' is also taken care of
1638: * here. A target is recognized as a transformation rule by calling
1639: * Suff_IsTransform. If it is a transformation rule, its node is gotten
1640: * from the suffix module via Suff_AddTransform rather than the standard
1641: * Targ_FindNode in the target module.
1.441 rillig 1642: *
1643: * Upon return, the value of the line is unspecified.
1.368 rillig 1644: */
1645: static void
1646: ParseDoDependency(char *line)
1647: {
1.469 rillig 1648: char *cp; /* our current position */
1649: GNodeType op; /* the operator on the line */
1650: SearchPathList *paths; /* search paths to alter when parsing
1.368 rillig 1651: * a list of .PATH targets */
1.469 rillig 1652: GNodeType tOp; /* operator from special target */
1653: /* target names to be found and added to the targets list */
1654: StringList curTargs = LST_INIT;
1655: char *lstart = line;
1656:
1657: /*
1658: * specType contains the SPECial TYPE of the current target. It is
1659: * SP_NOT if the target is unspecial. If it *is* special, however, the
1660: * children are linked as children of the parent but not vice versa.
1661: */
1662: ParseSpecial specType = SP_NOT;
1663:
1664: DEBUG1(PARSE, "ParseDoDependency(%s)\n", line);
1665: tOp = OP_NONE;
1666:
1667: paths = NULL;
1668:
1669: /*
1670: * First, grind through the targets.
1671: */
1.478 rillig 1672: /* XXX: don't use line as an iterator variable */
1.469 rillig 1673: if (!ParseDoDependencyTargets(&cp, &line, lstart, &specType, &tOp,
1674: &paths, &curTargs))
1675: goto out;
1676:
1677: /*
1678: * Don't need the list of target names anymore.
1679: * The targets themselves are now in the global variable 'targets'.
1680: */
1681: Lst_Done(&curTargs);
1682: Lst_Init(&curTargs);
1683:
1684: if (!Lst_IsEmpty(targets))
1685: ParseDoDependencyCheckSpec(specType);
1686:
1687: /*
1688: * Have now parsed all the target names. Must parse the operator next.
1689: */
1690: if (!ParseDoDependencyParseOp(&cp, lstart, &op))
1691: goto out;
1692:
1693: /*
1694: * Apply the operator to the target. This is how we remember which
1695: * operator a target was defined with. It fails if the operator
1696: * used isn't consistent across all references.
1697: */
1698: ApplyDependencyOperator(op);
1699:
1700: /*
1701: * Onward to the sources.
1702: *
1703: * LINE will now point to the first source word, if any, or the
1704: * end of the string if not.
1705: */
1706: pp_skip_whitespace(&cp);
1707: line = cp; /* XXX: 'line' is an inappropriate name */
1708:
1709: /*
1710: * Several special targets take different actions if present with no
1711: * sources:
1712: * a .SUFFIXES line with no sources clears out all old suffixes
1713: * a .PRECIOUS line makes all targets precious
1714: * a .IGNORE line ignores errors for all targets
1715: * a .SILENT line creates silence when making all targets
1716: * a .PATH removes all directories from the search path(s).
1717: */
1718: if (line[0] == '\0') {
1719: ParseDoDependencySourcesEmpty(specType, paths);
1720: } else if (specType == SP_MFLAGS) {
1721: /*
1722: * Call on functions in main.c to deal with these arguments and
1723: * set the initial character to a null-character so the loop to
1724: * get sources won't get anything
1725: */
1726: Main_ParseArgLine(line);
1727: *line = '\0';
1728: } else if (specType == SP_SHELL) {
1729: if (!Job_ParseShell(line)) {
1730: Parse_Error(PARSE_FATAL,
1731: "improper shell specification");
1732: goto out;
1733: }
1734: *line = '\0';
1735: } else if (specType == SP_NOTPARALLEL || specType == SP_SINGLESHELL ||
1736: specType == SP_DELETE_ON_ERROR) {
1737: *line = '\0';
1738: }
1739:
1740: /* Now go for the sources. */
1741: if (specType == SP_SUFFIXES || specType == SP_PATH ||
1742: specType == SP_INCLUDES || specType == SP_LIBS ||
1743: specType == SP_NULL || specType == SP_OBJDIR) {
1744: ParseDoDependencySourcesSpecial(line, cp, specType, paths);
1745: if (paths != NULL) {
1746: Lst_Free(paths);
1747: paths = NULL;
1748: }
1749: if (specType == SP_PATH)
1750: Dir_SetPATH();
1751: } else {
1752: assert(paths == NULL);
1753: if (!ParseDoDependencySourcesMundane(line, cp, specType, tOp))
1754: goto out;
1.1 cgd 1755: }
1.27 christos 1756:
1.469 rillig 1757: FindMainTarget();
1.1 cgd 1758:
1.112 christos 1759: out:
1.469 rillig 1760: if (paths != NULL)
1761: Lst_Free(paths);
1762: Lst_Done(&curTargs);
1.1 cgd 1763: }
1764:
1.389 rillig 1765: typedef struct VarAssignParsed {
1.469 rillig 1766: const char *nameStart; /* unexpanded */
1767: const char *nameEnd; /* before operator adjustment */
1768: const char *eq; /* the '=' of the assignment operator */
1.389 rillig 1769: } VarAssignParsed;
1770:
1.469 rillig 1771: /*
1772: * Determine the assignment operator and adjust the end of the variable
1773: * name accordingly.
1774: */
1.388 rillig 1775: static void
1.389 rillig 1776: AdjustVarassignOp(const VarAssignParsed *pvar, const char *value,
1777: VarAssign *out_var)
1.388 rillig 1778: {
1.469 rillig 1779: const char *op = pvar->eq;
1780: const char *const name = pvar->nameStart;
1781: VarAssignOp type;
1782:
1783: if (op > name && op[-1] == '+') {
1784: type = VAR_APPEND;
1785: op--;
1786:
1787: } else if (op > name && op[-1] == '?') {
1788: op--;
1789: type = VAR_DEFAULT;
1790:
1791: } else if (op > name && op[-1] == ':') {
1792: op--;
1793: type = VAR_SUBST;
1794:
1795: } else if (op > name && op[-1] == '!') {
1796: op--;
1797: type = VAR_SHELL;
1.388 rillig 1798:
1.469 rillig 1799: } else {
1800: type = VAR_NORMAL;
1.388 rillig 1801: #ifdef SUNSHCMD
1.469 rillig 1802: while (op > name && ch_isspace(op[-1]))
1803: op--;
1.388 rillig 1804:
1.469 rillig 1805: if (op >= name + 3 && op[-3] == ':' && op[-2] == 's' &&
1806: op[-1] == 'h') {
1807: type = VAR_SHELL;
1808: op -= 3;
1809: }
1810: #endif
1.388 rillig 1811: }
1812:
1.469 rillig 1813: {
1814: const char *nameEnd = pvar->nameEnd < op ? pvar->nameEnd : op;
1815: out_var->varname = bmake_strsedup(pvar->nameStart, nameEnd);
1816: out_var->op = type;
1817: out_var->value = value;
1818: }
1.388 rillig 1819: }
1820:
1.469 rillig 1821: /*
1822: * Parse a variable assignment, consisting of a single-word variable name,
1.368 rillig 1823: * optional whitespace, an assignment operator, optional whitespace and the
1824: * variable value.
1.84 wiz 1825: *
1.410 rillig 1826: * Note: There is a lexical ambiguity with assignment modifier characters
1827: * in variable names. This routine interprets the character before the =
1828: * as a modifier. Therefore, an assignment like
1829: * C++=/usr/bin/CC
1830: * is interpreted as "C+ +=" instead of "C++ =".
1831: *
1.469 rillig 1832: * Used for both lines in a file and command line arguments.
1833: */
1.1 cgd 1834: Boolean
1.368 rillig 1835: Parse_IsVar(const char *p, VarAssign *out_var)
1.1 cgd 1836: {
1.469 rillig 1837: VarAssignParsed pvar;
1838: const char *firstSpace = NULL;
1839: int level = 0;
1840:
1841: cpp_skip_hspace(&p); /* Skip to variable name */
1842:
1843: /*
1844: * During parsing, the '+' of the '+=' operator is initially parsed
1845: * as part of the variable name. It is later corrected, as is the
1846: * ':sh' modifier. Of these two (nameEnd and op), the earlier one
1847: * determines the actual end of the variable name.
1848: */
1849: pvar.nameStart = p;
1.368 rillig 1850: #ifdef CLEANUP
1.469 rillig 1851: pvar.nameEnd = NULL;
1852: pvar.eq = NULL;
1.368 rillig 1853: #endif
1.356 rillig 1854:
1.469 rillig 1855: /*
1856: * Scan for one of the assignment operators outside a variable
1857: * expansion.
1858: */
1859: while (*p != '\0') {
1860: char ch = *p++;
1861: if (ch == '(' || ch == '{') {
1862: level++;
1863: continue;
1864: }
1865: if (ch == ')' || ch == '}') {
1866: level--;
1867: continue;
1868: }
1869:
1870: if (level != 0)
1871: continue;
1872:
1873: if (ch == ' ' || ch == '\t')
1874: if (firstSpace == NULL)
1875: firstSpace = p - 1;
1876: while (ch == ' ' || ch == '\t')
1877: ch = *p++;
1.368 rillig 1878:
1.191 sjg 1879: #ifdef SUNSHCMD
1.469 rillig 1880: if (ch == ':' && p[0] == 's' && p[1] == 'h') {
1881: p += 2;
1882: continue;
1883: }
1884: #endif
1885: if (ch == '=') {
1886: pvar.eq = p - 1;
1887: pvar.nameEnd = firstSpace != NULL ? firstSpace : p - 1;
1888: cpp_skip_whitespace(&p);
1889: AdjustVarassignOp(&pvar, p, out_var);
1890: return TRUE;
1891: }
1892: if (*p == '=' &&
1893: (ch == '+' || ch == ':' || ch == '?' || ch == '!')) {
1894: pvar.eq = p;
1895: pvar.nameEnd = firstSpace != NULL ? firstSpace : p;
1896: p++;
1897: cpp_skip_whitespace(&p);
1898: AdjustVarassignOp(&pvar, p, out_var);
1899: return TRUE;
1900: }
1901: if (firstSpace != NULL)
1902: return FALSE;
1.191 sjg 1903: }
1.1 cgd 1904:
1.469 rillig 1905: return FALSE;
1.1 cgd 1906: }
1907:
1.469 rillig 1908: /*
1909: * Check for syntax errors such as unclosed expressions or unknown modifiers.
1910: */
1.368 rillig 1911: static void
1912: VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt)
1913: {
1.469 rillig 1914: if (opts.lint) {
1915: if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) {
1916: char *expandedValue;
1917:
1918: (void)Var_Subst(uvalue, ctxt, VARE_NONE,
1919: &expandedValue);
1920: /* TODO: handle errors */
1921: free(expandedValue);
1922: }
1.243 sjg 1923: }
1.368 rillig 1924: }
1925:
1.390 rillig 1926: static void
1.391 rillig 1927: VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt,
1.506 rillig 1928: FStr *out_avalue)
1.390 rillig 1929: {
1.469 rillig 1930: const char *avalue;
1931: char *evalue;
1932: Boolean savedPreserveUndefined = preserveUndefined;
1933:
1934: /* TODO: Can this assignment to preserveUndefined be moved further down
1935: * to the actually interesting Var_Subst call, without affecting any
1936: * edge cases?
1937: *
1938: * It might affect the implicit expansion of the variable name in the
1939: * Var_Exists and Var_Set calls, even though it's unlikely that anyone
1940: * cared about this edge case when adding this code. In addition,
1941: * variable assignments should not refer to any undefined variables in
1942: * the variable name. */
1943: preserveUndefined = TRUE;
1944:
1945: /*
1946: * make sure that we set the variable the first time to nothing
1947: * so that it gets substituted!
1948: */
1949: if (!Var_Exists(name, ctxt))
1950: Var_Set(name, "", ctxt);
1951:
1952: (void)Var_Subst(uvalue, ctxt, VARE_WANTRES | VARE_KEEP_DOLLAR, &evalue);
1953: /* TODO: handle errors */
1954: preserveUndefined = savedPreserveUndefined;
1955: avalue = evalue;
1956: Var_Set(name, avalue, ctxt);
1.390 rillig 1957:
1.506 rillig 1958: *out_avalue = (FStr){ avalue, evalue };
1.390 rillig 1959: }
1960:
1961: static void
1.391 rillig 1962: VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt,
1.506 rillig 1963: FStr *out_avalue)
1.390 rillig 1964: {
1.507 ! rillig 1965: FStr cmd;
! 1966: const char *errfmt;
1.469 rillig 1967: char *cmdOut;
1968:
1.507 ! rillig 1969: cmd = FStr_InitRefer(uvalue);
! 1970: if (strchr(cmd.str, '$') != NULL) {
! 1971: char *expanded;
! 1972: (void)Var_Subst(cmd.str, VAR_CMDLINE,
! 1973: VARE_WANTRES | VARE_UNDEFERR, &expanded);
1.469 rillig 1974: /* TODO: handle errors */
1.507 ! rillig 1975: cmd = FStr_InitOwn(expanded);
1.469 rillig 1976: }
1977:
1.507 ! rillig 1978: cmdOut = Cmd_Exec(cmd.str, &errfmt);
1.469 rillig 1979: Var_Set(name, cmdOut, ctxt);
1.506 rillig 1980: *out_avalue = FStr_InitOwn(cmdOut);
1.390 rillig 1981:
1.469 rillig 1982: if (errfmt != NULL)
1983: Parse_Error(PARSE_WARNING, errfmt, cmd);
1.390 rillig 1984:
1.507 ! rillig 1985: FStr_Done(&cmd);
1.390 rillig 1986: }
1987:
1.391 rillig 1988: /* Perform a variable assignment.
1989: *
1990: * The actual value of the variable is returned in *out_avalue and
1991: * *out_avalue_freeIt. Especially for VAR_SUBST and VAR_SHELL this can differ
1992: * from the literal value.
1993: *
1994: * Return whether the assignment was actually done. The assignment is only
1995: * skipped if the operator is '?=' and the variable already exists. */
1.368 rillig 1996: static Boolean
1.391 rillig 1997: VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
1.506 rillig 1998: GNode *ctxt, FStr *out_TRUE_avalue)
1.368 rillig 1999: {
1.506 rillig 2000: FStr avalue = FStr_InitRefer(uvalue);
1.469 rillig 2001:
2002: if (op == VAR_APPEND)
2003: Var_Append(name, uvalue, ctxt);
2004: else if (op == VAR_SUBST)
1.506 rillig 2005: VarAssign_EvalSubst(name, uvalue, ctxt, &avalue);
1.469 rillig 2006: else if (op == VAR_SHELL)
1.506 rillig 2007: VarAssign_EvalShell(name, uvalue, ctxt, &avalue);
1.469 rillig 2008: else {
1.506 rillig 2009: if (op == VAR_DEFAULT && Var_Exists(name, ctxt))
1.469 rillig 2010: return FALSE;
1.353 rillig 2011:
1.469 rillig 2012: /* Normal assignment -- just do it. */
2013: Var_Set(name, uvalue, ctxt);
2014: }
2015:
1.506 rillig 2016: *out_TRUE_avalue = avalue;
1.469 rillig 2017: return TRUE;
1.368 rillig 2018: }
2019:
2020: static void
2021: VarAssignSpecial(const char *name, const char *avalue)
2022: {
1.469 rillig 2023: if (strcmp(name, MAKEOVERRIDES) == 0)
2024: Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */
2025: else if (strcmp(name, ".CURDIR") == 0) {
2026: /*
2027: * Someone is being (too?) clever...
2028: * Let's pretend they know what they are doing and
2029: * re-initialize the 'cur' CachedDir.
2030: */
2031: Dir_InitCur(avalue);
2032: Dir_SetPATH();
2033: } else if (strcmp(name, MAKE_JOB_PREFIX) == 0)
2034: Job_SetPrefix();
2035: else if (strcmp(name, MAKE_EXPORTED) == 0)
1.473 rillig 2036: Var_ExportVars(avalue);
1.368 rillig 2037: }
2038:
1.410 rillig 2039: /* Perform the variable variable assignment in the given context. */
1.368 rillig 2040: void
2041: Parse_DoVar(VarAssign *var, GNode *ctxt)
2042: {
1.506 rillig 2043: FStr avalue; /* actual value (maybe expanded) */
1.368 rillig 2044:
1.469 rillig 2045: VarCheckSyntax(var->op, var->value, ctxt);
1.506 rillig 2046: if (VarAssign_Eval(var->varname, var->op, var->value, ctxt, &avalue)) {
2047: VarAssignSpecial(var->varname, avalue.str);
2048: FStr_Done(&avalue);
2049: }
1.368 rillig 2050:
1.469 rillig 2051: free(var->varname);
1.1 cgd 2052: }
1.23 christos 2053:
1.200 christos 2054:
1.432 rillig 2055: /* See if the command possibly calls a sub-make by using the variable
2056: * expressions ${.MAKE}, ${MAKE} or the plain word "make". */
1.195 christos 2057: static Boolean
1.432 rillig 2058: MaybeSubMake(const char *cmd)
1.195 christos 2059: {
1.469 rillig 2060: const char *start;
1.432 rillig 2061:
1.469 rillig 2062: for (start = cmd; *start != '\0'; start++) {
2063: const char *p = start;
2064: char endc;
2065:
2066: /* XXX: What if progname != "make"? */
2067: if (p[0] == 'm' && p[1] == 'a' && p[2] == 'k' && p[3] == 'e')
2068: if (start == cmd || !ch_isalnum(p[-1]))
2069: if (!ch_isalnum(p[4]))
2070: return TRUE;
2071:
2072: if (*p != '$')
2073: continue;
2074: p++;
2075:
2076: if (*p == '{')
2077: endc = '}';
2078: else if (*p == '(')
2079: endc = ')';
2080: else
2081: continue;
2082: p++;
1.432 rillig 2083:
1.469 rillig 2084: if (*p == '.') /* Accept either ${.MAKE} or ${MAKE}. */
2085: p++;
1.432 rillig 2086:
1.469 rillig 2087: if (p[0] == 'M' && p[1] == 'A' && p[2] == 'K' && p[3] == 'E')
2088: if (p[4] == endc)
2089: return TRUE;
2090: }
2091: return FALSE;
1.195 christos 2092: }
2093:
1.327 rillig 2094: /* Append the command to the target node.
1.1 cgd 2095: *
1.327 rillig 2096: * The node may be marked as a submake node if the command is determined to
2097: * be that. */
2098: static void
2099: ParseAddCmd(GNode *gn, char *cmd)
1.9 jtc 2100: {
1.469 rillig 2101: /* Add to last (ie current) cohort for :: targets */
2102: if ((gn->type & OP_DOUBLEDEP) && gn->cohorts.last != NULL)
2103: gn = gn->cohorts.last->datum;
2104:
2105: /* if target already supplied, ignore commands */
2106: if (!(gn->type & OP_HAS_COMMANDS)) {
2107: Lst_Append(&gn->commands, cmd);
2108: if (MaybeSubMake(cmd))
2109: gn->type |= OP_SUBMAKE;
2110: ParseMark(gn);
2111: } else {
1.327 rillig 2112: #if 0
1.469 rillig 2113: /* XXX: We cannot do this until we fix the tree */
2114: Lst_Append(&gn->commands, cmd);
2115: Parse_Error(PARSE_WARNING,
2116: "overriding commands for target \"%s\"; "
2117: "previous commands defined at %s: %d ignored",
2118: gn->name, gn->fname, gn->lineno);
1.203 joerg 2119: #else
1.469 rillig 2120: Parse_Error(PARSE_WARNING,
1.374 rillig 2121: "duplicate script for target \"%s\" ignored",
2122: gn->name);
1.469 rillig 2123: ParseErrorInternal(gn->fname, (size_t)gn->lineno, PARSE_WARNING,
2124: "using previous script for \"%s\" defined here",
2125: gn->name);
1.203 joerg 2126: #endif
1.469 rillig 2127: }
1.1 cgd 2128: }
2129:
1.469 rillig 2130: /*
2131: * Add a directory to the path searched for included makefiles bracketed
2132: * by double-quotes.
2133: */
1.1 cgd 2134: void
1.344 rillig 2135: Parse_AddIncludeDir(const char *dir)
1.1 cgd 2136: {
1.469 rillig 2137: (void)Dir_AddDir(parseIncPath, dir);
1.1 cgd 2138: }
2139:
1.441 rillig 2140: /* Handle one of the .[-ds]include directives by remembering the current file
2141: * and pushing the included file on the stack. After the included file has
2142: * finished, parsing continues with the including file; see Parse_SetInput
2143: * and ParseEOF.
2144: *
2145: * System includes are looked up in sysIncPath, any other includes are looked
2146: * up in the parsedir and then in the directories specified by the -I command
2147: * line options.
1.1 cgd 2148: */
2149: static void
1.434 rillig 2150: Parse_include_file(char *file, Boolean isSystem, Boolean depinc, Boolean silent)
1.1 cgd 2151: {
1.469 rillig 2152: struct loadedfile *lf;
2153: char *fullname; /* full pathname of file */
2154: char *newName;
2155: char *slash, *incdir;
2156: int fd;
2157: int i;
2158:
2159: fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
2160:
2161: if (fullname == NULL && !isSystem) {
2162: /*
2163: * Include files contained in double-quotes are first searched
2164: * relative to the including file's location. We don't want to
2165: * cd there, of course, so we just tack on the old file's
2166: * leading path components and call Dir_FindFile to see if
2167: * we can locate the file.
2168: */
2169:
2170: incdir = bmake_strdup(CurFile()->fname);
2171: slash = strrchr(incdir, '/');
2172: if (slash != NULL) {
2173: *slash = '\0';
2174: /*
2175: * Now do lexical processing of leading "../" on the
2176: * filename.
2177: */
2178: for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
2179: slash = strrchr(incdir + 1, '/');
2180: if (slash == NULL || strcmp(slash, "/..") == 0)
2181: break;
2182: *slash = '\0';
2183: }
2184: newName = str_concat3(incdir, "/", file + i);
2185: fullname = Dir_FindFile(newName, parseIncPath);
2186: if (fullname == NULL)
2187: fullname = Dir_FindFile(newName,
2188: &dirSearchPath);
2189: free(newName);
2190: }
2191: free(incdir);
2192:
2193: if (fullname == NULL) {
2194: /*
2195: * Makefile wasn't found in same directory as included
2196: * makefile.
2197: *
2198: * Search for it first on the -I search path, then on
2199: * the .PATH search path, if not found in a -I
2200: * directory. If we have a suffix-specific path, we
2201: * should use that.
2202: */
2203: const char *suff;
2204: SearchPath *suffPath = NULL;
2205:
2206: if ((suff = strrchr(file, '.'))) {
2207: suffPath = Suff_GetPath(suff);
2208: if (suffPath != NULL)
2209: fullname = Dir_FindFile(file, suffPath);
2210: }
2211: if (fullname == NULL) {
2212: fullname = Dir_FindFile(file, parseIncPath);
2213: if (fullname == NULL)
2214: fullname = Dir_FindFile(file,
2215: &dirSearchPath);
2216: }
2217: }
1.1 cgd 2218: }
1.140 dsl 2219:
1.469 rillig 2220: /* Looking for a system file or file still not found */
1.142 sjg 2221: if (fullname == NULL) {
1.469 rillig 2222: /*
2223: * Look for it on the system path
2224: */
2225: SearchPath *path = Lst_IsEmpty(sysIncPath) ? defSysIncPath
2226: : sysIncPath;
2227: fullname = Dir_FindFile(file, path);
2228: }
2229:
2230: if (fullname == NULL) {
2231: if (!silent)
2232: Parse_Error(PARSE_FATAL, "Could not find %s", file);
2233: return;
2234: }
2235:
2236: /* Actually open the file... */
2237: fd = open(fullname, O_RDONLY);
2238: if (fd == -1) {
2239: if (!silent)
2240: Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
2241: free(fullname);
2242: return;
2243: }
2244:
2245: /* load it */
2246: lf = loadfile(fullname, fd);
2247:
2248: /* Start reading from this file next */
1.471 rillig 2249: Parse_SetInput(fullname, 0, -1, loadedfile_readMore, lf);
1.469 rillig 2250: CurFile()->lf = lf;
2251: if (depinc)
2252: doing_depend = depinc; /* only turn it on */
1.123 dsl 2253: }
2254:
2255: static void
1.478 rillig 2256: ParseDoInclude(char *line /* XXX: bad name */)
1.123 dsl 2257: {
1.469 rillig 2258: char endc; /* the character which ends the file spec */
2259: char *cp; /* current position in file spec */
1.478 rillig 2260: Boolean silent = line[0] != 'i';
1.469 rillig 2261: char *file = line + (silent ? 8 : 7);
1.123 dsl 2262:
1.469 rillig 2263: /* Skip to delimiter character so we know where to look */
2264: pp_skip_hspace(&file);
1.123 dsl 2265:
1.469 rillig 2266: if (*file != '"' && *file != '<') {
2267: Parse_Error(PARSE_FATAL,
1.374 rillig 2268: ".include filename must be delimited by '\"' or '<'");
1.469 rillig 2269: return;
2270: }
1.123 dsl 2271:
1.469 rillig 2272: /*
2273: * Set the search path on which to find the include file based on the
2274: * characters which bracket its name. Angle-brackets imply it's
2275: * a system Makefile while double-quotes imply it's a user makefile
2276: */
2277: if (*file == '<')
2278: endc = '>';
2279: else
2280: endc = '"';
2281:
2282: /* Skip to matching delimiter */
2283: for (cp = ++file; *cp && *cp != endc; cp++)
2284: continue;
1.123 dsl 2285:
1.469 rillig 2286: if (*cp != endc) {
2287: Parse_Error(PARSE_FATAL,
1.441 rillig 2288: "Unclosed .include filename. '%c' expected", endc);
1.469 rillig 2289: return;
2290: }
1.430 rillig 2291:
1.469 rillig 2292: *cp = '\0';
1.123 dsl 2293:
1.469 rillig 2294: /*
2295: * Substitute for any variables in the filename before trying to
2296: * find the file.
2297: */
2298: (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &file);
2299: /* TODO: handle errors */
1.123 dsl 2300:
1.478 rillig 2301: Parse_include_file(file, endc == '>', line[0] == 'd', silent);
1.469 rillig 2302: free(file);
1.1 cgd 2303: }
2304:
1.281 rillig 2305: /* Split filename into dirname + basename, then assign these to the
2306: * given variables. */
1.193 christos 2307: static void
1.281 rillig 2308: SetFilenameVars(const char *filename, const char *dirvar, const char *filevar)
1.193 christos 2309: {
1.469 rillig 2310: const char *slash, *dirname, *basename;
2311: void *freeIt;
2312:
2313: slash = strrchr(filename, '/');
2314: if (slash == NULL) {
2315: dirname = curdir;
2316: basename = filename;
2317: freeIt = NULL;
2318: } else {
2319: dirname = freeIt = bmake_strsedup(filename, slash);
2320: basename = slash + 1;
2321: }
1.281 rillig 2322:
1.469 rillig 2323: Var_Set(dirvar, dirname, VAR_GLOBAL);
2324: Var_Set(filevar, basename, VAR_GLOBAL);
2325:
2326: DEBUG5(PARSE, "%s: ${%s} = `%s' ${%s} = `%s'\n",
2327: __func__, dirvar, dirname, filevar, basename);
2328: free(freeIt);
1.281 rillig 2329: }
2330:
1.469 rillig 2331: /*
2332: * Return the immediately including file.
1.281 rillig 2333: *
2334: * This is made complicated since the .for loop is implemented as a special
1.469 rillig 2335: * kind of .include; see For_Run.
2336: */
1.281 rillig 2337: static const char *
2338: GetActuallyIncludingFile(void)
2339: {
1.469 rillig 2340: size_t i;
2341: const IFile *incs = GetInclude(0);
1.193 christos 2342:
1.469 rillig 2343: for (i = includes.len; i >= 2; i--)
2344: if (!incs[i - 1].fromForLoop)
2345: return incs[i - 2].fname;
2346: return NULL;
1.193 christos 2347: }
1.281 rillig 2348:
1.285 rillig 2349: /* Set .PARSEDIR, .PARSEFILE, .INCLUDEDFROMDIR and .INCLUDEDFROMFILE. */
1.44 aidan 2350: static void
1.122 dsl 2351: ParseSetParseFile(const char *filename)
1.44 aidan 2352: {
1.469 rillig 2353: const char *including;
1.44 aidan 2354:
1.469 rillig 2355: SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE");
1.281 rillig 2356:
1.469 rillig 2357: including = GetActuallyIncludingFile();
2358: if (including != NULL) {
2359: SetFilenameVars(including,
2360: ".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE");
2361: } else {
2362: Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
2363: Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
2364: }
1.44 aidan 2365: }
2366:
1.418 rillig 2367: static Boolean
2368: StrContainsWord(const char *str, const char *word)
2369: {
1.469 rillig 2370: size_t strLen = strlen(str);
2371: size_t wordLen = strlen(word);
2372: const char *p, *end;
2373:
2374: if (strLen < wordLen)
2375: return FALSE; /* str is too short to contain word */
2376:
2377: end = str + strLen - wordLen;
2378: for (p = str; p != NULL; p = strchr(p, ' ')) {
2379: if (*p == ' ')
2380: p++;
2381: if (p > end)
2382: return FALSE; /* cannot contain word */
2383:
2384: if (memcmp(p, word, wordLen) == 0 &&
2385: (p[wordLen] == '\0' || p[wordLen] == ' '))
2386: return TRUE;
2387: }
2388: return FALSE;
2389: }
2390:
2391: /*
2392: * XXX: Searching through a set of words with this linear search is
2393: * inefficient for variables that contain thousands of words.
2394: *
2395: * XXX: The paths in this list don't seem to be normalized in any way.
2396: */
1.418 rillig 2397: static Boolean
2398: VarContainsWord(const char *varname, const char *word)
2399: {
1.505 rillig 2400: FStr val = Var_Value(varname, VAR_GLOBAL);
2401: Boolean found = val.str != NULL && StrContainsWord(val.str, word);
2402: FStr_Done(&val);
1.469 rillig 2403: return found;
1.418 rillig 2404: }
2405:
1.284 rillig 2406: /* Track the makefiles we read - so makefiles can set dependencies on them.
1.441 rillig 2407: * Avoid adding anything more than once.
2408: *
2409: * Time complexity: O(n) per call, in total O(n^2), where n is the number
2410: * of makefiles that have been loaded. */
1.184 sjg 2411: static void
2412: ParseTrackInput(const char *name)
2413: {
1.469 rillig 2414: if (!VarContainsWord(MAKE_MAKEFILES, name))
2415: Var_Append(MAKE_MAKEFILES, name, VAR_GLOBAL);
1.184 sjg 2416: }
1.137 sjg 2417:
1.44 aidan 2418:
1.469 rillig 2419: /*
2420: * Start parsing from the given source.
1.5 cgd 2421: *
1.469 rillig 2422: * The given file is added to the includes stack.
2423: */
1.5 cgd 2424: void
1.496 rillig 2425: Parse_SetInput(const char *name, int lineno, int fd,
1.471 rillig 2426: ReadMoreProc readMore, void *readMoreArg)
1.5 cgd 2427: {
1.469 rillig 2428: IFile *curFile;
2429: char *buf;
2430: size_t len;
2431: Boolean fromForLoop = name == NULL;
2432:
2433: if (fromForLoop)
2434: name = CurFile()->fname;
2435: else
2436: ParseTrackInput(name);
2437:
1.497 rillig 2438: DEBUG3(PARSE, "Parse_SetInput: %s %s, line %d\n",
2439: readMore == loadedfile_readMore ? "file" : ".for loop in",
2440: name, lineno);
1.5 cgd 2441:
1.471 rillig 2442: if (fd == -1 && readMore == NULL)
1.469 rillig 2443: /* sanity */
2444: return;
2445:
2446: curFile = Vector_Push(&includes);
2447: curFile->fname = bmake_strdup(name);
2448: curFile->fromForLoop = fromForLoop;
1.496 rillig 2449: curFile->lineno = lineno;
2450: curFile->first_lineno = lineno;
1.471 rillig 2451: curFile->readMore = readMore;
2452: curFile->readMoreArg = readMoreArg;
1.469 rillig 2453: curFile->lf = NULL;
2454: curFile->depending = doing_depend; /* restore this on EOF */
2455:
1.471 rillig 2456: assert(readMore != NULL);
1.469 rillig 2457:
2458: /* Get first block of input data */
1.471 rillig 2459: buf = curFile->readMore(curFile->readMoreArg, &len);
1.469 rillig 2460: if (buf == NULL) {
2461: /* Was all a waste of time ... */
2462: if (curFile->fname)
2463: free(curFile->fname);
2464: free(curFile);
2465: return;
2466: }
2467: curFile->buf_freeIt = buf;
2468: curFile->buf_ptr = buf;
2469: curFile->buf_end = buf + len;
2470:
2471: curFile->cond_depth = Cond_save_depth();
2472: ParseSetParseFile(name);
1.5 cgd 2473: }
2474:
1.375 rillig 2475: /* Check if the directive is an include directive. */
1.228 christos 2476: static Boolean
1.298 rillig 2477: IsInclude(const char *dir, Boolean sysv)
1.228 christos 2478: {
1.298 rillig 2479: if (dir[0] == 's' || dir[0] == '-' || (dir[0] == 'd' && !sysv))
2480: dir++;
1.228 christos 2481:
1.298 rillig 2482: if (strncmp(dir, "include", 7) != 0)
1.228 christos 2483: return FALSE;
2484:
1.248 rillig 2485: /* Space is not mandatory for BSD .include */
1.298 rillig 2486: return !sysv || ch_isspace(dir[7]);
1.228 christos 2487: }
2488:
2489:
1.5 cgd 2490: #ifdef SYSVINCLUDE
1.284 rillig 2491: /* Check if the line is a SYSV include directive. */
1.228 christos 2492: static Boolean
2493: IsSysVInclude(const char *line)
2494: {
2495: const char *p;
2496:
2497: if (!IsInclude(line, TRUE))
2498: return FALSE;
2499:
1.375 rillig 2500: /* Avoid interpreting a dependency line as an include */
1.228 christos 2501: for (p = line; (p = strchr(p, ':')) != NULL;) {
1.430 rillig 2502:
2503: /* end of line -> it's a dependency */
2504: if (*++p == '\0')
1.228 christos 2505: return FALSE;
1.430 rillig 2506:
2507: /* '::' operator or ': ' -> it's a dependency */
2508: if (*p == ':' || ch_isspace(*p))
1.228 christos 2509: return FALSE;
2510: }
2511: return TRUE;
2512: }
2513:
1.284 rillig 2514: /* Push to another file. The line points to the word "include". */
1.5 cgd 2515: static void
1.84 wiz 2516: ParseTraditionalInclude(char *line)
1.5 cgd 2517: {
1.469 rillig 2518: char *cp; /* current position in file spec */
2519: Boolean done = FALSE;
2520: Boolean silent = line[0] != 'i';
2521: char *file = line + (silent ? 8 : 7);
2522: char *all_files;
2523:
2524: DEBUG2(PARSE, "%s: %s\n", __func__, file);
2525:
2526: pp_skip_whitespace(&file);
2527:
2528: /*
2529: * Substitute for any variables in the file name before trying to
2530: * find the thing.
2531: */
2532: (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &all_files);
2533: /* TODO: handle errors */
2534:
2535: if (*file == '\0') {
2536: Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
2537: goto out;
2538: }
1.38 christos 2539:
1.469 rillig 2540: for (file = all_files; !done; file = cp + 1) {
2541: /* Skip to end of line or next whitespace */
2542: for (cp = file; *cp != '\0' && !ch_isspace(*cp); cp++)
2543: continue;
2544:
2545: if (*cp != '\0')
2546: *cp = '\0';
2547: else
2548: done = TRUE;
1.38 christos 2549:
1.469 rillig 2550: Parse_include_file(file, FALSE, FALSE, silent);
2551: }
1.224 riastrad 2552: out:
1.469 rillig 2553: free(all_files);
1.5 cgd 2554: }
2555: #endif
2556:
1.183 sjg 2557: #ifdef GMAKEEXPORT
1.375 rillig 2558: /* Parse "export <variable>=<value>", and actually export it. */
1.182 christos 2559: static void
2560: ParseGmakeExport(char *line)
2561: {
1.469 rillig 2562: char *variable = line + 6;
2563: char *value;
1.182 christos 2564:
1.469 rillig 2565: DEBUG2(PARSE, "%s: %s\n", __func__, variable);
1.182 christos 2566:
1.469 rillig 2567: pp_skip_whitespace(&variable);
1.182 christos 2568:
1.469 rillig 2569: for (value = variable; *value && *value != '='; value++)
2570: continue;
1.182 christos 2571:
1.469 rillig 2572: if (*value != '=') {
2573: Parse_Error(PARSE_FATAL,
1.284 rillig 2574: "Variable/Value missing from \"export\"");
1.469 rillig 2575: return;
2576: }
2577: *value++ = '\0'; /* terminate variable */
1.323 rillig 2578:
1.469 rillig 2579: /*
2580: * Expand the value before putting it in the environment.
2581: */
2582: (void)Var_Subst(value, VAR_CMDLINE, VARE_WANTRES, &value);
2583: /* TODO: handle errors */
2584:
2585: setenv(variable, value, 1);
2586: free(value);
1.182 christos 2587: }
2588: #endif
2589:
1.469 rillig 2590: /*
2591: * Called when EOF is reached in the current file. If we were reading an
1.441 rillig 2592: * include file or a .for loop, the includes stack is popped and things set
2593: * up to go back to reading the previous file at the previous location.
1.1 cgd 2594: *
2595: * Results:
1.376 rillig 2596: * TRUE to continue parsing, i.e. it had only reached the end of an
2597: * included file, FALSE if the main file has been parsed completely.
1.1 cgd 2598: */
1.376 rillig 2599: static Boolean
1.123 dsl 2600: ParseEOF(void)
1.1 cgd 2601: {
1.469 rillig 2602: char *ptr;
2603: size_t len;
2604: IFile *curFile = CurFile();
2605:
1.471 rillig 2606: assert(curFile->readMore != NULL);
1.469 rillig 2607:
2608: doing_depend = curFile->depending; /* restore this */
2609: /* get next input buffer, if any */
1.471 rillig 2610: ptr = curFile->readMore(curFile->readMoreArg, &len);
1.469 rillig 2611: curFile->buf_ptr = ptr;
2612: curFile->buf_freeIt = ptr;
1.470 rillig 2613: curFile->buf_end = ptr == NULL ? NULL : ptr + len;
1.469 rillig 2614: curFile->lineno = curFile->first_lineno;
2615: if (ptr != NULL)
2616: return TRUE; /* Iterate again */
2617:
2618: /* Ensure the makefile (or loop) didn't have mismatched conditionals */
2619: Cond_restore_depth(curFile->cond_depth);
2620:
2621: if (curFile->lf != NULL) {
2622: loadedfile_destroy(curFile->lf);
2623: curFile->lf = NULL;
2624: }
2625:
2626: /* Dispose of curFile info */
2627: /* Leak curFile->fname because all the gnodes have pointers to it. */
2628: free(curFile->buf_freeIt);
2629: Vector_Pop(&includes);
1.155 dsl 2630:
1.469 rillig 2631: if (includes.len == 0) {
2632: /* We've run out of input */
2633: Var_Delete(".PARSEDIR", VAR_GLOBAL);
2634: Var_Delete(".PARSEFILE", VAR_GLOBAL);
2635: Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
2636: Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
2637: return FALSE;
2638: }
1.170 dholland 2639:
1.469 rillig 2640: curFile = CurFile();
2641: DEBUG2(PARSE, "ParseEOF: returning to file %s, line %d\n",
2642: curFile->fname, curFile->lineno);
1.1 cgd 2643:
1.469 rillig 2644: ParseSetParseFile(curFile->fname);
2645: return TRUE;
1.1 cgd 2646: }
2647:
1.493 rillig 2648: typedef enum ParseRawLineResult {
2649: PRLR_LINE,
2650: PRLR_EOF,
2651: PRLR_ERROR
2652: } ParseRawLineResult;
2653:
1.489 rillig 2654: /*
1.492 rillig 2655: * Parse until the end of a line, taking into account lines that end with
2656: * backslash-newline.
1.489 rillig 2657: */
1.493 rillig 2658: static ParseRawLineResult
2659: ParseRawLine(IFile *curFile, char **out_line, char **out_line_end,
2660: char **out_firstBackslash, char **out_firstComment)
1.489 rillig 2661: {
1.493 rillig 2662: char *line = curFile->buf_ptr;
1.492 rillig 2663: char *p = line;
1.489 rillig 2664: char *line_end = line;
1.492 rillig 2665: char *firstBackslash = NULL;
2666: char *firstComment = NULL;
1.493 rillig 2667: ParseRawLineResult res = PRLR_LINE;
1.489 rillig 2668:
1.493 rillig 2669: curFile->lineno++;
1.490 rillig 2670:
1.489 rillig 2671: for (;;) {
1.492 rillig 2672: char ch;
2673:
1.493 rillig 2674: if (p == curFile->buf_end) {
2675: res = PRLR_EOF;
1.489 rillig 2676: break;
2677: }
2678:
1.492 rillig 2679: ch = *p;
1.489 rillig 2680: if (ch == '\0' ||
1.493 rillig 2681: (ch == '\\' && p + 1 < curFile->buf_end && p[1] == '\0')) {
1.492 rillig 2682: Parse_Error(PARSE_FATAL, "Zero byte read from file");
1.493 rillig 2683: return PRLR_ERROR;
1.489 rillig 2684: }
2685:
1.492 rillig 2686: /* Treat next character after '\' as literal. */
1.489 rillig 2687: if (ch == '\\') {
1.492 rillig 2688: if (firstBackslash == NULL)
2689: firstBackslash = p;
2690: if (p[1] == '\n')
1.493 rillig 2691: curFile->lineno++;
1.492 rillig 2692: p += 2;
2693: line_end = p;
1.489 rillig 2694: continue;
2695: }
2696:
2697: /*
1.492 rillig 2698: * Remember the first '#' for comment stripping, unless
2699: * the previous char was '[', as in the modifier ':[#]'.
2700: */
2701: if (ch == '#' && firstComment == NULL &&
2702: !(p > line && p[-1] == '['))
2703: firstComment = line_end;
1.489 rillig 2704:
1.492 rillig 2705: p++;
1.489 rillig 2706: if (ch == '\n')
2707: break;
2708:
2709: /* We are not interested in trailing whitespace. */
2710: if (!ch_isspace(ch))
1.492 rillig 2711: line_end = p;
1.489 rillig 2712: }
2713:
1.490 rillig 2714: *out_line = line;
1.493 rillig 2715: curFile->buf_ptr = p;
1.489 rillig 2716: *out_line_end = line_end;
1.492 rillig 2717: *out_firstBackslash = firstBackslash;
2718: *out_firstComment = firstComment;
1.493 rillig 2719: return res;
1.489 rillig 2720: }
2721:
1.491 rillig 2722: /*
2723: * Beginning at start, unescape '\#' to '#' and replace backslash-newline
2724: * with a single space.
2725: */
1.485 rillig 2726: static void
1.491 rillig 2727: UnescapeBackslash(char *const line, char *start)
1.487 rillig 2728: {
1.491 rillig 2729: char *src = start;
2730: char *dst = start;
2731: char *spaceStart = line;
1.485 rillig 2732:
2733: for (;;) {
1.491 rillig 2734: char ch = *src++;
1.485 rillig 2735: if (ch != '\\') {
2736: if (ch == '\0')
2737: break;
1.491 rillig 2738: *dst++ = ch;
1.485 rillig 2739: continue;
2740: }
2741:
1.491 rillig 2742: ch = *src++;
1.485 rillig 2743: if (ch == '\0') {
2744: /* Delete '\\' at end of buffer */
1.491 rillig 2745: dst--;
1.485 rillig 2746: break;
2747: }
2748:
2749: /* Delete '\\' from before '#' on non-command lines */
2750: if (ch == '#' && line[0] != '\t') {
1.491 rillig 2751: *dst++ = ch;
1.485 rillig 2752: continue;
2753: }
2754:
2755: if (ch != '\n') {
2756: /* Leave '\\' in buffer for later */
1.491 rillig 2757: *dst++ = '\\';
1.485 rillig 2758: /*
2759: * Make sure we don't delete an escaped ' ' from the
2760: * line end.
2761: */
1.491 rillig 2762: spaceStart = dst + 1;
2763: *dst++ = ch;
1.485 rillig 2764: continue;
2765: }
2766:
2767: /*
2768: * Escaped '\n' -- replace following whitespace with a single
2769: * ' '.
2770: */
1.491 rillig 2771: pp_skip_hspace(&src);
2772: *dst++ = ' ';
1.485 rillig 2773: }
2774:
1.487 rillig 2775: /* Delete any trailing spaces - eg from empty continuations */
1.491 rillig 2776: while (dst > spaceStart && ch_isspace(dst[-1]))
2777: dst--;
2778: *dst = '\0';
1.485 rillig 2779: }
2780:
1.441 rillig 2781: typedef enum GetLineMode {
1.495 rillig 2782: /*
1.498 rillig 2783: * Return the next line that is neither empty nor a comment.
1.495 rillig 2784: * Backslash line continuations are folded into a single space.
2785: * A trailing comment, if any, is discarded.
2786: */
1.499 rillig 2787: GLM_NONEMPTY,
1.495 rillig 2788:
2789: /*
1.498 rillig 2790: * Return the next line, even if it is empty or a comment.
1.499 rillig 2791: * Preserve backslash-newline to keep the line numbers correct.
1.495 rillig 2792: *
2793: * Used in .for loops to collect the body of the loop while waiting
2794: * for the corresponding .endfor.
2795: */
1.499 rillig 2796: GLM_FOR_BODY,
1.495 rillig 2797:
2798: /*
1.499 rillig 2799: * Return the next line that starts with a dot.
1.495 rillig 2800: * Backslash line continuations are folded into a single space.
2801: * A trailing comment, if any, is discarded.
2802: *
2803: * Used in .if directives to skip over irrelevant branches while
2804: * waiting for the corresponding .endif.
2805: */
1.499 rillig 2806: GLM_DOT
1.441 rillig 2807: } GetLineMode;
1.127 dsl 2808:
1.498 rillig 2809: /* Return the next "interesting" logical line from the current file. */
1.127 dsl 2810: static char *
1.441 rillig 2811: ParseGetLine(GetLineMode mode)
1.5 cgd 2812: {
1.493 rillig 2813: IFile *curFile = CurFile();
1.469 rillig 2814: char *line;
2815: char *line_end;
1.492 rillig 2816: char *firstBackslash;
2817: char *firstComment;
1.469 rillig 2818:
2819: /* Loop through blank lines and comment lines */
1.127 dsl 2820: for (;;) {
1.493 rillig 2821: ParseRawLineResult res = ParseRawLine(curFile,
2822: &line, &line_end, &firstBackslash, &firstComment);
2823: if (res == PRLR_ERROR)
1.489 rillig 2824: return NULL;
1.27 christos 2825:
1.492 rillig 2826: if (line_end == line || firstComment == line) {
1.493 rillig 2827: if (res == PRLR_EOF)
1.469 rillig 2828: return NULL;
1.499 rillig 2829: if (mode != GLM_FOR_BODY)
1.494 rillig 2830: continue;
1.469 rillig 2831: }
1.5 cgd 2832:
1.469 rillig 2833: /* We now have a line of data */
2834: *line_end = '\0';
1.5 cgd 2835:
1.499 rillig 2836: if (mode == GLM_FOR_BODY)
2837: return line; /* Don't join the physical lines. */
1.5 cgd 2838:
1.499 rillig 2839: if (mode == GLM_DOT && line[0] != '.')
2840: continue;
1.127 dsl 2841: break;
2842: }
1.5 cgd 2843:
1.469 rillig 2844: /* Brutally ignore anything after a non-escaped '#' in non-commands. */
1.492 rillig 2845: if (firstComment != NULL && line[0] != '\t') {
2846: line_end = firstComment;
1.469 rillig 2847: *line_end = '\0';
2848: }
2849:
2850: /* If we didn't see a '\\' then the in-situ data is fine. */
1.492 rillig 2851: if (firstBackslash == NULL)
1.469 rillig 2852: return line;
2853:
2854: /* Remove escapes from '\n' and '#' */
1.492 rillig 2855: UnescapeBackslash(line, firstBackslash);
1.27 christos 2856:
1.469 rillig 2857: return line;
1.5 cgd 2858: }
1.1 cgd 2859:
1.500 rillig 2860: static Boolean
1.501 rillig 2861: ParseSkippedBranches(void)
2862: {
2863: char *line;
2864:
2865: while ((line = ParseGetLine(GLM_DOT)) != NULL) {
2866: if (Cond_EvalLine(line) == COND_PARSE)
2867: break;
2868: /*
2869: * TODO: Check for typos in .elif directives
2870: * such as .elsif or .elseif.
2871: *
2872: * This check will probably duplicate some of
2873: * the code in ParseLine. Most of the code
2874: * there cannot apply, only ParseVarassign and
2875: * ParseDependency can, and to prevent code
2876: * duplication, these would need to be called
2877: * with a flag called onlyCheckSyntax.
2878: *
2879: * See directive-elif.mk for details.
2880: */
2881: }
2882:
2883: return line != NULL;
2884: }
2885:
2886: static Boolean
1.500 rillig 2887: ParseForLoop(const char *line)
2888: {
2889: int rval;
2890: int firstLineno;
2891:
2892: rval = For_Eval(line);
2893: if (rval == 0)
2894: return FALSE; /* Not a .for line */
2895: if (rval < 0)
2896: return TRUE; /* Syntax error - error printed, ignore line */
2897:
2898: firstLineno = CurFile()->lineno;
2899:
2900: /* Accumulate loop lines until matching .endfor */
2901: do {
2902: line = ParseGetLine(GLM_FOR_BODY);
2903: if (line == NULL) {
2904: Parse_Error(PARSE_FATAL,
2905: "Unexpected end of file in for loop.");
2906: break;
2907: }
2908: } while (For_Accum(line));
2909:
2910: For_Run(firstLineno); /* Stash each iteration as a new 'input file' */
2911:
2912: return TRUE; /* Read next line from for-loop buffer */
2913: }
2914:
1.469 rillig 2915: /*
1.482 rillig 2916: * Read an entire line from the input file.
2917: *
2918: * Empty lines, .if and .for are completely handled by this function,
2919: * leaving only variable assignments, other directives, dependency lines
2920: * and shell commands to the caller.
1.1 cgd 2921: *
2922: * Results:
1.482 rillig 2923: * A line without its newline and without any trailing whitespace,
2924: * or NULL.
1.1 cgd 2925: */
2926: static char *
1.84 wiz 2927: ParseReadLine(void)
1.1 cgd 2928: {
1.500 rillig 2929: char *line;
1.469 rillig 2930:
2931: for (;;) {
1.499 rillig 2932: line = ParseGetLine(GLM_NONEMPTY);
1.469 rillig 2933: if (line == NULL)
2934: return NULL;
2935:
2936: if (line[0] != '.')
2937: return line;
2938:
2939: /*
2940: * The line might be a conditional. Ask the conditional module
2941: * about it and act accordingly
2942: */
2943: switch (Cond_EvalLine(line)) {
2944: case COND_SKIP:
1.501 rillig 2945: if (!ParseSkippedBranches())
1.482 rillig 2946: return NULL;
1.469 rillig 2947: continue;
2948: case COND_PARSE:
2949: continue;
2950: case COND_INVALID: /* Not a conditional line */
1.500 rillig 2951: if (ParseForLoop(line))
1.469 rillig 2952: continue;
1.500 rillig 2953: break;
1.469 rillig 2954: }
2955: return line;
1.1 cgd 2956: }
2957: }
2958:
1.331 rillig 2959: static void
1.329 rillig 2960: FinishDependencyGroup(void)
1.1 cgd 2961: {
1.469 rillig 2962: GNodeListNode *ln;
1.430 rillig 2963:
1.469 rillig 2964: if (targets == NULL)
2965: return;
1.371 rillig 2966:
1.469 rillig 2967: for (ln = targets->first; ln != NULL; ln = ln->next) {
2968: GNode *gn = ln->datum;
1.371 rillig 2969:
1.469 rillig 2970: Suff_EndTransform(gn);
1.371 rillig 2971:
1.469 rillig 2972: /*
2973: * Mark the target as already having commands if it does, to
2974: * keep from having shell commands on multiple dependency
2975: * lines.
2976: */
2977: if (!Lst_IsEmpty(&gn->commands))
2978: gn->type |= OP_HAS_COMMANDS;
2979: }
1.430 rillig 2980:
1.469 rillig 2981: Lst_Free(targets);
2982: targets = NULL;
1.1 cgd 2983: }
1.27 christos 2984:
1.327 rillig 2985: /* Add the command to each target from the current dependency spec. */
1.326 rillig 2986: static void
1.375 rillig 2987: ParseLine_ShellCommand(const char *p)
1.326 rillig 2988: {
1.469 rillig 2989: cpp_skip_whitespace(&p);
2990: if (*p == '\0')
2991: return; /* skip empty commands */
1.327 rillig 2992:
1.469 rillig 2993: if (targets == NULL) {
2994: Parse_Error(PARSE_FATAL,
2995: "Unassociated shell command \"%s\"", p);
2996: return;
2997: }
1.327 rillig 2998:
1.469 rillig 2999: {
3000: char *cmd = bmake_strdup(p);
3001: GNodeListNode *ln;
3002:
3003: for (ln = targets->first; ln != NULL; ln = ln->next) {
3004: GNode *gn = ln->datum;
3005: ParseAddCmd(gn, cmd);
3006: }
1.326 rillig 3007: #ifdef CLEANUP
1.469 rillig 3008: Lst_Append(&targCmds, cmd);
1.326 rillig 3009: #endif
1.469 rillig 3010: }
1.326 rillig 3011: }
1.1 cgd 3012:
1.475 rillig 3013: MAKE_INLINE Boolean
3014: IsDirective(const char *dir, size_t dirlen, const char *name)
3015: {
3016: return dirlen == strlen(name) && memcmp(dir, name, dirlen) == 0;
3017: }
3018:
1.474 rillig 3019: /*
1.477 rillig 3020: * See if the line starts with one of the known directives, and if so, handle
3021: * the directive.
1.474 rillig 3022: */
1.379 rillig 3023: static Boolean
3024: ParseDirective(char *line)
3025: {
1.474 rillig 3026: char *cp = line + 1;
1.475 rillig 3027: const char *dir, *arg;
3028: size_t dirlen;
1.474 rillig 3029:
3030: pp_skip_whitespace(&cp);
3031: if (IsInclude(cp, FALSE)) {
3032: ParseDoInclude(cp);
3033: return TRUE;
3034: }
1.379 rillig 3035:
1.475 rillig 3036: dir = cp;
3037: while (ch_isalpha(*cp) || *cp == '-')
3038: cp++;
3039: dirlen = (size_t)(cp - dir);
3040:
3041: if (*cp != '\0' && !ch_isspace(*cp))
3042: return FALSE;
3043:
3044: pp_skip_whitespace(&cp);
3045: arg = cp;
3046:
3047: if (IsDirective(dir, dirlen, "undef")) {
1.502 rillig 3048: Var_Undef(cp);
1.474 rillig 3049: return TRUE;
1.476 rillig 3050: } else if (IsDirective(dir, dirlen, "export")) {
3051: Var_Export(VEM_PARENT, arg);
3052: return TRUE;
3053: } else if (IsDirective(dir, dirlen, "export-env")) {
3054: Var_Export(VEM_NORMAL, arg);
3055: return TRUE;
3056: } else if (IsDirective(dir, dirlen, "export-literal")) {
3057: Var_Export(VEM_LITERAL, arg);
1.474 rillig 3058: return TRUE;
1.479 rillig 3059: } else if (IsDirective(dir, dirlen, "unexport")) {
3060: Var_UnExport(FALSE, arg);
3061: return TRUE;
3062: } else if (IsDirective(dir, dirlen, "unexport-env")) {
3063: Var_UnExport(TRUE, arg);
1.474 rillig 3064: return TRUE;
1.475 rillig 3065: } else if (IsDirective(dir, dirlen, "info")) {
1.503 rillig 3066: ParseMessage(PARSE_INFO, "info", arg);
3067: return TRUE;
1.475 rillig 3068: } else if (IsDirective(dir, dirlen, "warning")) {
1.503 rillig 3069: ParseMessage(PARSE_WARNING, "warning", arg);
3070: return TRUE;
1.475 rillig 3071: } else if (IsDirective(dir, dirlen, "error")) {
1.503 rillig 3072: ParseMessage(PARSE_FATAL, "error", arg);
3073: return TRUE;
1.379 rillig 3074: }
1.469 rillig 3075: return FALSE;
1.379 rillig 3076: }
3077:
3078: static Boolean
3079: ParseVarassign(const char *line)
3080: {
1.469 rillig 3081: VarAssign var;
1.430 rillig 3082:
1.469 rillig 3083: if (!Parse_IsVar(line, &var))
3084: return FALSE;
1.430 rillig 3085:
1.469 rillig 3086: FinishDependencyGroup();
3087: Parse_DoVar(&var, VAR_GLOBAL);
3088: return TRUE;
1.379 rillig 3089: }
3090:
1.380 rillig 3091: static char *
3092: FindSemicolon(char *p)
3093: {
1.469 rillig 3094: int level = 0;
3095:
3096: for (; *p != '\0'; p++) {
3097: if (*p == '\\' && p[1] != '\0') {
3098: p++;
3099: continue;
3100: }
1.380 rillig 3101:
1.469 rillig 3102: if (*p == '$' && (p[1] == '(' || p[1] == '{'))
3103: level++;
3104: else if (level > 0 && (*p == ')' || *p == '}'))
3105: level--;
3106: else if (level == 0 && *p == ';')
3107: break;
3108: }
3109: return p;
1.380 rillig 3110: }
3111:
1.379 rillig 3112: /* dependency -> target... op [source...]
3113: * op -> ':' | '::' | '!' */
3114: static void
1.380 rillig 3115: ParseDependency(char *line)
1.379 rillig 3116: {
1.469 rillig 3117: VarEvalFlags eflags;
3118: char *expanded_line;
3119: const char *shellcmd = NULL;
3120:
3121: /*
3122: * For some reason - probably to make the parser impossible -
3123: * a ';' can be used to separate commands from dependencies.
3124: * Attempt to avoid ';' inside substitution patterns.
3125: */
3126: {
3127: char *semicolon = FindSemicolon(line);
3128: if (*semicolon != '\0') {
3129: /* Terminate the dependency list at the ';' */
3130: *semicolon = '\0';
3131: shellcmd = semicolon + 1;
3132: }
3133: }
1.379 rillig 3134:
1.469 rillig 3135: /*
3136: * We now know it's a dependency line so it needs to have all
3137: * variables expanded before being parsed.
3138: *
3139: * XXX: Ideally the dependency line would first be split into
3140: * its left-hand side, dependency operator and right-hand side,
3141: * and then each side would be expanded on its own. This would
3142: * allow for the left-hand side to allow only defined variables
3143: * and to allow variables on the right-hand side to be undefined
3144: * as well.
3145: *
3146: * Parsing the line first would also prevent that targets
3147: * generated from variable expressions are interpreted as the
3148: * dependency operator, such as in "target${:U\:} middle: source",
3149: * in which the middle is interpreted as a source, not a target.
3150: */
3151:
3152: /* In lint mode, allow undefined variables to appear in
3153: * dependency lines.
3154: *
3155: * Ideally, only the right-hand side would allow undefined
3156: * variables since it is common to have optional dependencies.
3157: * Having undefined variables on the left-hand side is more
3158: * unusual though. Since both sides are expanded in a single
3159: * pass, there is not much choice what to do here.
3160: *
3161: * In normal mode, it does not matter whether undefined
3162: * variables are allowed or not since as of 2020-09-14,
3163: * Var_Parse does not print any parse errors in such a case.
3164: * It simply returns the special empty string var_Error,
3165: * which cannot be detected in the result of Var_Subst. */
3166: eflags = opts.lint ? VARE_WANTRES : VARE_WANTRES | VARE_UNDEFERR;
3167: (void)Var_Subst(line, VAR_CMDLINE, eflags, &expanded_line);
3168: /* TODO: handle errors */
3169:
3170: /* Need a fresh list for the target nodes */
3171: if (targets != NULL)
3172: Lst_Free(targets);
3173: targets = Lst_New();
1.379 rillig 3174:
1.469 rillig 3175: ParseDoDependency(expanded_line);
3176: free(expanded_line);
1.380 rillig 3177:
1.469 rillig 3178: if (shellcmd != NULL)
3179: ParseLine_ShellCommand(shellcmd);
1.379 rillig 3180: }
3181:
1.381 rillig 3182: static void
3183: ParseLine(char *line)
3184: {
1.477 rillig 3185: /*
3186: * Lines that begin with '.' can be pretty much anything:
3187: * - directives like '.include' or '.if',
3188: * - suffix rules like '.c.o:',
3189: * - dependencies for filenames that start with '.',
3190: * - variable assignments like '.tmp=value'.
3191: */
1.474 rillig 3192: if (line[0] == '.' && ParseDirective(line))
1.469 rillig 3193: return;
1.381 rillig 3194:
1.478 rillig 3195: if (line[0] == '\t') {
1.469 rillig 3196: ParseLine_ShellCommand(line + 1);
3197: return;
3198: }
1.381 rillig 3199:
3200: #ifdef SYSVINCLUDE
1.469 rillig 3201: if (IsSysVInclude(line)) {
3202: /*
3203: * It's an S3/S5-style "include".
3204: */
3205: ParseTraditionalInclude(line);
3206: return;
3207: }
1.381 rillig 3208: #endif
3209:
3210: #ifdef GMAKEEXPORT
1.469 rillig 3211: if (strncmp(line, "export", 6) == 0 && ch_isspace(line[6]) &&
3212: strchr(line, ':') == NULL) {
3213: /*
3214: * It's a Gmake "export".
3215: */
3216: ParseGmakeExport(line);
3217: return;
3218: }
1.381 rillig 3219: #endif
3220:
1.469 rillig 3221: if (ParseVarassign(line))
3222: return;
1.381 rillig 3223:
1.469 rillig 3224: FinishDependencyGroup();
1.381 rillig 3225:
1.469 rillig 3226: ParseDependency(line);
1.381 rillig 3227: }
3228:
1.469 rillig 3229: /*
3230: * Parse a top-level makefile, incorporating its content into the global
1.441 rillig 3231: * dependency graph.
1.1 cgd 3232: *
1.84 wiz 3233: * Input:
1.297 rillig 3234: * name The name of the file being read
3235: * fd The open file to parse; will be closed at the end
1.1 cgd 3236: */
3237: void
1.125 dsl 3238: Parse_File(const char *name, int fd)
1.1 cgd 3239: {
1.469 rillig 3240: char *line; /* the line we're working on */
3241: struct loadedfile *lf;
1.170 dholland 3242:
1.469 rillig 3243: lf = loadfile(name, fd);
1.1 cgd 3244:
1.469 rillig 3245: assert(targets == NULL);
1.44 aidan 3246:
1.469 rillig 3247: if (name == NULL)
3248: name = "(stdin)";
1.170 dholland 3249:
1.471 rillig 3250: Parse_SetInput(name, 0, -1, loadedfile_readMore, lf);
1.469 rillig 3251: CurFile()->lf = lf;
1.1 cgd 3252:
1.469 rillig 3253: do {
3254: while ((line = ParseReadLine()) != NULL) {
3255: DEBUG2(PARSE, "ParseReadLine (%d): '%s'\n",
3256: CurFile()->lineno, line);
3257: ParseLine(line);
3258: }
3259: /* Reached EOF, but it may be just EOF of an include file. */
3260: } while (ParseEOF());
1.1 cgd 3261:
1.469 rillig 3262: FinishDependencyGroup();
1.328 rillig 3263:
1.469 rillig 3264: if (fatals != 0) {
3265: (void)fflush(stdout);
3266: (void)fprintf(stderr,
3267: "%s: Fatal errors encountered -- cannot continue",
3268: progname);
3269: PrintOnError(NULL, NULL);
3270: exit(1);
3271: }
1.1 cgd 3272: }
3273:
1.383 rillig 3274: /* Initialize the parsing module. */
1.5 cgd 3275: void
1.84 wiz 3276: Parse_Init(void)
1.1 cgd 3277: {
1.469 rillig 3278: mainNode = NULL;
3279: parseIncPath = SearchPath_New();
3280: sysIncPath = SearchPath_New();
3281: defSysIncPath = SearchPath_New();
3282: Vector_Init(&includes, sizeof(IFile));
1.1 cgd 3283: }
1.9 jtc 3284:
1.383 rillig 3285: /* Clean up the parsing module. */
1.9 jtc 3286: void
1.84 wiz 3287: Parse_End(void)
1.9 jtc 3288: {
1.45 mycroft 3289: #ifdef CLEANUP
1.469 rillig 3290: Lst_DoneCall(&targCmds, free);
3291: assert(targets == NULL);
3292: SearchPath_Free(defSysIncPath);
3293: SearchPath_Free(sysIncPath);
3294: SearchPath_Free(parseIncPath);
3295: assert(includes.len == 0);
3296: Vector_Done(&includes);
1.45 mycroft 3297: #endif
1.9 jtc 3298: }
1.27 christos 3299:
1.1 cgd 3300:
1.441 rillig 3301: /*
3302: * Return a list containing the single main target to create.
3303: * If no such target exists, we Punt with an obnoxious error message.
1.1 cgd 3304: */
1.461 rillig 3305: void
3306: Parse_MainName(GNodeList *mainList)
1.1 cgd 3307: {
1.469 rillig 3308: if (mainNode == NULL)
3309: Punt("no target to make.");
1.430 rillig 3310:
1.469 rillig 3311: if (mainNode->type & OP_DOUBLEDEP) {
3312: Lst_Append(mainList, mainNode);
3313: Lst_AppendAll(mainList, &mainNode->cohorts);
3314: } else
3315: Lst_Append(mainList, mainNode);
1.441 rillig 3316:
1.469 rillig 3317: Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL);
1.59 christos 3318: }
1.420 rillig 3319:
3320: int
3321: Parse_GetFatals(void)
3322: {
1.469 rillig 3323: return fatals;
1.420 rillig 3324: }
CVSweb <webmaster@jp.NetBSD.org>