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