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