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