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