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