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