Annotation of src/usr.bin/make/parse.c, Revision 1.65
1.59 espie 1: /* $OpenPackages$ */
1.64 espie 2: /* $OpenBSD: parse.c,v 1.63 2001/06/12 22:44:21 espie Exp $ */
1.13 millert 3: /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
1.1 deraadt 4:
5: /*
1.59 espie 6: * Copyright (c) 1999 Marc Espie.
7: *
8: * Extensive code changes for the OpenBSD project.
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: *
19: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
23: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31: /*
1.11 millert 32: * Copyright (c) 1988, 1989, 1990, 1993
33: * The Regents of the University of California. All rights reserved.
1.1 deraadt 34: * Copyright (c) 1989 by Berkeley Softworks
35: * All rights reserved.
36: *
37: * This code is derived from software contributed to Berkeley by
38: * Adam de Boor.
39: *
40: * Redistribution and use in source and binary forms, with or without
41: * modification, are permitted provided that the following conditions
42: * are met:
43: * 1. Redistributions of source code must retain the above copyright
44: * notice, this list of conditions and the following disclaimer.
45: * 2. Redistributions in binary form must reproduce the above copyright
46: * notice, this list of conditions and the following disclaimer in the
47: * documentation and/or other materials provided with the distribution.
48: * 3. All advertising materials mentioning features or use of this software
49: * must display the following acknowledgement:
50: * This product includes software developed by the University of
51: * California, Berkeley and its contributors.
52: * 4. Neither the name of the University nor the names of its contributors
53: * may be used to endorse or promote products derived from this software
54: * without specific prior written permission.
55: *
56: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66: * SUCH DAMAGE.
67: */
68:
1.59 espie 69: #include <assert.h>
1.61 espie 70: #include <ctype.h>
1.1 deraadt 71: #include <stdio.h>
1.62 espie 72: #include <stdlib.h>
1.61 espie 73: #include <string.h>
74: #include "config.h"
75: #include "defines.h"
1.1 deraadt 76: #include "dir.h"
77: #include "job.h"
78: #include "buf.h"
1.61 espie 79: #include "for.h"
1.50 espie 80: #include "lowparse.h"
1.61 espie 81: #include "arch.h"
82: #include "cond.h"
83: #include "suff.h"
84: #include "parse.h"
85: #include "var.h"
86: #include "targ.h"
87: #include "error.h"
88: #include "str.h"
89: #include "main.h"
90: #include "gnode.h"
91: #include "memory.h"
92: #include "extern.h"
93: #include "lst.h"
94: #include "parsevar.h"
1.63 espie 95: #include "stats.h"
96: #include "garray.h"
97:
98:
99: static struct growableArray gsources, gtargets;
100: #define SOURCES_SIZE 128
101: #define TARGETS_SIZE 32
1.61 espie 102:
103: static LIST theParseIncPath;/* list of directories for "..." includes */
104: static LIST theSysIncPath; /* list of directories for <...> includes */
105: Lst sysIncPath = &theSysIncPath;
106: Lst parseIncPath = &theParseIncPath;
1.59 espie 107:
1.20 espie 108: #ifdef CLEANUP
1.59 espie 109: static LIST targCmds; /* command lines for targets */
1.20 espie 110: #endif
1.59 espie 111:
1.1 deraadt 112: static GNode *mainNode; /* The main target to create. This is the
113: * first target on the first dependency
114: * line in the first makefile */
115: /*-
116: * specType contains the SPECial TYPE of the current target. It is
117: * Not if the target is unspecial. If it *is* special, however, the children
118: * are linked as children of the parent but not vice versa. This variable is
119: * set in ParseDoDependency
120: */
121: typedef enum {
1.59 espie 122: Begin, /* .BEGIN */
1.1 deraadt 123: Default, /* .DEFAULT */
1.59 espie 124: End, /* .END */
1.1 deraadt 125: Ignore, /* .IGNORE */
126: Includes, /* .INCLUDES */
127: Interrupt, /* .INTERRUPT */
128: Libs, /* .LIBS */
129: MFlags, /* .MFLAGS or .MAKEFLAGS */
130: Main, /* .MAIN and we don't have anything user-specified to
131: * make */
132: NoExport, /* .NOEXPORT */
1.17 espie 133: NoPath, /* .NOPATH */
1.1 deraadt 134: Not, /* Not special */
135: NotParallel, /* .NOTPARALELL */
1.59 espie 136: Null, /* .NULL */
137: Order, /* .ORDER */
1.3 deraadt 138: Parallel, /* .PARALLEL */
1.1 deraadt 139: ExPath, /* .PATH */
1.7 niklas 140: Phony, /* .PHONY */
1.1 deraadt 141: Precious, /* .PRECIOUS */
142: ExShell, /* .SHELL */
143: Silent, /* .SILENT */
144: SingleShell, /* .SINGLESHELL */
145: Suffixes, /* .SUFFIXES */
1.3 deraadt 146: Wait, /* .WAIT */
1.1 deraadt 147: Attribute /* Generic attribute */
148: } ParseSpecial;
149:
150: static ParseSpecial specType;
1.3 deraadt 151: static int waiting;
1.1 deraadt 152:
153: /*
1.33 espie 154: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 deraadt 155: * seen, then set to each successive source on the line.
156: */
157: static GNode *predecessor;
158:
159: /*
160: * The parseKeywords table is searched using binary search when deciding
161: * if a target or source is special. The 'spec' field is the ParseSpecial
162: * type of the keyword ("Not" if the keyword isn't special as a target) while
163: * the 'op' field is the operator to apply to the list of targets if the
164: * keyword is used as a source ("0" if the keyword isn't special as a source)
165: */
166: static struct {
1.59 espie 167: char *name; /* Name of keyword */
168: ParseSpecial spec; /* Type when used as a target */
169: int op; /* Operator when used as a source */
1.1 deraadt 170: } parseKeywords[] = {
1.59 espie 171: { ".BEGIN", Begin, 0 },
172: { ".DEFAULT", Default, 0 },
173: { ".END", End, 0 },
174: { ".EXEC", Attribute, OP_EXEC },
175: { ".IGNORE", Ignore, OP_IGNORE },
176: { ".INCLUDES", Includes, 0 },
177: { ".INTERRUPT", Interrupt, 0 },
178: { ".INVISIBLE", Attribute, OP_INVISIBLE },
179: { ".JOIN", Attribute, OP_JOIN },
180: { ".LIBS", Libs, 0 },
1.13 millert 181: { ".MADE", Attribute, OP_MADE },
1.59 espie 182: { ".MAIN", Main, 0 },
183: { ".MAKE", Attribute, OP_MAKE },
184: { ".MAKEFLAGS", MFlags, 0 },
185: { ".MFLAGS", MFlags, 0 },
1.17 espie 186: #if 0 /* basic scaffolding for NOPATH, not working yet */
187: { ".NOPATH", NoPath, OP_NOPATH },
188: #endif
1.59 espie 189: { ".NOTMAIN", Attribute, OP_NOTMAIN },
1.1 deraadt 190: { ".NOTPARALLEL", NotParallel, 0 },
1.3 deraadt 191: { ".NO_PARALLEL", NotParallel, 0 },
1.59 espie 192: { ".NULL", Null, 0 },
193: { ".OPTIONAL", Attribute, OP_OPTIONAL },
194: { ".ORDER", Order, 0 },
1.3 deraadt 195: { ".PARALLEL", Parallel, 0 },
1.1 deraadt 196: { ".PATH", ExPath, 0 },
1.7 niklas 197: { ".PHONY", Phony, OP_PHONY },
1.59 espie 198: { ".PRECIOUS", Precious, OP_PRECIOUS },
199: { ".RECURSIVE", Attribute, OP_MAKE },
200: { ".SHELL", ExShell, 0 },
201: { ".SILENT", Silent, OP_SILENT },
1.1 deraadt 202: { ".SINGLESHELL", SingleShell, 0 },
1.59 espie 203: { ".SUFFIXES", Suffixes, 0 },
204: { ".USE", Attribute, OP_USE },
1.3 deraadt 205: { ".WAIT", Wait, 0 },
1.1 deraadt 206: };
207:
1.59 espie 208: static int ParseFindKeyword(const char *);
209: static void ParseLinkSrc(GNode *, GNode *);
1.63 espie 210: static int ParseDoOp(GNode *, int);
211: static int ParseAddDep(GNode *, GNode *);
212: static void ParseDoSrc(int, const char *);
1.59 espie 213: static int ParseFindMain(void *, void *);
214: static void ParseAddDir(void *, void *);
215: static void ParseClearPath(void *);
216: static void ParseDoDependency(char *);
217: static void ParseAddCmd(void *, void *);
218: static void ParseHasCommands(void *);
219: static void ParseDoInclude(char *);
220: static void ParseTraditionalInclude(char *);
221: static void ParseConditionalInclude(char *);
1.61 espie 222: static void ParseLookupIncludeFile(char *, char *, bool, bool);
223: #define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop")
1.59 espie 224: static void ParseFinishDependency(void);
1.61 espie 225: static bool ParseIsCond(Buffer, Buffer, char *);
1.59 espie 226: static char *strip_comments(Buffer, const char *);
227:
228: static void ParseDoCommands(const char *);
1.1 deraadt 229:
230: /*-
231: *----------------------------------------------------------------------
232: * ParseFindKeyword --
233: * Look in the table of keywords for one matching the given string.
234: *
235: * Results:
236: * The index of the keyword, or -1 if it isn't there.
237: *----------------------------------------------------------------------
238: */
239: static int
1.59 espie 240: ParseFindKeyword(str)
241: const char *str; /* String to find */
1.1 deraadt 242: {
1.59 espie 243: int start,
1.1 deraadt 244: end,
245: cur;
1.59 espie 246: int diff;
1.11 millert 247:
1.1 deraadt 248: start = 0;
249: end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
250:
251: do {
1.59 espie 252: cur = start + (end - start) / 2;
253: diff = strcmp(str, parseKeywords[cur].name);
1.1 deraadt 254:
255: if (diff == 0) {
1.59 espie 256: return cur;
1.1 deraadt 257: } else if (diff < 0) {
258: end = cur - 1;
259: } else {
260: start = cur + 1;
261: }
262: } while (start <= end);
1.59 espie 263: return -1;
1.1 deraadt 264: }
265: /*-
266: *---------------------------------------------------------------------
267: * ParseLinkSrc --
1.59 espie 268: * Link the parent node to its new child. Used by
1.1 deraadt 269: * ParseDoDependency. If the specType isn't 'Not', the parent
270: * isn't linked as a parent of the child.
271: *
272: * Side Effects:
273: * New elements are added to the parents list of cgn and the
274: * children list of cgn. the unmade field of pgn is updated
275: * to reflect the additional child.
276: *---------------------------------------------------------------------
277: */
1.41 espie 278: static void
1.59 espie 279: ParseLinkSrc(pgn, cgn)
280: GNode *pgn; /* The parent node */
281: GNode *cgn; /* The child node */
282: {
1.61 espie 283: if (Lst_AddNew(&pgn->children, cgn)) {
1.41 espie 284: if (specType == Not)
1.43 espie 285: Lst_AtEnd(&cgn->parents, pgn);
1.59 espie 286: pgn->unmade++;
1.1 deraadt 287: }
288: }
289:
290: /*-
291: *---------------------------------------------------------------------
292: * ParseDoOp --
293: * Apply the parsed operator to the given target node. Used in a
1.41 espie 294: * Lst_Find call by ParseDoDependency once all targets have
1.1 deraadt 295: * been found and their operator parsed. If the previous and new
296: * operators are incompatible, a major error is taken.
297: *
298: * Side Effects:
299: * The type field of the node is altered to reflect any new bits in
300: * the op.
301: *---------------------------------------------------------------------
302: */
303: static int
1.63 espie 304: ParseDoOp(gn, op)
305: GNode *gn; /* The node to which the operator is to be
1.59 espie 306: * applied */
1.63 espie 307: int op; /* The operator to apply */
1.1 deraadt 308: {
309: /*
310: * If the dependency mask of the operator and the node don't match and
311: * the node has actually had an operator applied to it before, and
1.11 millert 312: * the operator actually has some dependency information in it, complain.
1.1 deraadt 313: */
314: if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
1.40 espie 315: !OP_NOP(gn->type) && !OP_NOP(op)) {
316: Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
317: return 0;
1.1 deraadt 318: }
319:
1.59 espie 320: if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
321: /* If the node was the object of a :: operator, we need to create a
1.1 deraadt 322: * new instance of it for the children and commands on this dependency
323: * line. The new instance is placed on the 'cohorts' list of the
324: * initial one (note the initial one is not on its own cohorts list)
325: * and the new instance is linked to all parents of the initial
1.59 espie 326: * instance. */
327: GNode *cohort;
328: LstNode ln;
1.63 espie 329: unsigned int i;
1.11 millert 330:
1.61 espie 331: cohort = Targ_NewGN(gn->name);
1.59 espie 332: /* Duplicate links to parents so graph traversal is simple. Perhaps
1.1 deraadt 333: * some type bits should be duplicated?
334: *
335: * Make the cohort invisible as well to avoid duplicating it into
336: * other variables. True, parents of this target won't tend to do
337: * anything with their local variables, but better safe than
1.59 espie 338: * sorry. */
339: for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln))
340: ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
1.1 deraadt 341: cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
1.43 espie 342: Lst_AtEnd(&gn->cohorts, cohort);
1.1 deraadt 343:
1.59 espie 344: /* Replace the node in the targets list with the new copy */
1.63 espie 345: for (i = 0; i < gtargets.n; i++)
346: if (gtargets.a[i] == gn)
347: break;
348: gtargets.a[i] = cohort;
1.1 deraadt 349: gn = cohort;
350: }
1.59 espie 351: /* We don't want to nuke any previous flags (whatever they were) so we
352: * just OR the new operator into the old. */
1.1 deraadt 353: gn->type |= op;
1.40 espie 354: return 1;
1.1 deraadt 355: }
356:
1.11 millert 357: /*-
1.3 deraadt 358: *---------------------------------------------------------------------
1.59 espie 359: * ParseAddDep --
1.3 deraadt 360: * Check if the pair of GNodes given needs to be synchronized.
361: * This has to be when two nodes are on different sides of a
362: * .WAIT directive.
363: *
364: * Results:
1.40 espie 365: * Returns 0 if the two targets need to be ordered, 1 otherwise.
1.59 espie 366: * If it returns 0, the search can stop.
1.3 deraadt 367: *
368: * Side Effects:
369: * A dependency can be added between the two nodes.
1.11 millert 370: *
1.3 deraadt 371: *---------------------------------------------------------------------
372: */
1.13 millert 373: static int
1.63 espie 374: ParseAddDep(p, s)
375: GNode *p;
376: GNode *s;
1.3 deraadt 377: {
378: if (p->order < s->order) {
1.59 espie 379: /* XXX: This can cause loops, and loops can cause unmade targets,
1.3 deraadt 380: * but checking is tedious, and the debugging output can show the
1.59 espie 381: * problem. */
1.43 espie 382: Lst_AtEnd(&p->successors, s);
383: Lst_AtEnd(&s->preds, p);
1.40 espie 384: return 1;
1.3 deraadt 385: }
386: else
1.40 espie 387: return 0;
1.3 deraadt 388: }
389:
390:
1.1 deraadt 391: /*-
392: *---------------------------------------------------------------------
393: * ParseDoSrc --
394: * Given the name of a source, figure out if it is an attribute
395: * and apply it to the targets if it is. Else decide if there is
396: * some attribute which should be applied *to* the source because
397: * of some special target and apply it if so. Otherwise, make the
398: * source be a child of the targets in the list 'targets'
399: *
400: * Side Effects:
401: * Operator bits may be added to the list of targets or to the source.
402: * The targets may have a new source added to their lists of children.
403: *---------------------------------------------------------------------
404: */
405: static void
1.63 espie 406: ParseDoSrc(tOp, src)
1.59 espie 407: int tOp; /* operator (if any) from special targets */
408: const char *src; /* name of the source to handle */
1.3 deraadt 409:
1.1 deraadt 410: {
1.3 deraadt 411: GNode *gn = NULL;
1.1 deraadt 412:
1.59 espie 413: if (*src == '.' && isupper(src[1])) {
1.1 deraadt 414: int keywd = ParseFindKeyword(src);
415: if (keywd != -1) {
1.3 deraadt 416: int op = parseKeywords[keywd].op;
417: if (op != 0) {
1.63 espie 418: Array_Find(>argets, ParseDoOp, op);
1.3 deraadt 419: return;
420: }
421: if (parseKeywords[keywd].spec == Wait) {
422: waiting++;
423: return;
424: }
1.1 deraadt 425: }
426: }
1.3 deraadt 427:
428: switch (specType) {
429: case Main:
1.1 deraadt 430: /*
431: * If we have noted the existence of a .MAIN, it means we need
432: * to add the sources of said target to the list of things
1.61 espie 433: * to create. The string 'src' is likely to be freed, so we
1.1 deraadt 434: * must make a new copy of it. Note that this will only be
435: * invoked if the user didn't specify a target on the command
436: * line. This is to allow #ifmake's to succeed, or something...
437: */
1.61 espie 438: Lst_AtEnd(create, estrdup(src));
1.1 deraadt 439: /*
1.61 espie 440: * Add the name to the .TARGETS variable as well, so the user can
1.1 deraadt 441: * employ that, if desired.
442: */
443: Var_Append(".TARGETS", src, VAR_GLOBAL);
1.3 deraadt 444: return;
445:
446: case Order:
1.1 deraadt 447: /*
448: * Create proper predecessor/successor links between the previous
449: * source and the current one.
450: */
1.61 espie 451: gn = Targ_FindNode(src, TARG_CREATE);
1.33 espie 452: if (predecessor != NULL) {
1.43 espie 453: Lst_AtEnd(&predecessor->successors, gn);
454: Lst_AtEnd(&gn->preds, predecessor);
1.1 deraadt 455: }
456: /*
457: * The current source now becomes the predecessor for the next one.
458: */
459: predecessor = gn;
1.3 deraadt 460: break;
461:
462: default:
1.1 deraadt 463: /*
464: * If the source is not an attribute, we need to find/create
465: * a node for it. After that we can apply any operator to it
466: * from a special target or link it to its parents, as
467: * appropriate.
468: *
469: * In the case of a source that was the object of a :: operator,
470: * the attribute is applied to all of its instances (as kept in
471: * the 'cohorts' list of the node) or all the cohorts are linked
472: * to all the targets.
473: */
1.61 espie 474: gn = Targ_FindNode(src, TARG_CREATE);
1.1 deraadt 475: if (tOp) {
476: gn->type |= tOp;
477: } else {
1.63 espie 478: Array_ForEach(>argets, ParseLinkSrc, gn);
1.1 deraadt 479: }
480: if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
1.59 espie 481: GNode *cohort;
482: LstNode ln;
1.1 deraadt 483:
1.46 espie 484: for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)){
1.1 deraadt 485: cohort = (GNode *)Lst_Datum(ln);
486: if (tOp) {
487: cohort->type |= tOp;
488: } else {
1.63 espie 489: Array_ForEach(>argets, ParseLinkSrc, cohort);
1.1 deraadt 490: }
491: }
492: }
1.3 deraadt 493: break;
494: }
495:
496: gn->order = waiting;
1.63 espie 497: Array_AtEnd(&gsources, gn);
1.59 espie 498: if (waiting) {
1.63 espie 499: Array_Find(&gsources, ParseAddDep, gn);
1.59 espie 500: }
1.1 deraadt 501: }
502:
503: /*-
504: *-----------------------------------------------------------------------
505: * ParseFindMain --
506: * Find a real target in the list and set it to be the main one.
507: * Called by ParseDoDependency when a main target hasn't been found
508: * yet.
509: *
510: * Results:
1.40 espie 511: * 1 if main not found yet, 0 if it is.
1.1 deraadt 512: *
513: * Side Effects:
514: * mainNode is changed and Targ_SetMain is called.
515: *-----------------------------------------------------------------------
516: */
517: static int
518: ParseFindMain(gnp, dummy)
1.59 espie 519: void *gnp; /* Node to examine */
520: void *dummy UNUSED;
1.1 deraadt 521: {
1.59 espie 522: GNode *gn = (GNode *)gnp;
1.17 espie 523: if ((gn->type & OP_NOTARGET) == 0) {
1.1 deraadt 524: mainNode = gn;
525: Targ_SetMain(gn);
1.54 espie 526: return 0;
1.59 espie 527: } else {
1.54 espie 528: return 1;
1.59 espie 529: }
1.1 deraadt 530: }
531:
532: /*-
533: *-----------------------------------------------------------------------
534: * ParseAddDir --
535: * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
536: *
537: * Side Effects:
538: * See Dir_AddDir.
539: *-----------------------------------------------------------------------
540: */
1.41 espie 541: static void
1.1 deraadt 542: ParseAddDir(path, name)
1.42 espie 543: void *path;
544: void *name;
1.1 deraadt 545: {
1.61 espie 546: Dir_AddDir((Lst)path, (char *)name);
1.1 deraadt 547: }
548:
549: /*-
550: *-----------------------------------------------------------------------
551: * ParseClearPath --
1.59 espie 552: * Reinit path to an empty path
1.1 deraadt 553: *-----------------------------------------------------------------------
554: */
1.41 espie 555: static void
1.59 espie 556: ParseClearPath(p)
557: void *p;
1.1 deraadt 558: {
1.59 espie 559: Lst path = (Lst)p;
560:
561: Lst_Destroy(path, Dir_Destroy);
562: Lst_Init(path);
1.1 deraadt 563: }
564:
565: /*-
566: *---------------------------------------------------------------------
567: * ParseDoDependency --
568: * Parse the dependency line in line.
569: *
570: * Side Effects:
571: * The nodes of the sources are linked as children to the nodes of the
572: * targets. Some nodes may be created.
573: *
574: * We parse a dependency line by first extracting words from the line and
575: * finding nodes in the list of all targets with that name. This is done
576: * until a character is encountered which is an operator character. Currently
577: * these are only ! and :. At this point the operator is parsed and the
578: * pointer into the line advanced until the first source is encountered.
1.59 espie 579: * The parsed operator is applied to each node in the 'targets' list,
1.1 deraadt 580: * which is where the nodes found for the targets are kept, by means of
581: * the ParseDoOp function.
582: * The sources are read in much the same way as the targets were except
583: * that now they are expanded using the wildcarding scheme of the C-Shell
584: * and all instances of the resulting words in the list of all targets
585: * are found. Each of the resulting nodes is then linked to each of the
586: * targets as one of its children.
587: * Certain targets are handled specially. These are the ones detailed
588: * by the specType variable.
589: * The storing of transformation rules is also taken care of here.
590: * A target is recognized as a transformation rule by calling
591: * Suff_IsTransform. If it is a transformation rule, its node is gotten
592: * from the suffix module via Suff_AddTransform rather than the standard
593: * Targ_FindNode in the target module.
594: *---------------------------------------------------------------------
595: */
596: static void
1.59 espie 597: ParseDoDependency(line)
598: char *line; /* the line to parse */
1.1 deraadt 599: {
1.59 espie 600: char *cp; /* our current position */
601: GNode *gn; /* a general purpose temporary node */
602: int op; /* the operator on the line */
603: char savec; /* a place to save a character */
604: LIST paths; /* List of search paths to alter when parsing
1.1 deraadt 605: * a list of .PATH targets */
1.59 espie 606: int tOp; /* operator from special target */
1.1 deraadt 607: tOp = 0;
608:
609: specType = Not;
1.3 deraadt 610: waiting = 0;
1.45 espie 611: Lst_Init(&paths);
1.1 deraadt 612:
1.63 espie 613: Array_Reset(&gsources);
1.11 millert 614:
1.1 deraadt 615: do {
1.59 espie 616: for (cp = line; *cp && !isspace(*cp) && *cp != '(';)
617: if (*cp == '$')
618: /* Must be a dynamic source (would have been expanded
1.1 deraadt 619: * otherwise), so call the Var module to parse the puppy
620: * so we can safely advance beyond it...There should be
621: * no errors in this, as they would have been discovered
1.59 espie 622: * in the initial Var_Subst and we wouldn't be here. */
623: cp += Var_ParseSkip(cp, NULL, NULL);
624: else {
625: /* We don't want to end a word on ':' or '!' if there is a
626: * better match later on in the string. By "better" I mean
627: * one that is followed by whitespace. This allows the user
628: * to have targets like:
629: * fie::fi:fo: fum
630: * where "fie::fi:fo" is the target. In real life this is used
631: * for perl5 library man pages where "::" separates an object
632: * from its class. Ie: "File::Spec::Unix". This behaviour
633: * is also consistent with other versions of make. */
634: if (*cp == '!' || *cp == ':') {
635: char *p = cp + 1;
636:
637: if (*cp == ':' && *p == ':')
638: p++;
639:
640: /* Found the best match already. */
641: if (isspace(*p) || *p == '\0')
642: break;
643:
644: do {
645: p += strcspn(p, "!:");
646: if (*p == '\0')
647: break;
648: p++;
649: } while (!isspace(*p));
1.1 deraadt 650:
1.59 espie 651: /* No better match later on... */
652: if (*p == '\0')
653: break;
1.1 deraadt 654:
655: }
1.59 espie 656: cp++;
1.1 deraadt 657: }
658: if (*cp == '(') {
1.63 espie 659: LIST temp;
660: Lst_Init(&temp);
1.59 espie 661: /* Archives must be handled specially to make sure the OP_ARCHV
1.1 deraadt 662: * flag is set in their 'type' field, for one thing, and because
663: * things like "archive(file1.o file2.o file3.o)" are permissible.
664: * Arch_ParseArchive will set 'line' to be the first non-blank
665: * after the archive-spec. It creates/finds nodes for the members
1.61 espie 666: * and places them on the given list, returning true if all
667: * went well and false if there was an error in the
1.59 espie 668: * specification. On error, line should remain untouched. */
1.63 espie 669: if (!Arch_ParseArchive(&line, &temp, NULL)) {
1.59 espie 670: Parse_Error(PARSE_FATAL,
1.1 deraadt 671: "Error in archive specification: \"%s\"", line);
672: return;
673: } else {
1.63 espie 674: AppendList2Array(&temp, >argets);
675: Lst_Destroy(&temp, NOFREE);
1.1 deraadt 676: continue;
677: }
678: }
679: savec = *cp;
1.11 millert 680:
1.59 espie 681: if (*cp == '\0') {
682: /* Ending a dependency line without an operator is a Bozo no-no */
683: Parse_Error(PARSE_FATAL, "Need an operator");
1.1 deraadt 684: return;
685: }
686: *cp = '\0';
1.59 espie 687: /* Have a word in line. See if it's a special target and set
688: * specType to match it. */
689: if (*line == '.' && isupper(line[1])) {
690: /* See if the target is a special target that must have it
691: * or its sources handled specially. */
1.1 deraadt 692: int keywd = ParseFindKeyword(line);
693: if (keywd != -1) {
694: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
695: Parse_Error(PARSE_FATAL, "Mismatched special targets");
696: return;
697: }
1.11 millert 698:
1.1 deraadt 699: specType = parseKeywords[keywd].spec;
700: tOp = parseKeywords[keywd].op;
701:
702: /*
703: * Certain special targets have special semantics:
704: * .PATH Have to set the dirSearchPath
705: * variable too
706: * .MAIN Its sources are only used if
707: * nothing has been specified to
708: * create.
1.59 espie 709: * .DEFAULT Need to create a node to hang
1.1 deraadt 710: * commands on, but we don't want
711: * it in the graph, nor do we want
712: * it to be the Main Target, so we
713: * create it, set OP_NOTMAIN and
714: * add it to the list, setting
715: * DEFAULT to the new node for
716: * later use. We claim the node is
1.59 espie 717: * A transformation rule to make
718: * life easier later, when we'll
719: * use Make_HandleUse to actually
720: * apply the .DEFAULT commands.
1.7 niklas 721: * .PHONY The list of targets
1.59 espie 722: * .NOPATH Don't search for file in the path
1.1 deraadt 723: * .BEGIN
724: * .END
1.59 espie 725: * .INTERRUPT Are not to be considered the
1.1 deraadt 726: * main target.
1.59 espie 727: * .NOTPARALLEL Make only one target at a time.
728: * .SINGLESHELL Create a shell for each command.
729: * .ORDER Must set initial predecessor to NULL
1.1 deraadt 730: */
731: switch (specType) {
732: case ExPath:
1.61 espie 733: Lst_AtEnd(&paths, dirSearchPath);
1.1 deraadt 734: break;
735: case Main:
1.61 espie 736: if (!Lst_IsEmpty(create)) {
1.1 deraadt 737: specType = Not;
738: }
739: break;
740: case Begin:
741: case End:
742: case Interrupt:
1.61 espie 743: gn = Targ_FindNode(line, TARG_CREATE);
1.1 deraadt 744: gn->type |= OP_NOTMAIN;
1.63 espie 745: Array_AtEnd(>argets, gn);
1.1 deraadt 746: break;
747: case Default:
1.61 espie 748: gn = Targ_NewGN(".DEFAULT");
1.59 espie 749: gn->type |= OP_NOTMAIN|OP_TRANSFORM;
1.63 espie 750: Array_AtEnd(>argets, gn);
1.1 deraadt 751: DEFAULT = gn;
752: break;
753: case NotParallel:
754: {
755: extern int maxJobs;
1.11 millert 756:
1.1 deraadt 757: maxJobs = 1;
758: break;
759: }
760: case SingleShell:
761: compatMake = 1;
762: break;
763: case Order:
1.33 espie 764: predecessor = NULL;
1.1 deraadt 765: break;
766: default:
767: break;
768: }
1.59 espie 769: } else if (strncmp(line, ".PATH", 5) == 0) {
1.1 deraadt 770: /*
771: * .PATH<suffix> has to be handled specially.
772: * Call on the suffix module to give us a path to
773: * modify.
774: */
1.59 espie 775: Lst path;
1.11 millert 776:
1.1 deraadt 777: specType = ExPath;
1.45 espie 778: path = Suff_GetPath(&line[5]);
1.33 espie 779: if (path == NULL) {
1.45 espie 780: Parse_Error(PARSE_FATAL,
1.1 deraadt 781: "Suffix '%s' not defined (yet)",
782: &line[5]);
783: return;
1.59 espie 784: } else {
1.45 espie 785: Lst_AtEnd(&paths, path);
1.59 espie 786: }
1.1 deraadt 787: }
788: }
1.11 millert 789:
1.1 deraadt 790: /*
791: * Have word in line. Get or create its node and stick it at
1.11 millert 792: * the end of the targets list
1.1 deraadt 793: */
1.59 espie 794: if (specType == Not && *line != '\0') {
1.34 espie 795: char *targName;
796:
1.1 deraadt 797: if (Dir_HasWildcards(line)) {
798: /*
799: * Targets are to be sought only in the current directory,
800: * so create an empty path for the thing. Note we need to
801: * use Dir_Destroy in the destruction of the path as the
802: * Dir module could have added a directory to the path...
803: */
1.43 espie 804: LIST emptyPath;
1.63 espie 805: LIST curTargs; /* list of target names to be found
806: * and added to the targets list */
1.59 espie 807:
1.43 espie 808: Lst_Init(&emptyPath);
1.63 espie 809: Lst_Init(&curTargs);
1.43 espie 810: Dir_Expand(line, &emptyPath, &curTargs);
811: Lst_Destroy(&emptyPath, Dir_Destroy);
1.59 espie 812: while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) {
1.63 espie 813: if (!Suff_IsTransform(targName))
1.61 espie 814: gn = Targ_FindNode(targName, TARG_CREATE);
1.63 espie 815: else
1.59 espie 816: gn = Suff_AddTransform(targName);
1.63 espie 817:
818: if (gn != NULL)
819: Array_AtEnd(>argets, gn);
1.1 deraadt 820: }
1.63 espie 821: Lst_Destroy(&curTargs, NOFREE);
822: } else {
823: if (!Suff_IsTransform(line))
824: gn = Targ_FindNode(line, TARG_CREATE);
825: else
826: gn = Suff_AddTransform(line);
1.11 millert 827:
1.16 millert 828: if (gn != NULL)
1.63 espie 829: Array_AtEnd(>argets, gn);
830: /* Don't need the list of target names anymore... */
1.1 deraadt 831: }
1.63 espie 832: } else if (specType == ExPath && *line != '.' && *line != '\0')
1.1 deraadt 833: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1.11 millert 834:
1.1 deraadt 835: *cp = savec;
836: /*
837: * If it is a special type and not .PATH, it's the only target we
838: * allow on this line...
839: */
840: if (specType != Not && specType != ExPath) {
1.61 espie 841: bool warn = false;
1.11 millert 842:
1.59 espie 843: while (*cp != '!' && *cp != ':' && *cp) {
1.1 deraadt 844: if (*cp != ' ' && *cp != '\t') {
1.61 espie 845: warn = true;
1.1 deraadt 846: }
847: cp++;
848: }
849: if (warn) {
850: Parse_Error(PARSE_WARNING, "Extra target ignored");
851: }
852: } else {
1.59 espie 853: while (*cp && isspace(*cp)) {
1.1 deraadt 854: cp++;
855: }
856: }
857: line = cp;
1.59 espie 858: } while (*line != '!' && *line != ':' && *line);
1.1 deraadt 859:
1.63 espie 860: if (!Array_IsEmpty(>argets)) {
1.59 espie 861: switch (specType) {
1.1 deraadt 862: default:
863: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
864: break;
865: case Default:
866: case Begin:
867: case End:
868: case Interrupt:
1.59 espie 869: /* These four create nodes on which to hang commands, so
870: * targets shouldn't be empty... */
1.1 deraadt 871: case Not:
1.59 espie 872: /* Nothing special here -- targets can be empty if it wants. */
1.1 deraadt 873: break;
874: }
875: }
876:
1.59 espie 877: /* Have now parsed all the target names. Must parse the operator next. The
878: * result is left in op . */
1.1 deraadt 879: if (*cp == '!') {
880: op = OP_FORCE;
881: } else if (*cp == ':') {
882: if (cp[1] == ':') {
883: op = OP_DOUBLEDEP;
884: cp++;
885: } else {
886: op = OP_DEPENDS;
887: }
888: } else {
1.59 espie 889: Parse_Error(PARSE_FATAL, "Missing dependency operator");
1.1 deraadt 890: return;
891: }
892:
893: cp++; /* Advance beyond operator */
894:
1.63 espie 895: Array_Find(>argets, ParseDoOp, op);
1.1 deraadt 896:
897: /*
1.11 millert 898: * Get to the first source
1.1 deraadt 899: */
1.59 espie 900: while (*cp && isspace(*cp)) {
1.1 deraadt 901: cp++;
902: }
903: line = cp;
904:
905: /*
906: * Several special targets take different actions if present with no
907: * sources:
908: * a .SUFFIXES line with no sources clears out all old suffixes
909: * a .PRECIOUS line makes all targets precious
910: * a .IGNORE line ignores errors for all targets
911: * a .SILENT line creates silence when making all targets
912: * a .PATH removes all directories from the search path(s).
913: */
914: if (!*line) {
915: switch (specType) {
916: case Suffixes:
1.59 espie 917: Suff_ClearSuffixes();
1.1 deraadt 918: break;
919: case Precious:
1.61 espie 920: allPrecious = true;
1.1 deraadt 921: break;
922: case Ignore:
1.61 espie 923: ignoreErrors = true;
1.1 deraadt 924: break;
925: case Silent:
1.61 espie 926: beSilent = true;
1.1 deraadt 927: break;
928: case ExPath:
1.45 espie 929: Lst_Every(&paths, ParseClearPath);
1.1 deraadt 930: break;
931: default:
932: break;
933: }
934: } else if (specType == MFlags) {
935: /*
936: * Call on functions in main.c to deal with these arguments and
937: * set the initial character to a null-character so the loop to
938: * get sources won't get anything
939: */
1.59 espie 940: Main_ParseArgLine(line);
1.1 deraadt 941: *line = '\0';
942: } else if (specType == ExShell) {
1.61 espie 943: if (!Job_ParseShell(line)) {
1.59 espie 944: Parse_Error(PARSE_FATAL, "improper shell specification");
1.1 deraadt 945: return;
946: }
947: *line = '\0';
1.59 espie 948: } else if (specType == NotParallel || specType == SingleShell) {
1.1 deraadt 949: *line = '\0';
950: }
1.11 millert 951:
1.1 deraadt 952: /*
1.11 millert 953: * NOW GO FOR THE SOURCES
1.1 deraadt 954: */
1.59 espie 955: if (specType == Suffixes || specType == ExPath ||
956: specType == Includes || specType == Libs ||
957: specType == Null) {
1.1 deraadt 958: while (*line) {
959: /*
960: * If the target was one that doesn't take files as its sources
961: * but takes something like suffixes, we take each
962: * space-separated word on the line as a something and deal
963: * with it accordingly.
964: *
965: * If the target was .SUFFIXES, we take each source as a
966: * suffix and add it to the list of suffixes maintained by the
967: * Suff module.
968: *
969: * If the target was a .PATH, we add the source as a directory
970: * to search on the search path.
971: *
972: * If it was .INCLUDES, the source is taken to be the suffix of
973: * files which will be #included and whose search path should
974: * be present in the .INCLUDES variable.
975: *
976: * If it was .LIBS, the source is taken to be the suffix of
977: * files which are considered libraries and whose search path
978: * should be present in the .LIBS variable.
979: *
980: * If it was .NULL, the source is the suffix to use when a file
981: * has no valid suffix.
982: */
983: char savec;
1.59 espie 984: while (*cp && !isspace(*cp)) {
1.1 deraadt 985: cp++;
986: }
987: savec = *cp;
988: *cp = '\0';
989: switch (specType) {
990: case Suffixes:
1.59 espie 991: Suff_AddSuffix(line);
1.1 deraadt 992: break;
993: case ExPath:
1.45 espie 994: Lst_ForEach(&paths, ParseAddDir, line);
1.1 deraadt 995: break;
996: case Includes:
1.59 espie 997: Suff_AddInclude(line);
1.1 deraadt 998: break;
999: case Libs:
1.59 espie 1000: Suff_AddLib(line);
1.1 deraadt 1001: break;
1002: case Null:
1.59 espie 1003: Suff_SetNull(line);
1.1 deraadt 1004: break;
1005: default:
1006: break;
1007: }
1008: *cp = savec;
1009: if (savec != '\0') {
1010: cp++;
1011: }
1.59 espie 1012: while (*cp && isspace(*cp)) {
1.1 deraadt 1013: cp++;
1014: }
1015: line = cp;
1016: }
1.45 espie 1017: Lst_Destroy(&paths, NOFREE);
1.1 deraadt 1018: } else {
1019: while (*line) {
1020: /*
1021: * The targets take real sources, so we must beware of archive
1022: * specifications (i.e. things with left parentheses in them)
1023: * and handle them accordingly.
1024: */
1.59 espie 1025: while (*cp && !isspace(*cp)) {
1026: if (*cp == '(' && cp > line && cp[-1] != '$') {
1.1 deraadt 1027: /*
1028: * Only stop for a left parenthesis if it isn't at the
1029: * start of a word (that'll be for variable changes
1030: * later) and isn't preceded by a dollar sign (a dynamic
1031: * source).
1032: */
1033: break;
1034: } else {
1035: cp++;
1036: }
1037: }
1038:
1039: if (*cp == '(') {
1040: GNode *gn;
1.59 espie 1041: LIST sources; /* list of archive source names after
1042: * expansion */
1.1 deraadt 1043:
1.43 espie 1044: Lst_Init(&sources);
1.61 espie 1045: if (!Arch_ParseArchive(&line, &sources, NULL)) {
1.59 espie 1046: Parse_Error(PARSE_FATAL,
1.1 deraadt 1047: "Error in source archive spec \"%s\"", line);
1048: return;
1049: }
1050:
1.43 espie 1051: while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL)
1.63 espie 1052: ParseDoSrc(tOp, gn->name);
1.1 deraadt 1053: cp = line;
1054: } else {
1055: if (*cp) {
1056: *cp = '\0';
1057: cp += 1;
1058: }
1059:
1.63 espie 1060: ParseDoSrc(tOp, line);
1.1 deraadt 1061: }
1.59 espie 1062: while (*cp && isspace(*cp)) {
1.1 deraadt 1063: cp++;
1064: }
1065: line = cp;
1066: }
1067: }
1.11 millert 1068:
1.33 espie 1069: if (mainNode == NULL) {
1.59 espie 1070: /* If we have yet to decide on a main target to make, in the
1.1 deraadt 1071: * absence of any user input, we want the first target on
1072: * the first dependency line that is actually a real target
1.59 espie 1073: * (i.e. isn't a .USE or .EXEC rule) to be made. */
1.63 espie 1074: Array_Find(>argets, ParseFindMain, NULL);
1.1 deraadt 1075: }
1076:
1.43 espie 1077: /* Finally, destroy the list of sources. */
1.1 deraadt 1078: }
1079:
1080: /*-
1.59 espie 1081: * ParseAddCmd --
1.1 deraadt 1082: * Lst_ForEach function to add a command line to all targets
1083: *
1084: * Side Effects:
1085: * A new element is added to the commands list of the node.
1086: */
1.41 espie 1087: static void
1.1 deraadt 1088: ParseAddCmd(gnp, cmd)
1.42 espie 1089: void *gnp; /* the node to which the command is to be added */
1090: void *cmd; /* the command to add */
1.1 deraadt 1091: {
1.41 espie 1092: GNode *gn = (GNode *)gnp;
1.1 deraadt 1093: /* if target already supplied, ignore commands */
1.39 espie 1094: if (!(gn->type & OP_HAS_COMMANDS)) {
1.43 espie 1095: Lst_AtEnd(&gn->commands, cmd);
1.39 espie 1096: if (!gn->lineno) {
1097: gn->lineno = Parse_Getlineno();
1098: gn->fname = Parse_Getfilename();
1099: }
1100: }
1.1 deraadt 1101: }
1102:
1103: /*-
1104: *-----------------------------------------------------------------------
1105: * ParseHasCommands --
1106: * Callback procedure for Parse_File when destroying the list of
1107: * targets on the last dependency line. Marks a target as already
1108: * having commands if it does, to keep from having shell commands
1109: * on multiple dependency lines.
1110: *
1111: * Side Effects:
1112: * OP_HAS_COMMANDS may be set for the target.
1113: *-----------------------------------------------------------------------
1114: */
1115: static void
1116: ParseHasCommands(gnp)
1.42 espie 1117: void *gnp; /* Node to examine */
1.1 deraadt 1118: {
1.59 espie 1119: GNode *gn = (GNode *)gnp;
1.43 espie 1120: if (!Lst_IsEmpty(&gn->commands)) {
1.1 deraadt 1121: gn->type |= OP_HAS_COMMANDS;
1122: }
1123: }
1124:
1125: /*-
1126: *-----------------------------------------------------------------------
1127: * Parse_AddIncludeDir --
1128: * Add a directory to the path searched for included makefiles
1129: * bracketed by double-quotes. Used by functions in main.c
1130: *-----------------------------------------------------------------------
1131: */
1132: void
1.43 espie 1133: Parse_AddIncludeDir(dir)
1.59 espie 1134: const char *dir; /* The name of the directory to add */
1.1 deraadt 1135: {
1.61 espie 1136: Dir_AddDir(parseIncPath, dir);
1.1 deraadt 1137: }
1138:
1139: /*-
1140: *---------------------------------------------------------------------
1141: * ParseDoInclude --
1142: * Push to another file.
1.11 millert 1143: *
1.1 deraadt 1144: * The input is the line minus the #include. A file spec is a string
1145: * enclosed in <> or "". The former is looked for only in sysIncPath.
1146: * The latter in . and the directories specified by -I command line
1147: * options
1148: *
1149: * Side Effects:
1.59 espie 1150: * old parse context is pushed on the stack, new file becomes
1.50 espie 1151: * current context.
1.1 deraadt 1152: *---------------------------------------------------------------------
1153: */
1154: static void
1.50 espie 1155: ParseDoInclude(file)
1.59 espie 1156: char *file; /* file specification */
1.1 deraadt 1157: {
1.59 espie 1158: char endc; /* the character which ends the file spec */
1159: char *cp; /* current position in file spec */
1.61 espie 1160: bool isSystem; /* true if makefile is a system makefile */
1.1 deraadt 1161:
1.59 espie 1162: /* Skip to delimiter character so we know where to look. */
1.50 espie 1163: while (*file == ' ' || *file == '\t')
1.1 deraadt 1164: file++;
1165:
1.50 espie 1166: if (*file != '"' && *file != '<') {
1.59 espie 1167: Parse_Error(PARSE_FATAL,
1.1 deraadt 1168: ".include filename must be delimited by '\"' or '<'");
1169: return;
1170: }
1171:
1.50 espie 1172: /* Set the search path on which to find the include file based on the
1.1 deraadt 1173: * characters which bracket its name. Angle-brackets imply it's
1.50 espie 1174: * a system Makefile while double-quotes imply it's a user makefile */
1.1 deraadt 1175: if (*file == '<') {
1.61 espie 1176: isSystem = true;
1.1 deraadt 1177: endc = '>';
1178: } else {
1.61 espie 1179: isSystem = false;
1.1 deraadt 1180: endc = '"';
1181: }
1182:
1.59 espie 1183: /* Skip to matching delimiter. */
1184: for (cp = ++file; *cp != endc; cp++) {
1185: if (*cp == '\0') {
1.50 espie 1186: Parse_Error(PARSE_FATAL,
1.1 deraadt 1187: "Unclosed %cinclude filename. '%c' expected",
1188: '.', endc);
1.50 espie 1189: return;
1.1 deraadt 1190: }
1191: }
1.61 espie 1192: ParseLookupIncludeFile(file, cp, isSystem, true);
1.1 deraadt 1193: }
1194:
1195: /*-
1196: *---------------------------------------------------------------------
1197: * ParseTraditionalInclude --
1198: * Push to another file.
1.11 millert 1199: *
1.1 deraadt 1200: * The input is the line minus the "include". The file name is
1201: * the string following the "include".
1202: *
1203: * Side Effects:
1.59 espie 1204: * old parse context is pushed on the stack, new file becomes
1.50 espie 1205: * current context.
1.59 espie 1206: *
1207: * XXX May wish to support multiple files and wildcards ?
1.1 deraadt 1208: *---------------------------------------------------------------------
1209: */
1210: static void
1.50 espie 1211: ParseTraditionalInclude(file)
1.59 espie 1212: char *file; /* file specification */
1.1 deraadt 1213: {
1.59 espie 1214: char *cp; /* current position in file spec */
1.1 deraadt 1215:
1.59 espie 1216: /* Skip over whitespace. */
1217: while (isspace(*file))
1.1 deraadt 1218: file++;
1.59 espie 1219: if (*file == '\0') {
1220: Parse_Error(PARSE_FATAL,
1221: "Filename missing from \"include\"");
1222: return;
1223: }
1224: /* Skip to end of line or next whitespace. */
1225: for (cp = file; *cp != '\0' && !isspace(*cp);)
1226: cp++;
1227:
1.61 espie 1228: ParseLookupIncludeFile(file, cp, true, true);
1.59 espie 1229: }
1230:
1231: /*-
1232: *---------------------------------------------------------------------
1233: * ParseConditionalInclude --
1234: * May push to another file.
1235: *
1236: * No error if the file does not exist.
1237: * See ParseTraditionalInclude otherwise.
1238: *---------------------------------------------------------------------
1239: */
1240: static void
1241: ParseConditionalInclude(file)
1242: char *file; /* file specification */
1243: {
1244: char *cp; /* current position in file spec */
1.1 deraadt 1245:
1.59 espie 1246: /* Skip over whitespace. */
1247: while (isspace(*file))
1248: file++;
1.1 deraadt 1249: if (*file == '\0') {
1.59 espie 1250: Parse_Error(PARSE_FATAL,
1.1 deraadt 1251: "Filename missing from \"include\"");
1252: return;
1253: }
1.59 espie 1254: /* Skip to end of line or next whitespace. */
1.50 espie 1255: for (cp = file; *cp != '\0' && !isspace(*cp);)
1.59 espie 1256: cp++;
1.1 deraadt 1257:
1.61 espie 1258: ParseLookupIncludeFile(file, cp, true, false);
1.50 espie 1259: }
1.1 deraadt 1260:
1.50 espie 1261: /* Common part to lookup and read an include file. */
1262: static void
1.59 espie 1263: ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound)
1.50 espie 1264: char *spec;
1265: char *endSpec;
1.61 espie 1266: bool isSystem;
1267: bool errIfNotFound;
1.50 espie 1268: {
1269: char *file;
1270: char *fullname;
1271: char endc;
1272:
1273: /* Substitute for any variables in the file name before trying to
1.59 espie 1274: * find the thing. */
1.50 espie 1275: endc = *endSpec;
1276: *endSpec = '\0';
1.61 espie 1277: file = Var_Subst(spec, NULL, false);
1.50 espie 1278: *endSpec = endc;
1279:
1280: /* Now that we know the file name and its search path, we attempt to
1281: * find the durn thing. NULL indicates the file still hasn't been
1282: * found. */
1283: fullname = NULL;
1284:
1285: /* Handle non-system non-absolute files... */
1286: if (!isSystem && file[0] != '/') {
1.59 espie 1287: /* ... by first searching relative to the including file's
1288: * location. We don't want to cd there, of course, so we
1289: * just tack on the old file's leading path components
1.50 espie 1290: * and call Dir_FindFile to see if we can locate the beast. */
1.61 espie 1291: char *slash;
1292: const char *fname;
1.50 espie 1293:
1.61 espie 1294: fname = Parse_Getfilename();
1295:
1296: slash = strrchr(fname, '/');
1.50 espie 1297: if (slash != NULL) {
1.61 espie 1298: char *newName;
1.50 espie 1299:
1.61 espie 1300: newName = Str_concati(fname, slash, file, strchr(file, '\0'), '/');
1301: fullname = Dir_FindFile(newName, parseIncPath);
1.50 espie 1302: if (fullname == NULL)
1.61 espie 1303: fullname = Dir_FindFile(newName, dirSearchPath);
1.50 espie 1304: free(newName);
1305: }
1.1 deraadt 1306: }
1307:
1.59 espie 1308: /* Now look first on the -I search path, then on the .PATH
1.50 espie 1309: * search path, if not found in a -I directory.
1310: * XXX: Suffix specific? */
1.59 espie 1311: if (fullname == NULL)
1.61 espie 1312: fullname = Dir_FindFile(file, parseIncPath);
1.50 espie 1313: if (fullname == NULL)
1.61 espie 1314: fullname = Dir_FindFile(file, dirSearchPath);
1.1 deraadt 1315:
1.50 espie 1316: /* Still haven't found the makefile. Look for it on the system
1317: * path as a last resort. */
1318: if (fullname == NULL)
1.61 espie 1319: fullname = Dir_FindFile(file, sysIncPath);
1.1 deraadt 1320:
1.59 espie 1321: if (fullname == NULL && errIfNotFound)
1322: Parse_Error(PARSE_FATAL, "Could not find %s", file);
1323:
1.1 deraadt 1324:
1.50 espie 1325: free(file);
1.1 deraadt 1326:
1.50 espie 1327: if (fullname != NULL) {
1.59 espie 1328: FILE *f;
1.1 deraadt 1329:
1.50 espie 1330: f = fopen(fullname, "r");
1.59 espie 1331: if (f == NULL && errIfNotFound) {
1.50 espie 1332: Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1333: } else {
1334: /* Once we find the absolute path to the file, we push the current
1335: * stream to the includes stack, and start reading from the new
1336: * file. We set up the file name to be its absolute name so that
1.59 espie 1337: * error messages are informative. */
1.50 espie 1338: Parse_FromFile(fullname, f);
1339: }
1.1 deraadt 1340: }
1341: }
1342:
1.59 espie 1343:
1344:
1345:
1346: /* Strip comments from the line. May return either a copy of the line, or
1347: * the line itself. */
1348: static char *
1349: strip_comments(copy, line)
1350: Buffer copy;
1351: const char *line;
1352: {
1353: const char *comment;
1354: const char *p;
1355:
1356: comment = strchr(line, '#');
1357: assert(comment != line);
1358: if (comment == NULL)
1359: return (char *)line;
1360: else {
1361: Buf_Reset(copy);
1362:
1363: for (p = line; *p != '\0'; p++) {
1364: if (*p == '\\') {
1365: if (p[1] == '#') {
1.61 espie 1366: Buf_Addi(copy, line, p);
1.59 espie 1367: Buf_AddChar(copy, '#');
1368: line = p+2;
1369: }
1370: if (p[1] != '\0')
1371: p++;
1372: } else if (*p == '#')
1373: break;
1374: }
1.61 espie 1375: Buf_Addi(copy, line, p);
1.59 espie 1376: Buf_KillTrailingSpaces(copy);
1377: return Buf_Retrieve(copy);
1378: }
1379: }
1380:
1.61 espie 1381: static bool
1.59 espie 1382: ParseIsCond(linebuf, copy, line)
1383: Buffer linebuf;
1384: Buffer copy;
1385: char *line;
1386: {
1387:
1388: char *stripped;
1389:
1390: while (*line != '\0' && isspace(*line))
1391: line++;
1392:
1393: /* The line might be a conditional. Ask the conditional module
1394: * about it and act accordingly. */
1395: switch (Cond_Eval(line)) {
1396: case COND_SKIP:
1397: /* Skip to next conditional that evaluates to COND_PARSE. */
1398: do {
1.61 espie 1399: line = Parse_ReadNextConditionalLine(linebuf);
1.59 espie 1400: if (line != NULL) {
1401: while (*line != '\0' && isspace(*line))
1402: line++;
1403: stripped = strip_comments(copy, line);
1404: }
1405: } while (line != NULL && Cond_Eval(stripped) != COND_PARSE);
1406: /* FALLTHROUGH */
1407: case COND_PARSE:
1.61 espie 1408: return true;
1.59 espie 1409: default:
1410: break;
1411: }
1412:
1413: {
1414: For *loop;
1415:
1416: loop = For_Eval(line);
1417: if (loop != NULL) {
1.61 espie 1418: bool ok;
1.59 espie 1419: do {
1420: /* Find the matching endfor. */
1.61 espie 1421: line = ParseReadLoopLine(linebuf);
1.59 espie 1422: if (line == NULL) {
1423: Parse_Error(PARSE_FATAL,
1424: "Unexpected end of file in for loop.\n");
1.61 espie 1425: return false;
1.59 espie 1426: }
1427: ok = For_Accumulate(loop, line);
1428: } while (ok);
1429: For_Run(loop);
1.61 espie 1430: return true;
1.59 espie 1431: }
1432: }
1433:
1434: if (strncmp(line, "include", 7) == 0) {
1435: ParseDoInclude(line + 7);
1.61 espie 1436: return true;
1.59 espie 1437: } else if (strncmp(line, "undef", 5) == 0) {
1438: char *cp;
1439:
1440: line+=5;
1441: while (*line != '\0' && isspace(*line))
1442: line++;
1443: for (cp = line; !isspace(*cp) && *cp != '\0';)
1444: cp++;
1445: *cp = '\0';
1446: Var_Delete(line);
1.61 espie 1447: return true;
1.59 espie 1448: }
1.61 espie 1449: return false;
1.59 espie 1450: }
1451:
1.1 deraadt 1452: /*-
1453: *-----------------------------------------------------------------------
1.59 espie 1454: * ParseFinishDependency --
1.1 deraadt 1455: * Handle the end of a dependency group.
1456: *
1457: * Side Effects:
1.59 espie 1458: * 'targets' list destroyed.
1.1 deraadt 1459: *
1460: *-----------------------------------------------------------------------
1461: */
1462: static void
1.59 espie 1463: ParseFinishDependency()
1.1 deraadt 1464: {
1.63 espie 1465: Array_Every(>argets, Suff_EndTransform);
1466: Array_Every(>argets, ParseHasCommands);
1467: Array_Reset(>argets);
1.1 deraadt 1468: }
1.11 millert 1469:
1.59 espie 1470: static void
1471: ParseDoCommands(line)
1472: const char *line;
1473: {
1474: /* add the command to the list of
1475: * commands of all targets in the dependency spec */
1476: char *cmd = estrdup(line);
1477:
1.63 espie 1478: Array_ForEach(>argets, ParseAddCmd, cmd);
1.59 espie 1479: #ifdef CLEANUP
1480: Lst_AtEnd(&targCmds, cmd);
1481: #endif
1482: }
1.1 deraadt 1483:
1484: void
1485: Parse_File(name, stream)
1.61 espie 1486: const char *name; /* the name of the file being read */
1.59 espie 1487: FILE *stream; /* Stream open to makefile to parse */
1.1 deraadt 1488: {
1.59 espie 1489: char *cp, /* pointer into the line */
1490: *line; /* the line we're working on */
1.61 espie 1491: bool inDependency; /* true if currently in a dependency
1.59 espie 1492: * line or its commands */
1493:
1494: BUFFER buf;
1495: BUFFER copy;
1496:
1497: Buf_Init(&buf, MAKE_BSIZE);
1498: Buf_Init(©, MAKE_BSIZE);
1.61 espie 1499: inDependency = false;
1.59 espie 1500: Parse_FromFile(name, stream);
1.1 deraadt 1501:
1502: do {
1.61 espie 1503: while ((line = Parse_ReadNormalLine(&buf)) != NULL) {
1.1 deraadt 1504: if (*line == '\t') {
1.59 espie 1505: if (inDependency)
1506: ParseDoCommands(line+1);
1507: else
1508: Parse_Error(PARSE_FATAL,
1509: "Unassociated shell command \"%s\"",
1510: line);
1.1 deraadt 1511: } else {
1.59 espie 1512: char *stripped;
1513: stripped = strip_comments(©, line);
1514: if (*stripped == '.' && ParseIsCond(&buf, ©, stripped+1))
1515: ;
1516: else if (FEATURES(FEATURE_SYSVINCLUDE) &&
1517: strncmp(stripped, "include", 7) == 0 &&
1518: isspace(stripped[7]) &&
1519: strchr(stripped, ':') == NULL) {
1520: /* It's an S3/S5-style "include". */
1521: ParseTraditionalInclude(stripped + 7);
1522: } else if (FEATURES(FEATURE_CONDINCLUDE) &&
1523: (*stripped == '-' || *stripped == 's') &&
1524: strncmp(stripped+1, "include", 7) == 0 &&
1525: isspace(stripped[8]) &&
1526: strchr(stripped, ':') == NULL) {
1527: ParseConditionalInclude(stripped+8);
1528: } else {
1529: char *dep;
1.11 millert 1530:
1.59 espie 1531: if (inDependency)
1532: ParseFinishDependency();
1.61 espie 1533: if (Parse_DoVar(stripped, VAR_GLOBAL))
1534: inDependency = false;
1535: else {
1.59 espie 1536: size_t pos;
1537: char *end;
1.11 millert 1538:
1.59 espie 1539: /* Need a new list for the target nodes. */
1.63 espie 1540: Array_Reset(>argets);
1.61 espie 1541: inDependency = true;
1.59 espie 1542:
1543: dep = NULL;
1544: /* First we need to find eventual dependencies */
1545: pos = strcspn(stripped, ":!");
1546: /* go over :!, and find ; */
1547: if (stripped[pos] != '\0' &&
1548: (end = strchr(stripped+pos+1, ';')) != NULL) {
1549: if (line != stripped)
1550: /* find matching ; in original... The
1551: * original might be slightly longer. */
1552: dep = strchr(line+(end-stripped), ';');
1553: else
1554: dep = end;
1555: /* kill end of line. */
1556: *end = '\0';
1557: }
1558: /* We now know it's a dependency line so it needs to
1559: * have all variables expanded before being parsed.
1560: * Tell the variable module to complain if some
1561: * variable is undefined... */
1.61 espie 1562: cp = Var_Subst(stripped, NULL, true);
1.59 espie 1563: ParseDoDependency(cp);
1564: free(cp);
1565:
1566: /* Parse dependency if it's not empty. */
1567: if (dep != NULL) {
1568: do {
1569: dep++;
1570: } while (isspace(*dep));
1571: if (*dep != '\0')
1572: ParseDoCommands(dep);
1573: }
1.1 deraadt 1574: }
1575: }
1576: }
1577: }
1.50 espie 1578: } while (Parse_NextFile());
1.1 deraadt 1579:
1.59 espie 1580: if (inDependency)
1581: ParseFinishDependency();
1582: /* Make sure conditionals are clean. */
1.1 deraadt 1583: Cond_End();
1584:
1.61 espie 1585: Parse_ReportErrors();
1.59 espie 1586: Buf_Destroy(&buf);
1587: Buf_Destroy(©);
1.1 deraadt 1588: }
1589:
1590: void
1.43 espie 1591: Parse_Init()
1.1 deraadt 1592: {
1.33 espie 1593: mainNode = NULL;
1.65 ! deraadt 1594: Lst_Init(parseIncPath);
! 1595: Lst_Init(sysIncPath);
1.63 espie 1596: Array_Init(&gsources, SOURCES_SIZE);
1597: Array_Init(>argets, TARGETS_SIZE);
1598:
1.61 espie 1599: LowParse_Init();
1.20 espie 1600: #ifdef CLEANUP
1.65 ! deraadt 1601: Lst_Init(&targCmds);
1.20 espie 1602: #endif
1.1 deraadt 1603: }
1604:
1.61 espie 1605: #ifdef CLEANUP
1.1 deraadt 1606: void
1607: Parse_End()
1608: {
1.43 espie 1609: Lst_Destroy(&targCmds, (SimpleProc)free);
1.61 espie 1610: Lst_Destroy(sysIncPath, Dir_Destroy);
1611: Lst_Destroy(parseIncPath, Dir_Destroy);
1.50 espie 1612: LowParse_End();
1.61 espie 1613: }
1.20 espie 1614: #endif
1.11 millert 1615:
1.1 deraadt 1616:
1.44 espie 1617: void
1618: Parse_MainName(listmain)
1.59 espie 1619: Lst listmain; /* result list */
1.1 deraadt 1620: {
1621:
1.59 espie 1622: if (mainNode == NULL) {
1623: Punt("no target to make.");
1624: /*NOTREACHED*/
1625: } else if (mainNode->type & OP_DOUBLEDEP) {
1.37 espie 1626: Lst_AtEnd(listmain, mainNode);
1.45 espie 1627: Lst_Concat(listmain, &mainNode->cohorts);
1.1 deraadt 1628: }
1629: else
1.37 espie 1630: Lst_AtEnd(listmain, mainNode);
1.1 deraadt 1631: }
1.59 espie 1632: