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