Annotation of src/usr.bin/make/parse.c, Revision 1.60
1.59 espie 1: /* $OpenPackages$ */
1.60 ! espie 2: /* $OpenBSD: parse.c,v 1.59 2001/05/03 13:41:08 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.
48: * 3. All advertising materials mentioning features or use of this software
49: * must display the following acknowledgement:
50: * This product includes software developed by the University of
51: * California, Berkeley and its contributors.
52: * 4. Neither the name of the University nor the names of its contributors
53: * may be used to endorse or promote products derived from this software
54: * without specific prior written permission.
55: *
56: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66: * SUCH DAMAGE.
67: */
68:
69: /*-
70: * parse.c --
71: * Functions to parse a makefile.
72: *
73: * One function, Parse_Init, must be called before any functions
74: * in this module are used. After that, the function Parse_File is the
75: * main entry point and controls most of the other functions in this
76: * module.
77: *
78: * Most important structures are kept in Lsts. Directories for
79: * the #include "..." function are kept in the 'parseIncPath' Lst, while
80: * those for the #include <...> are kept in the 'sysIncPath' Lst. The
81: * targets currently being defined are kept in the 'targets' Lst.
82: *
83: * The variables 'fname' and 'lineno' are used to track the name
84: * of the current file and the line number in that file so that error
85: * messages can be more meaningful.
86: *
87: * Interface:
1.59 espie 88: * Parse_Init Initialization function which must be
89: * called before anything else in this module
90: * is used.
1.1 deraadt 91: *
92: * Parse_End Cleanup the module
93: *
1.59 espie 94: * Parse_File Function used to parse a makefile. It must
95: * be given the name of the file, which should
96: * already have been opened, and a function
97: * to call to read a character from the file.
98: *
99: * Parse_IsVar Returns TRUE if the given line is a
100: * variable assignment. Used by MainParseArgs
101: * to determine if an argument is a target
102: * or a variable assignment. Used internally
103: * for pretty much the same thing...
104: *
105: * Parse_Error Function called when an error occurs in
106: * parsing. Used by the variable and
107: * conditional modules.
108: * Parse_MainName Returns a Lst of the main target to create.
1.1 deraadt 109: */
110:
1.15 mickey 111: #ifdef __STDC__
1.1 deraadt 112: #include <stdarg.h>
113: #else
114: #include <varargs.h>
115: #endif
1.59 espie 116: #include <assert.h>
1.57 espie 117: #include <stddef.h>
1.1 deraadt 118: #include <stdio.h>
119: #include <ctype.h>
120: #include <errno.h>
121: #include "make.h"
1.57 espie 122: #include "ohash.h"
1.1 deraadt 123: #include "dir.h"
124: #include "job.h"
125: #include "buf.h"
126: #include "pathnames.h"
1.50 espie 127: #include "lowparse.h"
1.1 deraadt 128:
1.53 espie 129: #ifndef lint
130: #if 0
131: static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
132: #else
133: UNUSED
1.60 ! espie 134: static char rcsid[] = "$OpenBSD: parse.c,v 1.59 2001/05/03 13:41:08 espie Exp $";
1.53 espie 135: #endif
136: #endif /* not lint */
137:
1.59 espie 138: LIST parseIncPath; /* list of directories for "..." includes */
139: LIST sysIncPath; /* list of directories for <...> includes */
140:
141: static LIST targets; /* targets we're working on */
1.20 espie 142: #ifdef CLEANUP
1.59 espie 143: static LIST targCmds; /* command lines for targets */
144: static LIST fileNames;
1.20 espie 145: #endif
1.59 espie 146:
1.1 deraadt 147: static GNode *mainNode; /* The main target to create. This is the
148: * first target on the first dependency
149: * line in the first makefile */
150: /*-
151: * specType contains the SPECial TYPE of the current target. It is
152: * Not if the target is unspecial. If it *is* special, however, the children
153: * are linked as children of the parent but not vice versa. This variable is
154: * set in ParseDoDependency
155: */
156: typedef enum {
1.59 espie 157: Begin, /* .BEGIN */
1.1 deraadt 158: Default, /* .DEFAULT */
1.59 espie 159: End, /* .END */
1.1 deraadt 160: Ignore, /* .IGNORE */
161: Includes, /* .INCLUDES */
162: Interrupt, /* .INTERRUPT */
163: Libs, /* .LIBS */
164: MFlags, /* .MFLAGS or .MAKEFLAGS */
165: Main, /* .MAIN and we don't have anything user-specified to
166: * make */
167: NoExport, /* .NOEXPORT */
1.17 espie 168: NoPath, /* .NOPATH */
1.1 deraadt 169: Not, /* Not special */
170: NotParallel, /* .NOTPARALELL */
1.59 espie 171: Null, /* .NULL */
172: Order, /* .ORDER */
1.3 deraadt 173: Parallel, /* .PARALLEL */
1.1 deraadt 174: ExPath, /* .PATH */
1.7 niklas 175: Phony, /* .PHONY */
1.1 deraadt 176: Precious, /* .PRECIOUS */
177: ExShell, /* .SHELL */
178: Silent, /* .SILENT */
179: SingleShell, /* .SINGLESHELL */
180: Suffixes, /* .SUFFIXES */
1.3 deraadt 181: Wait, /* .WAIT */
1.1 deraadt 182: Attribute /* Generic attribute */
183: } ParseSpecial;
184:
185: static ParseSpecial specType;
1.3 deraadt 186: static int waiting;
1.1 deraadt 187:
188: /*
1.33 espie 189: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 deraadt 190: * seen, then set to each successive source on the line.
191: */
192: static GNode *predecessor;
193:
194: /*
195: * The parseKeywords table is searched using binary search when deciding
196: * if a target or source is special. The 'spec' field is the ParseSpecial
197: * type of the keyword ("Not" if the keyword isn't special as a target) while
198: * the 'op' field is the operator to apply to the list of targets if the
199: * keyword is used as a source ("0" if the keyword isn't special as a source)
200: */
201: static struct {
1.59 espie 202: char *name; /* Name of keyword */
203: ParseSpecial spec; /* Type when used as a target */
204: int op; /* Operator when used as a source */
1.1 deraadt 205: } parseKeywords[] = {
1.59 espie 206: { ".BEGIN", Begin, 0 },
207: { ".DEFAULT", Default, 0 },
208: { ".END", End, 0 },
209: { ".EXEC", Attribute, OP_EXEC },
210: { ".IGNORE", Ignore, OP_IGNORE },
211: { ".INCLUDES", Includes, 0 },
212: { ".INTERRUPT", Interrupt, 0 },
213: { ".INVISIBLE", Attribute, OP_INVISIBLE },
214: { ".JOIN", Attribute, OP_JOIN },
215: { ".LIBS", Libs, 0 },
1.13 millert 216: { ".MADE", Attribute, OP_MADE },
1.59 espie 217: { ".MAIN", Main, 0 },
218: { ".MAKE", Attribute, OP_MAKE },
219: { ".MAKEFLAGS", MFlags, 0 },
220: { ".MFLAGS", MFlags, 0 },
1.17 espie 221: #if 0 /* basic scaffolding for NOPATH, not working yet */
222: { ".NOPATH", NoPath, OP_NOPATH },
223: #endif
1.59 espie 224: { ".NOTMAIN", Attribute, OP_NOTMAIN },
1.1 deraadt 225: { ".NOTPARALLEL", NotParallel, 0 },
1.3 deraadt 226: { ".NO_PARALLEL", NotParallel, 0 },
1.59 espie 227: { ".NULL", Null, 0 },
228: { ".OPTIONAL", Attribute, OP_OPTIONAL },
229: { ".ORDER", Order, 0 },
1.3 deraadt 230: { ".PARALLEL", Parallel, 0 },
1.1 deraadt 231: { ".PATH", ExPath, 0 },
1.7 niklas 232: { ".PHONY", Phony, OP_PHONY },
1.59 espie 233: { ".PRECIOUS", Precious, OP_PRECIOUS },
234: { ".RECURSIVE", Attribute, OP_MAKE },
235: { ".SHELL", ExShell, 0 },
236: { ".SILENT", Silent, OP_SILENT },
1.1 deraadt 237: { ".SINGLESHELL", SingleShell, 0 },
1.59 espie 238: { ".SUFFIXES", Suffixes, 0 },
239: { ".USE", Attribute, OP_USE },
1.3 deraadt 240: { ".WAIT", Wait, 0 },
1.1 deraadt 241: };
242:
1.59 espie 243: static int ParseFindKeyword(const char *);
244: static void ParseLinkSrc(GNode *, GNode *);
245: static int ParseDoOp(void *, void *);
246: static int ParseAddDep(void *, void *);
247: static void ParseDoSrc(int, const char *, Lst);
248: static int ParseFindMain(void *, void *);
249: static void ParseAddDir(void *, void *);
250: static void ParseClearPath(void *);
251: static void ParseDoDependency(char *);
252: static void ParseAddCmd(void *, void *);
253: static void ParseHasCommands(void *);
254: static void ParseDoInclude(char *);
255: static void ParseTraditionalInclude(char *);
256: static void ParseConditionalInclude(char *);
257: static void ParseLookupIncludeFile(char *, char *, Boolean, Boolean);
258: #define ParseGetLoopLine(linebuf) ParseGetLine(linebuf, "for loop")
259: static void ParseFinishDependency(void);
260: static Boolean ParseIsCond(Buffer, Buffer, char *);
261: static char *strip_comments(Buffer, const char *);
262:
263: static void ParseDoCommands(const char *);
264: static const char *find_op1(const char *);
265: static const char *find_op2(const char *);
1.1 deraadt 266:
267: /*-
268: *----------------------------------------------------------------------
269: * ParseFindKeyword --
270: * Look in the table of keywords for one matching the given string.
271: *
272: * Results:
273: * The index of the keyword, or -1 if it isn't there.
274: *----------------------------------------------------------------------
275: */
276: static int
1.59 espie 277: ParseFindKeyword(str)
278: const char *str; /* String to find */
1.1 deraadt 279: {
1.59 espie 280: int start,
1.1 deraadt 281: end,
282: cur;
1.59 espie 283: int diff;
1.11 millert 284:
1.1 deraadt 285: start = 0;
286: end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
287:
288: do {
1.59 espie 289: cur = start + (end - start) / 2;
290: diff = strcmp(str, parseKeywords[cur].name);
1.1 deraadt 291:
292: if (diff == 0) {
1.59 espie 293: return cur;
1.1 deraadt 294: } else if (diff < 0) {
295: end = cur - 1;
296: } else {
297: start = cur + 1;
298: }
299: } while (start <= end);
1.59 espie 300: return -1;
1.1 deraadt 301: }
302: /*-
303: *---------------------------------------------------------------------
304: * ParseLinkSrc --
1.59 espie 305: * Link the parent node to its new child. Used by
1.1 deraadt 306: * ParseDoDependency. If the specType isn't 'Not', the parent
307: * isn't linked as a parent of the child.
308: *
309: * Side Effects:
310: * New elements are added to the parents list of cgn and the
311: * children list of cgn. the unmade field of pgn is updated
312: * to reflect the additional child.
313: *---------------------------------------------------------------------
314: */
1.41 espie 315: static void
1.59 espie 316: ParseLinkSrc(pgn, cgn)
317: GNode *pgn; /* The parent node */
318: GNode *cgn; /* The child node */
319: {
320: if (Lst_AddNew(&pgn->children, cgn) == SUCCESS) {
1.41 espie 321: if (specType == Not)
1.43 espie 322: Lst_AtEnd(&cgn->parents, pgn);
1.59 espie 323: pgn->unmade++;
1.1 deraadt 324: }
325: }
326:
327: /*-
328: *---------------------------------------------------------------------
329: * ParseDoOp --
330: * Apply the parsed operator to the given target node. Used in a
1.41 espie 331: * Lst_Find call by ParseDoDependency once all targets have
1.1 deraadt 332: * been found and their operator parsed. If the previous and new
333: * operators are incompatible, a major error is taken.
334: *
335: * Side Effects:
336: * The type field of the node is altered to reflect any new bits in
337: * the op.
338: *---------------------------------------------------------------------
339: */
340: static int
1.59 espie 341: ParseDoOp(gnp, opp)
342: void *gnp; /* The node to which the operator is to be
343: * applied */
344: void *opp; /* The operator to apply */
1.1 deraadt 345: {
1.59 espie 346: GNode *gn = (GNode *)gnp;
347: int op = *(int *)opp;
1.1 deraadt 348: /*
349: * If the dependency mask of the operator and the node don't match and
350: * the node has actually had an operator applied to it before, and
1.11 millert 351: * the operator actually has some dependency information in it, complain.
1.1 deraadt 352: */
353: if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
1.40 espie 354: !OP_NOP(gn->type) && !OP_NOP(op)) {
355: Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
356: return 0;
1.1 deraadt 357: }
358:
1.59 espie 359: if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
360: /* If the node was the object of a :: operator, we need to create a
1.1 deraadt 361: * new instance of it for the children and commands on this dependency
362: * line. The new instance is placed on the 'cohorts' list of the
363: * initial one (note the initial one is not on its own cohorts list)
364: * and the new instance is linked to all parents of the initial
1.59 espie 365: * instance. */
366: GNode *cohort;
367: LstNode ln;
1.11 millert 368:
1.55 espie 369: cohort = Targ_NewGN(gn->name, NULL);
1.59 espie 370: /* Duplicate links to parents so graph traversal is simple. Perhaps
1.1 deraadt 371: * some type bits should be duplicated?
372: *
373: * Make the cohort invisible as well to avoid duplicating it into
374: * other variables. True, parents of this target won't tend to do
375: * anything with their local variables, but better safe than
1.59 espie 376: * sorry. */
377: for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln))
378: ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
1.1 deraadt 379: cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
1.43 espie 380: Lst_AtEnd(&gn->cohorts, cohort);
1.1 deraadt 381:
1.59 espie 382: /* Replace the node in the targets list with the new copy */
1.45 espie 383: ln = Lst_Member(&targets, gn);
1.37 espie 384: Lst_Replace(ln, cohort);
1.1 deraadt 385: gn = cohort;
386: }
1.59 espie 387: /* We don't want to nuke any previous flags (whatever they were) so we
388: * just OR the new operator into the old. */
1.1 deraadt 389: gn->type |= op;
1.40 espie 390: return 1;
1.1 deraadt 391: }
392:
1.11 millert 393: /*-
1.3 deraadt 394: *---------------------------------------------------------------------
1.59 espie 395: * ParseAddDep --
1.3 deraadt 396: * Check if the pair of GNodes given needs to be synchronized.
397: * This has to be when two nodes are on different sides of a
398: * .WAIT directive.
399: *
400: * Results:
1.40 espie 401: * Returns 0 if the two targets need to be ordered, 1 otherwise.
1.59 espie 402: * If it returns 0, the search can stop.
1.3 deraadt 403: *
404: * Side Effects:
405: * A dependency can be added between the two nodes.
1.11 millert 406: *
1.3 deraadt 407: *---------------------------------------------------------------------
408: */
1.13 millert 409: static int
1.3 deraadt 410: ParseAddDep(pp, sp)
1.42 espie 411: void *pp;
412: void *sp;
1.3 deraadt 413: {
1.59 espie 414: GNode *p = (GNode *)pp;
415: GNode *s = (GNode *)sp;
1.3 deraadt 416:
417: if (p->order < s->order) {
1.59 espie 418: /* XXX: This can cause loops, and loops can cause unmade targets,
1.3 deraadt 419: * but checking is tedious, and the debugging output can show the
1.59 espie 420: * problem. */
1.43 espie 421: Lst_AtEnd(&p->successors, s);
422: Lst_AtEnd(&s->preds, p);
1.40 espie 423: return 1;
1.3 deraadt 424: }
425: else
1.40 espie 426: return 0;
1.3 deraadt 427: }
428:
429:
1.1 deraadt 430: /*-
431: *---------------------------------------------------------------------
432: * ParseDoSrc --
433: * Given the name of a source, figure out if it is an attribute
434: * and apply it to the targets if it is. Else decide if there is
435: * some attribute which should be applied *to* the source because
436: * of some special target and apply it if so. Otherwise, make the
437: * source be a child of the targets in the list 'targets'
438: *
439: * Side Effects:
440: * Operator bits may be added to the list of targets or to the source.
441: * The targets may have a new source added to their lists of children.
442: *---------------------------------------------------------------------
443: */
444: static void
1.59 espie 445: ParseDoSrc(tOp, src, allsrc)
446: int tOp; /* operator (if any) from special targets */
447: const char *src; /* name of the source to handle */
448: Lst allsrc; /* List of all sources to wait for */
1.3 deraadt 449:
1.1 deraadt 450: {
1.3 deraadt 451: GNode *gn = NULL;
1.1 deraadt 452:
1.59 espie 453: if (*src == '.' && isupper(src[1])) {
1.1 deraadt 454: int keywd = ParseFindKeyword(src);
455: if (keywd != -1) {
1.3 deraadt 456: int op = parseKeywords[keywd].op;
457: if (op != 0) {
1.45 espie 458: Lst_Find(&targets, ParseDoOp, &op);
1.3 deraadt 459: return;
460: }
461: if (parseKeywords[keywd].spec == Wait) {
462: waiting++;
463: return;
464: }
1.1 deraadt 465: }
466: }
1.3 deraadt 467:
468: switch (specType) {
469: case Main:
1.1 deraadt 470: /*
471: * If we have noted the existence of a .MAIN, it means we need
472: * to add the sources of said target to the list of things
473: * to create. The string 'src' is likely to be free, so we
474: * must make a new copy of it. Note that this will only be
475: * invoked if the user didn't specify a target on the command
476: * line. This is to allow #ifmake's to succeed, or something...
477: */
1.43 espie 478: Lst_AtEnd(&create, estrdup(src));
1.1 deraadt 479: /*
480: * Add the name to the .TARGETS variable as well, so the user cna
481: * employ that, if desired.
482: */
483: Var_Append(".TARGETS", src, VAR_GLOBAL);
1.3 deraadt 484: return;
485:
486: case Order:
1.1 deraadt 487: /*
488: * Create proper predecessor/successor links between the previous
489: * source and the current one.
490: */
1.59 espie 491: gn = Targ_FindNode(src, NULL, TARG_CREATE);
1.33 espie 492: if (predecessor != NULL) {
1.43 espie 493: Lst_AtEnd(&predecessor->successors, gn);
494: Lst_AtEnd(&gn->preds, predecessor);
1.1 deraadt 495: }
496: /*
497: * The current source now becomes the predecessor for the next one.
498: */
499: predecessor = gn;
1.3 deraadt 500: break;
501:
502: default:
1.1 deraadt 503: /*
504: * If the source is not an attribute, we need to find/create
505: * a node for it. After that we can apply any operator to it
506: * from a special target or link it to its parents, as
507: * appropriate.
508: *
509: * In the case of a source that was the object of a :: operator,
510: * the attribute is applied to all of its instances (as kept in
511: * the 'cohorts' list of the node) or all the cohorts are linked
512: * to all the targets.
513: */
1.59 espie 514: gn = Targ_FindNode(src, NULL, TARG_CREATE);
1.1 deraadt 515: if (tOp) {
516: gn->type |= tOp;
517: } else {
1.59 espie 518: LstNode ln;
519:
520: for (ln = Lst_First(&targets); ln != NULL; ln = Lst_Adv(ln))
521: ParseLinkSrc((GNode *)Lst_Datum(ln), gn);
1.1 deraadt 522: }
523: if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
1.59 espie 524: GNode *cohort;
525: LstNode ln;
1.1 deraadt 526:
1.46 espie 527: for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)){
1.1 deraadt 528: cohort = (GNode *)Lst_Datum(ln);
529: if (tOp) {
530: cohort->type |= tOp;
531: } else {
1.59 espie 532: LstNode ln;
533:
534: for (ln = Lst_First(&targets); ln != NULL; ln = Lst_Adv(ln))
535: ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
1.1 deraadt 536: }
537: }
538: }
1.3 deraadt 539: break;
540: }
541:
542: gn->order = waiting;
1.37 espie 543: Lst_AtEnd(allsrc, gn);
1.59 espie 544: if (waiting) {
1.40 espie 545: Lst_Find(allsrc, ParseAddDep, gn);
1.59 espie 546: }
1.1 deraadt 547: }
548:
549: /*-
550: *-----------------------------------------------------------------------
551: * ParseFindMain --
552: * Find a real target in the list and set it to be the main one.
553: * Called by ParseDoDependency when a main target hasn't been found
554: * yet.
555: *
556: * Results:
1.40 espie 557: * 1 if main not found yet, 0 if it is.
1.1 deraadt 558: *
559: * Side Effects:
560: * mainNode is changed and Targ_SetMain is called.
561: *-----------------------------------------------------------------------
562: */
563: static int
564: ParseFindMain(gnp, dummy)
1.59 espie 565: void *gnp; /* Node to examine */
566: void *dummy UNUSED;
1.1 deraadt 567: {
1.59 espie 568: GNode *gn = (GNode *)gnp;
1.17 espie 569: if ((gn->type & OP_NOTARGET) == 0) {
1.1 deraadt 570: mainNode = gn;
571: Targ_SetMain(gn);
1.54 espie 572: return 0;
1.59 espie 573: } else {
1.54 espie 574: return 1;
1.59 espie 575: }
1.1 deraadt 576: }
577:
578: /*-
579: *-----------------------------------------------------------------------
580: * ParseAddDir --
581: * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
582: *
583: * Side Effects:
584: * See Dir_AddDir.
585: *-----------------------------------------------------------------------
586: */
1.41 espie 587: static void
1.1 deraadt 588: ParseAddDir(path, name)
1.42 espie 589: void *path;
590: void *name;
1.1 deraadt 591: {
1.56 espie 592: Dir_AddDir((Lst)path, (char *)name, NULL);
1.1 deraadt 593: }
594:
595: /*-
596: *-----------------------------------------------------------------------
597: * ParseClearPath --
1.59 espie 598: * Reinit path to an empty path
1.1 deraadt 599: *-----------------------------------------------------------------------
600: */
1.41 espie 601: static void
1.59 espie 602: ParseClearPath(p)
603: void *p;
1.1 deraadt 604: {
1.59 espie 605: Lst path = (Lst)p;
606:
607: Lst_Destroy(path, Dir_Destroy);
608: Lst_Init(path);
1.1 deraadt 609: }
610:
611: /*-
612: *---------------------------------------------------------------------
613: * ParseDoDependency --
614: * Parse the dependency line in line.
615: *
616: * Side Effects:
617: * The nodes of the sources are linked as children to the nodes of the
618: * targets. Some nodes may be created.
619: *
620: * We parse a dependency line by first extracting words from the line and
621: * finding nodes in the list of all targets with that name. This is done
622: * until a character is encountered which is an operator character. Currently
623: * these are only ! and :. At this point the operator is parsed and the
624: * pointer into the line advanced until the first source is encountered.
1.59 espie 625: * The parsed operator is applied to each node in the 'targets' list,
1.1 deraadt 626: * which is where the nodes found for the targets are kept, by means of
627: * the ParseDoOp function.
628: * The sources are read in much the same way as the targets were except
629: * that now they are expanded using the wildcarding scheme of the C-Shell
630: * and all instances of the resulting words in the list of all targets
631: * are found. Each of the resulting nodes is then linked to each of the
632: * targets as one of its children.
633: * Certain targets are handled specially. These are the ones detailed
634: * by the specType variable.
635: * The storing of transformation rules is also taken care of here.
636: * A target is recognized as a transformation rule by calling
637: * Suff_IsTransform. If it is a transformation rule, its node is gotten
638: * from the suffix module via Suff_AddTransform rather than the standard
639: * Targ_FindNode in the target module.
640: *---------------------------------------------------------------------
641: */
642: static void
1.59 espie 643: ParseDoDependency(line)
644: char *line; /* the line to parse */
1.1 deraadt 645: {
1.59 espie 646: char *cp; /* our current position */
647: GNode *gn; /* a general purpose temporary node */
648: int op; /* the operator on the line */
649: char savec; /* a place to save a character */
650: LIST paths; /* List of search paths to alter when parsing
1.1 deraadt 651: * a list of .PATH targets */
1.59 espie 652: int tOp; /* operator from special target */
653: LIST curTargs; /* list of target names to be found and added
1.1 deraadt 654: * to the targets list */
1.43 espie 655: LIST curSrcs; /* list of sources in order */
1.1 deraadt 656:
657: tOp = 0;
658:
659: specType = Not;
1.3 deraadt 660: waiting = 0;
1.45 espie 661: Lst_Init(&paths);
1.1 deraadt 662:
1.43 espie 663: Lst_Init(&curTargs);
664: Lst_Init(&curSrcs);
1.11 millert 665:
1.1 deraadt 666: do {
1.59 espie 667: for (cp = line; *cp && !isspace(*cp) && *cp != '(';)
668: if (*cp == '$')
669: /* Must be a dynamic source (would have been expanded
1.1 deraadt 670: * otherwise), so call the Var module to parse the puppy
671: * so we can safely advance beyond it...There should be
672: * no errors in this, as they would have been discovered
1.59 espie 673: * in the initial Var_Subst and we wouldn't be here. */
674: cp += Var_ParseSkip(cp, NULL, NULL);
675: else {
676: /* We don't want to end a word on ':' or '!' if there is a
677: * better match later on in the string. By "better" I mean
678: * one that is followed by whitespace. This allows the user
679: * to have targets like:
680: * fie::fi:fo: fum
681: * where "fie::fi:fo" is the target. In real life this is used
682: * for perl5 library man pages where "::" separates an object
683: * from its class. Ie: "File::Spec::Unix". This behaviour
684: * is also consistent with other versions of make. */
685: if (*cp == '!' || *cp == ':') {
686: char *p = cp + 1;
687:
688: if (*cp == ':' && *p == ':')
689: p++;
690:
691: /* Found the best match already. */
692: if (isspace(*p) || *p == '\0')
693: break;
694:
695: do {
696: p += strcspn(p, "!:");
697: if (*p == '\0')
698: break;
699: p++;
700: } while (!isspace(*p));
1.1 deraadt 701:
1.59 espie 702: /* No better match later on... */
703: if (*p == '\0')
704: break;
1.1 deraadt 705:
706: }
1.59 espie 707: cp++;
1.1 deraadt 708: }
709: if (*cp == '(') {
1.59 espie 710: /* Archives must be handled specially to make sure the OP_ARCHV
1.1 deraadt 711: * flag is set in their 'type' field, for one thing, and because
712: * things like "archive(file1.o file2.o file3.o)" are permissible.
713: * Arch_ParseArchive will set 'line' to be the first non-blank
714: * after the archive-spec. It creates/finds nodes for the members
715: * and places them on the given list, returning SUCCESS if all
716: * went well and FAILURE if there was an error in the
1.59 espie 717: * specification. On error, line should remain untouched. */
1.48 espie 718: if (Arch_ParseArchive(&line, &targets, NULL) != SUCCESS) {
1.59 espie 719: Parse_Error(PARSE_FATAL,
1.1 deraadt 720: "Error in archive specification: \"%s\"", line);
721: return;
722: } else {
723: continue;
724: }
725: }
726: savec = *cp;
1.11 millert 727:
1.59 espie 728: if (*cp == '\0') {
729: /* Ending a dependency line without an operator is a Bozo no-no */
730: Parse_Error(PARSE_FATAL, "Need an operator");
1.1 deraadt 731: return;
732: }
733: *cp = '\0';
1.59 espie 734: /* Have a word in line. See if it's a special target and set
735: * specType to match it. */
736: if (*line == '.' && isupper(line[1])) {
737: /* See if the target is a special target that must have it
738: * or its sources handled specially. */
1.1 deraadt 739: int keywd = ParseFindKeyword(line);
740: if (keywd != -1) {
741: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
742: Parse_Error(PARSE_FATAL, "Mismatched special targets");
743: return;
744: }
1.11 millert 745:
1.1 deraadt 746: specType = parseKeywords[keywd].spec;
747: tOp = parseKeywords[keywd].op;
748:
749: /*
750: * Certain special targets have special semantics:
751: * .PATH Have to set the dirSearchPath
752: * variable too
753: * .MAIN Its sources are only used if
754: * nothing has been specified to
755: * create.
1.59 espie 756: * .DEFAULT Need to create a node to hang
1.1 deraadt 757: * commands on, but we don't want
758: * it in the graph, nor do we want
759: * it to be the Main Target, so we
760: * create it, set OP_NOTMAIN and
761: * add it to the list, setting
762: * DEFAULT to the new node for
763: * later use. We claim the node is
1.59 espie 764: * A transformation rule to make
765: * life easier later, when we'll
766: * use Make_HandleUse to actually
767: * apply the .DEFAULT commands.
1.7 niklas 768: * .PHONY The list of targets
1.59 espie 769: * .NOPATH Don't search for file in the path
1.1 deraadt 770: * .BEGIN
771: * .END
1.59 espie 772: * .INTERRUPT Are not to be considered the
1.1 deraadt 773: * main target.
1.59 espie 774: * .NOTPARALLEL Make only one target at a time.
775: * .SINGLESHELL Create a shell for each command.
776: * .ORDER Must set initial predecessor to NULL
1.1 deraadt 777: */
778: switch (specType) {
779: case ExPath:
1.45 espie 780: Lst_AtEnd(&paths, &dirSearchPath);
1.1 deraadt 781: break;
782: case Main:
1.43 espie 783: if (!Lst_IsEmpty(&create)) {
1.1 deraadt 784: specType = Not;
785: }
786: break;
787: case Begin:
788: case End:
789: case Interrupt:
1.59 espie 790: gn = Targ_FindNode(line, NULL, TARG_CREATE);
1.1 deraadt 791: gn->type |= OP_NOTMAIN;
1.45 espie 792: Lst_AtEnd(&targets, gn);
1.1 deraadt 793: break;
794: case Default:
1.55 espie 795: gn = Targ_NewGN(".DEFAULT", NULL);
1.59 espie 796: gn->type |= OP_NOTMAIN|OP_TRANSFORM;
1.45 espie 797: Lst_AtEnd(&targets, gn);
1.1 deraadt 798: DEFAULT = gn;
799: break;
800: case NotParallel:
801: {
802: extern int maxJobs;
1.11 millert 803:
1.1 deraadt 804: maxJobs = 1;
805: break;
806: }
807: case SingleShell:
808: compatMake = 1;
809: break;
810: case Order:
1.33 espie 811: predecessor = NULL;
1.1 deraadt 812: break;
813: default:
814: break;
815: }
1.59 espie 816: } else if (strncmp(line, ".PATH", 5) == 0) {
1.1 deraadt 817: /*
818: * .PATH<suffix> has to be handled specially.
819: * Call on the suffix module to give us a path to
820: * modify.
821: */
1.59 espie 822: Lst path;
1.11 millert 823:
1.1 deraadt 824: specType = ExPath;
1.45 espie 825: path = Suff_GetPath(&line[5]);
1.33 espie 826: if (path == NULL) {
1.45 espie 827: Parse_Error(PARSE_FATAL,
1.1 deraadt 828: "Suffix '%s' not defined (yet)",
829: &line[5]);
830: return;
1.59 espie 831: } else {
1.45 espie 832: Lst_AtEnd(&paths, path);
1.59 espie 833: }
1.1 deraadt 834: }
835: }
1.11 millert 836:
1.1 deraadt 837: /*
838: * Have word in line. Get or create its node and stick it at
1.11 millert 839: * the end of the targets list
1.1 deraadt 840: */
1.59 espie 841: if (specType == Not && *line != '\0') {
1.34 espie 842: char *targName;
843:
1.1 deraadt 844: if (Dir_HasWildcards(line)) {
845: /*
846: * Targets are to be sought only in the current directory,
847: * so create an empty path for the thing. Note we need to
848: * use Dir_Destroy in the destruction of the path as the
849: * Dir module could have added a directory to the path...
850: */
1.43 espie 851: LIST emptyPath;
1.59 espie 852:
1.43 espie 853: Lst_Init(&emptyPath);
854: Dir_Expand(line, &emptyPath, &curTargs);
855: Lst_Destroy(&emptyPath, Dir_Destroy);
1.1 deraadt 856: } else {
857: /*
858: * No wildcards, but we want to avoid code duplication,
859: * so create a list with the word on it.
860: */
1.43 espie 861: Lst_AtEnd(&curTargs, line);
1.1 deraadt 862: }
1.11 millert 863:
1.59 espie 864: while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) {
865: if (!Suff_IsTransform(targName)) {
866: gn = Targ_FindNode(targName, NULL, TARG_CREATE);
1.1 deraadt 867: } else {
1.59 espie 868: gn = Suff_AddTransform(targName);
1.1 deraadt 869: }
1.11 millert 870:
1.16 millert 871: if (gn != NULL)
1.45 espie 872: Lst_AtEnd(&targets, gn);
1.1 deraadt 873: }
874: } else if (specType == ExPath && *line != '.' && *line != '\0') {
875: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
876: }
1.11 millert 877:
1.1 deraadt 878: *cp = savec;
879: /*
880: * If it is a special type and not .PATH, it's the only target we
881: * allow on this line...
882: */
883: if (specType != Not && specType != ExPath) {
884: Boolean warn = FALSE;
1.11 millert 885:
1.59 espie 886: while (*cp != '!' && *cp != ':' && *cp) {
1.1 deraadt 887: if (*cp != ' ' && *cp != '\t') {
888: warn = TRUE;
889: }
890: cp++;
891: }
892: if (warn) {
893: Parse_Error(PARSE_WARNING, "Extra target ignored");
894: }
895: } else {
1.59 espie 896: while (*cp && isspace(*cp)) {
1.1 deraadt 897: cp++;
898: }
899: }
900: line = cp;
1.59 espie 901: } while (*line != '!' && *line != ':' && *line);
1.1 deraadt 902:
1.59 espie 903: /*
904: * Don't need the list of target names anymore...
905: */
1.43 espie 906: Lst_Destroy(&curTargs, NOFREE);
1.1 deraadt 907:
1.45 espie 908: if (!Lst_IsEmpty(&targets)) {
1.59 espie 909: switch (specType) {
1.1 deraadt 910: default:
911: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
912: break;
913: case Default:
914: case Begin:
915: case End:
916: case Interrupt:
1.59 espie 917: /* These four create nodes on which to hang commands, so
918: * targets shouldn't be empty... */
1.1 deraadt 919: case Not:
1.59 espie 920: /* Nothing special here -- targets can be empty if it wants. */
1.1 deraadt 921: break;
922: }
923: }
924:
1.59 espie 925: /* Have now parsed all the target names. Must parse the operator next. The
926: * result is left in op . */
1.1 deraadt 927: if (*cp == '!') {
928: op = OP_FORCE;
929: } else if (*cp == ':') {
930: if (cp[1] == ':') {
931: op = OP_DOUBLEDEP;
932: cp++;
933: } else {
934: op = OP_DEPENDS;
935: }
936: } else {
1.59 espie 937: Parse_Error(PARSE_FATAL, "Missing dependency operator");
1.1 deraadt 938: return;
939: }
940:
941: cp++; /* Advance beyond operator */
942:
1.45 espie 943: Lst_Find(&targets, ParseDoOp, &op);
1.1 deraadt 944:
945: /*
1.11 millert 946: * Get to the first source
1.1 deraadt 947: */
1.59 espie 948: while (*cp && isspace(*cp)) {
1.1 deraadt 949: cp++;
950: }
951: line = cp;
952:
953: /*
954: * Several special targets take different actions if present with no
955: * sources:
956: * a .SUFFIXES line with no sources clears out all old suffixes
957: * a .PRECIOUS line makes all targets precious
958: * a .IGNORE line ignores errors for all targets
959: * a .SILENT line creates silence when making all targets
960: * a .PATH removes all directories from the search path(s).
961: */
962: if (!*line) {
963: switch (specType) {
964: case Suffixes:
1.59 espie 965: Suff_ClearSuffixes();
1.1 deraadt 966: break;
967: case Precious:
968: allPrecious = TRUE;
969: break;
970: case Ignore:
971: ignoreErrors = TRUE;
972: break;
973: case Silent:
974: beSilent = TRUE;
975: break;
976: case ExPath:
1.45 espie 977: Lst_Every(&paths, ParseClearPath);
1.1 deraadt 978: break;
979: default:
980: break;
981: }
982: } else if (specType == MFlags) {
983: /*
984: * Call on functions in main.c to deal with these arguments and
985: * set the initial character to a null-character so the loop to
986: * get sources won't get anything
987: */
1.59 espie 988: Main_ParseArgLine(line);
1.1 deraadt 989: *line = '\0';
990: } else if (specType == ExShell) {
1.59 espie 991: if (Job_ParseShell(line) != SUCCESS) {
992: Parse_Error(PARSE_FATAL, "improper shell specification");
1.1 deraadt 993: return;
994: }
995: *line = '\0';
1.59 espie 996: } else if (specType == NotParallel || specType == SingleShell) {
1.1 deraadt 997: *line = '\0';
998: }
1.11 millert 999:
1.1 deraadt 1000: /*
1.11 millert 1001: * NOW GO FOR THE SOURCES
1.1 deraadt 1002: */
1.59 espie 1003: if (specType == Suffixes || specType == ExPath ||
1004: specType == Includes || specType == Libs ||
1005: specType == Null) {
1.1 deraadt 1006: while (*line) {
1007: /*
1008: * If the target was one that doesn't take files as its sources
1009: * but takes something like suffixes, we take each
1010: * space-separated word on the line as a something and deal
1011: * with it accordingly.
1012: *
1013: * If the target was .SUFFIXES, we take each source as a
1014: * suffix and add it to the list of suffixes maintained by the
1015: * Suff module.
1016: *
1017: * If the target was a .PATH, we add the source as a directory
1018: * to search on the search path.
1019: *
1020: * If it was .INCLUDES, the source is taken to be the suffix of
1021: * files which will be #included and whose search path should
1022: * be present in the .INCLUDES variable.
1023: *
1024: * If it was .LIBS, the source is taken to be the suffix of
1025: * files which are considered libraries and whose search path
1026: * should be present in the .LIBS variable.
1027: *
1028: * If it was .NULL, the source is the suffix to use when a file
1029: * has no valid suffix.
1030: */
1031: char savec;
1.59 espie 1032: while (*cp && !isspace(*cp)) {
1.1 deraadt 1033: cp++;
1034: }
1035: savec = *cp;
1036: *cp = '\0';
1037: switch (specType) {
1038: case Suffixes:
1.59 espie 1039: Suff_AddSuffix(line);
1.1 deraadt 1040: break;
1041: case ExPath:
1.45 espie 1042: Lst_ForEach(&paths, ParseAddDir, line);
1.1 deraadt 1043: break;
1044: case Includes:
1.59 espie 1045: Suff_AddInclude(line);
1.1 deraadt 1046: break;
1047: case Libs:
1.59 espie 1048: Suff_AddLib(line);
1.1 deraadt 1049: break;
1050: case Null:
1.59 espie 1051: Suff_SetNull(line);
1.1 deraadt 1052: break;
1053: default:
1054: break;
1055: }
1056: *cp = savec;
1057: if (savec != '\0') {
1058: cp++;
1059: }
1.59 espie 1060: while (*cp && isspace(*cp)) {
1.1 deraadt 1061: cp++;
1062: }
1063: line = cp;
1064: }
1.45 espie 1065: Lst_Destroy(&paths, NOFREE);
1.1 deraadt 1066: } else {
1067: while (*line) {
1068: /*
1069: * The targets take real sources, so we must beware of archive
1070: * specifications (i.e. things with left parentheses in them)
1071: * and handle them accordingly.
1072: */
1.59 espie 1073: while (*cp && !isspace(*cp)) {
1074: if (*cp == '(' && cp > line && cp[-1] != '$') {
1.1 deraadt 1075: /*
1076: * Only stop for a left parenthesis if it isn't at the
1077: * start of a word (that'll be for variable changes
1078: * later) and isn't preceded by a dollar sign (a dynamic
1079: * source).
1080: */
1081: break;
1082: } else {
1083: cp++;
1084: }
1085: }
1086:
1087: if (*cp == '(') {
1088: GNode *gn;
1.59 espie 1089: LIST sources; /* list of archive source names after
1090: * expansion */
1.1 deraadt 1091:
1.43 espie 1092: Lst_Init(&sources);
1.48 espie 1093: if (Arch_ParseArchive(&line, &sources, NULL) != SUCCESS) {
1.59 espie 1094: Parse_Error(PARSE_FATAL,
1.1 deraadt 1095: "Error in source archive spec \"%s\"", line);
1096: return;
1097: }
1098:
1.43 espie 1099: while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL)
1100: ParseDoSrc(tOp, gn->name, &curSrcs);
1.1 deraadt 1101: cp = line;
1102: } else {
1103: if (*cp) {
1104: *cp = '\0';
1105: cp += 1;
1106: }
1107:
1.43 espie 1108: ParseDoSrc(tOp, line, &curSrcs);
1.1 deraadt 1109: }
1.59 espie 1110: while (*cp && isspace(*cp)) {
1.1 deraadt 1111: cp++;
1112: }
1113: line = cp;
1114: }
1115: }
1.11 millert 1116:
1.33 espie 1117: if (mainNode == NULL) {
1.59 espie 1118: /* If we have yet to decide on a main target to make, in the
1.1 deraadt 1119: * absence of any user input, we want the first target on
1120: * the first dependency line that is actually a real target
1.59 espie 1121: * (i.e. isn't a .USE or .EXEC rule) to be made. */
1.45 espie 1122: Lst_Find(&targets, ParseFindMain, NULL);
1.1 deraadt 1123: }
1124:
1.43 espie 1125: /* Finally, destroy the list of sources. */
1126: Lst_Destroy(&curSrcs, NOFREE);
1.1 deraadt 1127: }
1128:
1129: /*-
1130: *---------------------------------------------------------------------
1.59 espie 1131: * Parse_IsVar --
1.1 deraadt 1132: * Return TRUE if the passed line is a variable assignment. A variable
1133: * assignment consists of a single word followed by optional whitespace
1134: * followed by either a += or an = operator.
1135: * This function is used both by the Parse_File function and main when
1136: * parsing the command-line arguments.
1137: *
1138: * Results:
1139: * TRUE if it is. FALSE if it ain't
1140: *---------------------------------------------------------------------
1141: */
1142: Boolean
1.59 espie 1143: Parse_IsVar(line)
1144: char *line; /* the line to check */
1.1 deraadt 1145: {
1.59 espie 1146: Boolean wasSpace = FALSE; /* set TRUE if found a space */
1147: Boolean haveName = FALSE; /* Set TRUE if have a variable name */
1.1 deraadt 1148: int level = 0;
1149: #define ISEQOPERATOR(c) \
1.59 espie 1150: ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!')
1.1 deraadt 1151:
1152: for (; *line != '=' || level != 0; line++)
1153: switch (*line) {
1154: case '\0':
1.59 espie 1155: /* end-of-line -- can't be a variable assignment. */
1.1 deraadt 1156: return FALSE;
1157:
1158: case ' ':
1159: case '\t':
1160: /*
1161: * there can be as much white space as desired so long as there is
1.11 millert 1162: * only one word before the operator
1.1 deraadt 1163: */
1164: wasSpace = TRUE;
1165: break;
1166:
1167: case '(':
1168: case '{':
1169: level++;
1170: break;
1171:
1172: case '}':
1173: case ')':
1174: level--;
1175: break;
1.11 millert 1176:
1.1 deraadt 1177: default:
1178: if (wasSpace && haveName) {
1179: if (ISEQOPERATOR(*line)) {
1.59 espie 1180: /* We must have a finished word. */
1.9 briggs 1181: if (level != 0)
1182: return FALSE;
1183:
1.59 espie 1184: /* When an = operator [+?!:] is found, the next
1.9 briggs 1185: * character must be an = or it ain't a valid
1.59 espie 1186: * assignment. */
1.9 briggs 1187: if (line[1] == '=')
1.1 deraadt 1188: return haveName;
1.59 espie 1189: /* This is a shell command. */
1190: if (FEATURES(FEATURE_SUNSHCMD) &&
1191: strncmp(line, ":sh", 3) == 0)
1.9 briggs 1192: return haveName;
1.1 deraadt 1193: }
1.59 espie 1194: /* This is the start of another word, so not assignment. */
1.9 briggs 1195: return FALSE;
1.1 deraadt 1196: }
1197: else {
1.11 millert 1198: haveName = TRUE;
1.1 deraadt 1199: wasSpace = FALSE;
1200: }
1201: break;
1202: }
1203:
1204: return haveName;
1205: }
1206:
1.59 espie 1207: static const char *
1208: find_op1(p)
1209: const char *p;
1210: {
1211: for(;; p++) {
1212: if (*p == '=' || isspace(*p) || *p == '$')
1213: break;
1214: if (p[1] == '=' && (*p == '?' || *p == ':' || *p == '!' || *p == '+'))
1215: break;
1216: if (p[0] == ':' && p[1] == 's' && p[2] == 'h')
1217: break;
1218: }
1219: return p;
1220: }
1221:
1222: static const char *
1223: find_op2(p)
1224: const char *p;
1225: {
1226: for(;; p++) {
1227: if (*p == '=' || isspace(*p) || *p == '$')
1228: break;
1229: if (p[1] == '=' && (*p == '?' || *p == ':' || *p == '!' || *p == '+'))
1230: break;
1231: }
1232: return p;
1233: }
1234:
1.1 deraadt 1235: /*-
1236: *---------------------------------------------------------------------
1.59 espie 1237: * Parse_DoVar --
1.1 deraadt 1238: * Take the variable assignment in the passed line and do it in the
1239: * global context.
1240: *
1241: * Note: There is a lexical ambiguity with assignment modifier characters
1242: * in variable names. This routine interprets the character before the =
1243: * as a modifier. Therefore, an assignment like
1244: * C++=/usr/bin/CC
1245: * is interpreted as "C+ +=" instead of "C++ =".
1246: *
1247: * Side Effects:
1248: * the variable structure of the given variable name is altered in the
1249: * global context.
1250: *---------------------------------------------------------------------
1251: */
1252: void
1.59 espie 1253: Parse_DoVar(line, ctxt)
1254: const char *line; /* a line guaranteed to be a variable
1.1 deraadt 1255: * assignment. This reduces error checks */
1.59 espie 1256: GSymT *ctxt; /* Context in which to do the assignment */
1.1 deraadt 1257: {
1.59 espie 1258: const char *end;
1259: const char *arg;
1.1 deraadt 1260: enum {
1261: VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1.59 espie 1262: } type; /* Type of assignment */
1263: struct Name name;
1.1 deraadt 1264:
1.59 espie 1265: end = Var_Name_Get(line, &name, (SymTable *)ctxt, TRUE,
1266: FEATURES(FEATURE_SUNSHCMD) ? find_op1 : find_op2);
1.1 deraadt 1267:
1.59 espie 1268: while (isspace(*end))
1269: end++;
1.1 deraadt 1270:
1.59 espie 1271: /* Check operator type. */
1272: switch (*end) {
1.1 deraadt 1273: case '+':
1274: type = VAR_APPEND;
1275: break;
1276:
1277: case '?':
1.59 espie 1278: /* If the variable already has a value, we don't do anything. */
1279: if (Var_Value_interval(name.s, name.e) != NULL) {
1280: Var_Name_Free(&name);
1.1 deraadt 1281: return;
1282: }
1.59 espie 1283: type = VAR_NORMAL;
1.1 deraadt 1284: break;
1285:
1286: case ':':
1.60 ! espie 1287: if (FEATURES(FEATURE_SUNSHCMD) && strncmp(end, ":sh", 3) == 0)
! 1288: type = VAR_SHELL;
! 1289: else
! 1290: type = VAR_SUBST;
1.1 deraadt 1291: break;
1292:
1293: case '!':
1294: type = VAR_SHELL;
1295: break;
1296:
1297: default:
1.60 ! espie 1298: type = VAR_NORMAL;
1.1 deraadt 1299: break;
1300: }
1301:
1.59 espie 1302: /* Find operator itself and go over it. */
1303: arg = end;
1304: while (*arg != '=')
1305: arg++;
1306: arg++;
1307: while (isspace(*arg))
1308: arg++;
1309:
1310: if (type == VAR_APPEND)
1311: Var_Append_interval(name.s, name.e, arg, ctxt);
1312: else if (type == VAR_SUBST) {
1313: char *sub;
1.1 deraadt 1314: /*
1315: * Allow variables in the old value to be undefined, but leave their
1316: * invocation alone -- this is done by forcing oldVars to be false.
1317: * XXX: This can cause recursive variables, but that's not hard to do,
1318: * and this allows someone to do something like
1319: *
1320: * CFLAGS = $(.INCLUDES)
1321: * CFLAGS := -I.. $(CFLAGS)
1322: *
1323: * And not get an error.
1324: */
1.59 espie 1325: Boolean oldOldVars = oldVars;
1.1 deraadt 1326:
1327: oldVars = FALSE;
1.59 espie 1328: /* ensure the variable is set to something to avoid `variable
1329: * is recursive' errors. */
1330: if (Var_Value_interval(name.s, name.e) == NULL)
1331: Var_Set_interval(name.s, name.e, "", ctxt);
1332:
1333: sub = Var_Subst(arg, (SymTable *)ctxt, FALSE);
1.1 deraadt 1334: oldVars = oldOldVars;
1335:
1.59 espie 1336: Var_Set_interval(name.s, name.e, sub, ctxt);
1337: free(sub);
1.1 deraadt 1338: } else if (type == VAR_SHELL) {
1.9 briggs 1339: char *res, *err;
1.1 deraadt 1340:
1.59 espie 1341: if (strchr(arg, '$') != NULL) {
1342: char *sub;
1343: /* There's a dollar sign in the command, so perform variable
1344: * expansion on the whole thing. */
1345: sub = Var_Subst(arg, NULL, TRUE);
1346: res = Cmd_Exec(sub, &err);
1347: free(sub);
1348: } else
1349: res = Cmd_Exec(arg, &err);
1.1 deraadt 1350:
1.59 espie 1351: Var_Set_interval(name.s, name.e, res, ctxt);
1.9 briggs 1352: free(res);
1.1 deraadt 1353:
1.9 briggs 1354: if (err)
1.59 espie 1355: Parse_Error(PARSE_WARNING, err, arg);
1.1 deraadt 1356:
1.59 espie 1357: } else
1358: /* Normal assignment -- just do it. */
1359: Var_Set_interval(name.s, name.e, arg, ctxt);
1360: Var_Name_Free(&name);
1.1 deraadt 1361: }
1362:
1.9 briggs 1363:
1.1 deraadt 1364: /*-
1.59 espie 1365: * ParseAddCmd --
1.1 deraadt 1366: * Lst_ForEach function to add a command line to all targets
1367: *
1368: * Side Effects:
1369: * A new element is added to the commands list of the node.
1370: */
1.41 espie 1371: static void
1.1 deraadt 1372: ParseAddCmd(gnp, cmd)
1.42 espie 1373: void *gnp; /* the node to which the command is to be added */
1374: void *cmd; /* the command to add */
1.1 deraadt 1375: {
1.41 espie 1376: GNode *gn = (GNode *)gnp;
1.1 deraadt 1377: /* if target already supplied, ignore commands */
1.39 espie 1378: if (!(gn->type & OP_HAS_COMMANDS)) {
1.43 espie 1379: Lst_AtEnd(&gn->commands, cmd);
1.39 espie 1380: if (!gn->lineno) {
1381: gn->lineno = Parse_Getlineno();
1382: gn->fname = Parse_Getfilename();
1383: }
1384: }
1.1 deraadt 1385: }
1386:
1387: /*-
1388: *-----------------------------------------------------------------------
1389: * ParseHasCommands --
1390: * Callback procedure for Parse_File when destroying the list of
1391: * targets on the last dependency line. Marks a target as already
1392: * having commands if it does, to keep from having shell commands
1393: * on multiple dependency lines.
1394: *
1395: * Side Effects:
1396: * OP_HAS_COMMANDS may be set for the target.
1397: *-----------------------------------------------------------------------
1398: */
1399: static void
1400: ParseHasCommands(gnp)
1.42 espie 1401: void *gnp; /* Node to examine */
1.1 deraadt 1402: {
1.59 espie 1403: GNode *gn = (GNode *)gnp;
1.43 espie 1404: if (!Lst_IsEmpty(&gn->commands)) {
1.1 deraadt 1405: gn->type |= OP_HAS_COMMANDS;
1406: }
1407: }
1408:
1409: /*-
1410: *-----------------------------------------------------------------------
1411: * Parse_AddIncludeDir --
1412: * Add a directory to the path searched for included makefiles
1413: * bracketed by double-quotes. Used by functions in main.c
1414: *-----------------------------------------------------------------------
1415: */
1416: void
1.43 espie 1417: Parse_AddIncludeDir(dir)
1.59 espie 1418: const char *dir; /* The name of the directory to add */
1.1 deraadt 1419: {
1.56 espie 1420: Dir_AddDir(&parseIncPath, dir, NULL);
1.1 deraadt 1421: }
1422:
1423: /*-
1424: *---------------------------------------------------------------------
1425: * ParseDoInclude --
1426: * Push to another file.
1.11 millert 1427: *
1.1 deraadt 1428: * The input is the line minus the #include. A file spec is a string
1429: * enclosed in <> or "". The former is looked for only in sysIncPath.
1430: * The latter in . and the directories specified by -I command line
1431: * options
1432: *
1433: * Side Effects:
1.59 espie 1434: * old parse context is pushed on the stack, new file becomes
1.50 espie 1435: * current context.
1.1 deraadt 1436: *---------------------------------------------------------------------
1437: */
1438: static void
1.50 espie 1439: ParseDoInclude(file)
1.59 espie 1440: char *file; /* file specification */
1.1 deraadt 1441: {
1.59 espie 1442: char endc; /* the character which ends the file spec */
1443: char *cp; /* current position in file spec */
1444: Boolean isSystem; /* TRUE if makefile is a system makefile */
1.1 deraadt 1445:
1.59 espie 1446: /* Skip to delimiter character so we know where to look. */
1.50 espie 1447: while (*file == ' ' || *file == '\t')
1.1 deraadt 1448: file++;
1449:
1.50 espie 1450: if (*file != '"' && *file != '<') {
1.59 espie 1451: Parse_Error(PARSE_FATAL,
1.1 deraadt 1452: ".include filename must be delimited by '\"' or '<'");
1453: return;
1454: }
1455:
1.50 espie 1456: /* Set the search path on which to find the include file based on the
1.1 deraadt 1457: * characters which bracket its name. Angle-brackets imply it's
1.50 espie 1458: * a system Makefile while double-quotes imply it's a user makefile */
1.1 deraadt 1459: if (*file == '<') {
1460: isSystem = TRUE;
1461: endc = '>';
1462: } else {
1463: isSystem = FALSE;
1464: endc = '"';
1465: }
1466:
1.59 espie 1467: /* Skip to matching delimiter. */
1468: for (cp = ++file; *cp != endc; cp++) {
1469: if (*cp == '\0') {
1.50 espie 1470: Parse_Error(PARSE_FATAL,
1.1 deraadt 1471: "Unclosed %cinclude filename. '%c' expected",
1472: '.', endc);
1.50 espie 1473: return;
1.1 deraadt 1474: }
1475: }
1.59 espie 1476: ParseLookupIncludeFile(file, cp, isSystem, TRUE);
1.1 deraadt 1477: }
1478:
1479: /*-
1480: *---------------------------------------------------------------------
1481: * ParseTraditionalInclude --
1482: * Push to another file.
1.11 millert 1483: *
1.1 deraadt 1484: * The input is the line minus the "include". The file name is
1485: * the string following the "include".
1486: *
1487: * Side Effects:
1.59 espie 1488: * old parse context is pushed on the stack, new file becomes
1.50 espie 1489: * current context.
1.59 espie 1490: *
1491: * XXX May wish to support multiple files and wildcards ?
1.1 deraadt 1492: *---------------------------------------------------------------------
1493: */
1494: static void
1.50 espie 1495: ParseTraditionalInclude(file)
1.59 espie 1496: char *file; /* file specification */
1.1 deraadt 1497: {
1.59 espie 1498: char *cp; /* current position in file spec */
1.1 deraadt 1499:
1.59 espie 1500: /* Skip over whitespace. */
1501: while (isspace(*file))
1.1 deraadt 1502: file++;
1.59 espie 1503: if (*file == '\0') {
1504: Parse_Error(PARSE_FATAL,
1505: "Filename missing from \"include\"");
1506: return;
1507: }
1508: /* Skip to end of line or next whitespace. */
1509: for (cp = file; *cp != '\0' && !isspace(*cp);)
1510: cp++;
1511:
1512: ParseLookupIncludeFile(file, cp, TRUE, TRUE);
1513: }
1514:
1515: /*-
1516: *---------------------------------------------------------------------
1517: * ParseConditionalInclude --
1518: * May push to another file.
1519: *
1520: * No error if the file does not exist.
1521: * See ParseTraditionalInclude otherwise.
1522: *---------------------------------------------------------------------
1523: */
1524: static void
1525: ParseConditionalInclude(file)
1526: char *file; /* file specification */
1527: {
1528: char *cp; /* current position in file spec */
1.1 deraadt 1529:
1.59 espie 1530: /* Skip over whitespace. */
1531: while (isspace(*file))
1532: file++;
1.1 deraadt 1533: if (*file == '\0') {
1.59 espie 1534: Parse_Error(PARSE_FATAL,
1.1 deraadt 1535: "Filename missing from \"include\"");
1536: return;
1537: }
1.59 espie 1538: /* Skip to end of line or next whitespace. */
1.50 espie 1539: for (cp = file; *cp != '\0' && !isspace(*cp);)
1.59 espie 1540: cp++;
1.1 deraadt 1541:
1.59 espie 1542: ParseLookupIncludeFile(file, cp, TRUE, FALSE);
1.50 espie 1543: }
1.1 deraadt 1544:
1.50 espie 1545: /* Common part to lookup and read an include file. */
1546: static void
1.59 espie 1547: ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound)
1.50 espie 1548: char *spec;
1549: char *endSpec;
1550: Boolean isSystem;
1.59 espie 1551: Boolean errIfNotFound;
1.50 espie 1552: {
1553: char *file;
1554: char *fullname;
1555: char endc;
1556:
1557: /* Substitute for any variables in the file name before trying to
1.59 espie 1558: * find the thing. */
1.50 espie 1559: endc = *endSpec;
1560: *endSpec = '\0';
1561: file = Var_Subst(spec, NULL, FALSE);
1562: *endSpec = endc;
1563:
1564: /* Now that we know the file name and its search path, we attempt to
1565: * find the durn thing. NULL indicates the file still hasn't been
1566: * found. */
1567: fullname = NULL;
1568:
1569: /* Handle non-system non-absolute files... */
1570: if (!isSystem && file[0] != '/') {
1.59 espie 1571: /* ... by first searching relative to the including file's
1572: * location. We don't want to cd there, of course, so we
1573: * just tack on the old file's leading path components
1.50 espie 1574: * and call Dir_FindFile to see if we can locate the beast. */
1.59 espie 1575: char *slash;
1.50 espie 1576:
1577: slash = strrchr(Parse_Getfilename(), '/');
1578: if (slash != NULL) {
1579: char *base, *newName;
1580:
1581: base = interval_dup(Parse_Getfilename(), slash);
1.52 espie 1582: newName = str_concat(base, file, '/');
1.50 espie 1583: free(base);
1584: fullname = Dir_FindFile(newName, &parseIncPath);
1585: if (fullname == NULL)
1586: fullname = Dir_FindFile(newName, &dirSearchPath);
1587: free(newName);
1588: }
1.1 deraadt 1589: }
1590:
1.59 espie 1591: /* Now look first on the -I search path, then on the .PATH
1.50 espie 1592: * search path, if not found in a -I directory.
1593: * XXX: Suffix specific? */
1.59 espie 1594: if (fullname == NULL)
1.43 espie 1595: fullname = Dir_FindFile(file, &parseIncPath);
1.50 espie 1596: if (fullname == NULL)
1597: fullname = Dir_FindFile(file, &dirSearchPath);
1.1 deraadt 1598:
1.50 espie 1599: /* Still haven't found the makefile. Look for it on the system
1600: * path as a last resort. */
1601: if (fullname == NULL)
1.43 espie 1602: fullname = Dir_FindFile(file, &sysIncPath);
1.1 deraadt 1603:
1.59 espie 1604: if (fullname == NULL && errIfNotFound)
1605: Parse_Error(PARSE_FATAL, "Could not find %s", file);
1606:
1.1 deraadt 1607:
1.50 espie 1608: free(file);
1.1 deraadt 1609:
1.50 espie 1610: if (fullname != NULL) {
1.59 espie 1611: FILE *f;
1.1 deraadt 1612:
1.50 espie 1613: f = fopen(fullname, "r");
1.59 espie 1614: if (f == NULL && errIfNotFound) {
1.50 espie 1615: Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1616: } else {
1617: /* Once we find the absolute path to the file, we push the current
1618: * stream to the includes stack, and start reading from the new
1619: * file. We set up the file name to be its absolute name so that
1.59 espie 1620: * error messages are informative. */
1.50 espie 1621: Parse_FromFile(fullname, f);
1622: }
1.1 deraadt 1623: }
1624: }
1625:
1.59 espie 1626:
1627:
1628:
1629: /* Strip comments from the line. May return either a copy of the line, or
1630: * the line itself. */
1631: static char *
1632: strip_comments(copy, line)
1633: Buffer copy;
1634: const char *line;
1635: {
1636: const char *comment;
1637: const char *p;
1638:
1639: comment = strchr(line, '#');
1640: assert(comment != line);
1641: if (comment == NULL)
1642: return (char *)line;
1643: else {
1644: Buf_Reset(copy);
1645:
1646: for (p = line; *p != '\0'; p++) {
1647: if (*p == '\\') {
1648: if (p[1] == '#') {
1649: Buf_AddInterval(copy, line, p);
1650: Buf_AddChar(copy, '#');
1651: line = p+2;
1652: }
1653: if (p[1] != '\0')
1654: p++;
1655: } else if (*p == '#')
1656: break;
1657: }
1658: Buf_AddInterval(copy, line, p);
1659: Buf_KillTrailingSpaces(copy);
1660: return Buf_Retrieve(copy);
1661: }
1662: }
1663:
1664: static Boolean
1665: ParseIsCond(linebuf, copy, line)
1666: Buffer linebuf;
1667: Buffer copy;
1668: char *line;
1669: {
1670:
1671: char *stripped;
1672:
1673: while (*line != '\0' && isspace(*line))
1674: line++;
1675:
1676: /* The line might be a conditional. Ask the conditional module
1677: * about it and act accordingly. */
1678: switch (Cond_Eval(line)) {
1679: case COND_SKIP:
1680: /* Skip to next conditional that evaluates to COND_PARSE. */
1681: do {
1682: line = ParseSkipGetLine(linebuf);
1683: if (line != NULL) {
1684: while (*line != '\0' && isspace(*line))
1685: line++;
1686: stripped = strip_comments(copy, line);
1687: }
1688: } while (line != NULL && Cond_Eval(stripped) != COND_PARSE);
1689: /* FALLTHROUGH */
1690: case COND_PARSE:
1691: return TRUE;
1692: default:
1693: break;
1694: }
1695:
1696: {
1697: For *loop;
1698:
1699: loop = For_Eval(line);
1700: if (loop != NULL) {
1701: Boolean ok;
1702: do {
1703: /* Find the matching endfor. */
1704: line = ParseGetLoopLine(linebuf);
1705: if (line == NULL) {
1706: Parse_Error(PARSE_FATAL,
1707: "Unexpected end of file in for loop.\n");
1708: return FALSE;
1709: }
1710: ok = For_Accumulate(loop, line);
1711: } while (ok);
1712: For_Run(loop);
1713: return TRUE;
1714: }
1715: }
1716:
1717: if (strncmp(line, "include", 7) == 0) {
1718: ParseDoInclude(line + 7);
1719: return TRUE;
1720: } else if (strncmp(line, "undef", 5) == 0) {
1721: char *cp;
1722:
1723: line+=5;
1724: while (*line != '\0' && isspace(*line))
1725: line++;
1726: for (cp = line; !isspace(*cp) && *cp != '\0';)
1727: cp++;
1728: *cp = '\0';
1729: Var_Delete(line);
1730: return TRUE;
1731: }
1732: return FALSE;
1733: }
1734:
1.1 deraadt 1735: /*-
1736: *-----------------------------------------------------------------------
1.59 espie 1737: * ParseFinishDependency --
1.1 deraadt 1738: * Handle the end of a dependency group.
1739: *
1740: * Side Effects:
1.59 espie 1741: * 'targets' list destroyed.
1.1 deraadt 1742: *
1743: *-----------------------------------------------------------------------
1744: */
1745: static void
1.59 espie 1746: ParseFinishDependency()
1.1 deraadt 1747: {
1.59 espie 1748: Lst_Every(&targets, Suff_EndTransform);
1749: Lst_Destroy(&targets, ParseHasCommands);
1.1 deraadt 1750: }
1.11 millert 1751:
1.59 espie 1752: static void
1753: ParseDoCommands(line)
1754: const char *line;
1755: {
1756: /* add the command to the list of
1757: * commands of all targets in the dependency spec */
1758: char *cmd = estrdup(line);
1759:
1760: Lst_ForEach(&targets, ParseAddCmd, cmd);
1761: #ifdef CLEANUP
1762: Lst_AtEnd(&targCmds, cmd);
1763: #endif
1764: }
1.1 deraadt 1765:
1766: /*-
1767: *---------------------------------------------------------------------
1768: * Parse_File --
1769: * Parse a file into its component parts, incorporating it into the
1770: * current dependency graph. This is the main function and controls
1771: * almost every other function in this module
1772: *
1773: * Side Effects:
1774: * Loads. Nodes are added to the list of all targets, nodes and links
1775: * are added to the dependency graph. etc. etc. etc.
1776: *---------------------------------------------------------------------
1777: */
1778: void
1779: Parse_File(name, stream)
1.59 espie 1780: char *name; /* the name of the file being read */
1781: FILE *stream; /* Stream open to makefile to parse */
1.1 deraadt 1782: {
1.59 espie 1783: char *cp, /* pointer into the line */
1784: *line; /* the line we're working on */
1785: Boolean inDependency; /* true if currently in a dependency
1786: * line or its commands */
1787:
1788: BUFFER buf;
1789: BUFFER copy;
1790:
1791: Buf_Init(&buf, MAKE_BSIZE);
1792: Buf_Init(©, MAKE_BSIZE);
1793: inDependency = FALSE;
1794: Parse_FromFile(name, stream);
1.1 deraadt 1795:
1796: do {
1.59 espie 1797: while ((line = ParseReadLine(&buf)) != NULL) {
1.1 deraadt 1798: if (*line == '\t') {
1.59 espie 1799: if (inDependency)
1800: ParseDoCommands(line+1);
1801: else
1802: Parse_Error(PARSE_FATAL,
1803: "Unassociated shell command \"%s\"",
1804: line);
1.1 deraadt 1805: } else {
1.59 espie 1806: char *stripped;
1807: stripped = strip_comments(©, line);
1808: if (*stripped == '.' && ParseIsCond(&buf, ©, stripped+1))
1809: ;
1810: else if (FEATURES(FEATURE_SYSVINCLUDE) &&
1811: strncmp(stripped, "include", 7) == 0 &&
1812: isspace(stripped[7]) &&
1813: strchr(stripped, ':') == NULL) {
1814: /* It's an S3/S5-style "include". */
1815: ParseTraditionalInclude(stripped + 7);
1816: } else if (FEATURES(FEATURE_CONDINCLUDE) &&
1817: (*stripped == '-' || *stripped == 's') &&
1818: strncmp(stripped+1, "include", 7) == 0 &&
1819: isspace(stripped[8]) &&
1820: strchr(stripped, ':') == NULL) {
1821: ParseConditionalInclude(stripped+8);
1822: } else {
1823: char *dep;
1.11 millert 1824:
1.59 espie 1825: if (inDependency)
1826: ParseFinishDependency();
1827: if (Parse_IsVar(stripped)) {
1828: inDependency = FALSE;
1829: Parse_DoVar(stripped, VAR_GLOBAL);
1830: } else {
1831: size_t pos;
1832: char *end;
1.11 millert 1833:
1.59 espie 1834: /* Need a new list for the target nodes. */
1835: Lst_Init(&targets);
1836: inDependency = TRUE;
1837:
1838: dep = NULL;
1839: /* First we need to find eventual dependencies */
1840: pos = strcspn(stripped, ":!");
1841: /* go over :!, and find ; */
1842: if (stripped[pos] != '\0' &&
1843: (end = strchr(stripped+pos+1, ';')) != NULL) {
1844: if (line != stripped)
1845: /* find matching ; in original... The
1846: * original might be slightly longer. */
1847: dep = strchr(line+(end-stripped), ';');
1848: else
1849: dep = end;
1850: /* kill end of line. */
1851: *end = '\0';
1852: }
1853: /* We now know it's a dependency line so it needs to
1854: * have all variables expanded before being parsed.
1855: * Tell the variable module to complain if some
1856: * variable is undefined... */
1857: cp = Var_Subst(stripped, NULL, TRUE);
1858: ParseDoDependency(cp);
1859: free(cp);
1860:
1861: /* Parse dependency if it's not empty. */
1862: if (dep != NULL) {
1863: do {
1864: dep++;
1865: } while (isspace(*dep));
1866: if (*dep != '\0')
1867: ParseDoCommands(dep);
1868: }
1.1 deraadt 1869: }
1870: }
1871: }
1872: }
1.50 espie 1873: } while (Parse_NextFile());
1.1 deraadt 1874:
1.59 espie 1875: if (inDependency)
1876: ParseFinishDependency();
1877: /* Make sure conditionals are clean. */
1.1 deraadt 1878: Cond_End();
1879:
1.50 espie 1880: Finish_Errors();
1.59 espie 1881: Buf_Destroy(&buf);
1882: Buf_Destroy(©);
1.1 deraadt 1883: }
1884:
1885: /*-
1886: *---------------------------------------------------------------------
1887: * Parse_Init --
1888: * initialize the parsing module
1889: *
1890: * Side Effects:
1891: * the parseIncPath list is initialized...
1892: *---------------------------------------------------------------------
1893: */
1894: void
1.43 espie 1895: Parse_Init()
1.1 deraadt 1896: {
1.33 espie 1897: mainNode = NULL;
1.43 espie 1898: Lst_Init(&parseIncPath);
1899: Lst_Init(&sysIncPath);
1.45 espie 1900: Lst_Init(&targets);
1.20 espie 1901: #ifdef CLEANUP
1.50 espie 1902: LowParse_Init();
1.43 espie 1903: Lst_Init(&targCmds);
1904: Lst_Init(&fileNames);
1.20 espie 1905: #endif
1.1 deraadt 1906: }
1907:
1908: void
1909: Parse_End()
1910: {
1.20 espie 1911: #ifdef CLEANUP
1.43 espie 1912: Lst_Destroy(&targCmds, (SimpleProc)free);
1.58 espie 1913: Lst_Destroy(&fileNames, (SimpleProc)free);
1.59 espie 1914: Lst_Destroy(&targets, NOFREE);
1.43 espie 1915: Lst_Destroy(&sysIncPath, Dir_Destroy);
1916: Lst_Destroy(&parseIncPath, Dir_Destroy);
1.50 espie 1917: LowParse_End();
1.20 espie 1918: #endif
1.1 deraadt 1919: }
1.11 millert 1920:
1.1 deraadt 1921:
1922: /*-
1923: *-----------------------------------------------------------------------
1924: * Parse_MainName --
1925: * Return a Lst of the main target to create for main()'s sake. If
1926: * no such target exists, we Punt with an obnoxious error message.
1927: *
1.59 espie 1928: * Side effect:
1.44 espie 1929: * Add the node to create to the list.
1.1 deraadt 1930: *-----------------------------------------------------------------------
1931: */
1.44 espie 1932: void
1933: Parse_MainName(listmain)
1.59 espie 1934: Lst listmain; /* result list */
1.1 deraadt 1935: {
1936:
1.59 espie 1937: if (mainNode == NULL) {
1938: Punt("no target to make.");
1939: /*NOTREACHED*/
1940: } else if (mainNode->type & OP_DOUBLEDEP) {
1.37 espie 1941: Lst_AtEnd(listmain, mainNode);
1.45 espie 1942: Lst_Concat(listmain, &mainNode->cohorts);
1.1 deraadt 1943: }
1944: else
1.37 espie 1945: Lst_AtEnd(listmain, mainNode);
1.1 deraadt 1946: }
1.59 espie 1947: