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