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