Annotation of src/usr.bin/make/parse.c, Revision 1.87
1.59 espie 1: /* $OpenPackages$ */
1.87 ! espie 2: /* $OpenBSD: parse.c,v 1.86 2007/09/17 09:38:49 espie Exp $ */
1.13 millert 3: /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
1.1 deraadt 4:
5: /*
1.59 espie 6: * Copyright (c) 1999 Marc Espie.
7: *
8: * Extensive code changes for the OpenBSD project.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
23: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31: /*
1.11 millert 32: * Copyright (c) 1988, 1989, 1990, 1993
33: * The Regents of the University of California. All rights reserved.
1.1 deraadt 34: * Copyright (c) 1989 by Berkeley Softworks
35: * All rights reserved.
36: *
37: * This code is derived from software contributed to Berkeley by
38: * Adam de Boor.
39: *
40: * Redistribution and use in source and binary forms, with or without
41: * modification, are permitted provided that the following conditions
42: * are met:
43: * 1. Redistributions of source code must retain the above copyright
44: * notice, this list of conditions and the following disclaimer.
45: * 2. Redistributions in binary form must reproduce the above copyright
46: * notice, this list of conditions and the following disclaimer in the
47: * documentation and/or other materials provided with the distribution.
1.68 millert 48: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: */
64:
1.59 espie 65: #include <assert.h>
1.61 espie 66: #include <ctype.h>
1.1 deraadt 67: #include <stdio.h>
1.62 espie 68: #include <stdlib.h>
1.61 espie 69: #include <string.h>
70: #include "config.h"
71: #include "defines.h"
1.1 deraadt 72: #include "dir.h"
1.81 espie 73: #include "direxpand.h"
1.1 deraadt 74: #include "job.h"
75: #include "buf.h"
1.61 espie 76: #include "for.h"
1.50 espie 77: #include "lowparse.h"
1.61 espie 78: #include "arch.h"
79: #include "cond.h"
80: #include "suff.h"
81: #include "parse.h"
82: #include "var.h"
83: #include "targ.h"
84: #include "error.h"
85: #include "str.h"
86: #include "main.h"
87: #include "gnode.h"
88: #include "memory.h"
89: #include "extern.h"
90: #include "lst.h"
91: #include "parsevar.h"
1.63 espie 92: #include "stats.h"
93: #include "garray.h"
94:
95:
96: static struct growableArray gsources, gtargets;
97: #define SOURCES_SIZE 128
98: #define TARGETS_SIZE 32
1.61 espie 99:
100: static LIST theParseIncPath;/* list of directories for "..." includes */
101: static LIST theSysIncPath; /* list of directories for <...> includes */
102: Lst sysIncPath = &theSysIncPath;
103: Lst parseIncPath = &theParseIncPath;
1.59 espie 104:
1.20 espie 105: #ifdef CLEANUP
1.59 espie 106: static LIST targCmds; /* command lines for targets */
1.20 espie 107: #endif
1.59 espie 108:
1.1 deraadt 109: static GNode *mainNode; /* The main target to create. This is the
110: * first target on the first dependency
111: * line in the first makefile */
112: /*-
113: * specType contains the SPECial TYPE of the current target. It is
114: * Not if the target is unspecial. If it *is* special, however, the children
115: * are linked as children of the parent but not vice versa. This variable is
116: * set in ParseDoDependency
117: */
118: typedef enum {
1.59 espie 119: Begin, /* .BEGIN */
1.1 deraadt 120: Default, /* .DEFAULT */
1.59 espie 121: End, /* .END */
1.1 deraadt 122: Ignore, /* .IGNORE */
123: Includes, /* .INCLUDES */
124: Interrupt, /* .INTERRUPT */
125: Libs, /* .LIBS */
126: MFlags, /* .MFLAGS or .MAKEFLAGS */
127: Main, /* .MAIN and we don't have anything user-specified to
128: * make */
129: NoExport, /* .NOEXPORT */
1.17 espie 130: NoPath, /* .NOPATH */
1.1 deraadt 131: Not, /* Not special */
132: NotParallel, /* .NOTPARALELL */
1.59 espie 133: Null, /* .NULL */
134: Order, /* .ORDER */
1.3 deraadt 135: Parallel, /* .PARALLEL */
1.1 deraadt 136: ExPath, /* .PATH */
1.7 niklas 137: Phony, /* .PHONY */
1.1 deraadt 138: Precious, /* .PRECIOUS */
139: Silent, /* .SILENT */
140: SingleShell, /* .SINGLESHELL */
141: Suffixes, /* .SUFFIXES */
1.3 deraadt 142: Wait, /* .WAIT */
1.1 deraadt 143: Attribute /* Generic attribute */
144: } ParseSpecial;
145:
146: static ParseSpecial specType;
1.3 deraadt 147: static int waiting;
1.1 deraadt 148:
149: /*
1.33 espie 150: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 deraadt 151: * seen, then set to each successive source on the line.
152: */
153: static GNode *predecessor;
154:
155: /*
156: * The parseKeywords table is searched using binary search when deciding
157: * if a target or source is special. The 'spec' field is the ParseSpecial
158: * type of the keyword ("Not" if the keyword isn't special as a target) while
159: * the 'op' field is the operator to apply to the list of targets if the
160: * keyword is used as a source ("0" if the keyword isn't special as a source)
161: */
162: static struct {
1.59 espie 163: char *name; /* Name of keyword */
164: ParseSpecial spec; /* Type when used as a target */
165: int op; /* Operator when used as a source */
1.1 deraadt 166: } parseKeywords[] = {
1.59 espie 167: { ".BEGIN", Begin, 0 },
168: { ".DEFAULT", Default, 0 },
169: { ".END", End, 0 },
170: { ".EXEC", Attribute, OP_EXEC },
171: { ".IGNORE", Ignore, OP_IGNORE },
172: { ".INCLUDES", Includes, 0 },
173: { ".INTERRUPT", Interrupt, 0 },
174: { ".INVISIBLE", Attribute, OP_INVISIBLE },
175: { ".JOIN", Attribute, OP_JOIN },
176: { ".LIBS", Libs, 0 },
1.13 millert 177: { ".MADE", Attribute, OP_MADE },
1.59 espie 178: { ".MAIN", Main, 0 },
179: { ".MAKE", Attribute, OP_MAKE },
180: { ".MAKEFLAGS", MFlags, 0 },
181: { ".MFLAGS", MFlags, 0 },
1.17 espie 182: #if 0 /* basic scaffolding for NOPATH, not working yet */
183: { ".NOPATH", NoPath, OP_NOPATH },
184: #endif
1.59 espie 185: { ".NOTMAIN", Attribute, OP_NOTMAIN },
1.1 deraadt 186: { ".NOTPARALLEL", NotParallel, 0 },
1.3 deraadt 187: { ".NO_PARALLEL", NotParallel, 0 },
1.59 espie 188: { ".NULL", Null, 0 },
189: { ".OPTIONAL", Attribute, OP_OPTIONAL },
190: { ".ORDER", Order, 0 },
1.3 deraadt 191: { ".PARALLEL", Parallel, 0 },
1.1 deraadt 192: { ".PATH", ExPath, 0 },
1.7 niklas 193: { ".PHONY", Phony, OP_PHONY },
1.59 espie 194: { ".PRECIOUS", Precious, OP_PRECIOUS },
195: { ".RECURSIVE", Attribute, OP_MAKE },
196: { ".SILENT", Silent, OP_SILENT },
1.1 deraadt 197: { ".SINGLESHELL", SingleShell, 0 },
1.59 espie 198: { ".SUFFIXES", Suffixes, 0 },
199: { ".USE", Attribute, OP_USE },
1.3 deraadt 200: { ".WAIT", Wait, 0 },
1.1 deraadt 201: };
202:
1.59 espie 203: static int ParseFindKeyword(const char *);
204: static void ParseLinkSrc(GNode *, GNode *);
1.63 espie 205: static int ParseDoOp(GNode *, int);
206: static int ParseAddDep(GNode *, GNode *);
207: static void ParseDoSrc(int, const char *);
1.59 espie 208: static int ParseFindMain(void *, void *);
209: static void ParseAddDir(void *, void *);
210: static void ParseClearPath(void *);
1.77 espie 211:
212: static void add_target_node(const char *);
213: static void add_target_nodes(const char *);
1.59 espie 214: static void ParseDoDependency(char *);
215: static void ParseAddCmd(void *, void *);
216: static void ParseHasCommands(void *);
1.79 espie 217: static bool handle_poison(const char *);
218: static bool handle_for_loop(Buffer, const char *);
219: static bool handle_undef(const char *);
1.61 espie 220: #define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop")
1.59 espie 221: static void ParseFinishDependency(void);
1.79 espie 222: static bool handle_bsd_command(Buffer, Buffer, const char *);
1.59 espie 223: static char *strip_comments(Buffer, const char *);
1.79 espie 224: static char *resolve_include_filename(const char *, bool);
225: static void handle_include_file(const char *, const char *, bool, bool);
226: static bool lookup_bsd_include(const char *);
227: static void lookup_sysv_style_include(const char *, const char *, bool);
228: static void lookup_sysv_include(const char *, const char *);
229: static void lookup_conditional_include(const char *, const char *);
1.59 espie 230:
231: static void ParseDoCommands(const char *);
1.1 deraadt 232:
233: /*-
234: *----------------------------------------------------------------------
235: * ParseFindKeyword --
236: * Look in the table of keywords for one matching the given string.
237: *
238: * Results:
239: * The index of the keyword, or -1 if it isn't there.
240: *----------------------------------------------------------------------
241: */
242: static int
1.69 espie 243: ParseFindKeyword(const char *str) /* keyword to look up */
1.1 deraadt 244: {
1.59 espie 245: int start,
1.1 deraadt 246: end,
247: cur;
1.59 espie 248: int diff;
1.11 millert 249:
1.1 deraadt 250: start = 0;
251: end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
252:
253: do {
1.59 espie 254: cur = start + (end - start) / 2;
255: diff = strcmp(str, parseKeywords[cur].name);
1.1 deraadt 256:
257: if (diff == 0) {
1.59 espie 258: return cur;
1.1 deraadt 259: } else if (diff < 0) {
260: end = cur - 1;
261: } else {
262: start = cur + 1;
263: }
264: } while (start <= end);
1.59 espie 265: return -1;
1.1 deraadt 266: }
267: /*-
268: *---------------------------------------------------------------------
269: * ParseLinkSrc --
1.59 espie 270: * Link the parent node to its new child. Used by
1.1 deraadt 271: * ParseDoDependency. If the specType isn't 'Not', the parent
272: * isn't linked as a parent of the child.
273: *
274: * Side Effects:
275: * New elements are added to the parents list of cgn and the
276: * children list of cgn. the unmade field of pgn is updated
277: * to reflect the additional child.
278: *---------------------------------------------------------------------
279: */
1.41 espie 280: static void
1.69 espie 281: ParseLinkSrc(
282: GNode *pgn, /* The parent node */
283: GNode *cgn) /* The child node */
1.59 espie 284: {
1.86 espie 285: if (Lst_AddNew(&pgn->children, cgn)) {
286: if (specType == Not)
287: Lst_AtEnd(&cgn->parents, pgn);
288: pgn->unmade++;
289: }
1.1 deraadt 290: }
291:
292: /*-
293: *---------------------------------------------------------------------
294: * ParseDoOp --
295: * Apply the parsed operator to the given target node. Used in a
1.41 espie 296: * Lst_Find call by ParseDoDependency once all targets have
1.1 deraadt 297: * been found and their operator parsed. If the previous and new
298: * operators are incompatible, a major error is taken.
299: *
300: * Side Effects:
301: * The type field of the node is altered to reflect any new bits in
302: * the op.
303: *---------------------------------------------------------------------
304: */
305: static int
1.69 espie 306: ParseDoOp(
307: GNode *gn, /* The node to which the operator is to be applied */
308: int op) /* The operator to apply */
1.1 deraadt 309: {
1.86 espie 310: /*
311: * If the dependency mask of the operator and the node don't match and
312: * the node has actually had an operator applied to it before, and
313: * the operator actually has some dependency information in it, complain.
314: */
315: if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
316: !OP_NOP(gn->type) && !OP_NOP(op)) {
317: Parse_Error(PARSE_FATAL,
318: "Inconsistent operator for %s", gn->name);
319: return 0;
320: }
321:
322: if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
323: /* If the node was the object of a :: operator, we need to
324: * create a new instance of it for the children and commands on
325: * this dependency line. The new instance is placed on the
326: * 'cohorts' list of the initial one (note the initial one is
327: * not on its own cohorts list) and the new instance is linked
328: * to all parents of the initial instance. */
329: GNode *cohort;
330: LstNode ln;
331: unsigned int i;
332:
333: cohort = Targ_NewGN(gn->name);
334: /* Duplicate links to parents so graph traversal is simple.
335: * Perhaps some type bits should be duplicated?
336: *
337: * Make the cohort invisible as well to avoid duplicating it
338: * into other variables. True, parents of this target won't
339: * tend to do anything with their local variables, but better
340: * safe than sorry. */
341: for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln))
342: ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
343: cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
344: Lst_AtEnd(&gn->cohorts, cohort);
345:
346: /* Replace the node in the targets list with the new copy */
347: for (i = 0; i < gtargets.n; i++)
348: if (gtargets.a[i] == gn)
349: break;
350: gtargets.a[i] = cohort;
351: gn = cohort;
352: }
353: /* We don't want to nuke any previous flags (whatever they were) so we
354: * just OR the new operator into the old. */
355: gn->type |= op;
356: return 1;
1.1 deraadt 357: }
358:
1.11 millert 359: /*-
1.3 deraadt 360: *---------------------------------------------------------------------
1.59 espie 361: * ParseAddDep --
1.3 deraadt 362: * Check if the pair of GNodes given needs to be synchronized.
363: * This has to be when two nodes are on different sides of a
364: * .WAIT directive.
365: *
366: * Results:
1.40 espie 367: * Returns 0 if the two targets need to be ordered, 1 otherwise.
1.59 espie 368: * If it returns 0, the search can stop.
1.3 deraadt 369: *
370: * Side Effects:
371: * A dependency can be added between the two nodes.
1.11 millert 372: *
1.3 deraadt 373: *---------------------------------------------------------------------
374: */
1.13 millert 375: static int
1.69 espie 376: ParseAddDep(GNode *p, GNode *s)
1.3 deraadt 377: {
1.86 espie 378: if (p->order < s->order) {
379: /* XXX: This can cause loops, and loops can cause unmade
380: * targets, but checking is tedious, and the debugging output
381: * can show the problem. */
382: Lst_AtEnd(&p->successors, s);
383: Lst_AtEnd(&s->preds, p);
384: return 1;
385: }
386: else
387: return 0;
1.3 deraadt 388: }
389:
390:
1.1 deraadt 391: /*-
392: *---------------------------------------------------------------------
393: * ParseDoSrc --
394: * Given the name of a source, figure out if it is an attribute
395: * and apply it to the targets if it is. Else decide if there is
396: * some attribute which should be applied *to* the source because
397: * of some special target and apply it if so. Otherwise, make the
398: * source be a child of the targets in the list 'targets'
399: *
400: * Side Effects:
401: * Operator bits may be added to the list of targets or to the source.
402: * The targets may have a new source added to their lists of children.
403: *---------------------------------------------------------------------
404: */
405: static void
1.69 espie 406: ParseDoSrc(
407: int tOp, /* operator (if any) from special targets */
408: const char *src) /* name of the source to handle */
1.1 deraadt 409: {
1.86 espie 410: GNode *gn = NULL;
1.1 deraadt 411:
1.86 espie 412: if (*src == '.' && isupper(src[1])) {
413: int keywd = ParseFindKeyword(src);
414: if (keywd != -1) {
415: int op = parseKeywords[keywd].op;
416: if (op != 0) {
417: Array_Find(>argets, ParseDoOp, op);
418: return;
419: }
420: if (parseKeywords[keywd].spec == Wait) {
421: waiting++;
422: return;
423: }
424: }
1.1 deraadt 425: }
1.3 deraadt 426:
1.86 espie 427: switch (specType) {
428: case Main:
429: /*
430: * If we have noted the existence of a .MAIN, it means we need
431: * to add the sources of said target to the list of things
432: * to create. The string 'src' is likely to be freed, so we
433: * must make a new copy of it. Note that this will only be
434: * invoked if the user didn't specify a target on the command
435: * line. This is to allow #ifmake's to succeed, or something...
436: */
437: Lst_AtEnd(create, estrdup(src));
438: /*
439: * Add the name to the .TARGETS variable as well, so the user
440: * can employ that, if desired.
441: */
442: Var_Append(".TARGETS", src);
443: return;
1.3 deraadt 444:
1.86 espie 445: case Order:
446: /*
447: * Create proper predecessor/successor links between the
448: * previous source and the current one.
449: */
450: gn = Targ_FindNode(src, TARG_CREATE);
451: if (predecessor != NULL) {
452: Lst_AtEnd(&predecessor->successors, gn);
453: Lst_AtEnd(&gn->preds, predecessor);
454: }
455: /*
456: * The current source now becomes the predecessor for the next
457: * one.
458: */
459: predecessor = gn;
460: break;
1.3 deraadt 461:
1.86 espie 462: default:
463: /*
464: * If the source is not an attribute, we need to find/create
465: * a node for it. After that we can apply any operator to it
466: * from a special target or link it to its parents, as
467: * appropriate.
468: *
469: * In the case of a source that was the object of a :: operator,
470: * the attribute is applied to all of its instances (as kept in
471: * the 'cohorts' list of the node) or all the cohorts are linked
472: * to all the targets.
473: */
474: gn = Targ_FindNode(src, TARG_CREATE);
1.1 deraadt 475: if (tOp) {
1.86 espie 476: gn->type |= tOp;
1.1 deraadt 477: } else {
1.86 espie 478: Array_ForEach(>argets, ParseLinkSrc, gn);
479: }
480: if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
481: GNode *cohort;
482: LstNode ln;
483:
484: for (ln=Lst_First(&gn->cohorts); ln != NULL;
485: ln = Lst_Adv(ln)){
486: cohort = (GNode *)Lst_Datum(ln);
487: if (tOp) {
488: cohort->type |= tOp;
489: } else {
490: Array_ForEach(>argets, ParseLinkSrc,
491: cohort);
492: }
493: }
1.1 deraadt 494: }
1.86 espie 495: break;
1.1 deraadt 496: }
1.3 deraadt 497:
1.86 espie 498: gn->order = waiting;
499: Array_AtEnd(&gsources, gn);
500: if (waiting) {
501: Array_Find(&gsources, ParseAddDep, gn);
502: }
1.1 deraadt 503: }
504:
505: /*-
506: *-----------------------------------------------------------------------
507: * ParseFindMain --
508: * Find a real target in the list and set it to be the main one.
509: * Called by ParseDoDependency when a main target hasn't been found
510: * yet.
511: *
512: * Results:
1.40 espie 513: * 1 if main not found yet, 0 if it is.
1.1 deraadt 514: *
515: * Side Effects:
516: * mainNode is changed and Targ_SetMain is called.
517: *-----------------------------------------------------------------------
518: */
519: static int
1.69 espie 520: ParseFindMain(
521: void *gnp, /* Node to examine */
522: void *dummy UNUSED)
1.1 deraadt 523: {
1.86 espie 524: GNode *gn = (GNode *)gnp;
525: if ((gn->type & OP_NOTARGET) == 0) {
526: mainNode = gn;
527: Targ_SetMain(gn);
528: return 0;
529: } else {
530: return 1;
531: }
1.1 deraadt 532: }
533:
534: /*-
535: *-----------------------------------------------------------------------
536: * ParseAddDir --
537: * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
538: *
539: * Side Effects:
540: * See Dir_AddDir.
541: *-----------------------------------------------------------------------
542: */
1.41 espie 543: static void
1.69 espie 544: ParseAddDir(void *path, void *name)
1.1 deraadt 545: {
1.86 espie 546: Dir_AddDir((Lst)path, (char *)name);
1.1 deraadt 547: }
548:
549: /*-
550: *-----------------------------------------------------------------------
551: * ParseClearPath --
1.59 espie 552: * Reinit path to an empty path
1.1 deraadt 553: *-----------------------------------------------------------------------
554: */
1.41 espie 555: static void
1.69 espie 556: ParseClearPath(void *p)
1.1 deraadt 557: {
1.86 espie 558: Lst path = (Lst)p;
1.59 espie 559:
1.86 espie 560: Lst_Destroy(path, Dir_Destroy);
561: Lst_Init(path);
1.1 deraadt 562: }
563:
1.77 espie 564: static void
565: add_target_node(const char *line)
566: {
567: GNode *gn;
568:
569: if (!Suff_IsTransform(line))
570: gn = Targ_FindNode(line, TARG_CREATE);
571: else
572: gn = Suff_AddTransform(line);
573:
574: if (gn != NULL)
575: Array_AtEnd(>argets, gn);
576: }
577:
578: static void
579: add_target_nodes(const char *line)
580: {
581:
582: if (Dir_HasWildcards(line)) {
583: /*
584: * Targets are to be sought only in the current directory,
585: * so create an empty path for the thing. Note we need to
586: * use Dir_Destroy in the destruction of the path as the
587: * Dir module could have added a directory to the path...
588: */
589: char *targName;
590: LIST emptyPath;
591: LIST curTargs;
592:
593: Lst_Init(&emptyPath);
594: Lst_Init(&curTargs);
595: Dir_Expand(line, &emptyPath, &curTargs);
596: Lst_Destroy(&emptyPath, Dir_Destroy);
597: while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) {
1.80 espie 598: add_target_node(targName);
1.77 espie 599: }
600: Lst_Destroy(&curTargs, NOFREE);
601: } else {
602: add_target_node(line);
603: }
604: }
605:
1.1 deraadt 606: /*-
607: *---------------------------------------------------------------------
608: * ParseDoDependency --
609: * Parse the dependency line in line.
610: *
611: * Side Effects:
612: * The nodes of the sources are linked as children to the nodes of the
613: * targets. Some nodes may be created.
614: *
615: * We parse a dependency line by first extracting words from the line and
616: * finding nodes in the list of all targets with that name. This is done
617: * until a character is encountered which is an operator character. Currently
618: * these are only ! and :. At this point the operator is parsed and the
619: * pointer into the line advanced until the first source is encountered.
1.59 espie 620: * The parsed operator is applied to each node in the 'targets' list,
1.1 deraadt 621: * which is where the nodes found for the targets are kept, by means of
622: * the ParseDoOp function.
623: * The sources are read in much the same way as the targets were except
624: * that now they are expanded using the wildcarding scheme of the C-Shell
625: * and all instances of the resulting words in the list of all targets
626: * are found. Each of the resulting nodes is then linked to each of the
627: * targets as one of its children.
628: * Certain targets are handled specially. These are the ones detailed
629: * by the specType variable.
630: * The storing of transformation rules is also taken care of here.
631: * A target is recognized as a transformation rule by calling
632: * Suff_IsTransform. If it is a transformation rule, its node is gotten
633: * from the suffix module via Suff_AddTransform rather than the standard
634: * Targ_FindNode in the target module.
635: *---------------------------------------------------------------------
636: */
637: static void
1.69 espie 638: ParseDoDependency(char *line) /* the line to parse */
1.1 deraadt 639: {
1.59 espie 640: char *cp; /* our current position */
641: GNode *gn; /* a general purpose temporary node */
642: int op; /* the operator on the line */
643: char savec; /* a place to save a character */
644: LIST paths; /* List of search paths to alter when parsing
1.1 deraadt 645: * a list of .PATH targets */
1.59 espie 646: int tOp; /* operator from special target */
1.1 deraadt 647: tOp = 0;
648:
649: specType = Not;
1.3 deraadt 650: waiting = 0;
1.45 espie 651: Lst_Init(&paths);
1.1 deraadt 652:
1.63 espie 653: Array_Reset(&gsources);
1.11 millert 654:
1.1 deraadt 655: do {
1.59 espie 656: for (cp = line; *cp && !isspace(*cp) && *cp != '(';)
657: if (*cp == '$')
658: /* Must be a dynamic source (would have been expanded
1.1 deraadt 659: * otherwise), so call the Var module to parse the puppy
660: * so we can safely advance beyond it...There should be
661: * no errors in this, as they would have been discovered
1.59 espie 662: * in the initial Var_Subst and we wouldn't be here. */
1.74 espie 663: Var_ParseSkip(&cp, NULL);
1.59 espie 664: else {
665: /* We don't want to end a word on ':' or '!' if there is a
666: * better match later on in the string. By "better" I mean
667: * one that is followed by whitespace. This allows the user
668: * to have targets like:
669: * fie::fi:fo: fum
670: * where "fie::fi:fo" is the target. In real life this is used
671: * for perl5 library man pages where "::" separates an object
672: * from its class. Ie: "File::Spec::Unix". This behaviour
673: * is also consistent with other versions of make. */
674: if (*cp == '!' || *cp == ':') {
675: char *p = cp + 1;
676:
677: if (*cp == ':' && *p == ':')
678: p++;
679:
680: /* Found the best match already. */
681: if (isspace(*p) || *p == '\0')
682: break;
683:
684: do {
685: p += strcspn(p, "!:");
686: if (*p == '\0')
687: break;
688: p++;
689: } while (!isspace(*p));
1.1 deraadt 690:
1.59 espie 691: /* No better match later on... */
692: if (*p == '\0')
693: break;
1.1 deraadt 694:
695: }
1.59 espie 696: cp++;
1.1 deraadt 697: }
698: if (*cp == '(') {
1.63 espie 699: LIST temp;
700: Lst_Init(&temp);
1.59 espie 701: /* Archives must be handled specially to make sure the OP_ARCHV
1.1 deraadt 702: * flag is set in their 'type' field, for one thing, and because
703: * things like "archive(file1.o file2.o file3.o)" are permissible.
704: * Arch_ParseArchive will set 'line' to be the first non-blank
705: * after the archive-spec. It creates/finds nodes for the members
1.61 espie 706: * and places them on the given list, returning true if all
707: * went well and false if there was an error in the
1.59 espie 708: * specification. On error, line should remain untouched. */
1.63 espie 709: if (!Arch_ParseArchive(&line, &temp, NULL)) {
1.59 espie 710: Parse_Error(PARSE_FATAL,
1.1 deraadt 711: "Error in archive specification: \"%s\"", line);
712: return;
713: } else {
1.63 espie 714: AppendList2Array(&temp, >argets);
715: Lst_Destroy(&temp, NOFREE);
1.1 deraadt 716: continue;
717: }
718: }
719: savec = *cp;
1.11 millert 720:
1.59 espie 721: if (*cp == '\0') {
722: /* Ending a dependency line without an operator is a Bozo no-no */
723: Parse_Error(PARSE_FATAL, "Need an operator");
1.1 deraadt 724: return;
725: }
726: *cp = '\0';
1.59 espie 727: /* Have a word in line. See if it's a special target and set
728: * specType to match it. */
729: if (*line == '.' && isupper(line[1])) {
730: /* See if the target is a special target that must have it
731: * or its sources handled specially. */
1.1 deraadt 732: int keywd = ParseFindKeyword(line);
733: if (keywd != -1) {
734: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
735: Parse_Error(PARSE_FATAL, "Mismatched special targets");
736: return;
737: }
1.11 millert 738:
1.1 deraadt 739: specType = parseKeywords[keywd].spec;
740: tOp = parseKeywords[keywd].op;
741:
742: /*
743: * Certain special targets have special semantics:
1.83 espie 744: * .PATH Have to set the defaultPath
1.1 deraadt 745: * variable too
746: * .MAIN Its sources are only used if
747: * nothing has been specified to
748: * create.
1.59 espie 749: * .DEFAULT Need to create a node to hang
1.1 deraadt 750: * commands on, but we don't want
751: * it in the graph, nor do we want
752: * it to be the Main Target, so we
753: * create it, set OP_NOTMAIN and
754: * add it to the list, setting
755: * DEFAULT to the new node for
756: * later use. We claim the node is
1.59 espie 757: * A transformation rule to make
758: * life easier later, when we'll
759: * use Make_HandleUse to actually
760: * apply the .DEFAULT commands.
1.7 niklas 761: * .PHONY The list of targets
1.59 espie 762: * .NOPATH Don't search for file in the path
1.1 deraadt 763: * .BEGIN
764: * .END
1.59 espie 765: * .INTERRUPT Are not to be considered the
1.1 deraadt 766: * main target.
1.59 espie 767: * .NOTPARALLEL Make only one target at a time.
768: * .SINGLESHELL Create a shell for each command.
769: * .ORDER Must set initial predecessor to NULL
1.1 deraadt 770: */
771: switch (specType) {
772: case ExPath:
1.83 espie 773: Lst_AtEnd(&paths, defaultPath);
1.1 deraadt 774: break;
775: case Main:
1.61 espie 776: if (!Lst_IsEmpty(create)) {
1.1 deraadt 777: specType = Not;
778: }
779: break;
780: case Begin:
781: case End:
782: case Interrupt:
1.61 espie 783: gn = Targ_FindNode(line, TARG_CREATE);
1.1 deraadt 784: gn->type |= OP_NOTMAIN;
1.63 espie 785: Array_AtEnd(>argets, gn);
1.1 deraadt 786: break;
787: case Default:
1.61 espie 788: gn = Targ_NewGN(".DEFAULT");
1.59 espie 789: gn->type |= OP_NOTMAIN|OP_TRANSFORM;
1.63 espie 790: Array_AtEnd(>argets, gn);
1.1 deraadt 791: DEFAULT = gn;
792: break;
793: case NotParallel:
794: {
795: extern int maxJobs;
1.11 millert 796:
1.1 deraadt 797: maxJobs = 1;
798: break;
799: }
800: case SingleShell:
801: compatMake = 1;
802: break;
803: case Order:
1.33 espie 804: predecessor = NULL;
1.1 deraadt 805: break;
806: default:
807: break;
808: }
1.59 espie 809: } else if (strncmp(line, ".PATH", 5) == 0) {
1.1 deraadt 810: /*
811: * .PATH<suffix> has to be handled specially.
812: * Call on the suffix module to give us a path to
813: * modify.
814: */
1.59 espie 815: Lst path;
1.11 millert 816:
1.1 deraadt 817: specType = ExPath;
1.45 espie 818: path = Suff_GetPath(&line[5]);
1.33 espie 819: if (path == NULL) {
1.45 espie 820: Parse_Error(PARSE_FATAL,
1.1 deraadt 821: "Suffix '%s' not defined (yet)",
822: &line[5]);
823: return;
1.59 espie 824: } else {
1.45 espie 825: Lst_AtEnd(&paths, path);
1.59 espie 826: }
1.1 deraadt 827: }
828: }
1.11 millert 829:
1.1 deraadt 830: /*
831: * Have word in line. Get or create its node and stick it at
1.11 millert 832: * the end of the targets list
1.1 deraadt 833: */
1.59 espie 834: if (specType == Not && *line != '\0') {
1.77 espie 835: add_target_nodes(line);
1.63 espie 836: } else if (specType == ExPath && *line != '.' && *line != '\0')
1.1 deraadt 837: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1.11 millert 838:
1.1 deraadt 839: *cp = savec;
840: /*
841: * If it is a special type and not .PATH, it's the only target we
842: * allow on this line...
843: */
844: if (specType != Not && specType != ExPath) {
1.61 espie 845: bool warn = false;
1.11 millert 846:
1.59 espie 847: while (*cp != '!' && *cp != ':' && *cp) {
1.1 deraadt 848: if (*cp != ' ' && *cp != '\t') {
1.61 espie 849: warn = true;
1.1 deraadt 850: }
851: cp++;
852: }
853: if (warn) {
854: Parse_Error(PARSE_WARNING, "Extra target ignored");
855: }
856: } else {
1.71 tedu 857: while (isspace(*cp)) {
1.1 deraadt 858: cp++;
859: }
860: }
861: line = cp;
1.59 espie 862: } while (*line != '!' && *line != ':' && *line);
1.1 deraadt 863:
1.63 espie 864: if (!Array_IsEmpty(>argets)) {
1.59 espie 865: switch (specType) {
1.1 deraadt 866: default:
867: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
868: break;
869: case Default:
870: case Begin:
871: case End:
872: case Interrupt:
1.59 espie 873: /* These four create nodes on which to hang commands, so
874: * targets shouldn't be empty... */
1.1 deraadt 875: case Not:
1.59 espie 876: /* Nothing special here -- targets can be empty if it wants. */
1.1 deraadt 877: break;
878: }
879: }
880:
1.59 espie 881: /* Have now parsed all the target names. Must parse the operator next. The
882: * result is left in op . */
1.1 deraadt 883: if (*cp == '!') {
884: op = OP_FORCE;
885: } else if (*cp == ':') {
886: if (cp[1] == ':') {
887: op = OP_DOUBLEDEP;
888: cp++;
889: } else {
890: op = OP_DEPENDS;
891: }
892: } else {
1.59 espie 893: Parse_Error(PARSE_FATAL, "Missing dependency operator");
1.1 deraadt 894: return;
895: }
896:
897: cp++; /* Advance beyond operator */
898:
1.63 espie 899: Array_Find(>argets, ParseDoOp, op);
1.1 deraadt 900:
901: /*
1.11 millert 902: * Get to the first source
1.1 deraadt 903: */
1.71 tedu 904: while (isspace(*cp)) {
1.1 deraadt 905: cp++;
906: }
907: line = cp;
908:
909: /*
910: * Several special targets take different actions if present with no
911: * sources:
912: * a .SUFFIXES line with no sources clears out all old suffixes
913: * a .PRECIOUS line makes all targets precious
914: * a .IGNORE line ignores errors for all targets
915: * a .SILENT line creates silence when making all targets
916: * a .PATH removes all directories from the search path(s).
917: */
918: if (!*line) {
919: switch (specType) {
920: case Suffixes:
1.59 espie 921: Suff_ClearSuffixes();
1.1 deraadt 922: break;
923: case Precious:
1.61 espie 924: allPrecious = true;
1.1 deraadt 925: break;
926: case Ignore:
1.61 espie 927: ignoreErrors = true;
1.1 deraadt 928: break;
929: case Silent:
1.61 espie 930: beSilent = true;
1.1 deraadt 931: break;
932: case ExPath:
1.45 espie 933: Lst_Every(&paths, ParseClearPath);
1.1 deraadt 934: break;
935: default:
936: break;
937: }
938: } else if (specType == MFlags) {
939: /*
940: * Call on functions in main.c to deal with these arguments and
941: * set the initial character to a null-character so the loop to
942: * get sources won't get anything
943: */
1.59 espie 944: Main_ParseArgLine(line);
1.1 deraadt 945: *line = '\0';
1.59 espie 946: } else if (specType == NotParallel || specType == SingleShell) {
1.1 deraadt 947: *line = '\0';
948: }
1.11 millert 949:
1.1 deraadt 950: /*
1.11 millert 951: * NOW GO FOR THE SOURCES
1.1 deraadt 952: */
1.59 espie 953: if (specType == Suffixes || specType == ExPath ||
954: specType == Includes || specType == Libs ||
955: specType == Null) {
1.1 deraadt 956: while (*line) {
957: /*
958: * If the target was one that doesn't take files as its sources
959: * but takes something like suffixes, we take each
960: * space-separated word on the line as a something and deal
961: * with it accordingly.
962: *
963: * If the target was .SUFFIXES, we take each source as a
964: * suffix and add it to the list of suffixes maintained by the
965: * Suff module.
966: *
967: * If the target was a .PATH, we add the source as a directory
968: * to search on the search path.
969: *
970: * If it was .INCLUDES, the source is taken to be the suffix of
971: * files which will be #included and whose search path should
972: * be present in the .INCLUDES variable.
973: *
974: * If it was .LIBS, the source is taken to be the suffix of
975: * files which are considered libraries and whose search path
976: * should be present in the .LIBS variable.
977: *
978: * If it was .NULL, the source is the suffix to use when a file
979: * has no valid suffix.
980: */
981: char savec;
1.59 espie 982: while (*cp && !isspace(*cp)) {
1.1 deraadt 983: cp++;
984: }
985: savec = *cp;
986: *cp = '\0';
987: switch (specType) {
988: case Suffixes:
1.59 espie 989: Suff_AddSuffix(line);
1.1 deraadt 990: break;
991: case ExPath:
1.45 espie 992: Lst_ForEach(&paths, ParseAddDir, line);
1.1 deraadt 993: break;
994: case Includes:
1.59 espie 995: Suff_AddInclude(line);
1.1 deraadt 996: break;
997: case Libs:
1.59 espie 998: Suff_AddLib(line);
1.1 deraadt 999: break;
1000: case Null:
1.59 espie 1001: Suff_SetNull(line);
1.1 deraadt 1002: break;
1003: default:
1004: break;
1005: }
1006: *cp = savec;
1007: if (savec != '\0') {
1008: cp++;
1009: }
1.71 tedu 1010: while (isspace(*cp)) {
1.1 deraadt 1011: cp++;
1012: }
1013: line = cp;
1014: }
1.45 espie 1015: Lst_Destroy(&paths, NOFREE);
1.1 deraadt 1016: } else {
1017: while (*line) {
1018: /*
1019: * The targets take real sources, so we must beware of archive
1020: * specifications (i.e. things with left parentheses in them)
1021: * and handle them accordingly.
1022: */
1.59 espie 1023: while (*cp && !isspace(*cp)) {
1024: if (*cp == '(' && cp > line && cp[-1] != '$') {
1.1 deraadt 1025: /*
1026: * Only stop for a left parenthesis if it isn't at the
1027: * start of a word (that'll be for variable changes
1028: * later) and isn't preceded by a dollar sign (a dynamic
1029: * source).
1030: */
1031: break;
1032: } else {
1033: cp++;
1034: }
1035: }
1036:
1037: if (*cp == '(') {
1038: GNode *gn;
1.59 espie 1039: LIST sources; /* list of archive source names after
1040: * expansion */
1.1 deraadt 1041:
1.43 espie 1042: Lst_Init(&sources);
1.61 espie 1043: if (!Arch_ParseArchive(&line, &sources, NULL)) {
1.59 espie 1044: Parse_Error(PARSE_FATAL,
1.1 deraadt 1045: "Error in source archive spec \"%s\"", line);
1046: return;
1047: }
1048:
1.43 espie 1049: while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL)
1.63 espie 1050: ParseDoSrc(tOp, gn->name);
1.1 deraadt 1051: cp = line;
1052: } else {
1053: if (*cp) {
1054: *cp = '\0';
1.84 espie 1055: cp++;
1.1 deraadt 1056: }
1057:
1.63 espie 1058: ParseDoSrc(tOp, line);
1.1 deraadt 1059: }
1.71 tedu 1060: while (isspace(*cp)) {
1.1 deraadt 1061: cp++;
1062: }
1063: line = cp;
1064: }
1065: }
1.11 millert 1066:
1.33 espie 1067: if (mainNode == NULL) {
1.59 espie 1068: /* If we have yet to decide on a main target to make, in the
1.1 deraadt 1069: * absence of any user input, we want the first target on
1070: * the first dependency line that is actually a real target
1.59 espie 1071: * (i.e. isn't a .USE or .EXEC rule) to be made. */
1.63 espie 1072: Array_Find(>argets, ParseFindMain, NULL);
1.1 deraadt 1073: }
1074:
1.43 espie 1075: /* Finally, destroy the list of sources. */
1.1 deraadt 1076: }
1077:
1078: /*-
1.59 espie 1079: * ParseAddCmd --
1.1 deraadt 1080: * Lst_ForEach function to add a command line to all targets
1081: *
1082: * Side Effects:
1083: * A new element is added to the commands list of the node.
1084: */
1.41 espie 1085: static void
1.69 espie 1086: ParseAddCmd(
1087: void *gnp, /* the node to which the command is to be added */
1088: void *cmd) /* the command to add */
1.1 deraadt 1089: {
1.86 espie 1090: GNode *gn = (GNode *)gnp;
1091: /* if target already supplied, ignore commands */
1092: if (!(gn->type & OP_HAS_COMMANDS)) {
1093: Lst_AtEnd(&gn->commands, cmd);
1094: if (!gn->lineno) {
1095: gn->lineno = Parse_Getlineno();
1096: gn->fname = Parse_Getfilename();
1097: }
1.39 espie 1098: }
1.1 deraadt 1099: }
1100:
1101: /*-
1102: *-----------------------------------------------------------------------
1103: * ParseHasCommands --
1104: * Callback procedure for Parse_File when destroying the list of
1105: * targets on the last dependency line. Marks a target as already
1106: * having commands if it does, to keep from having shell commands
1107: * on multiple dependency lines.
1108: *
1109: * Side Effects:
1110: * OP_HAS_COMMANDS may be set for the target.
1111: *-----------------------------------------------------------------------
1112: */
1113: static void
1.69 espie 1114: ParseHasCommands(void *gnp) /* Node to examine */
1.1 deraadt 1115: {
1.86 espie 1116: GNode *gn = (GNode *)gnp;
1117: if (!Lst_IsEmpty(&gn->commands)) {
1118: gn->type |= OP_HAS_COMMANDS;
1119: }
1.1 deraadt 1120: }
1121:
1.79 espie 1122:
1123:
1124: /***
1125: *** Support for various include constructs
1126: ***/
1127:
1128:
1.1 deraadt 1129: void
1.79 espie 1130: Parse_AddIncludeDir(const char *dir)
1.1 deraadt 1131: {
1.79 espie 1132: Dir_AddDir(parseIncPath, dir);
1.1 deraadt 1133: }
1134:
1.79 espie 1135: static char *
1136: resolve_include_filename(const char *file, bool isSystem)
1.1 deraadt 1137: {
1.79 espie 1138: char *fullname;
1.87 ! espie 1139:
1.79 espie 1140: /* Look up system files on the system path first */
1141: if (isSystem) {
1142: fullname = Dir_FindFileNoDot(file, sysIncPath);
1143: if (fullname)
1144: return fullname;
1145: }
1146:
1147: /* Handle non-system non-absolute files... */
1148: if (!isSystem && file[0] != '/') {
1.85 espie 1149: /* ... by looking first under the same directory as the
1.79 espie 1150: * current file */
1151: char *slash;
1152: const char *fname;
1153:
1154: fname = Parse_Getfilename();
1155:
1156: slash = strrchr(fname, '/');
1157: if (slash != NULL) {
1158: char *newName;
1159:
1.85 espie 1160: newName = Str_concati(fname, slash, file,
1.79 espie 1161: strchr(file, '\0'), '/');
1162: fullname = Dir_FindFile(newName, parseIncPath);
1163: if (fullname == NULL)
1.83 espie 1164: fullname = Dir_FindFile(newName, defaultPath);
1.79 espie 1165: free(newName);
1166: if (fullname)
1167: return fullname;
1168: }
1169: }
1.1 deraadt 1170:
1.79 espie 1171: /* Now look first on the -I search path, then on the .PATH
1172: * search path, if not found in a -I directory.
1173: * XXX: Suffix specific? */
1174: fullname = Dir_FindFile(file, parseIncPath);
1175: if (fullname)
1176: return fullname;
1.83 espie 1177: fullname = Dir_FindFile(file, defaultPath);
1.79 espie 1178: if (fullname)
1179: return fullname;
1.1 deraadt 1180:
1.79 espie 1181: /* Still haven't found the makefile. Look for it on the system
1182: * path as a last resort (if we haven't already). */
1183: if (isSystem)
1184: return NULL;
1185: else
1186: return Dir_FindFile(file, sysIncPath);
1.1 deraadt 1187: }
1188:
1189: static void
1.85 espie 1190: handle_include_file(const char *name, const char *ename, bool isSystem,
1.79 espie 1191: bool errIfNotFound)
1.1 deraadt 1192: {
1.79 espie 1193: char *file;
1194: char *fullname;
1195:
1196: /* Substitute for any variables in the file name before trying to
1197: * find the thing. */
1198: file = Var_Substi(name, ename, NULL, false);
1199:
1200: fullname = resolve_include_filename(file, isSystem);
1201: if (fullname == NULL && errIfNotFound)
1202: Parse_Error(PARSE_FATAL, "Could not find %s", file);
1203: free(file);
1204:
1.1 deraadt 1205:
1.79 espie 1206: if (fullname != NULL) {
1207: FILE *f;
1.59 espie 1208:
1.79 espie 1209: f = fopen(fullname, "r");
1210: if (f == NULL && errIfNotFound)
1211: Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1212: else
1213: Parse_FromFile(fullname, f);
1214: }
1.59 espie 1215: }
1216:
1.79 espie 1217: /* .include <file> (system) or .include "file" (normal) */
1218: static bool
1219: lookup_bsd_include(const char *file)
1.59 espie 1220: {
1.85 espie 1221: char endc;
1.79 espie 1222: const char *efile;
1223: bool isSystem;
1224:
1225: /* find starting delimiter */
1226: while (isspace(*file))
1227: file++;
1228:
1229: /* determine type of file */
1230: if (*file == '<') {
1231: isSystem = true;
1232: endc = '>';
1233: } else if (*file == '"') {
1234: isSystem = false;
1235: endc = '"';
1236: } else {
1237: Parse_Error(PARSE_WARNING,
1238: ".include filename must be delimited by '\"' or '<'");
1239: return false;
1240: }
1.1 deraadt 1241:
1.79 espie 1242: /* delimit file name between file and efile */
1243: for (efile = ++file; *efile != endc; efile++) {
1244: if (*efile == '\0') {
1245: Parse_Error(PARSE_WARNING,
1246: "Unclosed .include filename. '%c' expected", endc);
1247: return false;
1248: }
1249: }
1250: handle_include_file(file, efile, isSystem, true);
1251: return true;
1252: }
1.1 deraadt 1253:
1254:
1.79 espie 1255: static void
1.85 espie 1256: lookup_sysv_style_include(const char *file, const char *directive,
1.79 espie 1257: bool errIfMissing)
1.50 espie 1258: {
1.79 espie 1259: const char *efile;
1.50 espie 1260:
1.79 espie 1261: /* find beginning of name */
1262: while (isspace(*file))
1263: file++;
1264: if (*file == '\0') {
1265: Parse_Error(PARSE_FATAL, "Filename missing from \"%s\"",
1266: directive);
1267: return;
1.50 espie 1268: }
1.79 espie 1269: /* sys5 delimits file up to next blank character or end of line */
1270: for (efile = file; *efile != '\0' && !isspace(*efile);)
1271: efile++;
1.1 deraadt 1272:
1.79 espie 1273: handle_include_file(file, efile, true, errIfMissing);
1.70 espie 1274: }
1275:
1.79 espie 1276:
1277: /* system V construct: include file */
1.70 espie 1278: static void
1.79 espie 1279: lookup_sysv_include(const char *file, const char *directive)
1.70 espie 1280: {
1.79 espie 1281: lookup_sysv_style_include(file, directive, true);
1282: }
1.1 deraadt 1283:
1284:
1.79 espie 1285: /* sinclude file and -include file */
1286: static void
1287: lookup_conditional_include(const char *file, const char *directive)
1288: {
1289: lookup_sysv_style_include(file, directive, false);
1.1 deraadt 1290: }
1291:
1.59 espie 1292:
1.79 espie 1293: static bool
1294: handle_poison(const char *line)
1.72 espie 1295: {
1.79 espie 1296: const char *p = line;
1.72 espie 1297: int type = POISON_NORMAL;
1298: bool not = false;
1299: bool paren_to_match = false;
1.79 espie 1300: const char *name, *ename;
1.72 espie 1301:
1302: while (isspace(*p))
1303: p++;
1304: if (*p == '!') {
1305: not = true;
1306: p++;
1307: }
1308: while (isspace(*p))
1309: p++;
1310: if (strncmp(p, "defined", 7) == 0) {
1311: type = POISON_DEFINED;
1312: p += 7;
1313: } else if (strncmp(p, "empty", 5) == 0) {
1314: type = POISON_EMPTY;
1315: p += 5;
1316: }
1317: while (isspace(*p))
1318: p++;
1319: if (*p == '(') {
1320: paren_to_match = true;
1321: p++;
1322: }
1323: while (isspace(*p))
1324: p++;
1325: name = ename = p;
1326: while (*p != '\0' && !isspace(*p)) {
1327: if (*p == ')' && paren_to_match) {
1328: paren_to_match = false;
1329: p++;
1330: break;
1331: }
1332: p++;
1333: ename = p;
1334: }
1335: while (isspace(*p))
1336: p++;
1337: switch(type) {
1338: case POISON_NORMAL:
1339: case POISON_EMPTY:
1340: if (not)
1341: type = POISON_INVALID;
1342: break;
1343: case POISON_DEFINED:
1344: if (not)
1345: type = POISON_NOT_DEFINED;
1346: else
1347: type = POISON_INVALID;
1348: break;
1349: }
1.79 espie 1350: if ((*p != '\0' && *p != '#') || type == POISON_INVALID) {
1.85 espie 1351: Parse_Error(PARSE_WARNING, "Invalid syntax for .poison: %s",
1.72 espie 1352: line);
1.79 espie 1353: return false;
1354: } else {
1355: Var_MarkPoisoned(name, ename, type);
1356: return true;
1357: }
1.72 espie 1358: }
1.59 espie 1359:
1360:
1.79 espie 1361: /* Strip comments from the line. Build a copy in buffer if necessary, */
1.59 espie 1362: static char *
1.69 espie 1363: strip_comments(Buffer copy, const char *line)
1.59 espie 1364: {
1.79 espie 1365: const char *comment;
1366: const char *p;
1.59 espie 1367:
1.79 espie 1368: comment = strchr(line, '#');
1369: assert(comment != line);
1370: if (comment == NULL)
1371: return (char *)line;
1372: else {
1373: Buf_Reset(copy);
1374:
1375: for (p = line; *p != '\0'; p++) {
1376: if (*p == '\\') {
1377: if (p[1] == '#') {
1378: Buf_Addi(copy, line, p);
1379: Buf_AddChar(copy, '#');
1380: line = p+2;
1381: }
1382: if (p[1] != '\0')
1383: p++;
1384: } else if (*p == '#')
1385: break;
1.59 espie 1386: }
1.79 espie 1387: Buf_Addi(copy, line, p);
1388: Buf_KillTrailingSpaces(copy);
1389: return Buf_Retrieve(copy);
1.59 espie 1390: }
1391: }
1392:
1.61 espie 1393: static bool
1.79 espie 1394: handle_for_loop(Buffer linebuf, const char *line)
1.59 espie 1395: {
1.79 espie 1396: For *loop;
1.59 espie 1397:
1.79 espie 1398: loop = For_Eval(line+3);
1399: if (loop != NULL) {
1400: bool ok;
1401: do {
1402: /* Find the matching endfor. */
1403: line = ParseReadLoopLine(linebuf);
1404: if (line == NULL) {
1405: Parse_Error(PARSE_FATAL,
1406: "Unexpected end of file in for loop.\n");
1407: return false;
1408: }
1409: ok = For_Accumulate(loop, line);
1410: } while (ok);
1411: For_Run(loop);
1412: return true;
1413: } else
1414: return false;
1415: }
1.59 espie 1416:
1.79 espie 1417: static bool
1418: handle_undef(const char *line)
1419: {
1420: const char *eline;
1.59 espie 1421:
1.79 espie 1422: while (isspace(*line))
1423: line++;
1424: for (eline = line; !isspace(*eline) && *eline != '\0';)
1425: eline++;
1426: Var_Deletei(line, eline);
1.61 espie 1427: return true;
1.79 espie 1428: }
1.67 espie 1429:
1.79 espie 1430: static bool
1431: handle_bsd_command(Buffer linebuf, Buffer copy, const char *line)
1432: {
1433: char *stripped;
1.59 espie 1434:
1.71 tedu 1435: while (isspace(*line))
1.79 espie 1436: line++;
1437:
1438: /* The line might be a conditional. Ask the conditional module
1439: * about it and act accordingly. */
1440: switch (Cond_Eval(line)) {
1441: case COND_SKIP:
1442: /* Skip to next conditional that evaluates to COND_PARSE. */
1443: do {
1444: line = Parse_ReadNextConditionalLine(linebuf);
1445: if (line != NULL) {
1446: while (isspace(*line))
1447: line++;
1448: stripped = strip_comments(copy, line);
1449: }
1450: } while (line != NULL && Cond_Eval(stripped) != COND_PARSE);
1451: /* FALLTHROUGH */
1452: case COND_PARSE:
1453: return true;
1.85 espie 1454: case COND_ISFOR:
1.79 espie 1455: return handle_for_loop(linebuf, line);
1456: case COND_ISINCLUDE:
1457: return lookup_bsd_include(line + 7);
1458: case COND_ISPOISON:
1459: return handle_poison(line+6);
1.85 espie 1460: case COND_ISUNDEF:
1.79 espie 1461: return handle_undef(line + 5);
1462: default:
1463: break;
1464: }
1.67 espie 1465:
1.79 espie 1466: return false;
1.59 espie 1467: }
1468:
1.1 deraadt 1469: /*-
1470: *-----------------------------------------------------------------------
1.59 espie 1471: * ParseFinishDependency --
1.1 deraadt 1472: * Handle the end of a dependency group.
1473: *
1474: * Side Effects:
1.59 espie 1475: * 'targets' list destroyed.
1.1 deraadt 1476: *
1477: *-----------------------------------------------------------------------
1478: */
1479: static void
1.69 espie 1480: ParseFinishDependency(void)
1.1 deraadt 1481: {
1.86 espie 1482: Array_Every(>argets, Suff_EndTransform);
1483: Array_Every(>argets, ParseHasCommands);
1484: Array_Reset(>argets);
1.1 deraadt 1485: }
1.11 millert 1486:
1.59 espie 1487: static void
1.69 espie 1488: ParseDoCommands(const char *line)
1.59 espie 1489: {
1.86 espie 1490: /* add the command to the list of
1491: * commands of all targets in the dependency spec */
1492: char *cmd = estrdup(line);
1.59 espie 1493:
1.86 espie 1494: Array_ForEach(>argets, ParseAddCmd, cmd);
1.59 espie 1495: #ifdef CLEANUP
1.86 espie 1496: Lst_AtEnd(&targCmds, cmd);
1.59 espie 1497: #endif
1498: }
1.1 deraadt 1499:
1500: void
1.69 espie 1501: Parse_File(
1502: const char *name, /* the name of the file being read */
1503: FILE *stream) /* Stream open to makefile to parse */
1.1 deraadt 1504: {
1.59 espie 1505: char *cp, /* pointer into the line */
1506: *line; /* the line we're working on */
1.61 espie 1507: bool inDependency; /* true if currently in a dependency
1.59 espie 1508: * line or its commands */
1509:
1510: BUFFER buf;
1511: BUFFER copy;
1512:
1513: Buf_Init(&buf, MAKE_BSIZE);
1514: Buf_Init(©, MAKE_BSIZE);
1.61 espie 1515: inDependency = false;
1.59 espie 1516: Parse_FromFile(name, stream);
1.1 deraadt 1517:
1518: do {
1.61 espie 1519: while ((line = Parse_ReadNormalLine(&buf)) != NULL) {
1.1 deraadt 1520: if (*line == '\t') {
1.59 espie 1521: if (inDependency)
1522: ParseDoCommands(line+1);
1523: else
1524: Parse_Error(PARSE_FATAL,
1525: "Unassociated shell command \"%s\"",
1526: line);
1.1 deraadt 1527: } else {
1.59 espie 1528: char *stripped;
1529: stripped = strip_comments(©, line);
1.85 espie 1530: if (*stripped == '.' && handle_bsd_command(&buf, ©,
1.79 espie 1531: stripped+1))
1532: ;
1.85 espie 1533: else if (FEATURES(FEATURE_SYSVINCLUDE) &&
1.59 espie 1534: strncmp(stripped, "include", 7) == 0 &&
1535: isspace(stripped[7]) &&
1536: strchr(stripped, ':') == NULL) {
1537: /* It's an S3/S5-style "include". */
1.79 espie 1538: lookup_sysv_include(stripped + 7, "include");
1.59 espie 1539: } else if (FEATURES(FEATURE_CONDINCLUDE) &&
1.85 espie 1540: strncmp(stripped, "sinclude", 8) == 0 &&
1.59 espie 1541: isspace(stripped[8]) &&
1542: strchr(stripped, ':') == NULL) {
1.79 espie 1543: lookup_conditional_include(stripped+8, "sinclude");
1544: } else if (FEATURES(FEATURE_CONDINCLUDE) &&
1.85 espie 1545: strncmp(stripped, "-include", 8) == 0 &&
1.79 espie 1546: isspace(stripped[8]) &&
1547: strchr(stripped, ':') == NULL) {
1548: lookup_conditional_include(stripped+8, "-include");
1.59 espie 1549: } else {
1550: char *dep;
1.11 millert 1551:
1.59 espie 1552: if (inDependency)
1553: ParseFinishDependency();
1.72 espie 1554: if (Parse_DoVar(stripped))
1.61 espie 1555: inDependency = false;
1556: else {
1.59 espie 1557: size_t pos;
1558: char *end;
1.11 millert 1559:
1.59 espie 1560: /* Need a new list for the target nodes. */
1.63 espie 1561: Array_Reset(>argets);
1.61 espie 1562: inDependency = true;
1.59 espie 1563:
1564: dep = NULL;
1565: /* First we need to find eventual dependencies */
1566: pos = strcspn(stripped, ":!");
1567: /* go over :!, and find ; */
1568: if (stripped[pos] != '\0' &&
1569: (end = strchr(stripped+pos+1, ';')) != NULL) {
1570: if (line != stripped)
1571: /* find matching ; in original... The
1572: * original might be slightly longer. */
1573: dep = strchr(line+(end-stripped), ';');
1574: else
1575: dep = end;
1576: /* kill end of line. */
1577: *end = '\0';
1578: }
1579: /* We now know it's a dependency line so it needs to
1580: * have all variables expanded before being parsed.
1581: * Tell the variable module to complain if some
1582: * variable is undefined... */
1.61 espie 1583: cp = Var_Subst(stripped, NULL, true);
1.59 espie 1584: ParseDoDependency(cp);
1585: free(cp);
1586:
1587: /* Parse dependency if it's not empty. */
1588: if (dep != NULL) {
1589: do {
1590: dep++;
1591: } while (isspace(*dep));
1592: if (*dep != '\0')
1593: ParseDoCommands(dep);
1594: }
1.1 deraadt 1595: }
1596: }
1597: }
1598: }
1.50 espie 1599: } while (Parse_NextFile());
1.1 deraadt 1600:
1.59 espie 1601: if (inDependency)
1602: ParseFinishDependency();
1603: /* Make sure conditionals are clean. */
1.1 deraadt 1604: Cond_End();
1605:
1.61 espie 1606: Parse_ReportErrors();
1.59 espie 1607: Buf_Destroy(&buf);
1608: Buf_Destroy(©);
1.1 deraadt 1609: }
1610:
1611: void
1.69 espie 1612: Parse_Init(void)
1.1 deraadt 1613: {
1.79 espie 1614: mainNode = NULL;
1615: Static_Lst_Init(parseIncPath);
1616: Static_Lst_Init(sysIncPath);
1617: Array_Init(&gsources, SOURCES_SIZE);
1618: Array_Init(>argets, TARGETS_SIZE);
1619:
1620: LowParse_Init();
1.20 espie 1621: #ifdef CLEANUP
1.79 espie 1622: Static_Lst_Init(&targCmds);
1.20 espie 1623: #endif
1.1 deraadt 1624: }
1625:
1.61 espie 1626: #ifdef CLEANUP
1.1 deraadt 1627: void
1.69 espie 1628: Parse_End(void)
1.1 deraadt 1629: {
1.79 espie 1630: Lst_Destroy(&targCmds, (SimpleProc)free);
1631: Lst_Destroy(sysIncPath, Dir_Destroy);
1632: Lst_Destroy(parseIncPath, Dir_Destroy);
1633: LowParse_End();
1.61 espie 1634: }
1.20 espie 1635: #endif
1.11 millert 1636:
1.1 deraadt 1637:
1.44 espie 1638: void
1.69 espie 1639: Parse_MainName(Lst listmain) /* result list */
1.1 deraadt 1640: {
1641:
1.86 espie 1642: if (mainNode == NULL) {
1643: Punt("no target to make.");
1644: /*NOTREACHED*/
1645: } else if (mainNode->type & OP_DOUBLEDEP) {
1646: Lst_AtEnd(listmain, mainNode);
1647: Lst_Concat(listmain, &mainNode->cohorts);
1648: }
1649: else
1650: Lst_AtEnd(listmain, mainNode);
1.1 deraadt 1651: }
1.59 espie 1652: