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