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