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