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