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