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