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