Annotation of src/usr.bin/make/parse.c, Revision 1.41
1.41 ! espie 1: /* $OpenBSD: parse.c,v 1.40 2000/06/10 01:26:37 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.41 ! espie 46: static char rcsid[] = "$OpenBSD: parse.c,v 1.40 2000/06/10 01:26:37 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
108: static Lst fileNames; /* file names to free at end */
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.1 deraadt 120: static Lst 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:
150: static Lst includes; /* stack of IFiles generated by
151: * #includes */
152: Lst parseIncPath; /* list of directories for "..." includes */
153: Lst sysIncPath; /* list of directories for <...> includes */
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.41 ! espie 251: static void ParseLinkSrc __P((ClientData, ClientData));
1.1 deraadt 252: static int ParseDoOp __P((ClientData, ClientData));
1.3 deraadt 253: static int ParseAddDep __P((ClientData, ClientData));
254: static void ParseDoSrc __P((int, char *, Lst));
1.1 deraadt 255: static int ParseFindMain __P((ClientData, ClientData));
1.41 ! espie 256: static void ParseAddDir __P((ClientData, ClientData));
! 257: static void ParseClearPath __P((ClientData));
1.1 deraadt 258: static void ParseDoDependency __P((char *));
1.41 ! espie 259: static void ParseAddCmd __P((ClientData, ClientData));
1.21 espie 260: static int __inline ParseReadc __P((void));
1.1 deraadt 261: static void ParseUnreadc __P((int));
262: static void ParseHasCommands __P((ClientData));
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.1 deraadt 433: ClientData pgnp; /* The parent node */
434: ClientData cgnp; /* The child node */
435: {
1.41 ! espie 436: GNode *pgn = (GNode *)pgnp;
! 437: GNode *cgn = (GNode *)cgnp;
1.37 espie 438: if (Lst_Member(pgn->children, cgn) == NULL) {
439: Lst_AtEnd(pgn->children, cgn);
1.41 ! espie 440: if (specType == Not)
1.37 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)
464: ClientData gnp; /* The node to which the operator is to be
465: * applied */
466: ClientData opp; /* The operator to apply */
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.37 espie 503: Lst_ForEach(gn->parents, ParseLinkSrc, cohort);
1.1 deraadt 504: cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
1.37 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)
541: ClientData pp;
542: ClientData sp;
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.37 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.37 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.37 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.33 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)
694: ClientData gnp; /* Node to examine */
695: ClientData dummy;
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)
719: ClientData path;
720: ClientData name;
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.1 deraadt 737: ClientData path;
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.3 deraadt 787: Lst sources; /* list of archive source names after
788: * expansion */
1.1 deraadt 789: Lst curTargs; /* list of target names to be found and added
790: * to the targets list */
1.3 deraadt 791: Lst curSrcs; /* list of sources in order */
1.1 deraadt 792:
793: tOp = 0;
794:
795: specType = Not;
1.3 deraadt 796: waiting = 0;
1.1 deraadt 797: paths = (Lst)NULL;
798:
1.32 espie 799: curTargs = Lst_Init();
800: curSrcs = Lst_Init();
1.11 millert 801:
1.1 deraadt 802: do {
803: for (cp = line;
1.18 millert 804: *cp && !isspace (*cp) && (*cp != '(');
1.1 deraadt 805: cp++)
806: {
1.19 millert 807: /*
808: * We don't want to end a word on ':' or '!' if there is a
809: * better match later on in the string. By "better" I mean
810: * one that is followed by whitespace. This allows the user
811: * to have targets like:
812: * fie::fi:fo: fum
813: * where "fie::fi:fo" is the target. In real life this is used
814: * for perl5 library man pages where "::" separates an object
815: * from its class. Ie: "File::Spec::Unix". This behaviour
816: * is also consistent with other versions of make.
817: */
1.18 millert 818: if (*cp == '!' || *cp == ':') {
819: char *p = cp + 1;
820:
821: if (*p == '\0')
822: break; /* no chance, not enough room */
823: /*
824: * Only end the word on ':' or '!' if there is not
1.19 millert 825: * a match later on followed by whitespace.
1.18 millert 826: */
827: while ((p = strchr(p + 1, *cp)) && !isspace(*(p + 1)))
828: ;
829: if (!p || !isspace(*(p + 1)))
830: break;
831: } else if (*cp == '$') {
1.1 deraadt 832: /*
833: * Must be a dynamic source (would have been expanded
834: * otherwise), so call the Var module to parse the puppy
835: * so we can safely advance beyond it...There should be
836: * no errors in this, as they would have been discovered
837: * in the initial Var_Subst and we wouldn't be here.
838: */
1.36 espie 839: size_t length;
1.1 deraadt 840: Boolean freeIt;
841: char *result;
842:
843: result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
844:
845: if (freeIt) {
846: free(result);
847: }
848: cp += length-1;
849: }
850: continue;
851: }
852: if (*cp == '(') {
853: /*
854: * Archives must be handled specially to make sure the OP_ARCHV
855: * flag is set in their 'type' field, for one thing, and because
856: * things like "archive(file1.o file2.o file3.o)" are permissible.
857: * Arch_ParseArchive will set 'line' to be the first non-blank
858: * after the archive-spec. It creates/finds nodes for the members
859: * and places them on the given list, returning SUCCESS if all
860: * went well and FAILURE if there was an error in the
861: * specification. On error, line should remain untouched.
862: */
863: if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
864: Parse_Error (PARSE_FATAL,
865: "Error in archive specification: \"%s\"", line);
866: return;
867: } else {
868: continue;
869: }
870: }
871: savec = *cp;
1.11 millert 872:
1.1 deraadt 873: if (!*cp) {
874: /*
875: * Ending a dependency line without an operator is a Bozo
1.11 millert 876: * no-no
1.1 deraadt 877: */
878: Parse_Error (PARSE_FATAL, "Need an operator");
879: return;
880: }
881: *cp = '\0';
882: /*
883: * Have a word in line. See if it's a special target and set
884: * specType to match it.
885: */
886: if (*line == '.' && isupper (line[1])) {
887: /*
888: * See if the target is a special target that must have it
1.11 millert 889: * or its sources handled specially.
1.1 deraadt 890: */
891: int keywd = ParseFindKeyword(line);
892: if (keywd != -1) {
893: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
894: Parse_Error(PARSE_FATAL, "Mismatched special targets");
895: return;
896: }
1.11 millert 897:
1.1 deraadt 898: specType = parseKeywords[keywd].spec;
899: tOp = parseKeywords[keywd].op;
900:
901: /*
902: * Certain special targets have special semantics:
903: * .PATH Have to set the dirSearchPath
904: * variable too
905: * .MAIN Its sources are only used if
906: * nothing has been specified to
907: * create.
908: * .DEFAULT Need to create a node to hang
909: * commands on, but we don't want
910: * it in the graph, nor do we want
911: * it to be the Main Target, so we
912: * create it, set OP_NOTMAIN and
913: * add it to the list, setting
914: * DEFAULT to the new node for
915: * later use. We claim the node is
916: * A transformation rule to make
917: * life easier later, when we'll
918: * use Make_HandleUse to actually
919: * apply the .DEFAULT commands.
1.7 niklas 920: * .PHONY The list of targets
1.17 espie 921: * .NOPATH Don't search for file in the path
1.1 deraadt 922: * .BEGIN
923: * .END
924: * .INTERRUPT Are not to be considered the
925: * main target.
926: * .NOTPARALLEL Make only one target at a time.
927: * .SINGLESHELL Create a shell for each command.
1.33 espie 928: * .ORDER Must set initial predecessor to NULL
1.1 deraadt 929: */
930: switch (specType) {
931: case ExPath:
932: if (paths == NULL) {
1.32 espie 933: paths = Lst_Init();
1.1 deraadt 934: }
1.37 espie 935: Lst_AtEnd(paths, dirSearchPath);
1.1 deraadt 936: break;
937: case Main:
938: if (!Lst_IsEmpty(create)) {
939: specType = Not;
940: }
941: break;
942: case Begin:
943: case End:
944: case Interrupt:
945: gn = Targ_FindNode(line, TARG_CREATE);
946: gn->type |= OP_NOTMAIN;
1.37 espie 947: Lst_AtEnd(targets, gn);
1.1 deraadt 948: break;
949: case Default:
950: gn = Targ_NewGN(".DEFAULT");
951: gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
1.37 espie 952: Lst_AtEnd(targets, gn);
1.1 deraadt 953: DEFAULT = gn;
954: break;
955: case NotParallel:
956: {
957: extern int maxJobs;
1.11 millert 958:
1.1 deraadt 959: maxJobs = 1;
960: break;
961: }
962: case SingleShell:
963: compatMake = 1;
964: break;
965: case Order:
1.33 espie 966: predecessor = NULL;
1.1 deraadt 967: break;
968: default:
969: break;
970: }
971: } else if (strncmp (line, ".PATH", 5) == 0) {
972: /*
973: * .PATH<suffix> has to be handled specially.
974: * Call on the suffix module to give us a path to
975: * modify.
976: */
977: Lst path;
1.11 millert 978:
1.1 deraadt 979: specType = ExPath;
980: path = Suff_GetPath (&line[5]);
1.33 espie 981: if (path == NULL) {
1.1 deraadt 982: Parse_Error (PARSE_FATAL,
983: "Suffix '%s' not defined (yet)",
984: &line[5]);
985: return;
986: } else {
1.33 espie 987: if (paths == NULL) {
1.32 espie 988: paths = Lst_Init();
1.1 deraadt 989: }
1.37 espie 990: Lst_AtEnd(paths, path);
1.1 deraadt 991: }
992: }
993: }
1.11 millert 994:
1.1 deraadt 995: /*
996: * Have word in line. Get or create its node and stick it at
1.11 millert 997: * the end of the targets list
1.1 deraadt 998: */
999: if ((specType == Not) && (*line != '\0')) {
1.34 espie 1000: char *targName;
1001:
1.1 deraadt 1002: if (Dir_HasWildcards(line)) {
1003: /*
1004: * Targets are to be sought only in the current directory,
1005: * so create an empty path for the thing. Note we need to
1006: * use Dir_Destroy in the destruction of the path as the
1007: * Dir module could have added a directory to the path...
1008: */
1.32 espie 1009: Lst emptyPath = Lst_Init();
1.11 millert 1010:
1.1 deraadt 1011: Dir_Expand(line, emptyPath, curTargs);
1.11 millert 1012:
1.1 deraadt 1013: Lst_Destroy(emptyPath, Dir_Destroy);
1014: } else {
1015: /*
1016: * No wildcards, but we want to avoid code duplication,
1017: * so create a list with the word on it.
1018: */
1.37 espie 1019: Lst_AtEnd(curTargs, line);
1.1 deraadt 1020: }
1.11 millert 1021:
1.34 espie 1022: while((targName = (char *)Lst_DeQueue(curTargs)) != NULL) {
1.1 deraadt 1023: if (!Suff_IsTransform (targName)) {
1024: gn = Targ_FindNode (targName, TARG_CREATE);
1025: } else {
1026: gn = Suff_AddTransform (targName);
1027: }
1.11 millert 1028:
1.16 millert 1029: if (gn != NULL)
1.37 espie 1030: Lst_AtEnd(targets, gn);
1.1 deraadt 1031: }
1032: } else if (specType == ExPath && *line != '.' && *line != '\0') {
1033: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1034: }
1.11 millert 1035:
1.1 deraadt 1036: *cp = savec;
1037: /*
1038: * If it is a special type and not .PATH, it's the only target we
1039: * allow on this line...
1040: */
1041: if (specType != Not && specType != ExPath) {
1042: Boolean warn = FALSE;
1.11 millert 1043:
1.1 deraadt 1044: while ((*cp != '!') && (*cp != ':') && *cp) {
1045: if (*cp != ' ' && *cp != '\t') {
1046: warn = TRUE;
1047: }
1048: cp++;
1049: }
1050: if (warn) {
1051: Parse_Error(PARSE_WARNING, "Extra target ignored");
1052: }
1053: } else {
1054: while (*cp && isspace (*cp)) {
1055: cp++;
1056: }
1057: }
1058: line = cp;
1059: } while ((*line != '!') && (*line != ':') && *line);
1060:
1061: /*
1062: * Don't need the list of target names anymore...
1063: */
1064: Lst_Destroy(curTargs, NOFREE);
1065:
1066: if (!Lst_IsEmpty(targets)) {
1067: switch(specType) {
1068: default:
1069: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
1070: break;
1071: case Default:
1072: case Begin:
1073: case End:
1074: case Interrupt:
1075: /*
1076: * These four create nodes on which to hang commands, so
1077: * targets shouldn't be empty...
1078: */
1079: case Not:
1080: /*
1081: * Nothing special here -- targets can be empty if it wants.
1082: */
1083: break;
1084: }
1085: }
1086:
1087: /*
1088: * Have now parsed all the target names. Must parse the operator next. The
1089: * result is left in op .
1090: */
1091: if (*cp == '!') {
1092: op = OP_FORCE;
1093: } else if (*cp == ':') {
1094: if (cp[1] == ':') {
1095: op = OP_DOUBLEDEP;
1096: cp++;
1097: } else {
1098: op = OP_DEPENDS;
1099: }
1100: } else {
1101: Parse_Error (PARSE_FATAL, "Missing dependency operator");
1102: return;
1103: }
1104:
1105: cp++; /* Advance beyond operator */
1106:
1.40 espie 1107: Lst_Find(targets, ParseDoOp, &op);
1.1 deraadt 1108:
1109: /*
1.11 millert 1110: * Get to the first source
1.1 deraadt 1111: */
1112: while (*cp && isspace (*cp)) {
1113: cp++;
1114: }
1115: line = cp;
1116:
1117: /*
1118: * Several special targets take different actions if present with no
1119: * sources:
1120: * a .SUFFIXES line with no sources clears out all old suffixes
1121: * a .PRECIOUS line makes all targets precious
1122: * a .IGNORE line ignores errors for all targets
1123: * a .SILENT line creates silence when making all targets
1124: * a .PATH removes all directories from the search path(s).
1125: */
1126: if (!*line) {
1127: switch (specType) {
1128: case Suffixes:
1129: Suff_ClearSuffixes ();
1130: break;
1131: case Precious:
1132: allPrecious = TRUE;
1133: break;
1134: case Ignore:
1135: ignoreErrors = TRUE;
1136: break;
1137: case Silent:
1138: beSilent = TRUE;
1139: break;
1140: case ExPath:
1.41 ! espie 1141: Lst_Every(paths, ParseClearPath);
1.1 deraadt 1142: break;
1143: default:
1144: break;
1145: }
1146: } else if (specType == MFlags) {
1147: /*
1148: * Call on functions in main.c to deal with these arguments and
1149: * set the initial character to a null-character so the loop to
1150: * get sources won't get anything
1151: */
1152: Main_ParseArgLine (line);
1153: *line = '\0';
1154: } else if (specType == ExShell) {
1155: if (Job_ParseShell (line) != SUCCESS) {
1156: Parse_Error (PARSE_FATAL, "improper shell specification");
1157: return;
1158: }
1159: *line = '\0';
1160: } else if ((specType == NotParallel) || (specType == SingleShell)) {
1161: *line = '\0';
1162: }
1.11 millert 1163:
1.1 deraadt 1164: /*
1.11 millert 1165: * NOW GO FOR THE SOURCES
1.1 deraadt 1166: */
1167: if ((specType == Suffixes) || (specType == ExPath) ||
1168: (specType == Includes) || (specType == Libs) ||
1169: (specType == Null))
1170: {
1171: while (*line) {
1172: /*
1173: * If the target was one that doesn't take files as its sources
1174: * but takes something like suffixes, we take each
1175: * space-separated word on the line as a something and deal
1176: * with it accordingly.
1177: *
1178: * If the target was .SUFFIXES, we take each source as a
1179: * suffix and add it to the list of suffixes maintained by the
1180: * Suff module.
1181: *
1182: * If the target was a .PATH, we add the source as a directory
1183: * to search on the search path.
1184: *
1185: * If it was .INCLUDES, the source is taken to be the suffix of
1186: * files which will be #included and whose search path should
1187: * be present in the .INCLUDES variable.
1188: *
1189: * If it was .LIBS, the source is taken to be the suffix of
1190: * files which are considered libraries and whose search path
1191: * should be present in the .LIBS variable.
1192: *
1193: * If it was .NULL, the source is the suffix to use when a file
1194: * has no valid suffix.
1195: */
1196: char savec;
1197: while (*cp && !isspace (*cp)) {
1198: cp++;
1199: }
1200: savec = *cp;
1201: *cp = '\0';
1202: switch (specType) {
1203: case Suffixes:
1204: Suff_AddSuffix (line);
1205: break;
1206: case ExPath:
1.37 espie 1207: Lst_ForEach(paths, ParseAddDir, line);
1.1 deraadt 1208: break;
1209: case Includes:
1210: Suff_AddInclude (line);
1211: break;
1212: case Libs:
1213: Suff_AddLib (line);
1214: break;
1215: case Null:
1216: Suff_SetNull (line);
1217: break;
1218: default:
1219: break;
1220: }
1221: *cp = savec;
1222: if (savec != '\0') {
1223: cp++;
1224: }
1225: while (*cp && isspace (*cp)) {
1226: cp++;
1227: }
1228: line = cp;
1229: }
1230: if (paths) {
1231: Lst_Destroy(paths, NOFREE);
1232: }
1233: } else {
1234: while (*line) {
1235: /*
1236: * The targets take real sources, so we must beware of archive
1237: * specifications (i.e. things with left parentheses in them)
1238: * and handle them accordingly.
1239: */
1240: while (*cp && !isspace (*cp)) {
1241: if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
1242: /*
1243: * Only stop for a left parenthesis if it isn't at the
1244: * start of a word (that'll be for variable changes
1245: * later) and isn't preceded by a dollar sign (a dynamic
1246: * source).
1247: */
1248: break;
1249: } else {
1250: cp++;
1251: }
1252: }
1253:
1254: if (*cp == '(') {
1255: GNode *gn;
1256:
1.32 espie 1257: sources = Lst_Init();
1.1 deraadt 1258: if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
1259: Parse_Error (PARSE_FATAL,
1260: "Error in source archive spec \"%s\"", line);
1261: return;
1262: }
1263:
1.34 espie 1264: while ((gn = (GNode *)Lst_DeQueue(sources)) != NULL)
1265: ParseDoSrc(tOp, gn->name, curSrcs);
1.41 ! espie 1266: Lst_Destroy(sources, NOFREE);
1.1 deraadt 1267: cp = line;
1268: } else {
1269: if (*cp) {
1270: *cp = '\0';
1271: cp += 1;
1272: }
1273:
1.3 deraadt 1274: ParseDoSrc (tOp, line, curSrcs);
1.1 deraadt 1275: }
1276: while (*cp && isspace (*cp)) {
1277: cp++;
1278: }
1279: line = cp;
1280: }
1281: }
1.11 millert 1282:
1.33 espie 1283: if (mainNode == NULL) {
1.1 deraadt 1284: /*
1285: * If we have yet to decide on a main target to make, in the
1286: * absence of any user input, we want the first target on
1287: * the first dependency line that is actually a real target
1288: * (i.e. isn't a .USE or .EXEC rule) to be made.
1289: */
1.40 espie 1290: Lst_Find(targets, ParseFindMain, NULL);
1.1 deraadt 1291: }
1292:
1.3 deraadt 1293: /*
1294: * Finally, destroy the list of sources
1295: */
1296: Lst_Destroy(curSrcs, NOFREE);
1.1 deraadt 1297: }
1298:
1299: /*-
1300: *---------------------------------------------------------------------
1301: * Parse_IsVar --
1302: * Return TRUE if the passed line is a variable assignment. A variable
1303: * assignment consists of a single word followed by optional whitespace
1304: * followed by either a += or an = operator.
1305: * This function is used both by the Parse_File function and main when
1306: * parsing the command-line arguments.
1307: *
1308: * Results:
1309: * TRUE if it is. FALSE if it ain't
1310: *
1311: * Side Effects:
1312: * none
1313: *---------------------------------------------------------------------
1314: */
1315: Boolean
1316: Parse_IsVar (line)
1317: register char *line; /* the line to check */
1318: {
1319: register Boolean wasSpace = FALSE; /* set TRUE if found a space */
1320: register Boolean haveName = FALSE; /* Set TRUE if have a variable name */
1321: int level = 0;
1322: #define ISEQOPERATOR(c) \
1323: (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1324:
1325: /*
1326: * Skip to variable name
1327: */
1.11 millert 1328: for (;(*line == ' ') || (*line == '\t'); line++)
1.1 deraadt 1329: continue;
1330:
1331: for (; *line != '=' || level != 0; line++)
1332: switch (*line) {
1333: case '\0':
1334: /*
1335: * end-of-line -- can't be a variable assignment.
1336: */
1337: return FALSE;
1338:
1339: case ' ':
1340: case '\t':
1341: /*
1342: * there can be as much white space as desired so long as there is
1.11 millert 1343: * only one word before the operator
1.1 deraadt 1344: */
1345: wasSpace = TRUE;
1346: break;
1347:
1348: case '(':
1349: case '{':
1350: level++;
1351: break;
1352:
1353: case '}':
1354: case ')':
1355: level--;
1356: break;
1.11 millert 1357:
1.1 deraadt 1358: default:
1359: if (wasSpace && haveName) {
1360: if (ISEQOPERATOR(*line)) {
1361: /*
1.9 briggs 1362: * We must have a finished word
1363: */
1364: if (level != 0)
1365: return FALSE;
1366:
1367: /*
1.1 deraadt 1368: * When an = operator [+?!:] is found, the next
1.9 briggs 1369: * character must be an = or it ain't a valid
1.1 deraadt 1370: * assignment.
1371: */
1.9 briggs 1372: if (line[1] == '=')
1.1 deraadt 1373: return haveName;
1.9 briggs 1374: #ifdef SUNSHCMD
1.1 deraadt 1375: /*
1.9 briggs 1376: * This is a shell command
1.1 deraadt 1377: */
1.9 briggs 1378: if (strncmp(line, ":sh", 3) == 0)
1379: return haveName;
1380: #endif
1.1 deraadt 1381: }
1.9 briggs 1382: /*
1383: * This is the start of another word, so not assignment.
1384: */
1385: return FALSE;
1.1 deraadt 1386: }
1387: else {
1.11 millert 1388: haveName = TRUE;
1.1 deraadt 1389: wasSpace = FALSE;
1390: }
1391: break;
1392: }
1393:
1394: return haveName;
1395: }
1396:
1397: /*-
1398: *---------------------------------------------------------------------
1399: * Parse_DoVar --
1400: * Take the variable assignment in the passed line and do it in the
1401: * global context.
1402: *
1403: * Note: There is a lexical ambiguity with assignment modifier characters
1404: * in variable names. This routine interprets the character before the =
1405: * as a modifier. Therefore, an assignment like
1406: * C++=/usr/bin/CC
1407: * is interpreted as "C+ +=" instead of "C++ =".
1408: *
1409: * Results:
1410: * none
1411: *
1412: * Side Effects:
1413: * the variable structure of the given variable name is altered in the
1414: * global context.
1415: *---------------------------------------------------------------------
1416: */
1417: void
1418: Parse_DoVar (line, ctxt)
1419: char *line; /* a line guaranteed to be a variable
1420: * assignment. This reduces error checks */
1421: GNode *ctxt; /* Context in which to do the assignment */
1422: {
1423: char *cp; /* pointer into line */
1424: enum {
1425: VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1426: } type; /* Type of assignment */
1.11 millert 1427: char *opc; /* ptr to operator character to
1.1 deraadt 1428: * null-terminate the variable name */
1.11 millert 1429: /*
1.1 deraadt 1430: * Avoid clobbered variable warnings by forcing the compiler
1431: * to ``unregister'' variables
1432: */
1433: #if __GNUC__
1434: (void) &cp;
1435: (void) &line;
1436: #endif
1437:
1438: /*
1439: * Skip to variable name
1440: */
1441: while ((*line == ' ') || (*line == '\t')) {
1442: line++;
1443: }
1444:
1445: /*
1446: * Skip to operator character, nulling out whitespace as we go
1447: */
1448: for (cp = line + 1; *cp != '='; cp++) {
1449: if (isspace (*cp)) {
1450: *cp = '\0';
1451: }
1452: }
1453: opc = cp-1; /* operator is the previous character */
1454: *cp++ = '\0'; /* nuke the = */
1455:
1456: /*
1457: * Check operator type
1458: */
1459: switch (*opc) {
1460: case '+':
1461: type = VAR_APPEND;
1462: *opc = '\0';
1463: break;
1464:
1465: case '?':
1466: /*
1467: * If the variable already has a value, we don't do anything.
1468: */
1469: *opc = '\0';
1470: if (Var_Exists(line, ctxt)) {
1471: return;
1472: } else {
1473: type = VAR_NORMAL;
1474: }
1475: break;
1476:
1477: case ':':
1478: type = VAR_SUBST;
1479: *opc = '\0';
1480: break;
1481:
1482: case '!':
1483: type = VAR_SHELL;
1484: *opc = '\0';
1485: break;
1486:
1487: default:
1.9 briggs 1488: #ifdef SUNSHCMD
1489: while (*opc != ':')
1490: if (--opc < line)
1491: break;
1492:
1493: if (strncmp(opc, ":sh", 3) == 0) {
1494: type = VAR_SHELL;
1495: *opc = '\0';
1496: break;
1497: }
1498: #endif
1.1 deraadt 1499: type = VAR_NORMAL;
1500: break;
1501: }
1502:
1503: while (isspace (*cp)) {
1504: cp++;
1505: }
1506:
1507: if (type == VAR_APPEND) {
1508: Var_Append (line, cp, ctxt);
1509: } else if (type == VAR_SUBST) {
1510: /*
1511: * Allow variables in the old value to be undefined, but leave their
1512: * invocation alone -- this is done by forcing oldVars to be false.
1513: * XXX: This can cause recursive variables, but that's not hard to do,
1514: * and this allows someone to do something like
1515: *
1516: * CFLAGS = $(.INCLUDES)
1517: * CFLAGS := -I.. $(CFLAGS)
1518: *
1519: * And not get an error.
1520: */
1521: Boolean oldOldVars = oldVars;
1522:
1523: oldVars = FALSE;
1.31 espie 1524: cp = Var_Subst(cp, ctxt, FALSE);
1.1 deraadt 1525: oldVars = oldOldVars;
1526:
1527: Var_Set(line, cp, ctxt);
1528: free(cp);
1529: } else if (type == VAR_SHELL) {
1.9 briggs 1530: Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
1531: * if any variable expansion was performed */
1532: char *res, *err;
1.1 deraadt 1533:
1.9 briggs 1534: if (strchr(cp, '$') != NULL) {
1.1 deraadt 1535: /*
1536: * There's a dollar sign in the command, so perform variable
1537: * expansion on the whole thing. The resulting string will need
1538: * freeing when we're done, so set freeCmd to TRUE.
1539: */
1.31 espie 1540: cp = Var_Subst(cp, VAR_CMD, TRUE);
1.1 deraadt 1541: freeCmd = TRUE;
1542: }
1543:
1.9 briggs 1544: res = Cmd_Exec(cp, &err);
1545: Var_Set(line, res, ctxt);
1546: free(res);
1.1 deraadt 1547:
1.9 briggs 1548: if (err)
1549: Parse_Error(PARSE_WARNING, err, cp);
1.1 deraadt 1550:
1.9 briggs 1551: if (freeCmd)
1552: free(cp);
1.1 deraadt 1553: } else {
1554: /*
1555: * Normal assignment -- just do it.
1556: */
1.9 briggs 1557: Var_Set(line, cp, ctxt);
1.1 deraadt 1558: }
1559: }
1560:
1.9 briggs 1561:
1.1 deraadt 1562: /*-
1563: * ParseAddCmd --
1564: * Lst_ForEach function to add a command line to all targets
1565: *
1566: * Side Effects:
1567: * A new element is added to the commands list of the node.
1568: */
1.41 ! espie 1569: static void
1.1 deraadt 1570: ParseAddCmd(gnp, cmd)
1571: ClientData gnp; /* the node to which the command is to be added */
1572: ClientData cmd; /* the command to add */
1573: {
1.41 ! espie 1574: GNode *gn = (GNode *)gnp;
1.1 deraadt 1575: /* if target already supplied, ignore commands */
1.39 espie 1576: if (!(gn->type & OP_HAS_COMMANDS)) {
1.35 espie 1577: Lst_AtEnd(gn->commands, cmd);
1.39 espie 1578: if (!gn->lineno) {
1579: gn->lineno = Parse_Getlineno();
1580: gn->fname = Parse_Getfilename();
1581: }
1582: }
1.1 deraadt 1583: }
1584:
1585: /*-
1586: *-----------------------------------------------------------------------
1587: * ParseHasCommands --
1588: * Callback procedure for Parse_File when destroying the list of
1589: * targets on the last dependency line. Marks a target as already
1590: * having commands if it does, to keep from having shell commands
1591: * on multiple dependency lines.
1592: *
1593: * Results:
1594: * None
1595: *
1596: * Side Effects:
1597: * OP_HAS_COMMANDS may be set for the target.
1598: *
1599: *-----------------------------------------------------------------------
1600: */
1601: static void
1602: ParseHasCommands(gnp)
1603: ClientData gnp; /* Node to examine */
1604: {
1605: GNode *gn = (GNode *) gnp;
1606: if (!Lst_IsEmpty(gn->commands)) {
1607: gn->type |= OP_HAS_COMMANDS;
1608: }
1609: }
1610:
1611: /*-
1612: *-----------------------------------------------------------------------
1613: * Parse_AddIncludeDir --
1614: * Add a directory to the path searched for included makefiles
1615: * bracketed by double-quotes. Used by functions in main.c
1616: *
1617: * Results:
1618: * None.
1619: *
1620: * Side Effects:
1621: * The directory is appended to the list.
1622: *
1623: *-----------------------------------------------------------------------
1624: */
1625: void
1626: Parse_AddIncludeDir (dir)
1627: char *dir; /* The name of the directory to add */
1628: {
1629: Dir_AddDir (parseIncPath, dir);
1630: }
1631:
1632: /*-
1633: *---------------------------------------------------------------------
1634: * ParseDoInclude --
1635: * Push to another file.
1.11 millert 1636: *
1.1 deraadt 1637: * The input is the line minus the #include. A file spec is a string
1638: * enclosed in <> or "". The former is looked for only in sysIncPath.
1639: * The latter in . and the directories specified by -I command line
1640: * options
1641: *
1642: * Results:
1643: * None
1644: *
1645: * Side Effects:
1646: * A structure is added to the includes Lst and readProc, lineno,
1647: * fname and curFILE are altered for the new file
1648: *---------------------------------------------------------------------
1649: */
1650: static void
1651: ParseDoInclude (file)
1652: char *file; /* file specification */
1653: {
1654: char *fullname; /* full pathname of file */
1655: IFile *oldFile; /* state associated with current file */
1656: char endc; /* the character which ends the file spec */
1657: char *cp; /* current position in file spec */
1658: Boolean isSystem; /* TRUE if makefile is a system makefile */
1659:
1660: /*
1661: * Skip to delimiter character so we know where to look
1662: */
1663: while ((*file == ' ') || (*file == '\t')) {
1664: file++;
1665: }
1666:
1667: if ((*file != '"') && (*file != '<')) {
1668: Parse_Error (PARSE_FATAL,
1669: ".include filename must be delimited by '\"' or '<'");
1670: return;
1671: }
1672:
1673: /*
1674: * Set the search path on which to find the include file based on the
1675: * characters which bracket its name. Angle-brackets imply it's
1676: * a system Makefile while double-quotes imply it's a user makefile
1677: */
1678: if (*file == '<') {
1679: isSystem = TRUE;
1680: endc = '>';
1681: } else {
1682: isSystem = FALSE;
1683: endc = '"';
1684: }
1685:
1686: /*
1687: * Skip to matching delimiter
1688: */
1689: for (cp = ++file; *cp && *cp != endc; cp++) {
1690: continue;
1691: }
1692:
1693: if (*cp != endc) {
1694: Parse_Error (PARSE_FATAL,
1695: "Unclosed %cinclude filename. '%c' expected",
1696: '.', endc);
1697: return;
1698: }
1699: *cp = '\0';
1700:
1701: /*
1702: * Substitute for any variables in the file name before trying to
1703: * find the thing.
1704: */
1.31 espie 1705: file = Var_Subst(file, VAR_CMD, FALSE);
1.1 deraadt 1706:
1707: /*
1708: * Now we know the file's name and its search path, we attempt to
1709: * find the durn thing. A return of NULL indicates the file don't
1710: * exist.
1711: */
1712: if (!isSystem) {
1713: /*
1714: * Include files contained in double-quotes are first searched for
1715: * relative to the including file's location. We don't want to
1716: * cd there, of course, so we just tack on the old file's
1717: * leading path components and call Dir_FindFile to see if
1718: * we can locate the beast.
1719: */
1.4 niklas 1720: char *prefEnd, *Fname;
1.1 deraadt 1721:
1.4 niklas 1722: /* Make a temporary copy of this, to be safe. */
1.9 briggs 1723: Fname = estrdup(fname);
1.4 niklas 1724:
1725: prefEnd = strrchr (Fname, '/');
1.1 deraadt 1726: if (prefEnd != (char *)NULL) {
1727: char *newName;
1.11 millert 1728:
1.1 deraadt 1729: *prefEnd = '\0';
1730: if (file[0] == '/')
1.9 briggs 1731: newName = estrdup(file);
1.1 deraadt 1732: else
1.4 niklas 1733: newName = str_concat (Fname, file, STR_ADDSLASH);
1.1 deraadt 1734: fullname = Dir_FindFile (newName, parseIncPath);
1735: if (fullname == (char *)NULL) {
1736: fullname = Dir_FindFile(newName, dirSearchPath);
1737: }
1738: free (newName);
1739: *prefEnd = '/';
1740: } else {
1741: fullname = (char *)NULL;
1742: }
1.4 niklas 1743: free (Fname);
1.1 deraadt 1744: } else {
1745: fullname = (char *)NULL;
1746: }
1747:
1748: if (fullname == (char *)NULL) {
1749: /*
1750: * System makefile or makefile wasn't found in same directory as
1751: * included makefile. Search for it first on the -I search path,
1752: * then on the .PATH search path, if not found in a -I directory.
1753: * XXX: Suffix specific?
1754: */
1755: fullname = Dir_FindFile (file, parseIncPath);
1756: if (fullname == (char *)NULL) {
1757: fullname = Dir_FindFile(file, dirSearchPath);
1758: }
1759: }
1760:
1761: if (fullname == (char *)NULL) {
1762: /*
1763: * Still haven't found the makefile. Look for it on the system
1764: * path as a last resort.
1765: */
1766: fullname = Dir_FindFile(file, sysIncPath);
1767: }
1768:
1769: if (fullname == (char *) NULL) {
1770: *cp = endc;
1771: Parse_Error (PARSE_FATAL, "Could not find %s", file);
1772: return;
1773: }
1774:
1775: free(file);
1776:
1777: /*
1778: * Once we find the absolute path to the file, we get to save all the
1779: * state from the current file before we can start reading this
1780: * include file. The state is stored in an IFile structure which
1781: * is placed on a list with other IFile structures. The list makes
1782: * a very nice stack to track how we got here...
1783: */
1784: oldFile = (IFile *) emalloc (sizeof (IFile));
1785: oldFile->fname = fname;
1786:
1787: oldFile->F = curFILE;
1788: oldFile->p = curPTR;
1789: oldFile->lineno = lineno;
1790:
1.37 espie 1791: Lst_AtFront(includes, oldFile);
1.1 deraadt 1792:
1793: /*
1794: * Once the previous state has been saved, we can get down to reading
1795: * the new file. We set up the name of the file to be the absolute
1796: * name of the include file so error messages refer to the right
1797: * place. Naturally enough, we start reading at line number 0.
1798: */
1799: fname = fullname;
1.38 espie 1800: #ifdef CLEANUP
1801: Lst_AtEnd(fileNames, fname);
1802: #endif
1.1 deraadt 1803: lineno = 0;
1804:
1805: curFILE = fopen (fullname, "r");
1806: curPTR = NULL;
1807: if (curFILE == (FILE * ) NULL) {
1808: Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1809: /*
1810: * Pop to previous file
1811: */
1812: (void) ParseEOF(0);
1813: }
1814: }
1815:
1816:
1817: /*-
1818: *---------------------------------------------------------------------
1819: * Parse_FromString --
1820: * Start Parsing from the given string
1.11 millert 1821: *
1.1 deraadt 1822: * Results:
1823: * None
1824: *
1825: * Side Effects:
1826: * A structure is added to the includes Lst and readProc, lineno,
1827: * fname and curFILE are altered for the new file
1828: *---------------------------------------------------------------------
1829: */
1830: void
1.24 espie 1831: Parse_FromString(str, newlineno)
1832: char *str;
1833: unsigned long newlineno;
1.1 deraadt 1834: {
1835: IFile *oldFile; /* state associated with this file */
1836:
1837: if (DEBUG(FOR))
1838: (void) fprintf(stderr, "%s\n----\n", str);
1839:
1840: oldFile = (IFile *) emalloc (sizeof (IFile));
1841: oldFile->lineno = lineno;
1842: oldFile->fname = fname;
1843: oldFile->F = curFILE;
1844: oldFile->p = curPTR;
1.11 millert 1845:
1.37 espie 1846: Lst_AtFront(includes, oldFile);
1.1 deraadt 1847:
1848: curFILE = NULL;
1849: curPTR = (PTR *) emalloc (sizeof (PTR));
1850: curPTR->str = curPTR->ptr = str;
1.24 espie 1851: lineno = newlineno;
1.1 deraadt 1852: }
1853:
1854:
1855: #ifdef SYSVINCLUDE
1856: /*-
1857: *---------------------------------------------------------------------
1858: * ParseTraditionalInclude --
1859: * Push to another file.
1.11 millert 1860: *
1.1 deraadt 1861: * The input is the line minus the "include". The file name is
1862: * the string following the "include".
1863: *
1864: * Results:
1865: * None
1866: *
1867: * Side Effects:
1868: * A structure is added to the includes Lst and readProc, lineno,
1869: * fname and curFILE are altered for the new file
1870: *---------------------------------------------------------------------
1871: */
1872: static void
1873: ParseTraditionalInclude (file)
1874: char *file; /* file specification */
1875: {
1876: char *fullname; /* full pathname of file */
1877: IFile *oldFile; /* state associated with current file */
1878: char *cp; /* current position in file spec */
1879: char *prefEnd;
1880:
1881: /*
1882: * Skip over whitespace
1883: */
1884: while ((*file == ' ') || (*file == '\t')) {
1885: file++;
1886: }
1887:
1888: if (*file == '\0') {
1889: Parse_Error (PARSE_FATAL,
1890: "Filename missing from \"include\"");
1891: return;
1892: }
1893:
1894: /*
1895: * Skip to end of line or next whitespace
1896: */
1897: for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1898: continue;
1899: }
1900:
1901: *cp = '\0';
1902:
1903: /*
1904: * Substitute for any variables in the file name before trying to
1905: * find the thing.
1906: */
1.31 espie 1907: file = Var_Subst(file, VAR_CMD, FALSE);
1.1 deraadt 1908:
1909: /*
1910: * Now we know the file's name, we attempt to find the durn thing.
1911: * A return of NULL indicates the file don't exist.
1912: *
1913: * Include files are first searched for relative to the including
1914: * file's location. We don't want to cd there, of course, so we
1915: * just tack on the old file's leading path components and call
1916: * Dir_FindFile to see if we can locate the beast.
1917: * XXX - this *does* search in the current directory, right?
1918: */
1919:
1920: prefEnd = strrchr (fname, '/');
1921: if (prefEnd != (char *)NULL) {
1922: char *newName;
1.11 millert 1923:
1.1 deraadt 1924: *prefEnd = '\0';
1925: newName = str_concat (fname, file, STR_ADDSLASH);
1926: fullname = Dir_FindFile (newName, parseIncPath);
1927: if (fullname == (char *)NULL) {
1928: fullname = Dir_FindFile(newName, dirSearchPath);
1929: }
1930: free (newName);
1931: *prefEnd = '/';
1932: } else {
1933: fullname = (char *)NULL;
1934: }
1935:
1936: if (fullname == (char *)NULL) {
1937: /*
1938: * System makefile or makefile wasn't found in same directory as
1939: * included makefile. Search for it first on the -I search path,
1940: * then on the .PATH search path, if not found in a -I directory.
1941: * XXX: Suffix specific?
1942: */
1943: fullname = Dir_FindFile (file, parseIncPath);
1944: if (fullname == (char *)NULL) {
1945: fullname = Dir_FindFile(file, dirSearchPath);
1946: }
1947: }
1948:
1949: if (fullname == (char *)NULL) {
1950: /*
1951: * Still haven't found the makefile. Look for it on the system
1952: * path as a last resort.
1953: */
1954: fullname = Dir_FindFile(file, sysIncPath);
1955: }
1956:
1957: if (fullname == (char *) NULL) {
1958: Parse_Error (PARSE_FATAL, "Could not find %s", file);
1959: return;
1960: }
1961:
1962: /*
1963: * Once we find the absolute path to the file, we get to save all the
1964: * state from the current file before we can start reading this
1965: * include file. The state is stored in an IFile structure which
1966: * is placed on a list with other IFile structures. The list makes
1967: * a very nice stack to track how we got here...
1968: */
1969: oldFile = (IFile *) emalloc (sizeof (IFile));
1970: oldFile->fname = fname;
1971:
1972: oldFile->F = curFILE;
1973: oldFile->p = curPTR;
1974: oldFile->lineno = lineno;
1975:
1.37 espie 1976: Lst_AtFront(includes, oldFile);
1.1 deraadt 1977:
1978: /*
1979: * Once the previous state has been saved, we can get down to reading
1980: * the new file. We set up the name of the file to be the absolute
1981: * name of the include file so error messages refer to the right
1982: * place. Naturally enough, we start reading at line number 0.
1983: */
1984: fname = fullname;
1.38 espie 1985: #ifdef CLEANUP
1986: lst_AtEnd(fileNames, fname);
1987: #endif
1.1 deraadt 1988: lineno = 0;
1989:
1990: curFILE = fopen (fullname, "r");
1991: curPTR = NULL;
1992: if (curFILE == (FILE * ) NULL) {
1993: Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1994: /*
1995: * Pop to previous file
1996: */
1997: (void) ParseEOF(1);
1998: }
1999: }
2000: #endif
2001:
2002: /*-
2003: *---------------------------------------------------------------------
2004: * ParseEOF --
2005: * Called when EOF is reached in the current file. If we were reading
2006: * an include file, the includes stack is popped and things set up
2007: * to go back to reading the previous file at the previous location.
2008: *
2009: * Results:
2010: * CONTINUE if there's more to do. DONE if not.
2011: *
2012: * Side Effects:
2013: * The old curFILE, is closed. The includes list is shortened.
2014: * lineno, curFILE, and fname are changed if CONTINUE is returned.
2015: *---------------------------------------------------------------------
2016: */
2017: static int
2018: ParseEOF (opened)
2019: int opened;
2020: {
2021: IFile *ifile; /* the state on the top of the includes stack */
2022:
1.34 espie 2023: if ((ifile = (IFile *)Lst_DeQueue(includes)) == NULL)
2024: return DONE;
1.1 deraadt 2025: fname = ifile->fname;
2026: lineno = ifile->lineno;
2027: if (opened && curFILE)
2028: (void) fclose (curFILE);
2029: if (curPTR) {
2030: free((Address) curPTR->str);
2031: free((Address) curPTR);
2032: }
2033: curFILE = ifile->F;
2034: curPTR = ifile->p;
2035: free ((Address)ifile);
2036: return (CONTINUE);
2037: }
2038:
2039: /*-
2040: *---------------------------------------------------------------------
2041: * ParseReadc --
1.11 millert 2042: * Read a character from the current file
1.1 deraadt 2043: *
2044: * Results:
2045: * The character that was read
2046: *
2047: * Side Effects:
2048: *---------------------------------------------------------------------
2049: */
1.21 espie 2050: static int __inline
1.1 deraadt 2051: ParseReadc()
2052: {
2053: if (curFILE)
2054: return fgetc(curFILE);
1.11 millert 2055:
1.1 deraadt 2056: if (curPTR && *curPTR->ptr)
2057: return *curPTR->ptr++;
2058: return EOF;
2059: }
2060:
2061:
2062: /*-
2063: *---------------------------------------------------------------------
2064: * ParseUnreadc --
1.11 millert 2065: * Put back a character to the current file
1.1 deraadt 2066: *
2067: * Results:
2068: * None.
2069: *
2070: * Side Effects:
2071: *---------------------------------------------------------------------
2072: */
2073: static void
2074: ParseUnreadc(c)
2075: int c;
2076: {
2077: if (curFILE) {
2078: ungetc(c, curFILE);
2079: return;
2080: }
2081: if (curPTR) {
2082: *--(curPTR->ptr) = c;
2083: return;
2084: }
2085: }
2086:
2087:
2088: /* ParseSkipLine():
2089: * Grab the next line
2090: */
2091: static char *
2092: ParseSkipLine(skip)
2093: int skip; /* Skip lines that don't start with . */
2094: {
2095: char *line;
1.25 espie 2096: int c, lastc;
1.29 espie 2097: BUFFER buf;
1.1 deraadt 2098:
1.29 espie 2099: Buf_Init(&buf, MAKE_BSIZE);
1.11 millert 2100:
1.22 espie 2101: for (;;) {
1.29 espie 2102: Buf_Reset(&buf);
1.11 millert 2103: lastc = '\0';
2104:
2105: while (((c = ParseReadc()) != '\n' || lastc == '\\')
2106: && c != EOF) {
2107: if (c == '\n') {
1.29 espie 2108: Buf_ReplaceLastChar(&buf, ' ');
1.11 millert 2109: lineno++;
2110:
2111: while ((c = ParseReadc()) == ' ' || c == '\t');
2112:
2113: if (c == EOF)
2114: break;
2115: }
2116:
1.29 espie 2117: Buf_AddChar(&buf, c);
1.11 millert 2118: lastc = c;
2119: }
2120:
1.29 espie 2121: line = Buf_Retrieve(&buf);
1.22 espie 2122: lineno++;
2123: /* allow for non-newline terminated lines while skipping */
2124: if (line[0] == '.')
2125: break;
2126:
1.11 millert 2127: if (c == EOF) {
2128: Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
1.29 espie 2129: Buf_Destroy(&buf);
2130: return NULL;
1.11 millert 2131: }
1.22 espie 2132: if (skip == 0)
2133: break;
1.11 millert 2134:
1.22 espie 2135: }
1.1 deraadt 2136:
2137: return line;
2138: }
2139:
2140:
2141: /*-
2142: *---------------------------------------------------------------------
2143: * ParseReadLine --
2144: * Read an entire line from the input file. Called only by Parse_File.
2145: * To facilitate escaped newlines and what have you, a character is
2146: * buffered in 'lastc', which is '\0' when no characters have been
2147: * read. When we break out of the loop, c holds the terminating
2148: * character and lastc holds a character that should be added to
2149: * the line (unless we don't read anything but a terminator).
2150: *
2151: * Results:
2152: * A line w/o its newline
2153: *
2154: * Side Effects:
2155: * Only those associated with reading a character
2156: *---------------------------------------------------------------------
2157: */
2158: static char *
2159: ParseReadLine ()
2160: {
1.29 espie 2161: BUFFER buf; /* Buffer for current line */
1.1 deraadt 2162: register int c; /* the current character */
2163: register int lastc; /* The most-recent character */
2164: Boolean semiNL; /* treat semi-colons as newlines */
2165: Boolean ignDepOp; /* TRUE if should ignore dependency operators
2166: * for the purposes of setting semiNL */
2167: Boolean ignComment; /* TRUE if should ignore comments (in a
2168: * shell command */
2169: char *line; /* Result */
2170: char *ep; /* to strip trailing blanks */
2171:
2172: semiNL = FALSE;
2173: ignDepOp = FALSE;
2174: ignComment = FALSE;
2175:
2176: /*
2177: * Handle special-characters at the beginning of the line. Either a
2178: * leading tab (shell command) or pound-sign (possible conditional)
2179: * forces us to ignore comments and dependency operators and treat
2180: * semi-colons as semi-colons (by leaving semiNL FALSE). This also
2181: * discards completely blank lines.
2182: */
2183: for (;;) {
2184: c = ParseReadc();
2185:
2186: if (c == '\t') {
2187: ignComment = ignDepOp = TRUE;
2188: break;
2189: } else if (c == '\n') {
2190: lineno++;
2191: } else if (c == '#') {
2192: ParseUnreadc(c);
2193: break;
2194: } else {
2195: /*
2196: * Anything else breaks out without doing anything
2197: */
2198: break;
2199: }
2200: }
1.11 millert 2201:
1.1 deraadt 2202: if (c != EOF) {
2203: lastc = c;
1.29 espie 2204: Buf_Init(&buf, MAKE_BSIZE);
1.11 millert 2205:
1.1 deraadt 2206: while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
2207: (c != EOF))
2208: {
2209: test_char:
2210: switch(c) {
2211: case '\n':
2212: /*
2213: * Escaped newline: read characters until a non-space or an
2214: * unescaped newline and replace them all by a single space.
2215: * This is done by storing the space over the backslash and
2216: * dropping through with the next nonspace. If it is a
2217: * semi-colon and semiNL is TRUE, it will be recognized as a
2218: * newline in the code below this...
2219: */
2220: lineno++;
2221: lastc = ' ';
2222: while ((c = ParseReadc ()) == ' ' || c == '\t') {
2223: continue;
2224: }
2225: if (c == EOF || c == '\n') {
2226: goto line_read;
2227: } else {
2228: /*
2229: * Check for comments, semiNL's, etc. -- easier than
2230: * ParseUnreadc(c); continue;
2231: */
2232: goto test_char;
2233: }
2234: /*NOTREACHED*/
2235: break;
2236:
2237: case ';':
2238: /*
2239: * Semi-colon: Need to see if it should be interpreted as a
2240: * newline
2241: */
2242: if (semiNL) {
2243: /*
2244: * To make sure the command that may be following this
2245: * semi-colon begins with a tab, we push one back into the
2246: * input stream. This will overwrite the semi-colon in the
2247: * buffer. If there is no command following, this does no
2248: * harm, since the newline remains in the buffer and the
2249: * whole line is ignored.
2250: */
2251: ParseUnreadc('\t');
2252: goto line_read;
1.11 millert 2253: }
1.1 deraadt 2254: break;
2255: case '=':
2256: if (!semiNL) {
2257: /*
2258: * Haven't seen a dependency operator before this, so this
2259: * must be a variable assignment -- don't pay attention to
2260: * dependency operators after this.
2261: */
2262: ignDepOp = TRUE;
2263: } else if (lastc == ':' || lastc == '!') {
2264: /*
2265: * Well, we've seen a dependency operator already, but it
2266: * was the previous character, so this is really just an
2267: * expanded variable assignment. Revert semi-colons to
2268: * being just semi-colons again and ignore any more
2269: * dependency operators.
2270: *
2271: * XXX: Note that a line like "foo : a:=b" will blow up,
2272: * but who'd write a line like that anyway?
2273: */
2274: ignDepOp = TRUE; semiNL = FALSE;
2275: }
2276: break;
2277: case '#':
2278: if (!ignComment) {
1.2 deraadt 2279: if (
2280: #if 0
2281: compatMake &&
2282: #endif
2283: (lastc != '\\')) {
1.1 deraadt 2284: /*
2285: * If the character is a hash mark and it isn't escaped
2286: * (or we're being compatible), the thing is a comment.
2287: * Skip to the end of the line.
2288: */
2289: do {
2290: c = ParseReadc();
2291: } while ((c != '\n') && (c != EOF));
2292: goto line_read;
2293: } else {
2294: /*
2295: * Don't add the backslash. Just let the # get copied
2296: * over.
2297: */
2298: lastc = c;
2299: continue;
2300: }
2301: }
2302: break;
2303: case ':':
2304: case '!':
2305: if (!ignDepOp && (c == ':' || c == '!')) {
2306: /*
2307: * A semi-colon is recognized as a newline only on
2308: * dependency lines. Dependency lines are lines with a
2309: * colon or an exclamation point. Ergo...
2310: */
2311: semiNL = TRUE;
2312: }
2313: break;
2314: }
2315: /*
2316: * Copy in the previous character and save this one in lastc.
2317: */
1.29 espie 2318: Buf_AddChar(&buf, lastc);
1.1 deraadt 2319: lastc = c;
1.11 millert 2320:
1.1 deraadt 2321: }
2322: line_read:
2323: lineno++;
1.11 millert 2324:
1.28 espie 2325: if (lastc != '\0')
1.29 espie 2326: Buf_AddChar(&buf, lastc);
2327: line = Buf_Retrieve(&buf);
1.1 deraadt 2328:
2329: /*
2330: * Strip trailing blanks and tabs from the line.
2331: * Do not strip a blank or tab that is preceeded by
2332: * a '\'
2333: */
2334: ep = line;
2335: while (*ep)
2336: ++ep;
1.11 millert 2337: while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
1.1 deraadt 2338: if (ep > line + 1 && ep[-2] == '\\')
2339: break;
2340: --ep;
2341: }
2342: *ep = 0;
1.11 millert 2343:
1.1 deraadt 2344: if (line[0] == '.') {
2345: /*
2346: * The line might be a conditional. Ask the conditional module
2347: * about it and act accordingly
2348: */
2349: switch (Cond_Eval (line)) {
2350: case COND_SKIP:
2351: /*
2352: * Skip to next conditional that evaluates to COND_PARSE.
2353: */
2354: do {
2355: free (line);
2356: line = ParseSkipLine(1);
2357: } while (line && Cond_Eval(line) != COND_PARSE);
2358: if (line == NULL)
2359: break;
2360: /*FALLTHRU*/
2361: case COND_PARSE:
2362: free ((Address) line);
2363: line = ParseReadLine();
2364: break;
2365: case COND_INVALID:
1.30 espie 2366: {
2367: For *loop;
2368:
2369: loop = For_Eval(line);
2370: if (loop != NULL) {
2371: Boolean ok;
2372:
1.1 deraadt 2373: free(line);
2374: do {
1.30 espie 2375: /* Find the matching endfor. */
1.1 deraadt 2376: line = ParseSkipLine(0);
2377: if (line == NULL) {
1.30 espie 2378: Parse_Error(PARSE_FATAL,
1.1 deraadt 2379: "Unexpected end of file in for loop.\n");
1.30 espie 2380: return line;
1.1 deraadt 2381: }
1.30 espie 2382: ok = For_Accumulate(loop, line);
1.1 deraadt 2383: free(line);
1.30 espie 2384: } while (ok);
2385: For_Run(loop);
1.1 deraadt 2386: line = ParseReadLine();
2387: }
2388: break;
1.30 espie 2389: }
1.1 deraadt 2390: }
2391: }
2392: return (line);
2393:
2394: } else {
2395: /*
2396: * Hit end-of-file, so return a NULL line to indicate this.
2397: */
2398: return((char *)NULL);
2399: }
2400: }
2401:
2402: /*-
2403: *-----------------------------------------------------------------------
2404: * ParseFinishLine --
2405: * Handle the end of a dependency group.
2406: *
2407: * Side Effects:
2408: * inLine set FALSE. 'targets' list destroyed.
2409: *
2410: *-----------------------------------------------------------------------
2411: */
2412: static void
2413: ParseFinishLine()
2414: {
2415: if (inLine) {
1.41 ! espie 2416: Lst_Every(targets, Suff_EndTransform);
! 2417: Lst_Destroy(targets, ParseHasCommands);
1.1 deraadt 2418: targets = NULL;
2419: inLine = FALSE;
2420: }
2421: }
1.11 millert 2422:
1.1 deraadt 2423:
2424: /*-
2425: *---------------------------------------------------------------------
2426: * Parse_File --
2427: * Parse a file into its component parts, incorporating it into the
2428: * current dependency graph. This is the main function and controls
2429: * almost every other function in this module
2430: *
2431: * Results:
2432: * None
2433: *
2434: * Side Effects:
2435: * Loads. Nodes are added to the list of all targets, nodes and links
2436: * are added to the dependency graph. etc. etc. etc.
2437: *---------------------------------------------------------------------
2438: */
2439: void
2440: Parse_File(name, stream)
2441: char *name; /* the name of the file being read */
2442: FILE * stream; /* Stream open to makefile to parse */
2443: {
2444: register char *cp, /* pointer into the line */
2445: *line; /* the line we're working on */
2446:
2447: inLine = FALSE;
1.38 espie 2448: fname = estrdup(name);
2449: #ifdef CLEANUP
2450: Lst_AtEnd(fileNames, fname);
2451: #endif
1.1 deraadt 2452: curFILE = stream;
2453: lineno = 0;
2454: fatals = 0;
2455:
2456: do {
2457: while ((line = ParseReadLine ()) != NULL) {
2458: if (*line == '.') {
2459: /*
2460: * Lines that begin with the special character are either
2461: * include or undef directives.
2462: */
2463: for (cp = line + 1; isspace (*cp); cp++) {
2464: continue;
2465: }
2466: if (strncmp (cp, "include", 7) == 0) {
2467: ParseDoInclude (cp + 7);
2468: goto nextLine;
2469: } else if (strncmp(cp, "undef", 5) == 0) {
2470: char *cp2;
2471: for (cp += 5; isspace((unsigned char) *cp); cp++) {
2472: continue;
2473: }
2474:
2475: for (cp2 = cp; !isspace((unsigned char) *cp2) &&
2476: (*cp2 != '\0'); cp2++) {
2477: continue;
2478: }
2479:
2480: *cp2 = '\0';
2481:
2482: Var_Delete(cp, VAR_GLOBAL);
2483: goto nextLine;
2484: }
2485: }
1.11 millert 2486: if (*line == '#') {
2487: /* If we're this far, the line must be a comment. */
1.1 deraadt 2488: goto nextLine;
2489: }
1.11 millert 2490:
1.1 deraadt 2491: if (*line == '\t') {
2492: /*
2493: * If a line starts with a tab, it can only hope to be
2494: * a creation command.
2495: */
2496: #ifndef POSIX
2497: shellCommand:
2498: #endif
2499: for (cp = line + 1; isspace (*cp); cp++) {
2500: continue;
2501: }
2502: if (*cp) {
2503: if (inLine) {
2504: /*
2505: * So long as it's not a blank line and we're actually
2506: * in a dependency spec, add the command to the list of
1.11 millert 2507: * commands of all targets in the dependency spec
1.1 deraadt 2508: */
1.41 ! espie 2509: Lst_ForEach(targets, ParseAddCmd, cp);
1.20 espie 2510: #ifdef CLEANUP
1.37 espie 2511: Lst_AtEnd(targCmds, line);
1.20 espie 2512: #endif
1.1 deraadt 2513: continue;
2514: } else {
2515: Parse_Error (PARSE_FATAL,
1.10 briggs 2516: "Unassociated shell command \"%s\"",
1.1 deraadt 2517: cp);
2518: }
2519: }
2520: #ifdef SYSVINCLUDE
1.11 millert 2521: } else if (strncmp (line, "include", 7) == 0 &&
1.6 tholo 2522: isspace((unsigned char) line[7]) &&
1.1 deraadt 2523: strchr(line, ':') == NULL) {
2524: /*
2525: * It's an S3/S5-style "include".
2526: */
2527: ParseTraditionalInclude (line + 7);
2528: goto nextLine;
2529: #endif
2530: } else if (Parse_IsVar (line)) {
2531: ParseFinishLine();
2532: Parse_DoVar (line, VAR_GLOBAL);
2533: } else {
2534: /*
2535: * We now know it's a dependency line so it needs to have all
2536: * variables expanded before being parsed. Tell the variable
2537: * module to complain if some variable is undefined...
2538: * To make life easier on novices, if the line is indented we
2539: * first make sure the line has a dependency operator in it.
2540: * If it doesn't have an operator and we're in a dependency
2541: * line's script, we assume it's actually a shell command
2542: * and add it to the current list of targets.
2543: */
2544: #ifndef POSIX
2545: Boolean nonSpace = FALSE;
2546: #endif
1.11 millert 2547:
1.1 deraadt 2548: cp = line;
2549: if (isspace((unsigned char) line[0])) {
2550: while ((*cp != '\0') && isspace((unsigned char) *cp)) {
2551: cp++;
2552: }
2553: if (*cp == '\0') {
2554: goto nextLine;
2555: }
2556: #ifndef POSIX
2557: while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
2558: nonSpace = TRUE;
2559: cp++;
2560: }
2561: #endif
2562: }
1.11 millert 2563:
1.1 deraadt 2564: #ifndef POSIX
2565: if (*cp == '\0') {
2566: if (inLine) {
2567: Parse_Error (PARSE_WARNING,
2568: "Shell command needs a leading tab");
2569: goto shellCommand;
2570: } else if (nonSpace) {
2571: Parse_Error (PARSE_FATAL, "Missing operator");
2572: }
2573: } else {
2574: #endif
2575: ParseFinishLine();
2576:
1.31 espie 2577: cp = Var_Subst(line, VAR_CMD, TRUE);
1.1 deraadt 2578: free (line);
2579: line = cp;
1.11 millert 2580:
1.1 deraadt 2581: /*
1.11 millert 2582: * Need a non-circular list for the target nodes
1.1 deraadt 2583: */
2584: if (targets)
2585: Lst_Destroy(targets, NOFREE);
2586:
1.32 espie 2587: targets = Lst_Init();
1.1 deraadt 2588: inLine = TRUE;
1.11 millert 2589:
1.1 deraadt 2590: ParseDoDependency (line);
2591: #ifndef POSIX
2592: }
2593: #endif
2594: }
2595:
2596: nextLine:
2597:
2598: free (line);
2599: }
2600: /*
1.11 millert 2601: * Reached EOF, but it may be just EOF of an include file...
1.1 deraadt 2602: */
2603: } while (ParseEOF(1) == CONTINUE);
2604:
2605: /*
2606: * Make sure conditionals are clean
2607: */
2608: Cond_End();
2609:
2610: if (fatals) {
2611: fprintf (stderr, "Fatal errors encountered -- cannot continue\n");
2612: exit (1);
2613: }
2614: }
2615:
2616: /*-
2617: *---------------------------------------------------------------------
2618: * Parse_Init --
2619: * initialize the parsing module
2620: *
2621: * Results:
2622: * none
2623: *
2624: * Side Effects:
2625: * the parseIncPath list is initialized...
2626: *---------------------------------------------------------------------
2627: */
2628: void
2629: Parse_Init ()
2630: {
1.33 espie 2631: mainNode = NULL;
1.32 espie 2632: parseIncPath = Lst_Init();
2633: sysIncPath = Lst_Init();
2634: includes = Lst_Init();
1.20 espie 2635: #ifdef CLEANUP
1.32 espie 2636: targCmds = Lst_Init();
1.38 espie 2637: fileNames = Lst_Init();
1.20 espie 2638: #endif
1.1 deraadt 2639: }
2640:
2641: void
2642: Parse_End()
2643: {
1.20 espie 2644: #ifdef CLEANUP
1.41 ! espie 2645: Lst_Destroy(targCmds, (SimpleProc)free);
1.38 espie 2646: Lst_Destroy(fileNames, (void (*) __P((ClientData))) free);
1.1 deraadt 2647: if (targets)
2648: Lst_Destroy(targets, NOFREE);
2649: Lst_Destroy(sysIncPath, Dir_Destroy);
2650: Lst_Destroy(parseIncPath, Dir_Destroy);
2651: Lst_Destroy(includes, NOFREE); /* Should be empty now */
1.20 espie 2652: #endif
1.1 deraadt 2653: }
1.11 millert 2654:
1.1 deraadt 2655:
2656: /*-
2657: *-----------------------------------------------------------------------
2658: * Parse_MainName --
2659: * Return a Lst of the main target to create for main()'s sake. If
2660: * no such target exists, we Punt with an obnoxious error message.
2661: *
2662: * Results:
2663: * A Lst of the single node to create.
2664: *
2665: * Side Effects:
2666: * None.
2667: *
2668: *-----------------------------------------------------------------------
2669: */
2670: Lst
2671: Parse_MainName()
2672: {
1.14 millert 2673: Lst listmain; /* result list */
1.1 deraadt 2674:
1.32 espie 2675: listmain = Lst_Init();
1.1 deraadt 2676:
1.33 espie 2677: if (mainNode == NULL) {
1.8 deraadt 2678: Punt ("no target to make.");
1.1 deraadt 2679: /*NOTREACHED*/
2680: } else if (mainNode->type & OP_DOUBLEDEP) {
1.37 espie 2681: Lst_AtEnd(listmain, mainNode);
1.14 millert 2682: Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW);
1.1 deraadt 2683: }
2684: else
1.37 espie 2685: Lst_AtEnd(listmain, mainNode);
1.14 millert 2686: return (listmain);
1.1 deraadt 2687: }
1.24 espie 2688:
2689: unsigned long
2690: Parse_Getlineno()
2691: {
2692: return lineno;
1.38 espie 2693: }
2694:
2695: const char *
2696: Parse_Getfilename()
2697: {
2698: return fname;
1.24 espie 2699: }
2700: