Annotation of src/usr.bin/make/parse.c, Revision 1.44
1.44 ! espie 1: /* $OpenBSD: parse.c,v 1.43 2000/06/17 14:38:18 espie Exp $ */
1.13 millert 2: /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
1.1 deraadt 3:
4: /*
1.11 millert 5: * Copyright (c) 1988, 1989, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
1.1 deraadt 7: * Copyright (c) 1989 by Berkeley Softworks
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Adam de Boor.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the University of
24: * California, Berkeley and its contributors.
25: * 4. Neither the name of the University nor the names of its contributors
26: * may be used to endorse or promote products derived from this software
27: * without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: */
41:
42: #ifndef lint
43: #if 0
1.11 millert 44: static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
1.1 deraadt 45: #else
1.44 ! espie 46: static char rcsid[] = "$OpenBSD: parse.c,v 1.43 2000/06/17 14:38:18 espie Exp $";
1.1 deraadt 47: #endif
48: #endif /* not lint */
49:
50: /*-
51: * parse.c --
52: * Functions to parse a makefile.
53: *
54: * One function, Parse_Init, must be called before any functions
55: * in this module are used. After that, the function Parse_File is the
56: * main entry point and controls most of the other functions in this
57: * module.
58: *
59: * Most important structures are kept in Lsts. Directories for
60: * the #include "..." function are kept in the 'parseIncPath' Lst, while
61: * those for the #include <...> are kept in the 'sysIncPath' Lst. The
62: * targets currently being defined are kept in the 'targets' Lst.
63: *
64: * The variables 'fname' and 'lineno' are used to track the name
65: * of the current file and the line number in that file so that error
66: * messages can be more meaningful.
67: *
68: * Interface:
69: * Parse_Init Initialization function which must be
70: * called before anything else in this module
71: * is used.
72: *
73: * Parse_End Cleanup the module
74: *
75: * Parse_File Function used to parse a makefile. It must
76: * be given the name of the file, which should
77: * already have been opened, and a function
78: * to call to read a character from the file.
79: *
80: * Parse_IsVar Returns TRUE if the given line is a
81: * variable assignment. Used by MainParseArgs
82: * to determine if an argument is a target
83: * or a variable assignment. Used internally
84: * for pretty much the same thing...
85: *
86: * Parse_Error Function called when an error occurs in
87: * parsing. Used by the variable and
88: * conditional modules.
89: * Parse_MainName Returns a Lst of the main target to create.
90: */
91:
1.15 mickey 92: #ifdef __STDC__
1.1 deraadt 93: #include <stdarg.h>
94: #else
95: #include <varargs.h>
96: #endif
97: #include <stdio.h>
98: #include <ctype.h>
99: #include <errno.h>
100: #include "make.h"
101: #include "hash.h"
102: #include "dir.h"
103: #include "job.h"
104: #include "buf.h"
105: #include "pathnames.h"
106:
1.38 espie 107: #ifdef CLEANUP
1.43 espie 108: static LIST fileNames; /* file names to free at end */
1.38 espie 109: #endif
110:
1.1 deraadt 111: /*
112: * These values are returned by ParseEOF to tell Parse_File whether to
113: * CONTINUE parsing, i.e. it had only reached the end of an include file,
114: * or if it's DONE.
115: */
116: #define CONTINUE 1
117: #define DONE 0
118: static Lst targets; /* targets we're working on */
1.20 espie 119: #ifdef CLEANUP
1.43 espie 120: static LIST targCmds; /* command lines for targets */
1.20 espie 121: #endif
1.1 deraadt 122: static Boolean inLine; /* true if currently in a dependency
123: * line or its commands */
124: typedef struct {
125: char *str;
126: char *ptr;
127: } PTR;
128:
129: static char *fname; /* name of current file (for errors) */
1.23 espie 130: static unsigned long lineno; /* line number in current file */
1.1 deraadt 131: static FILE *curFILE = NULL; /* current makefile */
132:
133: static PTR *curPTR = NULL; /* current makefile */
134:
135: static int fatals = 0;
136:
137: static GNode *mainNode; /* The main target to create. This is the
138: * first target on the first dependency
139: * line in the first makefile */
140: /*
141: * Definitions for handling #include specifications
142: */
143: typedef struct IFile {
1.24 espie 144: char *fname; /* name of previous file */
145: unsigned long lineno; /* saved line number */
146: FILE *F; /* the open stream */
147: PTR *p; /* the char pointer */
1.1 deraadt 148: } IFile;
149:
1.43 espie 150: static LIST includes; /* stack of IFiles generated by
1.1 deraadt 151: * #includes */
1.43 espie 152: LIST parseIncPath; /* list of directories for "..." includes */
153: LIST sysIncPath; /* list of directories for <...> includes */
1.1 deraadt 154:
155: /*-
156: * specType contains the SPECial TYPE of the current target. It is
157: * Not if the target is unspecial. If it *is* special, however, the children
158: * are linked as children of the parent but not vice versa. This variable is
159: * set in ParseDoDependency
160: */
161: typedef enum {
162: Begin, /* .BEGIN */
163: Default, /* .DEFAULT */
164: End, /* .END */
165: Ignore, /* .IGNORE */
166: Includes, /* .INCLUDES */
167: Interrupt, /* .INTERRUPT */
168: Libs, /* .LIBS */
169: MFlags, /* .MFLAGS or .MAKEFLAGS */
170: Main, /* .MAIN and we don't have anything user-specified to
171: * make */
172: NoExport, /* .NOEXPORT */
1.17 espie 173: NoPath, /* .NOPATH */
1.1 deraadt 174: Not, /* Not special */
175: NotParallel, /* .NOTPARALELL */
176: Null, /* .NULL */
177: Order, /* .ORDER */
1.3 deraadt 178: Parallel, /* .PARALLEL */
1.1 deraadt 179: ExPath, /* .PATH */
1.7 niklas 180: Phony, /* .PHONY */
1.1 deraadt 181: Precious, /* .PRECIOUS */
182: ExShell, /* .SHELL */
183: Silent, /* .SILENT */
184: SingleShell, /* .SINGLESHELL */
185: Suffixes, /* .SUFFIXES */
1.3 deraadt 186: Wait, /* .WAIT */
1.1 deraadt 187: Attribute /* Generic attribute */
188: } ParseSpecial;
189:
190: static ParseSpecial specType;
1.3 deraadt 191: static int waiting;
1.1 deraadt 192:
193: /*
1.33 espie 194: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 deraadt 195: * seen, then set to each successive source on the line.
196: */
197: static GNode *predecessor;
198:
199: /*
200: * The parseKeywords table is searched using binary search when deciding
201: * if a target or source is special. The 'spec' field is the ParseSpecial
202: * type of the keyword ("Not" if the keyword isn't special as a target) while
203: * the 'op' field is the operator to apply to the list of targets if the
204: * keyword is used as a source ("0" if the keyword isn't special as a source)
205: */
206: static struct {
207: char *name; /* Name of keyword */
208: ParseSpecial spec; /* Type when used as a target */
209: int op; /* Operator when used as a source */
210: } parseKeywords[] = {
211: { ".BEGIN", Begin, 0 },
212: { ".DEFAULT", Default, 0 },
213: { ".END", End, 0 },
214: { ".EXEC", Attribute, OP_EXEC },
215: { ".IGNORE", Ignore, OP_IGNORE },
216: { ".INCLUDES", Includes, 0 },
217: { ".INTERRUPT", Interrupt, 0 },
218: { ".INVISIBLE", Attribute, OP_INVISIBLE },
219: { ".JOIN", Attribute, OP_JOIN },
220: { ".LIBS", Libs, 0 },
1.13 millert 221: { ".MADE", Attribute, OP_MADE },
1.1 deraadt 222: { ".MAIN", Main, 0 },
223: { ".MAKE", Attribute, OP_MAKE },
224: { ".MAKEFLAGS", MFlags, 0 },
225: { ".MFLAGS", MFlags, 0 },
1.17 espie 226: #if 0 /* basic scaffolding for NOPATH, not working yet */
227: { ".NOPATH", NoPath, OP_NOPATH },
228: #endif
1.1 deraadt 229: { ".NOTMAIN", Attribute, OP_NOTMAIN },
230: { ".NOTPARALLEL", NotParallel, 0 },
1.3 deraadt 231: { ".NO_PARALLEL", NotParallel, 0 },
1.1 deraadt 232: { ".NULL", Null, 0 },
233: { ".OPTIONAL", Attribute, OP_OPTIONAL },
234: { ".ORDER", Order, 0 },
1.3 deraadt 235: { ".PARALLEL", Parallel, 0 },
1.1 deraadt 236: { ".PATH", ExPath, 0 },
1.7 niklas 237: { ".PHONY", Phony, OP_PHONY },
1.1 deraadt 238: { ".PRECIOUS", Precious, OP_PRECIOUS },
239: { ".RECURSIVE", Attribute, OP_MAKE },
240: { ".SHELL", ExShell, 0 },
241: { ".SILENT", Silent, OP_SILENT },
242: { ".SINGLESHELL", SingleShell, 0 },
243: { ".SUFFIXES", Suffixes, 0 },
244: { ".USE", Attribute, OP_USE },
1.3 deraadt 245: { ".WAIT", Wait, 0 },
1.1 deraadt 246: };
247:
1.23 espie 248: static void ParseErrorInternal __P((char *, unsigned long, int, char *, ...));
249: static void ParseVErrorInternal __P((char *, unsigned long, int, char *, va_list));
1.1 deraadt 250: static int ParseFindKeyword __P((char *));
1.42 espie 251: static void ParseLinkSrc __P((void *, void *));
252: static int ParseDoOp __P((void *, void *));
253: static int ParseAddDep __P((void *, void *));
1.3 deraadt 254: static void ParseDoSrc __P((int, char *, Lst));
1.42 espie 255: static int ParseFindMain __P((void *, void *));
256: static void ParseAddDir __P((void *, void *));
257: static void ParseClearPath __P((void *));
1.1 deraadt 258: static void ParseDoDependency __P((char *));
1.42 espie 259: static void ParseAddCmd __P((void *, void *));
1.21 espie 260: static int __inline ParseReadc __P((void));
1.1 deraadt 261: static void ParseUnreadc __P((int));
1.42 espie 262: static void ParseHasCommands __P((void *));
1.1 deraadt 263: static void ParseDoInclude __P((char *));
264: #ifdef SYSVINCLUDE
265: static void ParseTraditionalInclude __P((char *));
266: #endif
267: static int ParseEOF __P((int));
268: static char *ParseReadLine __P((void));
269: static char *ParseSkipLine __P((int));
270: static void ParseFinishLine __P((void));
271:
272: /*-
273: *----------------------------------------------------------------------
274: * ParseFindKeyword --
275: * Look in the table of keywords for one matching the given string.
276: *
277: * Results:
278: * The index of the keyword, or -1 if it isn't there.
279: *
280: * Side Effects:
281: * None
282: *----------------------------------------------------------------------
283: */
284: static int
285: ParseFindKeyword (str)
286: char *str; /* String to find */
287: {
288: register int start,
289: end,
290: cur;
291: register int diff;
1.11 millert 292:
1.1 deraadt 293: start = 0;
294: end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
295:
296: do {
297: cur = start + ((end - start) / 2);
298: diff = strcmp (str, parseKeywords[cur].name);
299:
300: if (diff == 0) {
301: return (cur);
302: } else if (diff < 0) {
303: end = cur - 1;
304: } else {
305: start = cur + 1;
306: }
307: } while (start <= end);
308: return (-1);
309: }
310:
311: /*-
1.17 espie 312: * ParseVErrorInternal --
1.1 deraadt 313: * Error message abort function for parsing. Prints out the context
314: * of the error (line number and file) as well as the message with
315: * two optional arguments.
316: *
317: * Results:
318: * None
319: *
320: * Side Effects:
321: * "fatals" is incremented if the level is PARSE_FATAL.
322: */
323: /* VARARGS */
1.17 espie 324: static void
325: #ifdef __STDC__
1.23 espie 326: ParseVErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt,
1.17 espie 327: va_list ap)
328: #else
329: ParseVErrorInternal(va_alist)
330: va_dcl
331: #endif
332: {
1.23 espie 333: (void)fprintf(stderr, "\"%s\", line %lu: ", cfname, clineno);
1.17 espie 334: if (type == PARSE_WARNING)
335: (void)fprintf(stderr, "warning: ");
336: (void)vfprintf(stderr, fmt, ap);
337: va_end(ap);
338: (void)fprintf(stderr, "\n");
339: (void)fflush(stderr);
340: if (type == PARSE_FATAL)
341: fatals += 1;
342: }
343:
344: /*-
345: * ParseErrorInternal --
346: * Error function
347: *
348: * Results:
349: * None
350: *
351: * Side Effects:
352: * None
353: */
354: /* VARARGS */
355: static void
356: #ifdef __STDC__
1.23 espie 357: ParseErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt, ...)
1.17 espie 358: #else
359: ParseErrorInternal(va_alist)
360: va_dcl
361: #endif
362: {
363: va_list ap;
364: #ifdef __STDC__
365: va_start(ap, fmt);
366: #else
367: int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */
368: char *fmt;
369: char *cfname;
1.23 espie 370: unsigned long clineno;
1.17 espie 371:
372: va_start(ap);
373: cfname = va_arg(ap, char *);
1.23 espie 374: clineno = va_arg(ap, unsigned long);
1.17 espie 375: type = va_arg(ap, int);
376: fmt = va_arg(ap, char *);
377: #endif
378:
379: ParseVErrorInternal(cfname, clineno, type, fmt, ap);
380: va_end(ap);
381: }
382:
383: /*-
384: * Parse_Error --
385: * External interface to ParseErrorInternal; uses the default filename
386: * Line number.
387: *
388: * Results:
389: * None
390: *
391: * Side Effects:
392: * None
393: */
394: /* VARARGS */
1.1 deraadt 395: void
1.15 mickey 396: #ifdef __STDC__
1.1 deraadt 397: Parse_Error(int type, char *fmt, ...)
398: #else
399: Parse_Error(va_alist)
400: va_dcl
401: #endif
402: {
403: va_list ap;
1.15 mickey 404: #ifdef __STDC__
1.1 deraadt 405: va_start(ap, fmt);
406: #else
407: int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */
408: char *fmt;
409:
410: va_start(ap);
411: type = va_arg(ap, int);
412: fmt = va_arg(ap, char *);
413: #endif
414:
1.17 espie 415: ParseVErrorInternal(fname, lineno, type, fmt, ap);
1.1 deraadt 416: }
417:
418: /*-
419: *---------------------------------------------------------------------
420: * ParseLinkSrc --
421: * Link the parent node to its new child. Used in a Lst_ForEach by
422: * ParseDoDependency. If the specType isn't 'Not', the parent
423: * isn't linked as a parent of the child.
424: *
425: * Side Effects:
426: * New elements are added to the parents list of cgn and the
427: * children list of cgn. the unmade field of pgn is updated
428: * to reflect the additional child.
429: *---------------------------------------------------------------------
430: */
1.41 espie 431: static void
432: ParseLinkSrc(pgnp, cgnp)
1.42 espie 433: void *pgnp; /* The parent node */
434: void *cgnp; /* The child node */
1.1 deraadt 435: {
1.41 espie 436: GNode *pgn = (GNode *)pgnp;
437: GNode *cgn = (GNode *)cgnp;
1.43 espie 438: if (Lst_Member(&pgn->children, cgn) == NULL) {
439: Lst_AtEnd(&pgn->children, cgn);
1.41 espie 440: if (specType == Not)
1.43 espie 441: Lst_AtEnd(&cgn->parents, pgn);
1.1 deraadt 442: pgn->unmade += 1;
443: }
444: }
445:
446: /*-
447: *---------------------------------------------------------------------
448: * ParseDoOp --
449: * Apply the parsed operator to the given target node. Used in a
1.41 espie 450: * Lst_Find call by ParseDoDependency once all targets have
1.1 deraadt 451: * been found and their operator parsed. If the previous and new
452: * operators are incompatible, a major error is taken.
453: *
454: * Results:
1.40 espie 455: * 0 if a problem, 1 if ok.
1.1 deraadt 456: *
457: * Side Effects:
458: * The type field of the node is altered to reflect any new bits in
459: * the op.
460: *---------------------------------------------------------------------
461: */
462: static int
463: ParseDoOp (gnp, opp)
1.42 espie 464: void *gnp; /* The node to which the operator is to be
465: * applied */
466: void *opp; /* The operator to apply */
1.1 deraadt 467: {
468: GNode *gn = (GNode *) gnp;
469: int op = *(int *) opp;
470: /*
471: * If the dependency mask of the operator and the node don't match and
472: * the node has actually had an operator applied to it before, and
1.11 millert 473: * the operator actually has some dependency information in it, complain.
1.1 deraadt 474: */
475: if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
1.40 espie 476: !OP_NOP(gn->type) && !OP_NOP(op)) {
477: Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
478: return 0;
1.1 deraadt 479: }
480:
481: if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
482: /*
483: * If the node was the object of a :: operator, we need to create a
484: * new instance of it for the children and commands on this dependency
485: * line. The new instance is placed on the 'cohorts' list of the
486: * initial one (note the initial one is not on its own cohorts list)
487: * and the new instance is linked to all parents of the initial
488: * instance.
489: */
490: register GNode *cohort;
491: LstNode ln;
1.11 millert 492:
1.1 deraadt 493: cohort = Targ_NewGN(gn->name);
494: /*
495: * Duplicate links to parents so graph traversal is simple. Perhaps
496: * some type bits should be duplicated?
497: *
498: * Make the cohort invisible as well to avoid duplicating it into
499: * other variables. True, parents of this target won't tend to do
500: * anything with their local variables, but better safe than
501: * sorry.
502: */
1.43 espie 503: Lst_ForEach(&gn->parents, ParseLinkSrc, cohort);
1.1 deraadt 504: cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
1.43 espie 505: Lst_AtEnd(&gn->cohorts, cohort);
1.1 deraadt 506:
507: /*
508: * Replace the node in the targets list with the new copy
509: */
1.37 espie 510: ln = Lst_Member(targets, gn);
511: Lst_Replace(ln, cohort);
1.1 deraadt 512: gn = cohort;
513: }
514: /*
515: * We don't want to nuke any previous flags (whatever they were) so we
1.11 millert 516: * just OR the new operator into the old
1.1 deraadt 517: */
518: gn->type |= op;
519:
1.40 espie 520: return 1;
1.1 deraadt 521: }
522:
1.11 millert 523: /*-
1.3 deraadt 524: *---------------------------------------------------------------------
525: * ParseAddDep --
526: * Check if the pair of GNodes given needs to be synchronized.
527: * This has to be when two nodes are on different sides of a
528: * .WAIT directive.
529: *
530: * Results:
1.40 espie 531: * Returns 0 if the two targets need to be ordered, 1 otherwise.
532: * If it returns 0, the search can stop
1.3 deraadt 533: *
534: * Side Effects:
535: * A dependency can be added between the two nodes.
1.11 millert 536: *
1.3 deraadt 537: *---------------------------------------------------------------------
538: */
1.13 millert 539: static int
1.3 deraadt 540: ParseAddDep(pp, sp)
1.42 espie 541: void *pp;
542: void *sp;
1.3 deraadt 543: {
544: GNode *p = (GNode *) pp;
545: GNode *s = (GNode *) sp;
546:
547: if (p->order < s->order) {
548: /*
549: * XXX: This can cause loops, and loops can cause unmade targets,
550: * but checking is tedious, and the debugging output can show the
551: * problem
552: */
1.43 espie 553: Lst_AtEnd(&p->successors, s);
554: Lst_AtEnd(&s->preds, p);
1.40 espie 555: return 1;
1.3 deraadt 556: }
557: else
1.40 espie 558: return 0;
1.3 deraadt 559: }
560:
561:
1.1 deraadt 562: /*-
563: *---------------------------------------------------------------------
564: * ParseDoSrc --
565: * Given the name of a source, figure out if it is an attribute
566: * and apply it to the targets if it is. Else decide if there is
567: * some attribute which should be applied *to* the source because
568: * of some special target and apply it if so. Otherwise, make the
569: * source be a child of the targets in the list 'targets'
570: *
571: * Results:
572: * None
573: *
574: * Side Effects:
575: * Operator bits may be added to the list of targets or to the source.
576: * The targets may have a new source added to their lists of children.
577: *---------------------------------------------------------------------
578: */
579: static void
1.3 deraadt 580: ParseDoSrc (tOp, src, allsrc)
1.1 deraadt 581: int tOp; /* operator (if any) from special targets */
582: char *src; /* name of the source to handle */
1.3 deraadt 583: Lst allsrc; /* List of all sources to wait for */
584:
1.1 deraadt 585: {
1.3 deraadt 586: GNode *gn = NULL;
1.1 deraadt 587:
588: if (*src == '.' && isupper (src[1])) {
589: int keywd = ParseFindKeyword(src);
590: if (keywd != -1) {
1.3 deraadt 591: int op = parseKeywords[keywd].op;
592: if (op != 0) {
1.40 espie 593: Lst_Find(targets, ParseDoOp, &op);
1.3 deraadt 594: return;
595: }
596: if (parseKeywords[keywd].spec == Wait) {
597: waiting++;
598: return;
599: }
1.1 deraadt 600: }
601: }
1.3 deraadt 602:
603: switch (specType) {
604: case Main:
1.1 deraadt 605: /*
606: * If we have noted the existence of a .MAIN, it means we need
607: * to add the sources of said target to the list of things
608: * to create. The string 'src' is likely to be free, so we
609: * must make a new copy of it. Note that this will only be
610: * invoked if the user didn't specify a target on the command
611: * line. This is to allow #ifmake's to succeed, or something...
612: */
1.43 espie 613: Lst_AtEnd(&create, estrdup(src));
1.1 deraadt 614: /*
615: * Add the name to the .TARGETS variable as well, so the user cna
616: * employ that, if desired.
617: */
618: Var_Append(".TARGETS", src, VAR_GLOBAL);
1.3 deraadt 619: return;
620:
621: case Order:
1.1 deraadt 622: /*
623: * Create proper predecessor/successor links between the previous
624: * source and the current one.
625: */
626: gn = Targ_FindNode(src, TARG_CREATE);
1.33 espie 627: if (predecessor != NULL) {
1.43 espie 628: Lst_AtEnd(&predecessor->successors, gn);
629: Lst_AtEnd(&gn->preds, predecessor);
1.1 deraadt 630: }
631: /*
632: * The current source now becomes the predecessor for the next one.
633: */
634: predecessor = gn;
1.3 deraadt 635: break;
636:
637: default:
1.1 deraadt 638: /*
639: * If the source is not an attribute, we need to find/create
640: * a node for it. After that we can apply any operator to it
641: * from a special target or link it to its parents, as
642: * appropriate.
643: *
644: * In the case of a source that was the object of a :: operator,
645: * the attribute is applied to all of its instances (as kept in
646: * the 'cohorts' list of the node) or all the cohorts are linked
647: * to all the targets.
648: */
649: gn = Targ_FindNode (src, TARG_CREATE);
650: if (tOp) {
651: gn->type |= tOp;
652: } else {
1.37 espie 653: Lst_ForEach(targets, ParseLinkSrc, gn);
1.1 deraadt 654: }
655: if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
656: register GNode *cohort;
657: register LstNode ln;
658:
1.43 espie 659: for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Succ(ln)){
1.1 deraadt 660: cohort = (GNode *)Lst_Datum(ln);
661: if (tOp) {
662: cohort->type |= tOp;
663: } else {
1.37 espie 664: Lst_ForEach(targets, ParseLinkSrc, cohort);
1.1 deraadt 665: }
666: }
667: }
1.3 deraadt 668: break;
669: }
670:
671: gn->order = waiting;
1.37 espie 672: Lst_AtEnd(allsrc, gn);
1.40 espie 673: if (waiting)
674: Lst_Find(allsrc, ParseAddDep, gn);
1.1 deraadt 675: }
676:
677: /*-
678: *-----------------------------------------------------------------------
679: * ParseFindMain --
680: * Find a real target in the list and set it to be the main one.
681: * Called by ParseDoDependency when a main target hasn't been found
682: * yet.
683: *
684: * Results:
1.40 espie 685: * 1 if main not found yet, 0 if it is.
1.1 deraadt 686: *
687: * Side Effects:
688: * mainNode is changed and Targ_SetMain is called.
689: *
690: *-----------------------------------------------------------------------
691: */
692: static int
693: ParseFindMain(gnp, dummy)
1.42 espie 694: void *gnp; /* Node to examine */
695: void *dummy;
1.1 deraadt 696: {
697: GNode *gn = (GNode *) gnp;
1.17 espie 698: if ((gn->type & OP_NOTARGET) == 0) {
1.1 deraadt 699: mainNode = gn;
700: Targ_SetMain(gn);
1.40 espie 701: return (dummy ? 0 : 0);
702: } else {
1.1 deraadt 703: return (dummy ? 1 : 1);
704: }
705: }
706:
707: /*-
708: *-----------------------------------------------------------------------
709: * ParseAddDir --
710: * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
711: *
712: * Side Effects:
713: * See Dir_AddDir.
714: *
715: *-----------------------------------------------------------------------
716: */
1.41 espie 717: static void
1.1 deraadt 718: ParseAddDir(path, name)
1.42 espie 719: void *path;
720: void *name;
1.1 deraadt 721: {
1.41 espie 722: Dir_AddDir((Lst)path, (char *)name);
1.1 deraadt 723: }
724:
725: /*-
726: *-----------------------------------------------------------------------
727: * ParseClearPath --
728: * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
729: *
730: * Side Effects:
731: * See Dir_ClearPath
732: *
733: *-----------------------------------------------------------------------
734: */
1.41 espie 735: static void
736: ParseClearPath(path)
1.42 espie 737: void *path;
1.1 deraadt 738: {
1.41 espie 739: Dir_ClearPath((Lst)path);
1.1 deraadt 740: }
741:
742: /*-
743: *---------------------------------------------------------------------
744: * ParseDoDependency --
745: * Parse the dependency line in line.
746: *
747: * Results:
748: * None
749: *
750: * Side Effects:
751: * The nodes of the sources are linked as children to the nodes of the
752: * targets. Some nodes may be created.
753: *
754: * We parse a dependency line by first extracting words from the line and
755: * finding nodes in the list of all targets with that name. This is done
756: * until a character is encountered which is an operator character. Currently
757: * these are only ! and :. At this point the operator is parsed and the
758: * pointer into the line advanced until the first source is encountered.
759: * The parsed operator is applied to each node in the 'targets' list,
760: * which is where the nodes found for the targets are kept, by means of
761: * the ParseDoOp function.
762: * The sources are read in much the same way as the targets were except
763: * that now they are expanded using the wildcarding scheme of the C-Shell
764: * and all instances of the resulting words in the list of all targets
765: * are found. Each of the resulting nodes is then linked to each of the
766: * targets as one of its children.
767: * Certain targets are handled specially. These are the ones detailed
768: * by the specType variable.
769: * The storing of transformation rules is also taken care of here.
770: * A target is recognized as a transformation rule by calling
771: * Suff_IsTransform. If it is a transformation rule, its node is gotten
772: * from the suffix module via Suff_AddTransform rather than the standard
773: * Targ_FindNode in the target module.
774: *---------------------------------------------------------------------
775: */
776: static void
777: ParseDoDependency (line)
778: char *line; /* the line to parse */
779: {
780: char *cp; /* our current position */
781: GNode *gn; /* a general purpose temporary node */
782: int op; /* the operator on the line */
783: char savec; /* a place to save a character */
784: Lst paths; /* List of search paths to alter when parsing
785: * a list of .PATH targets */
786: int tOp; /* operator from special target */
1.43 espie 787: LIST curTargs; /* list of target names to be found and added
1.1 deraadt 788: * to the targets list */
1.43 espie 789: LIST curSrcs; /* list of sources in order */
1.1 deraadt 790:
791: tOp = 0;
792:
793: specType = Not;
1.3 deraadt 794: waiting = 0;
1.1 deraadt 795: paths = (Lst)NULL;
796:
1.43 espie 797: Lst_Init(&curTargs);
798: Lst_Init(&curSrcs);
1.11 millert 799:
1.1 deraadt 800: do {
801: for (cp = line;
1.18 millert 802: *cp && !isspace (*cp) && (*cp != '(');
1.1 deraadt 803: cp++)
804: {
1.19 millert 805: /*
806: * We don't want to end a word on ':' or '!' if there is a
807: * better match later on in the string. By "better" I mean
808: * one that is followed by whitespace. This allows the user
809: * to have targets like:
810: * fie::fi:fo: fum
811: * where "fie::fi:fo" is the target. In real life this is used
812: * for perl5 library man pages where "::" separates an object
813: * from its class. Ie: "File::Spec::Unix". This behaviour
814: * is also consistent with other versions of make.
815: */
1.18 millert 816: if (*cp == '!' || *cp == ':') {
817: char *p = cp + 1;
818:
819: if (*p == '\0')
820: break; /* no chance, not enough room */
821: /*
822: * Only end the word on ':' or '!' if there is not
1.19 millert 823: * a match later on followed by whitespace.
1.18 millert 824: */
825: while ((p = strchr(p + 1, *cp)) && !isspace(*(p + 1)))
826: ;
827: if (!p || !isspace(*(p + 1)))
828: break;
829: } else if (*cp == '$') {
1.1 deraadt 830: /*
831: * Must be a dynamic source (would have been expanded
832: * otherwise), so call the Var module to parse the puppy
833: * so we can safely advance beyond it...There should be
834: * no errors in this, as they would have been discovered
835: * in the initial Var_Subst and we wouldn't be here.
836: */
1.36 espie 837: size_t length;
1.1 deraadt 838: Boolean freeIt;
839: char *result;
840:
841: result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
842:
843: if (freeIt) {
844: free(result);
845: }
846: cp += length-1;
847: }
848: continue;
849: }
850: if (*cp == '(') {
851: /*
852: * Archives must be handled specially to make sure the OP_ARCHV
853: * flag is set in their 'type' field, for one thing, and because
854: * things like "archive(file1.o file2.o file3.o)" are permissible.
855: * Arch_ParseArchive will set 'line' to be the first non-blank
856: * after the archive-spec. It creates/finds nodes for the members
857: * and places them on the given list, returning SUCCESS if all
858: * went well and FAILURE if there was an error in the
859: * specification. On error, line should remain untouched.
860: */
861: if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
862: Parse_Error (PARSE_FATAL,
863: "Error in archive specification: \"%s\"", line);
864: return;
865: } else {
866: continue;
867: }
868: }
869: savec = *cp;
1.11 millert 870:
1.1 deraadt 871: if (!*cp) {
872: /*
873: * Ending a dependency line without an operator is a Bozo
1.11 millert 874: * no-no
1.1 deraadt 875: */
876: Parse_Error (PARSE_FATAL, "Need an operator");
877: return;
878: }
879: *cp = '\0';
880: /*
881: * Have a word in line. See if it's a special target and set
882: * specType to match it.
883: */
884: if (*line == '.' && isupper (line[1])) {
885: /*
886: * See if the target is a special target that must have it
1.11 millert 887: * or its sources handled specially.
1.1 deraadt 888: */
889: int keywd = ParseFindKeyword(line);
890: if (keywd != -1) {
891: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
892: Parse_Error(PARSE_FATAL, "Mismatched special targets");
893: return;
894: }
1.11 millert 895:
1.1 deraadt 896: specType = parseKeywords[keywd].spec;
897: tOp = parseKeywords[keywd].op;
898:
899: /*
900: * Certain special targets have special semantics:
901: * .PATH Have to set the dirSearchPath
902: * variable too
903: * .MAIN Its sources are only used if
904: * nothing has been specified to
905: * create.
906: * .DEFAULT Need to create a node to hang
907: * commands on, but we don't want
908: * it in the graph, nor do we want
909: * it to be the Main Target, so we
910: * create it, set OP_NOTMAIN and
911: * add it to the list, setting
912: * DEFAULT to the new node for
913: * later use. We claim the node is
914: * A transformation rule to make
915: * life easier later, when we'll
916: * use Make_HandleUse to actually
917: * apply the .DEFAULT commands.
1.7 niklas 918: * .PHONY The list of targets
1.17 espie 919: * .NOPATH Don't search for file in the path
1.1 deraadt 920: * .BEGIN
921: * .END
922: * .INTERRUPT Are not to be considered the
923: * main target.
924: * .NOTPARALLEL Make only one target at a time.
925: * .SINGLESHELL Create a shell for each command.
1.33 espie 926: * .ORDER Must set initial predecessor to NULL
1.1 deraadt 927: */
928: switch (specType) {
929: case ExPath:
1.43 espie 930: if (paths == NULL)
931: paths = Lst_New();
932: Lst_AtEnd(paths, &dirSearchPath);
1.1 deraadt 933: break;
934: case Main:
1.43 espie 935: if (!Lst_IsEmpty(&create)) {
1.1 deraadt 936: specType = Not;
937: }
938: break;
939: case Begin:
940: case End:
941: case Interrupt:
942: gn = Targ_FindNode(line, TARG_CREATE);
943: gn->type |= OP_NOTMAIN;
1.37 espie 944: Lst_AtEnd(targets, gn);
1.1 deraadt 945: break;
946: case Default:
947: gn = Targ_NewGN(".DEFAULT");
948: gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
1.37 espie 949: Lst_AtEnd(targets, gn);
1.1 deraadt 950: DEFAULT = gn;
951: break;
952: case NotParallel:
953: {
954: extern int maxJobs;
1.11 millert 955:
1.1 deraadt 956: maxJobs = 1;
957: break;
958: }
959: case SingleShell:
960: compatMake = 1;
961: break;
962: case Order:
1.33 espie 963: predecessor = NULL;
1.1 deraadt 964: break;
965: default:
966: break;
967: }
968: } else if (strncmp (line, ".PATH", 5) == 0) {
969: /*
970: * .PATH<suffix> has to be handled specially.
971: * Call on the suffix module to give us a path to
972: * modify.
973: */
974: Lst path;
1.11 millert 975:
1.1 deraadt 976: specType = ExPath;
977: path = Suff_GetPath (&line[5]);
1.33 espie 978: if (path == NULL) {
1.1 deraadt 979: Parse_Error (PARSE_FATAL,
980: "Suffix '%s' not defined (yet)",
981: &line[5]);
982: return;
983: } else {
1.43 espie 984: if (paths == NULL)
985: paths = Lst_New();
1.37 espie 986: Lst_AtEnd(paths, path);
1.1 deraadt 987: }
988: }
989: }
1.11 millert 990:
1.1 deraadt 991: /*
992: * Have word in line. Get or create its node and stick it at
1.11 millert 993: * the end of the targets list
1.1 deraadt 994: */
995: if ((specType == Not) && (*line != '\0')) {
1.34 espie 996: char *targName;
997:
1.1 deraadt 998: if (Dir_HasWildcards(line)) {
999: /*
1000: * Targets are to be sought only in the current directory,
1001: * so create an empty path for the thing. Note we need to
1002: * use Dir_Destroy in the destruction of the path as the
1003: * Dir module could have added a directory to the path...
1004: */
1.43 espie 1005: LIST emptyPath;
1006:
1007: Lst_Init(&emptyPath);
1.11 millert 1008:
1.43 espie 1009: Dir_Expand(line, &emptyPath, &curTargs);
1.11 millert 1010:
1.43 espie 1011: Lst_Destroy(&emptyPath, Dir_Destroy);
1.1 deraadt 1012: } else {
1013: /*
1014: * No wildcards, but we want to avoid code duplication,
1015: * so create a list with the word on it.
1016: */
1.43 espie 1017: Lst_AtEnd(&curTargs, line);
1.1 deraadt 1018: }
1.11 millert 1019:
1.43 espie 1020: while((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) {
1.1 deraadt 1021: if (!Suff_IsTransform (targName)) {
1022: gn = Targ_FindNode (targName, TARG_CREATE);
1023: } else {
1024: gn = Suff_AddTransform (targName);
1025: }
1.11 millert 1026:
1.16 millert 1027: if (gn != NULL)
1.37 espie 1028: Lst_AtEnd(targets, gn);
1.1 deraadt 1029: }
1030: } else if (specType == ExPath && *line != '.' && *line != '\0') {
1031: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1032: }
1.11 millert 1033:
1.1 deraadt 1034: *cp = savec;
1035: /*
1036: * If it is a special type and not .PATH, it's the only target we
1037: * allow on this line...
1038: */
1039: if (specType != Not && specType != ExPath) {
1040: Boolean warn = FALSE;
1.11 millert 1041:
1.1 deraadt 1042: while ((*cp != '!') && (*cp != ':') && *cp) {
1043: if (*cp != ' ' && *cp != '\t') {
1044: warn = TRUE;
1045: }
1046: cp++;
1047: }
1048: if (warn) {
1049: Parse_Error(PARSE_WARNING, "Extra target ignored");
1050: }
1051: } else {
1052: while (*cp && isspace (*cp)) {
1053: cp++;
1054: }
1055: }
1056: line = cp;
1057: } while ((*line != '!') && (*line != ':') && *line);
1058:
1.43 espie 1059: /* Don't need the list of target names any more */
1060: Lst_Destroy(&curTargs, NOFREE);
1.1 deraadt 1061:
1062: if (!Lst_IsEmpty(targets)) {
1063: switch(specType) {
1064: default:
1065: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
1066: break;
1067: case Default:
1068: case Begin:
1069: case End:
1070: case Interrupt:
1071: /*
1072: * These four create nodes on which to hang commands, so
1073: * targets shouldn't be empty...
1074: */
1075: case Not:
1076: /*
1077: * Nothing special here -- targets can be empty if it wants.
1078: */
1079: break;
1080: }
1081: }
1082:
1083: /*
1084: * Have now parsed all the target names. Must parse the operator next. The
1085: * result is left in op .
1086: */
1087: if (*cp == '!') {
1088: op = OP_FORCE;
1089: } else if (*cp == ':') {
1090: if (cp[1] == ':') {
1091: op = OP_DOUBLEDEP;
1092: cp++;
1093: } else {
1094: op = OP_DEPENDS;
1095: }
1096: } else {
1097: Parse_Error (PARSE_FATAL, "Missing dependency operator");
1098: return;
1099: }
1100:
1101: cp++; /* Advance beyond operator */
1102:
1.40 espie 1103: Lst_Find(targets, ParseDoOp, &op);
1.1 deraadt 1104:
1105: /*
1.11 millert 1106: * Get to the first source
1.1 deraadt 1107: */
1108: while (*cp && isspace (*cp)) {
1109: cp++;
1110: }
1111: line = cp;
1112:
1113: /*
1114: * Several special targets take different actions if present with no
1115: * sources:
1116: * a .SUFFIXES line with no sources clears out all old suffixes
1117: * a .PRECIOUS line makes all targets precious
1118: * a .IGNORE line ignores errors for all targets
1119: * a .SILENT line creates silence when making all targets
1120: * a .PATH removes all directories from the search path(s).
1121: */
1122: if (!*line) {
1123: switch (specType) {
1124: case Suffixes:
1125: Suff_ClearSuffixes ();
1126: break;
1127: case Precious:
1128: allPrecious = TRUE;
1129: break;
1130: case Ignore:
1131: ignoreErrors = TRUE;
1132: break;
1133: case Silent:
1134: beSilent = TRUE;
1135: break;
1136: case ExPath:
1.41 espie 1137: Lst_Every(paths, ParseClearPath);
1.1 deraadt 1138: break;
1139: default:
1140: break;
1141: }
1142: } else if (specType == MFlags) {
1143: /*
1144: * Call on functions in main.c to deal with these arguments and
1145: * set the initial character to a null-character so the loop to
1146: * get sources won't get anything
1147: */
1148: Main_ParseArgLine (line);
1149: *line = '\0';
1150: } else if (specType == ExShell) {
1151: if (Job_ParseShell (line) != SUCCESS) {
1152: Parse_Error (PARSE_FATAL, "improper shell specification");
1153: return;
1154: }
1155: *line = '\0';
1156: } else if ((specType == NotParallel) || (specType == SingleShell)) {
1157: *line = '\0';
1158: }
1.11 millert 1159:
1.1 deraadt 1160: /*
1.11 millert 1161: * NOW GO FOR THE SOURCES
1.1 deraadt 1162: */
1163: if ((specType == Suffixes) || (specType == ExPath) ||
1164: (specType == Includes) || (specType == Libs) ||
1165: (specType == Null))
1166: {
1167: while (*line) {
1168: /*
1169: * If the target was one that doesn't take files as its sources
1170: * but takes something like suffixes, we take each
1171: * space-separated word on the line as a something and deal
1172: * with it accordingly.
1173: *
1174: * If the target was .SUFFIXES, we take each source as a
1175: * suffix and add it to the list of suffixes maintained by the
1176: * Suff module.
1177: *
1178: * If the target was a .PATH, we add the source as a directory
1179: * to search on the search path.
1180: *
1181: * If it was .INCLUDES, the source is taken to be the suffix of
1182: * files which will be #included and whose search path should
1183: * be present in the .INCLUDES variable.
1184: *
1185: * If it was .LIBS, the source is taken to be the suffix of
1186: * files which are considered libraries and whose search path
1187: * should be present in the .LIBS variable.
1188: *
1189: * If it was .NULL, the source is the suffix to use when a file
1190: * has no valid suffix.
1191: */
1192: char savec;
1193: while (*cp && !isspace (*cp)) {
1194: cp++;
1195: }
1196: savec = *cp;
1197: *cp = '\0';
1198: switch (specType) {
1199: case Suffixes:
1200: Suff_AddSuffix (line);
1201: break;
1202: case ExPath:
1.37 espie 1203: Lst_ForEach(paths, ParseAddDir, line);
1.1 deraadt 1204: break;
1205: case Includes:
1206: Suff_AddInclude (line);
1207: break;
1208: case Libs:
1209: Suff_AddLib (line);
1210: break;
1211: case Null:
1212: Suff_SetNull (line);
1213: break;
1214: default:
1215: break;
1216: }
1217: *cp = savec;
1218: if (savec != '\0') {
1219: cp++;
1220: }
1221: while (*cp && isspace (*cp)) {
1222: cp++;
1223: }
1224: line = cp;
1225: }
1.43 espie 1226: if (paths)
1227: Lst_Delete(paths, NOFREE);
1.1 deraadt 1228: } else {
1229: while (*line) {
1230: /*
1231: * The targets take real sources, so we must beware of archive
1232: * specifications (i.e. things with left parentheses in them)
1233: * and handle them accordingly.
1234: */
1235: while (*cp && !isspace (*cp)) {
1236: if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
1237: /*
1238: * Only stop for a left parenthesis if it isn't at the
1239: * start of a word (that'll be for variable changes
1240: * later) and isn't preceded by a dollar sign (a dynamic
1241: * source).
1242: */
1243: break;
1244: } else {
1245: cp++;
1246: }
1247: }
1248:
1249: if (*cp == '(') {
1250: GNode *gn;
1.43 espie 1251: LIST sources; /* list of archive source names after
1252: * expansion */
1.1 deraadt 1253:
1.43 espie 1254: Lst_Init(&sources);
1255: if (Arch_ParseArchive(&line, &sources, VAR_CMD) != SUCCESS) {
1.1 deraadt 1256: Parse_Error (PARSE_FATAL,
1257: "Error in source archive spec \"%s\"", line);
1258: return;
1259: }
1260:
1.43 espie 1261: while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL)
1262: ParseDoSrc(tOp, gn->name, &curSrcs);
1263: Lst_Destroy(&sources, NOFREE);
1.1 deraadt 1264: cp = line;
1265: } else {
1266: if (*cp) {
1267: *cp = '\0';
1268: cp += 1;
1269: }
1270:
1.43 espie 1271: ParseDoSrc(tOp, line, &curSrcs);
1.1 deraadt 1272: }
1273: while (*cp && isspace (*cp)) {
1274: cp++;
1275: }
1276: line = cp;
1277: }
1278: }
1.11 millert 1279:
1.33 espie 1280: if (mainNode == NULL) {
1.1 deraadt 1281: /*
1282: * If we have yet to decide on a main target to make, in the
1283: * absence of any user input, we want the first target on
1284: * the first dependency line that is actually a real target
1285: * (i.e. isn't a .USE or .EXEC rule) to be made.
1286: */
1.40 espie 1287: Lst_Find(targets, ParseFindMain, NULL);
1.1 deraadt 1288: }
1289:
1.43 espie 1290: /* Finally, destroy the list of sources. */
1291: Lst_Destroy(&curSrcs, NOFREE);
1.1 deraadt 1292: }
1293:
1294: /*-
1295: *---------------------------------------------------------------------
1296: * Parse_IsVar --
1297: * Return TRUE if the passed line is a variable assignment. A variable
1298: * assignment consists of a single word followed by optional whitespace
1299: * followed by either a += or an = operator.
1300: * This function is used both by the Parse_File function and main when
1301: * parsing the command-line arguments.
1302: *
1303: * Results:
1304: * TRUE if it is. FALSE if it ain't
1305: *
1306: * Side Effects:
1307: * none
1308: *---------------------------------------------------------------------
1309: */
1310: Boolean
1311: Parse_IsVar (line)
1312: register char *line; /* the line to check */
1313: {
1314: register Boolean wasSpace = FALSE; /* set TRUE if found a space */
1315: register Boolean haveName = FALSE; /* Set TRUE if have a variable name */
1316: int level = 0;
1317: #define ISEQOPERATOR(c) \
1318: (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1319:
1320: /*
1321: * Skip to variable name
1322: */
1.11 millert 1323: for (;(*line == ' ') || (*line == '\t'); line++)
1.1 deraadt 1324: continue;
1325:
1326: for (; *line != '=' || level != 0; line++)
1327: switch (*line) {
1328: case '\0':
1329: /*
1330: * end-of-line -- can't be a variable assignment.
1331: */
1332: return FALSE;
1333:
1334: case ' ':
1335: case '\t':
1336: /*
1337: * there can be as much white space as desired so long as there is
1.11 millert 1338: * only one word before the operator
1.1 deraadt 1339: */
1340: wasSpace = TRUE;
1341: break;
1342:
1343: case '(':
1344: case '{':
1345: level++;
1346: break;
1347:
1348: case '}':
1349: case ')':
1350: level--;
1351: break;
1.11 millert 1352:
1.1 deraadt 1353: default:
1354: if (wasSpace && haveName) {
1355: if (ISEQOPERATOR(*line)) {
1356: /*
1.9 briggs 1357: * We must have a finished word
1358: */
1359: if (level != 0)
1360: return FALSE;
1361:
1362: /*
1.1 deraadt 1363: * When an = operator [+?!:] is found, the next
1.9 briggs 1364: * character must be an = or it ain't a valid
1.1 deraadt 1365: * assignment.
1366: */
1.9 briggs 1367: if (line[1] == '=')
1.1 deraadt 1368: return haveName;
1.9 briggs 1369: #ifdef SUNSHCMD
1.1 deraadt 1370: /*
1.9 briggs 1371: * This is a shell command
1.1 deraadt 1372: */
1.9 briggs 1373: if (strncmp(line, ":sh", 3) == 0)
1374: return haveName;
1375: #endif
1.1 deraadt 1376: }
1.9 briggs 1377: /*
1378: * This is the start of another word, so not assignment.
1379: */
1380: return FALSE;
1.1 deraadt 1381: }
1382: else {
1.11 millert 1383: haveName = TRUE;
1.1 deraadt 1384: wasSpace = FALSE;
1385: }
1386: break;
1387: }
1388:
1389: return haveName;
1390: }
1391:
1392: /*-
1393: *---------------------------------------------------------------------
1394: * Parse_DoVar --
1395: * Take the variable assignment in the passed line and do it in the
1396: * global context.
1397: *
1398: * Note: There is a lexical ambiguity with assignment modifier characters
1399: * in variable names. This routine interprets the character before the =
1400: * as a modifier. Therefore, an assignment like
1401: * C++=/usr/bin/CC
1402: * is interpreted as "C+ +=" instead of "C++ =".
1403: *
1404: * Results:
1405: * none
1406: *
1407: * Side Effects:
1408: * the variable structure of the given variable name is altered in the
1409: * global context.
1410: *---------------------------------------------------------------------
1411: */
1412: void
1413: Parse_DoVar (line, ctxt)
1414: char *line; /* a line guaranteed to be a variable
1415: * assignment. This reduces error checks */
1416: GNode *ctxt; /* Context in which to do the assignment */
1417: {
1418: char *cp; /* pointer into line */
1419: enum {
1420: VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1421: } type; /* Type of assignment */
1.11 millert 1422: char *opc; /* ptr to operator character to
1.1 deraadt 1423: * null-terminate the variable name */
1.11 millert 1424: /*
1.1 deraadt 1425: * Avoid clobbered variable warnings by forcing the compiler
1426: * to ``unregister'' variables
1427: */
1428: #if __GNUC__
1429: (void) &cp;
1430: (void) &line;
1431: #endif
1432:
1433: /*
1434: * Skip to variable name
1435: */
1436: while ((*line == ' ') || (*line == '\t')) {
1437: line++;
1438: }
1439:
1440: /*
1441: * Skip to operator character, nulling out whitespace as we go
1442: */
1443: for (cp = line + 1; *cp != '='; cp++) {
1444: if (isspace (*cp)) {
1445: *cp = '\0';
1446: }
1447: }
1448: opc = cp-1; /* operator is the previous character */
1449: *cp++ = '\0'; /* nuke the = */
1450:
1451: /*
1452: * Check operator type
1453: */
1454: switch (*opc) {
1455: case '+':
1456: type = VAR_APPEND;
1457: *opc = '\0';
1458: break;
1459:
1460: case '?':
1461: /*
1462: * If the variable already has a value, we don't do anything.
1463: */
1464: *opc = '\0';
1465: if (Var_Exists(line, ctxt)) {
1466: return;
1467: } else {
1468: type = VAR_NORMAL;
1469: }
1470: break;
1471:
1472: case ':':
1473: type = VAR_SUBST;
1474: *opc = '\0';
1475: break;
1476:
1477: case '!':
1478: type = VAR_SHELL;
1479: *opc = '\0';
1480: break;
1481:
1482: default:
1.9 briggs 1483: #ifdef SUNSHCMD
1484: while (*opc != ':')
1485: if (--opc < line)
1486: break;
1487:
1488: if (strncmp(opc, ":sh", 3) == 0) {
1489: type = VAR_SHELL;
1490: *opc = '\0';
1491: break;
1492: }
1493: #endif
1.1 deraadt 1494: type = VAR_NORMAL;
1495: break;
1496: }
1497:
1498: while (isspace (*cp)) {
1499: cp++;
1500: }
1501:
1502: if (type == VAR_APPEND) {
1503: Var_Append (line, cp, ctxt);
1504: } else if (type == VAR_SUBST) {
1505: /*
1506: * Allow variables in the old value to be undefined, but leave their
1507: * invocation alone -- this is done by forcing oldVars to be false.
1508: * XXX: This can cause recursive variables, but that's not hard to do,
1509: * and this allows someone to do something like
1510: *
1511: * CFLAGS = $(.INCLUDES)
1512: * CFLAGS := -I.. $(CFLAGS)
1513: *
1514: * And not get an error.
1515: */
1516: Boolean oldOldVars = oldVars;
1517:
1518: oldVars = FALSE;
1.31 espie 1519: cp = Var_Subst(cp, ctxt, FALSE);
1.1 deraadt 1520: oldVars = oldOldVars;
1521:
1522: Var_Set(line, cp, ctxt);
1523: free(cp);
1524: } else if (type == VAR_SHELL) {
1.9 briggs 1525: Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
1526: * if any variable expansion was performed */
1527: char *res, *err;
1.1 deraadt 1528:
1.9 briggs 1529: if (strchr(cp, '$') != NULL) {
1.1 deraadt 1530: /*
1531: * There's a dollar sign in the command, so perform variable
1532: * expansion on the whole thing. The resulting string will need
1533: * freeing when we're done, so set freeCmd to TRUE.
1534: */
1.31 espie 1535: cp = Var_Subst(cp, VAR_CMD, TRUE);
1.1 deraadt 1536: freeCmd = TRUE;
1537: }
1538:
1.9 briggs 1539: res = Cmd_Exec(cp, &err);
1540: Var_Set(line, res, ctxt);
1541: free(res);
1.1 deraadt 1542:
1.9 briggs 1543: if (err)
1544: Parse_Error(PARSE_WARNING, err, cp);
1.1 deraadt 1545:
1.9 briggs 1546: if (freeCmd)
1547: free(cp);
1.1 deraadt 1548: } else {
1549: /*
1550: * Normal assignment -- just do it.
1551: */
1.9 briggs 1552: Var_Set(line, cp, ctxt);
1.1 deraadt 1553: }
1554: }
1555:
1.9 briggs 1556:
1.1 deraadt 1557: /*-
1558: * ParseAddCmd --
1559: * Lst_ForEach function to add a command line to all targets
1560: *
1561: * Side Effects:
1562: * A new element is added to the commands list of the node.
1563: */
1.41 espie 1564: static void
1.1 deraadt 1565: ParseAddCmd(gnp, cmd)
1.42 espie 1566: void *gnp; /* the node to which the command is to be added */
1567: void *cmd; /* the command to add */
1.1 deraadt 1568: {
1.41 espie 1569: GNode *gn = (GNode *)gnp;
1.1 deraadt 1570: /* if target already supplied, ignore commands */
1.39 espie 1571: if (!(gn->type & OP_HAS_COMMANDS)) {
1.43 espie 1572: Lst_AtEnd(&gn->commands, cmd);
1.39 espie 1573: if (!gn->lineno) {
1574: gn->lineno = Parse_Getlineno();
1575: gn->fname = Parse_Getfilename();
1576: }
1577: }
1.1 deraadt 1578: }
1579:
1580: /*-
1581: *-----------------------------------------------------------------------
1582: * ParseHasCommands --
1583: * Callback procedure for Parse_File when destroying the list of
1584: * targets on the last dependency line. Marks a target as already
1585: * having commands if it does, to keep from having shell commands
1586: * on multiple dependency lines.
1587: *
1588: * Results:
1589: * None
1590: *
1591: * Side Effects:
1592: * OP_HAS_COMMANDS may be set for the target.
1593: *
1594: *-----------------------------------------------------------------------
1595: */
1596: static void
1597: ParseHasCommands(gnp)
1.42 espie 1598: void *gnp; /* Node to examine */
1.1 deraadt 1599: {
1600: GNode *gn = (GNode *) gnp;
1.43 espie 1601: if (!Lst_IsEmpty(&gn->commands)) {
1.1 deraadt 1602: gn->type |= OP_HAS_COMMANDS;
1603: }
1604: }
1605:
1606: /*-
1607: *-----------------------------------------------------------------------
1608: * Parse_AddIncludeDir --
1609: * Add a directory to the path searched for included makefiles
1610: * bracketed by double-quotes. Used by functions in main.c
1611: *
1612: * Results:
1613: * None.
1614: *
1615: * Side Effects:
1616: * The directory is appended to the list.
1617: *
1618: *-----------------------------------------------------------------------
1619: */
1620: void
1.43 espie 1621: Parse_AddIncludeDir(dir)
1.1 deraadt 1622: char *dir; /* The name of the directory to add */
1623: {
1.43 espie 1624: Dir_AddDir(&parseIncPath, dir);
1.1 deraadt 1625: }
1626:
1627: /*-
1628: *---------------------------------------------------------------------
1629: * ParseDoInclude --
1630: * Push to another file.
1.11 millert 1631: *
1.1 deraadt 1632: * The input is the line minus the #include. A file spec is a string
1633: * enclosed in <> or "". The former is looked for only in sysIncPath.
1634: * The latter in . and the directories specified by -I command line
1635: * options
1636: *
1637: * Results:
1638: * None
1639: *
1640: * Side Effects:
1641: * A structure is added to the includes Lst and readProc, lineno,
1642: * fname and curFILE are altered for the new file
1643: *---------------------------------------------------------------------
1644: */
1645: static void
1646: ParseDoInclude (file)
1647: char *file; /* file specification */
1648: {
1649: char *fullname; /* full pathname of file */
1650: IFile *oldFile; /* state associated with current file */
1651: char endc; /* the character which ends the file spec */
1652: char *cp; /* current position in file spec */
1653: Boolean isSystem; /* TRUE if makefile is a system makefile */
1654:
1655: /*
1656: * Skip to delimiter character so we know where to look
1657: */
1658: while ((*file == ' ') || (*file == '\t')) {
1659: file++;
1660: }
1661:
1662: if ((*file != '"') && (*file != '<')) {
1663: Parse_Error (PARSE_FATAL,
1664: ".include filename must be delimited by '\"' or '<'");
1665: return;
1666: }
1667:
1668: /*
1669: * Set the search path on which to find the include file based on the
1670: * characters which bracket its name. Angle-brackets imply it's
1671: * a system Makefile while double-quotes imply it's a user makefile
1672: */
1673: if (*file == '<') {
1674: isSystem = TRUE;
1675: endc = '>';
1676: } else {
1677: isSystem = FALSE;
1678: endc = '"';
1679: }
1680:
1681: /*
1682: * Skip to matching delimiter
1683: */
1684: for (cp = ++file; *cp && *cp != endc; cp++) {
1685: continue;
1686: }
1687:
1688: if (*cp != endc) {
1689: Parse_Error (PARSE_FATAL,
1690: "Unclosed %cinclude filename. '%c' expected",
1691: '.', endc);
1692: return;
1693: }
1694: *cp = '\0';
1695:
1696: /*
1697: * Substitute for any variables in the file name before trying to
1698: * find the thing.
1699: */
1.31 espie 1700: file = Var_Subst(file, VAR_CMD, FALSE);
1.1 deraadt 1701:
1702: /*
1703: * Now we know the file's name and its search path, we attempt to
1704: * find the durn thing. A return of NULL indicates the file don't
1705: * exist.
1706: */
1707: if (!isSystem) {
1708: /*
1709: * Include files contained in double-quotes are first searched for
1710: * relative to the including file's location. We don't want to
1711: * cd there, of course, so we just tack on the old file's
1712: * leading path components and call Dir_FindFile to see if
1713: * we can locate the beast.
1714: */
1.4 niklas 1715: char *prefEnd, *Fname;
1.1 deraadt 1716:
1.4 niklas 1717: /* Make a temporary copy of this, to be safe. */
1.9 briggs 1718: Fname = estrdup(fname);
1.4 niklas 1719:
1720: prefEnd = strrchr (Fname, '/');
1.1 deraadt 1721: if (prefEnd != (char *)NULL) {
1722: char *newName;
1.11 millert 1723:
1.1 deraadt 1724: *prefEnd = '\0';
1725: if (file[0] == '/')
1.9 briggs 1726: newName = estrdup(file);
1.1 deraadt 1727: else
1.4 niklas 1728: newName = str_concat (Fname, file, STR_ADDSLASH);
1.43 espie 1729: fullname = Dir_FindFile(newName, &parseIncPath);
1.1 deraadt 1730: if (fullname == (char *)NULL) {
1.43 espie 1731: fullname = Dir_FindFile(newName, &dirSearchPath);
1.1 deraadt 1732: }
1733: free (newName);
1734: *prefEnd = '/';
1735: } else {
1736: fullname = (char *)NULL;
1737: }
1.4 niklas 1738: free (Fname);
1.1 deraadt 1739: } else {
1740: fullname = (char *)NULL;
1741: }
1742:
1743: if (fullname == (char *)NULL) {
1744: /*
1745: * System makefile or makefile wasn't found in same directory as
1746: * included makefile. Search for it first on the -I search path,
1747: * then on the .PATH search path, if not found in a -I directory.
1748: * XXX: Suffix specific?
1749: */
1.43 espie 1750: fullname = Dir_FindFile(file, &parseIncPath);
1.1 deraadt 1751: if (fullname == (char *)NULL) {
1.43 espie 1752: fullname = Dir_FindFile(file, &dirSearchPath);
1.1 deraadt 1753: }
1754: }
1755:
1756: if (fullname == (char *)NULL) {
1757: /*
1758: * Still haven't found the makefile. Look for it on the system
1759: * path as a last resort.
1760: */
1.43 espie 1761: fullname = Dir_FindFile(file, &sysIncPath);
1.1 deraadt 1762: }
1763:
1764: if (fullname == (char *) NULL) {
1765: *cp = endc;
1766: Parse_Error (PARSE_FATAL, "Could not find %s", file);
1767: return;
1768: }
1769:
1770: free(file);
1771:
1772: /*
1773: * Once we find the absolute path to the file, we get to save all the
1774: * state from the current file before we can start reading this
1775: * include file. The state is stored in an IFile structure which
1776: * is placed on a list with other IFile structures. The list makes
1777: * a very nice stack to track how we got here...
1778: */
1779: oldFile = (IFile *) emalloc (sizeof (IFile));
1780: oldFile->fname = fname;
1781:
1782: oldFile->F = curFILE;
1783: oldFile->p = curPTR;
1784: oldFile->lineno = lineno;
1785:
1.43 espie 1786: Lst_AtFront(&includes, oldFile);
1.1 deraadt 1787:
1788: /*
1789: * Once the previous state has been saved, we can get down to reading
1790: * the new file. We set up the name of the file to be the absolute
1791: * name of the include file so error messages refer to the right
1792: * place. Naturally enough, we start reading at line number 0.
1793: */
1794: fname = fullname;
1.38 espie 1795: #ifdef CLEANUP
1.43 espie 1796: Lst_AtEnd(&fileNames, fname);
1.38 espie 1797: #endif
1.1 deraadt 1798: lineno = 0;
1799:
1800: curFILE = fopen (fullname, "r");
1801: curPTR = NULL;
1802: if (curFILE == (FILE * ) NULL) {
1803: Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1804: /*
1805: * Pop to previous file
1806: */
1807: (void) ParseEOF(0);
1808: }
1809: }
1810:
1811:
1812: /*-
1813: *---------------------------------------------------------------------
1814: * Parse_FromString --
1815: * Start Parsing from the given string
1.11 millert 1816: *
1.1 deraadt 1817: * Results:
1818: * None
1819: *
1820: * Side Effects:
1821: * A structure is added to the includes Lst and readProc, lineno,
1822: * fname and curFILE are altered for the new file
1823: *---------------------------------------------------------------------
1824: */
1825: void
1.24 espie 1826: Parse_FromString(str, newlineno)
1827: char *str;
1828: unsigned long newlineno;
1.1 deraadt 1829: {
1830: IFile *oldFile; /* state associated with this file */
1831:
1832: if (DEBUG(FOR))
1833: (void) fprintf(stderr, "%s\n----\n", str);
1834:
1835: oldFile = (IFile *) emalloc (sizeof (IFile));
1836: oldFile->lineno = lineno;
1837: oldFile->fname = fname;
1838: oldFile->F = curFILE;
1839: oldFile->p = curPTR;
1.11 millert 1840:
1.43 espie 1841: Lst_AtFront(&includes, oldFile);
1.1 deraadt 1842:
1843: curFILE = NULL;
1844: curPTR = (PTR *) emalloc (sizeof (PTR));
1845: curPTR->str = curPTR->ptr = str;
1.24 espie 1846: lineno = newlineno;
1.1 deraadt 1847: }
1848:
1849:
1850: #ifdef SYSVINCLUDE
1851: /*-
1852: *---------------------------------------------------------------------
1853: * ParseTraditionalInclude --
1854: * Push to another file.
1.11 millert 1855: *
1.1 deraadt 1856: * The input is the line minus the "include". The file name is
1857: * the string following the "include".
1858: *
1859: * Results:
1860: * None
1861: *
1862: * Side Effects:
1863: * A structure is added to the includes Lst and readProc, lineno,
1864: * fname and curFILE are altered for the new file
1865: *---------------------------------------------------------------------
1866: */
1867: static void
1868: ParseTraditionalInclude (file)
1869: char *file; /* file specification */
1870: {
1871: char *fullname; /* full pathname of file */
1872: IFile *oldFile; /* state associated with current file */
1873: char *cp; /* current position in file spec */
1874: char *prefEnd;
1875:
1876: /*
1877: * Skip over whitespace
1878: */
1879: while ((*file == ' ') || (*file == '\t')) {
1880: file++;
1881: }
1882:
1883: if (*file == '\0') {
1884: Parse_Error (PARSE_FATAL,
1885: "Filename missing from \"include\"");
1886: return;
1887: }
1888:
1889: /*
1890: * Skip to end of line or next whitespace
1891: */
1892: for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1893: continue;
1894: }
1895:
1896: *cp = '\0';
1897:
1898: /*
1899: * Substitute for any variables in the file name before trying to
1900: * find the thing.
1901: */
1.31 espie 1902: file = Var_Subst(file, VAR_CMD, FALSE);
1.1 deraadt 1903:
1904: /*
1905: * Now we know the file's name, we attempt to find the durn thing.
1906: * A return of NULL indicates the file don't exist.
1907: *
1908: * Include files are first searched for relative to the including
1909: * file's location. We don't want to cd there, of course, so we
1910: * just tack on the old file's leading path components and call
1911: * Dir_FindFile to see if we can locate the beast.
1912: * XXX - this *does* search in the current directory, right?
1913: */
1914:
1915: prefEnd = strrchr (fname, '/');
1916: if (prefEnd != (char *)NULL) {
1917: char *newName;
1.11 millert 1918:
1.1 deraadt 1919: *prefEnd = '\0';
1920: newName = str_concat (fname, file, STR_ADDSLASH);
1.43 espie 1921: fullname = Dir_FindFile(newName, &parseIncPath);
1922: if (fullname == NULL)
1923: fullname = Dir_FindFile(newName, &dirSearchPath);
1.1 deraadt 1924: free (newName);
1925: *prefEnd = '/';
1926: } else {
1927: fullname = (char *)NULL;
1928: }
1929:
1930: if (fullname == (char *)NULL) {
1931: /*
1932: * System makefile or makefile wasn't found in same directory as
1933: * included makefile. Search for it first on the -I search path,
1934: * then on the .PATH search path, if not found in a -I directory.
1935: * XXX: Suffix specific?
1936: */
1.43 espie 1937: fullname = Dir_FindFile(file, &parseIncPath);
1938: if (fullname == NULL)
1939: fullname = Dir_FindFile(file, &dirSearchPath);
1.1 deraadt 1940: }
1941:
1942: if (fullname == (char *)NULL) {
1943: /*
1944: * Still haven't found the makefile. Look for it on the system
1945: * path as a last resort.
1946: */
1.43 espie 1947: fullname = Dir_FindFile(file, &sysIncPath);
1.1 deraadt 1948: }
1949:
1950: if (fullname == (char *) NULL) {
1951: Parse_Error (PARSE_FATAL, "Could not find %s", file);
1952: return;
1953: }
1954:
1955: /*
1956: * Once we find the absolute path to the file, we get to save all the
1957: * state from the current file before we can start reading this
1958: * include file. The state is stored in an IFile structure which
1959: * is placed on a list with other IFile structures. The list makes
1960: * a very nice stack to track how we got here...
1961: */
1962: oldFile = (IFile *) emalloc (sizeof (IFile));
1963: oldFile->fname = fname;
1964:
1965: oldFile->F = curFILE;
1966: oldFile->p = curPTR;
1967: oldFile->lineno = lineno;
1968:
1.43 espie 1969: Lst_AtFront(&includes, oldFile);
1.1 deraadt 1970:
1971: /*
1972: * Once the previous state has been saved, we can get down to reading
1973: * the new file. We set up the name of the file to be the absolute
1974: * name of the include file so error messages refer to the right
1975: * place. Naturally enough, we start reading at line number 0.
1976: */
1977: fname = fullname;
1.38 espie 1978: #ifdef CLEANUP
1.43 espie 1979: Lst_AtEnd(&fileNames, fname);
1.38 espie 1980: #endif
1.1 deraadt 1981: lineno = 0;
1982:
1983: curFILE = fopen (fullname, "r");
1984: curPTR = NULL;
1985: if (curFILE == (FILE * ) NULL) {
1986: Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1987: /*
1988: * Pop to previous file
1989: */
1990: (void) ParseEOF(1);
1991: }
1992: }
1993: #endif
1994:
1995: /*-
1996: *---------------------------------------------------------------------
1997: * ParseEOF --
1998: * Called when EOF is reached in the current file. If we were reading
1999: * an include file, the includes stack is popped and things set up
2000: * to go back to reading the previous file at the previous location.
2001: *
2002: * Results:
2003: * CONTINUE if there's more to do. DONE if not.
2004: *
2005: * Side Effects:
2006: * The old curFILE, is closed. The includes list is shortened.
2007: * lineno, curFILE, and fname are changed if CONTINUE is returned.
2008: *---------------------------------------------------------------------
2009: */
2010: static int
2011: ParseEOF (opened)
2012: int opened;
2013: {
2014: IFile *ifile; /* the state on the top of the includes stack */
2015:
1.43 espie 2016: if ((ifile = (IFile *)Lst_DeQueue(&includes)) == NULL)
1.34 espie 2017: return DONE;
1.1 deraadt 2018: fname = ifile->fname;
2019: lineno = ifile->lineno;
2020: if (opened && curFILE)
2021: (void) fclose (curFILE);
2022: if (curPTR) {
1.42 espie 2023: free(curPTR->str);
2024: free(curPTR);
1.1 deraadt 2025: }
2026: curFILE = ifile->F;
2027: curPTR = ifile->p;
1.42 espie 2028: free(ifile);
1.1 deraadt 2029: return (CONTINUE);
2030: }
2031:
2032: /*-
2033: *---------------------------------------------------------------------
2034: * ParseReadc --
1.11 millert 2035: * Read a character from the current file
1.1 deraadt 2036: *
2037: * Results:
2038: * The character that was read
2039: *
2040: * Side Effects:
2041: *---------------------------------------------------------------------
2042: */
1.21 espie 2043: static int __inline
1.1 deraadt 2044: ParseReadc()
2045: {
2046: if (curFILE)
2047: return fgetc(curFILE);
1.11 millert 2048:
1.1 deraadt 2049: if (curPTR && *curPTR->ptr)
2050: return *curPTR->ptr++;
2051: return EOF;
2052: }
2053:
2054:
2055: /*-
2056: *---------------------------------------------------------------------
2057: * ParseUnreadc --
1.11 millert 2058: * Put back a character to the current file
1.1 deraadt 2059: *
2060: * Results:
2061: * None.
2062: *
2063: * Side Effects:
2064: *---------------------------------------------------------------------
2065: */
2066: static void
2067: ParseUnreadc(c)
2068: int c;
2069: {
2070: if (curFILE) {
2071: ungetc(c, curFILE);
2072: return;
2073: }
2074: if (curPTR) {
2075: *--(curPTR->ptr) = c;
2076: return;
2077: }
2078: }
2079:
2080:
2081: /* ParseSkipLine():
2082: * Grab the next line
2083: */
2084: static char *
2085: ParseSkipLine(skip)
2086: int skip; /* Skip lines that don't start with . */
2087: {
2088: char *line;
1.25 espie 2089: int c, lastc;
1.29 espie 2090: BUFFER buf;
1.1 deraadt 2091:
1.29 espie 2092: Buf_Init(&buf, MAKE_BSIZE);
1.11 millert 2093:
1.22 espie 2094: for (;;) {
1.29 espie 2095: Buf_Reset(&buf);
1.11 millert 2096: lastc = '\0';
2097:
2098: while (((c = ParseReadc()) != '\n' || lastc == '\\')
2099: && c != EOF) {
2100: if (c == '\n') {
1.29 espie 2101: Buf_ReplaceLastChar(&buf, ' ');
1.11 millert 2102: lineno++;
2103:
2104: while ((c = ParseReadc()) == ' ' || c == '\t');
2105:
2106: if (c == EOF)
2107: break;
2108: }
2109:
1.29 espie 2110: Buf_AddChar(&buf, c);
1.11 millert 2111: lastc = c;
2112: }
2113:
1.29 espie 2114: line = Buf_Retrieve(&buf);
1.22 espie 2115: lineno++;
2116: /* allow for non-newline terminated lines while skipping */
2117: if (line[0] == '.')
2118: break;
2119:
1.11 millert 2120: if (c == EOF) {
2121: Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
1.29 espie 2122: Buf_Destroy(&buf);
2123: return NULL;
1.11 millert 2124: }
1.22 espie 2125: if (skip == 0)
2126: break;
1.11 millert 2127:
1.22 espie 2128: }
1.1 deraadt 2129:
2130: return line;
2131: }
2132:
2133:
2134: /*-
2135: *---------------------------------------------------------------------
2136: * ParseReadLine --
2137: * Read an entire line from the input file. Called only by Parse_File.
2138: * To facilitate escaped newlines and what have you, a character is
2139: * buffered in 'lastc', which is '\0' when no characters have been
2140: * read. When we break out of the loop, c holds the terminating
2141: * character and lastc holds a character that should be added to
2142: * the line (unless we don't read anything but a terminator).
2143: *
2144: * Results:
2145: * A line w/o its newline
2146: *
2147: * Side Effects:
2148: * Only those associated with reading a character
2149: *---------------------------------------------------------------------
2150: */
2151: static char *
2152: ParseReadLine ()
2153: {
1.29 espie 2154: BUFFER buf; /* Buffer for current line */
1.1 deraadt 2155: register int c; /* the current character */
2156: register int lastc; /* The most-recent character */
2157: Boolean semiNL; /* treat semi-colons as newlines */
2158: Boolean ignDepOp; /* TRUE if should ignore dependency operators
2159: * for the purposes of setting semiNL */
2160: Boolean ignComment; /* TRUE if should ignore comments (in a
2161: * shell command */
2162: char *line; /* Result */
2163: char *ep; /* to strip trailing blanks */
2164:
2165: semiNL = FALSE;
2166: ignDepOp = FALSE;
2167: ignComment = FALSE;
2168:
2169: /*
2170: * Handle special-characters at the beginning of the line. Either a
2171: * leading tab (shell command) or pound-sign (possible conditional)
2172: * forces us to ignore comments and dependency operators and treat
2173: * semi-colons as semi-colons (by leaving semiNL FALSE). This also
2174: * discards completely blank lines.
2175: */
2176: for (;;) {
2177: c = ParseReadc();
2178:
2179: if (c == '\t') {
2180: ignComment = ignDepOp = TRUE;
2181: break;
2182: } else if (c == '\n') {
2183: lineno++;
2184: } else if (c == '#') {
2185: ParseUnreadc(c);
2186: break;
2187: } else {
2188: /*
2189: * Anything else breaks out without doing anything
2190: */
2191: break;
2192: }
2193: }
1.11 millert 2194:
1.1 deraadt 2195: if (c != EOF) {
2196: lastc = c;
1.29 espie 2197: Buf_Init(&buf, MAKE_BSIZE);
1.11 millert 2198:
1.1 deraadt 2199: while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
2200: (c != EOF))
2201: {
2202: test_char:
2203: switch(c) {
2204: case '\n':
2205: /*
2206: * Escaped newline: read characters until a non-space or an
2207: * unescaped newline and replace them all by a single space.
2208: * This is done by storing the space over the backslash and
2209: * dropping through with the next nonspace. If it is a
2210: * semi-colon and semiNL is TRUE, it will be recognized as a
2211: * newline in the code below this...
2212: */
2213: lineno++;
2214: lastc = ' ';
2215: while ((c = ParseReadc ()) == ' ' || c == '\t') {
2216: continue;
2217: }
2218: if (c == EOF || c == '\n') {
2219: goto line_read;
2220: } else {
2221: /*
2222: * Check for comments, semiNL's, etc. -- easier than
2223: * ParseUnreadc(c); continue;
2224: */
2225: goto test_char;
2226: }
2227: /*NOTREACHED*/
2228: break;
2229:
2230: case ';':
2231: /*
2232: * Semi-colon: Need to see if it should be interpreted as a
2233: * newline
2234: */
2235: if (semiNL) {
2236: /*
2237: * To make sure the command that may be following this
2238: * semi-colon begins with a tab, we push one back into the
2239: * input stream. This will overwrite the semi-colon in the
2240: * buffer. If there is no command following, this does no
2241: * harm, since the newline remains in the buffer and the
2242: * whole line is ignored.
2243: */
2244: ParseUnreadc('\t');
2245: goto line_read;
1.11 millert 2246: }
1.1 deraadt 2247: break;
2248: case '=':
2249: if (!semiNL) {
2250: /*
2251: * Haven't seen a dependency operator before this, so this
2252: * must be a variable assignment -- don't pay attention to
2253: * dependency operators after this.
2254: */
2255: ignDepOp = TRUE;
2256: } else if (lastc == ':' || lastc == '!') {
2257: /*
2258: * Well, we've seen a dependency operator already, but it
2259: * was the previous character, so this is really just an
2260: * expanded variable assignment. Revert semi-colons to
2261: * being just semi-colons again and ignore any more
2262: * dependency operators.
2263: *
2264: * XXX: Note that a line like "foo : a:=b" will blow up,
2265: * but who'd write a line like that anyway?
2266: */
2267: ignDepOp = TRUE; semiNL = FALSE;
2268: }
2269: break;
2270: case '#':
2271: if (!ignComment) {
1.2 deraadt 2272: if (
2273: #if 0
2274: compatMake &&
2275: #endif
2276: (lastc != '\\')) {
1.1 deraadt 2277: /*
2278: * If the character is a hash mark and it isn't escaped
2279: * (or we're being compatible), the thing is a comment.
2280: * Skip to the end of the line.
2281: */
2282: do {
2283: c = ParseReadc();
2284: } while ((c != '\n') && (c != EOF));
2285: goto line_read;
2286: } else {
2287: /*
2288: * Don't add the backslash. Just let the # get copied
2289: * over.
2290: */
2291: lastc = c;
2292: continue;
2293: }
2294: }
2295: break;
2296: case ':':
2297: case '!':
2298: if (!ignDepOp && (c == ':' || c == '!')) {
2299: /*
2300: * A semi-colon is recognized as a newline only on
2301: * dependency lines. Dependency lines are lines with a
2302: * colon or an exclamation point. Ergo...
2303: */
2304: semiNL = TRUE;
2305: }
2306: break;
2307: }
2308: /*
2309: * Copy in the previous character and save this one in lastc.
2310: */
1.29 espie 2311: Buf_AddChar(&buf, lastc);
1.1 deraadt 2312: lastc = c;
1.11 millert 2313:
1.1 deraadt 2314: }
2315: line_read:
2316: lineno++;
1.11 millert 2317:
1.28 espie 2318: if (lastc != '\0')
1.29 espie 2319: Buf_AddChar(&buf, lastc);
2320: line = Buf_Retrieve(&buf);
1.1 deraadt 2321:
2322: /*
2323: * Strip trailing blanks and tabs from the line.
2324: * Do not strip a blank or tab that is preceeded by
2325: * a '\'
2326: */
2327: ep = line;
2328: while (*ep)
2329: ++ep;
1.11 millert 2330: while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
1.1 deraadt 2331: if (ep > line + 1 && ep[-2] == '\\')
2332: break;
2333: --ep;
2334: }
2335: *ep = 0;
1.11 millert 2336:
1.1 deraadt 2337: if (line[0] == '.') {
2338: /*
2339: * The line might be a conditional. Ask the conditional module
2340: * about it and act accordingly
2341: */
2342: switch (Cond_Eval (line)) {
2343: case COND_SKIP:
2344: /*
2345: * Skip to next conditional that evaluates to COND_PARSE.
2346: */
2347: do {
2348: free (line);
2349: line = ParseSkipLine(1);
2350: } while (line && Cond_Eval(line) != COND_PARSE);
2351: if (line == NULL)
2352: break;
2353: /*FALLTHRU*/
2354: case COND_PARSE:
1.42 espie 2355: free(line);
1.1 deraadt 2356: line = ParseReadLine();
2357: break;
2358: case COND_INVALID:
1.30 espie 2359: {
2360: For *loop;
2361:
2362: loop = For_Eval(line);
2363: if (loop != NULL) {
2364: Boolean ok;
2365:
1.1 deraadt 2366: free(line);
2367: do {
1.30 espie 2368: /* Find the matching endfor. */
1.1 deraadt 2369: line = ParseSkipLine(0);
2370: if (line == NULL) {
1.30 espie 2371: Parse_Error(PARSE_FATAL,
1.1 deraadt 2372: "Unexpected end of file in for loop.\n");
1.30 espie 2373: return line;
1.1 deraadt 2374: }
1.30 espie 2375: ok = For_Accumulate(loop, line);
1.1 deraadt 2376: free(line);
1.30 espie 2377: } while (ok);
2378: For_Run(loop);
1.1 deraadt 2379: line = ParseReadLine();
2380: }
2381: break;
1.30 espie 2382: }
1.1 deraadt 2383: }
2384: }
2385: return (line);
2386:
2387: } else {
2388: /*
2389: * Hit end-of-file, so return a NULL line to indicate this.
2390: */
2391: return((char *)NULL);
2392: }
2393: }
2394:
2395: /*-
2396: *-----------------------------------------------------------------------
2397: * ParseFinishLine --
2398: * Handle the end of a dependency group.
2399: *
2400: * Side Effects:
2401: * inLine set FALSE. 'targets' list destroyed.
2402: *
2403: *-----------------------------------------------------------------------
2404: */
2405: static void
2406: ParseFinishLine()
2407: {
2408: if (inLine) {
1.41 espie 2409: Lst_Every(targets, Suff_EndTransform);
1.43 espie 2410: Lst_Delete(targets, ParseHasCommands);
1.1 deraadt 2411: targets = NULL;
2412: inLine = FALSE;
2413: }
2414: }
1.11 millert 2415:
1.1 deraadt 2416:
2417: /*-
2418: *---------------------------------------------------------------------
2419: * Parse_File --
2420: * Parse a file into its component parts, incorporating it into the
2421: * current dependency graph. This is the main function and controls
2422: * almost every other function in this module
2423: *
2424: * Results:
2425: * None
2426: *
2427: * Side Effects:
2428: * Loads. Nodes are added to the list of all targets, nodes and links
2429: * are added to the dependency graph. etc. etc. etc.
2430: *---------------------------------------------------------------------
2431: */
2432: void
2433: Parse_File(name, stream)
2434: char *name; /* the name of the file being read */
2435: FILE * stream; /* Stream open to makefile to parse */
2436: {
2437: register char *cp, /* pointer into the line */
2438: *line; /* the line we're working on */
2439:
2440: inLine = FALSE;
1.38 espie 2441: fname = estrdup(name);
2442: #ifdef CLEANUP
1.43 espie 2443: Lst_AtEnd(&fileNames, fname);
1.38 espie 2444: #endif
1.1 deraadt 2445: curFILE = stream;
2446: lineno = 0;
2447: fatals = 0;
2448:
2449: do {
2450: while ((line = ParseReadLine ()) != NULL) {
2451: if (*line == '.') {
2452: /*
2453: * Lines that begin with the special character are either
2454: * include or undef directives.
2455: */
2456: for (cp = line + 1; isspace (*cp); cp++) {
2457: continue;
2458: }
2459: if (strncmp (cp, "include", 7) == 0) {
2460: ParseDoInclude (cp + 7);
2461: goto nextLine;
2462: } else if (strncmp(cp, "undef", 5) == 0) {
2463: char *cp2;
2464: for (cp += 5; isspace((unsigned char) *cp); cp++) {
2465: continue;
2466: }
2467:
2468: for (cp2 = cp; !isspace((unsigned char) *cp2) &&
2469: (*cp2 != '\0'); cp2++) {
2470: continue;
2471: }
2472:
2473: *cp2 = '\0';
2474:
2475: Var_Delete(cp, VAR_GLOBAL);
2476: goto nextLine;
2477: }
2478: }
1.11 millert 2479: if (*line == '#') {
2480: /* If we're this far, the line must be a comment. */
1.1 deraadt 2481: goto nextLine;
2482: }
1.11 millert 2483:
1.1 deraadt 2484: if (*line == '\t') {
2485: /*
2486: * If a line starts with a tab, it can only hope to be
2487: * a creation command.
2488: */
2489: #ifndef POSIX
2490: shellCommand:
2491: #endif
2492: for (cp = line + 1; isspace (*cp); cp++) {
2493: continue;
2494: }
2495: if (*cp) {
2496: if (inLine) {
2497: /*
2498: * So long as it's not a blank line and we're actually
2499: * in a dependency spec, add the command to the list of
1.11 millert 2500: * commands of all targets in the dependency spec
1.1 deraadt 2501: */
1.41 espie 2502: Lst_ForEach(targets, ParseAddCmd, cp);
1.20 espie 2503: #ifdef CLEANUP
1.43 espie 2504: Lst_AtEnd(&targCmds, line);
1.20 espie 2505: #endif
1.1 deraadt 2506: continue;
2507: } else {
2508: Parse_Error (PARSE_FATAL,
1.10 briggs 2509: "Unassociated shell command \"%s\"",
1.1 deraadt 2510: cp);
2511: }
2512: }
2513: #ifdef SYSVINCLUDE
1.11 millert 2514: } else if (strncmp (line, "include", 7) == 0 &&
1.6 tholo 2515: isspace((unsigned char) line[7]) &&
1.1 deraadt 2516: strchr(line, ':') == NULL) {
2517: /*
2518: * It's an S3/S5-style "include".
2519: */
2520: ParseTraditionalInclude (line + 7);
2521: goto nextLine;
2522: #endif
2523: } else if (Parse_IsVar (line)) {
2524: ParseFinishLine();
2525: Parse_DoVar (line, VAR_GLOBAL);
2526: } else {
2527: /*
2528: * We now know it's a dependency line so it needs to have all
2529: * variables expanded before being parsed. Tell the variable
2530: * module to complain if some variable is undefined...
2531: * To make life easier on novices, if the line is indented we
2532: * first make sure the line has a dependency operator in it.
2533: * If it doesn't have an operator and we're in a dependency
2534: * line's script, we assume it's actually a shell command
2535: * and add it to the current list of targets.
2536: */
2537: #ifndef POSIX
2538: Boolean nonSpace = FALSE;
2539: #endif
1.11 millert 2540:
1.1 deraadt 2541: cp = line;
2542: if (isspace((unsigned char) line[0])) {
2543: while ((*cp != '\0') && isspace((unsigned char) *cp)) {
2544: cp++;
2545: }
2546: if (*cp == '\0') {
2547: goto nextLine;
2548: }
2549: #ifndef POSIX
2550: while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
2551: nonSpace = TRUE;
2552: cp++;
2553: }
2554: #endif
2555: }
1.11 millert 2556:
1.1 deraadt 2557: #ifndef POSIX
2558: if (*cp == '\0') {
2559: if (inLine) {
2560: Parse_Error (PARSE_WARNING,
2561: "Shell command needs a leading tab");
2562: goto shellCommand;
2563: } else if (nonSpace) {
2564: Parse_Error (PARSE_FATAL, "Missing operator");
2565: }
2566: } else {
2567: #endif
2568: ParseFinishLine();
2569:
1.31 espie 2570: cp = Var_Subst(line, VAR_CMD, TRUE);
1.1 deraadt 2571: free (line);
2572: line = cp;
1.11 millert 2573:
1.1 deraadt 2574: /*
1.11 millert 2575: * Need a non-circular list for the target nodes
1.1 deraadt 2576: */
2577: if (targets)
1.43 espie 2578: Lst_Delete(targets, NOFREE);
1.1 deraadt 2579:
1.43 espie 2580: targets = Lst_New();
1.1 deraadt 2581: inLine = TRUE;
1.11 millert 2582:
1.1 deraadt 2583: ParseDoDependency (line);
2584: #ifndef POSIX
2585: }
2586: #endif
2587: }
2588:
2589: nextLine:
2590:
2591: free (line);
2592: }
2593: /*
1.11 millert 2594: * Reached EOF, but it may be just EOF of an include file...
1.1 deraadt 2595: */
2596: } while (ParseEOF(1) == CONTINUE);
2597:
2598: /*
2599: * Make sure conditionals are clean
2600: */
2601: Cond_End();
2602:
2603: if (fatals) {
2604: fprintf (stderr, "Fatal errors encountered -- cannot continue\n");
2605: exit (1);
2606: }
2607: }
2608:
2609: /*-
2610: *---------------------------------------------------------------------
2611: * Parse_Init --
2612: * initialize the parsing module
2613: *
2614: * Side Effects:
2615: * the parseIncPath list is initialized...
2616: *---------------------------------------------------------------------
2617: */
2618: void
1.43 espie 2619: Parse_Init()
1.1 deraadt 2620: {
1.33 espie 2621: mainNode = NULL;
1.43 espie 2622: Lst_Init(&parseIncPath);
2623: Lst_Init(&sysIncPath);
2624: Lst_Init(&includes);
1.20 espie 2625: #ifdef CLEANUP
1.43 espie 2626: Lst_Init(&targCmds);
2627: Lst_Init(&fileNames);
1.20 espie 2628: #endif
1.1 deraadt 2629: }
2630:
2631: void
2632: Parse_End()
2633: {
1.20 espie 2634: #ifdef CLEANUP
1.43 espie 2635: Lst_Destroy(&targCmds, (SimpleProc)free);
2636: Lst_Destroy(&fileNames, (void (*) __P((ClientData))) free);
1.1 deraadt 2637: if (targets)
1.43 espie 2638: Lst_Delete(targets, NOFREE);
2639: Lst_Destroy(&sysIncPath, Dir_Destroy);
2640: Lst_Destroy(&parseIncPath, Dir_Destroy);
2641: Lst_Destroy(&includes, NOFREE); /* Should be empty now */
1.20 espie 2642: #endif
1.1 deraadt 2643: }
1.11 millert 2644:
1.1 deraadt 2645:
2646: /*-
2647: *-----------------------------------------------------------------------
2648: * Parse_MainName --
2649: * Return a Lst of the main target to create for main()'s sake. If
2650: * no such target exists, we Punt with an obnoxious error message.
2651: *
2652: * Side Effects:
1.44 ! espie 2653: * Add the node to create to the list.
1.1 deraadt 2654: *
2655: *-----------------------------------------------------------------------
2656: */
1.44 ! espie 2657: void
! 2658: Parse_MainName(listmain)
! 2659: Lst listmain; /* result list */
1.1 deraadt 2660: {
2661:
1.44 ! espie 2662: if (mainNode == NULL)
1.8 deraadt 2663: Punt ("no target to make.");
1.1 deraadt 2664: /*NOTREACHED*/
1.44 ! espie 2665: else if (mainNode->type & OP_DOUBLEDEP) {
1.37 espie 2666: Lst_AtEnd(listmain, mainNode);
1.43 espie 2667: Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
1.1 deraadt 2668: }
2669: else
1.37 espie 2670: Lst_AtEnd(listmain, mainNode);
1.1 deraadt 2671: }
1.24 espie 2672:
2673: unsigned long
2674: Parse_Getlineno()
2675: {
2676: return lineno;
1.38 espie 2677: }
2678:
2679: const char *
2680: Parse_Getfilename()
2681: {
2682: return fname;
1.24 espie 2683: }
2684: