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