Annotation of src/usr.bin/make/parse.c, Revision 1.54
1.54 ! espie 1: /* $OpenBSD: parse.c,v 1.53 2000/09/14 13:32:07 espie Exp $ */
1.13 millert 2: /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
1.1 deraadt 3:
4: /*
1.11 millert 5: * Copyright (c) 1988, 1989, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
1.1 deraadt 7: * Copyright (c) 1989 by Berkeley Softworks
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Adam de Boor.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the University of
24: * California, Berkeley and its contributors.
25: * 4. Neither the name of the University nor the names of its contributors
26: * may be used to endorse or promote products derived from this software
27: * without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: */
41:
42: /*-
43: * parse.c --
44: * Functions to parse a makefile.
45: *
46: * One function, Parse_Init, must be called before any functions
47: * in this module are used. After that, the function Parse_File is the
48: * main entry point and controls most of the other functions in this
49: * module.
50: *
51: * Most important structures are kept in Lsts. Directories for
52: * the #include "..." function are kept in the 'parseIncPath' Lst, while
53: * those for the #include <...> are kept in the 'sysIncPath' Lst. The
54: * targets currently being defined are kept in the 'targets' Lst.
55: *
56: * The variables 'fname' and 'lineno' are used to track the name
57: * of the current file and the line number in that file so that error
58: * messages can be more meaningful.
59: *
60: * Interface:
61: * Parse_Init Initialization function which must be
62: * called before anything else in this module
63: * is used.
64: *
65: * Parse_End Cleanup the module
66: *
67: * Parse_File Function used to parse a makefile. It must
68: * be given the name of the file, which should
69: * already have been opened, and a function
70: * to call to read a character from the file.
71: *
72: * Parse_IsVar Returns TRUE if the given line is a
73: * variable assignment. Used by MainParseArgs
74: * to determine if an argument is a target
75: * or a variable assignment. Used internally
76: * for pretty much the same thing...
77: *
78: * Parse_Error Function called when an error occurs in
79: * parsing. Used by the variable and
80: * conditional modules.
81: * Parse_MainName Returns a Lst of the main target to create.
82: */
83:
1.15 mickey 84: #ifdef __STDC__
1.1 deraadt 85: #include <stdarg.h>
86: #else
87: #include <varargs.h>
88: #endif
89: #include <stdio.h>
90: #include <ctype.h>
91: #include <errno.h>
92: #include "make.h"
93: #include "hash.h"
94: #include "dir.h"
95: #include "job.h"
96: #include "buf.h"
97: #include "pathnames.h"
1.50 espie 98: #include "lowparse.h"
1.1 deraadt 99:
1.53 espie 100: #ifndef lint
101: #if 0
102: static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
103: #else
104: UNUSED
1.54 ! espie 105: static char rcsid[] = "$OpenBSD: parse.c,v 1.53 2000/09/14 13:32:07 espie Exp $";
1.53 espie 106: #endif
107: #endif /* not lint */
108:
1.45 espie 109: static LIST targets; /* targets we're working on */
1.20 espie 110: #ifdef CLEANUP
1.45 espie 111: static LIST targCmds; /* command lines for targets */
1.20 espie 112: #endif
1.45 espie 113: static Boolean inLine; /* true if currently in a dependency
114: * line or its commands */
1.1 deraadt 115: static GNode *mainNode; /* The main target to create. This is the
116: * first target on the first dependency
117: * line in the first makefile */
1.43 espie 118: LIST parseIncPath; /* list of directories for "..." includes */
119: LIST sysIncPath; /* list of directories for <...> includes */
1.1 deraadt 120:
121: /*-
122: * specType contains the SPECial TYPE of the current target. It is
123: * Not if the target is unspecial. If it *is* special, however, the children
124: * are linked as children of the parent but not vice versa. This variable is
125: * set in ParseDoDependency
126: */
127: typedef enum {
128: Begin, /* .BEGIN */
129: Default, /* .DEFAULT */
130: End, /* .END */
131: Ignore, /* .IGNORE */
132: Includes, /* .INCLUDES */
133: Interrupt, /* .INTERRUPT */
134: Libs, /* .LIBS */
135: MFlags, /* .MFLAGS or .MAKEFLAGS */
136: Main, /* .MAIN and we don't have anything user-specified to
137: * make */
138: NoExport, /* .NOEXPORT */
1.17 espie 139: NoPath, /* .NOPATH */
1.1 deraadt 140: Not, /* Not special */
141: NotParallel, /* .NOTPARALELL */
142: Null, /* .NULL */
143: Order, /* .ORDER */
1.3 deraadt 144: Parallel, /* .PARALLEL */
1.1 deraadt 145: ExPath, /* .PATH */
1.7 niklas 146: Phony, /* .PHONY */
1.1 deraadt 147: Precious, /* .PRECIOUS */
148: ExShell, /* .SHELL */
149: Silent, /* .SILENT */
150: SingleShell, /* .SINGLESHELL */
151: Suffixes, /* .SUFFIXES */
1.3 deraadt 152: Wait, /* .WAIT */
1.1 deraadt 153: Attribute /* Generic attribute */
154: } ParseSpecial;
155:
156: static ParseSpecial specType;
1.3 deraadt 157: static int waiting;
1.1 deraadt 158:
159: /*
1.33 espie 160: * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1.1 deraadt 161: * seen, then set to each successive source on the line.
162: */
163: static GNode *predecessor;
164:
165: /*
166: * The parseKeywords table is searched using binary search when deciding
167: * if a target or source is special. The 'spec' field is the ParseSpecial
168: * type of the keyword ("Not" if the keyword isn't special as a target) while
169: * the 'op' field is the operator to apply to the list of targets if the
170: * keyword is used as a source ("0" if the keyword isn't special as a source)
171: */
172: static struct {
173: char *name; /* Name of keyword */
174: ParseSpecial spec; /* Type when used as a target */
175: int op; /* Operator when used as a source */
176: } parseKeywords[] = {
177: { ".BEGIN", Begin, 0 },
178: { ".DEFAULT", Default, 0 },
179: { ".END", End, 0 },
180: { ".EXEC", Attribute, OP_EXEC },
181: { ".IGNORE", Ignore, OP_IGNORE },
182: { ".INCLUDES", Includes, 0 },
183: { ".INTERRUPT", Interrupt, 0 },
184: { ".INVISIBLE", Attribute, OP_INVISIBLE },
185: { ".JOIN", Attribute, OP_JOIN },
186: { ".LIBS", Libs, 0 },
1.13 millert 187: { ".MADE", Attribute, OP_MADE },
1.1 deraadt 188: { ".MAIN", Main, 0 },
189: { ".MAKE", Attribute, OP_MAKE },
190: { ".MAKEFLAGS", MFlags, 0 },
191: { ".MFLAGS", MFlags, 0 },
1.17 espie 192: #if 0 /* basic scaffolding for NOPATH, not working yet */
193: { ".NOPATH", NoPath, OP_NOPATH },
194: #endif
1.1 deraadt 195: { ".NOTMAIN", Attribute, OP_NOTMAIN },
196: { ".NOTPARALLEL", NotParallel, 0 },
1.3 deraadt 197: { ".NO_PARALLEL", NotParallel, 0 },
1.1 deraadt 198: { ".NULL", Null, 0 },
199: { ".OPTIONAL", Attribute, OP_OPTIONAL },
200: { ".ORDER", Order, 0 },
1.3 deraadt 201: { ".PARALLEL", Parallel, 0 },
1.1 deraadt 202: { ".PATH", ExPath, 0 },
1.7 niklas 203: { ".PHONY", Phony, OP_PHONY },
1.1 deraadt 204: { ".PRECIOUS", Precious, OP_PRECIOUS },
205: { ".RECURSIVE", Attribute, OP_MAKE },
206: { ".SHELL", ExShell, 0 },
207: { ".SILENT", Silent, OP_SILENT },
208: { ".SINGLESHELL", SingleShell, 0 },
209: { ".SUFFIXES", Suffixes, 0 },
210: { ".USE", Attribute, OP_USE },
1.3 deraadt 211: { ".WAIT", Wait, 0 },
1.1 deraadt 212: };
213:
214: static int ParseFindKeyword __P((char *));
1.42 espie 215: static void ParseLinkSrc __P((void *, void *));
216: static int ParseDoOp __P((void *, void *));
217: static int ParseAddDep __P((void *, void *));
1.3 deraadt 218: static void ParseDoSrc __P((int, char *, Lst));
1.42 espie 219: static int ParseFindMain __P((void *, void *));
220: static void ParseAddDir __P((void *, void *));
221: static void ParseClearPath __P((void *));
1.1 deraadt 222: static void ParseDoDependency __P((char *));
1.42 espie 223: static void ParseAddCmd __P((void *, void *));
224: static void ParseHasCommands __P((void *));
1.1 deraadt 225: static void ParseDoInclude __P((char *));
226: #ifdef SYSVINCLUDE
227: static void ParseTraditionalInclude __P((char *));
228: #endif
1.50 espie 229: static void ParseLookupIncludeFile __P((char *, char *, Boolean));
1.1 deraadt 230: static void ParseFinishLine __P((void));
231:
232: /*-
233: *----------------------------------------------------------------------
234: * ParseFindKeyword --
235: * Look in the table of keywords for one matching the given string.
236: *
237: * Results:
238: * The index of the keyword, or -1 if it isn't there.
239: *
240: * Side Effects:
241: * None
242: *----------------------------------------------------------------------
243: */
244: static int
245: ParseFindKeyword (str)
246: char *str; /* String to find */
247: {
248: register int start,
249: end,
250: cur;
251: register int diff;
1.11 millert 252:
1.1 deraadt 253: start = 0;
254: end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
255:
256: do {
257: cur = start + ((end - start) / 2);
258: diff = strcmp (str, parseKeywords[cur].name);
259:
260: if (diff == 0) {
261: return (cur);
262: } else if (diff < 0) {
263: end = cur - 1;
264: } else {
265: start = cur + 1;
266: }
267: } while (start <= end);
268: return (-1);
269: }
270:
271: /*-
272: *---------------------------------------------------------------------
273: * ParseLinkSrc --
274: * Link the parent node to its new child. Used in a Lst_ForEach by
275: * ParseDoDependency. If the specType isn't 'Not', the parent
276: * isn't linked as a parent of the child.
277: *
278: * Side Effects:
279: * New elements are added to the parents list of cgn and the
280: * children list of cgn. the unmade field of pgn is updated
281: * to reflect the additional child.
282: *---------------------------------------------------------------------
283: */
1.41 espie 284: static void
285: ParseLinkSrc(pgnp, cgnp)
1.42 espie 286: void *pgnp; /* The parent node */
287: void *cgnp; /* The child node */
1.1 deraadt 288: {
1.41 espie 289: GNode *pgn = (GNode *)pgnp;
290: GNode *cgn = (GNode *)cgnp;
1.43 espie 291: if (Lst_Member(&pgn->children, cgn) == NULL) {
292: Lst_AtEnd(&pgn->children, cgn);
1.41 espie 293: if (specType == Not)
1.43 espie 294: Lst_AtEnd(&cgn->parents, pgn);
1.1 deraadt 295: pgn->unmade += 1;
296: }
297: }
298:
299: /*-
300: *---------------------------------------------------------------------
301: * ParseDoOp --
302: * Apply the parsed operator to the given target node. Used in a
1.41 espie 303: * Lst_Find call by ParseDoDependency once all targets have
1.1 deraadt 304: * been found and their operator parsed. If the previous and new
305: * operators are incompatible, a major error is taken.
306: *
307: * Results:
1.40 espie 308: * 0 if a problem, 1 if ok.
1.1 deraadt 309: *
310: * Side Effects:
311: * The type field of the node is altered to reflect any new bits in
312: * the op.
313: *---------------------------------------------------------------------
314: */
315: static int
316: ParseDoOp (gnp, opp)
1.42 espie 317: void *gnp; /* The node to which the operator is to be
318: * applied */
319: void *opp; /* The operator to apply */
1.1 deraadt 320: {
321: GNode *gn = (GNode *) gnp;
322: int op = *(int *) opp;
323: /*
324: * If the dependency mask of the operator and the node don't match and
325: * the node has actually had an operator applied to it before, and
1.11 millert 326: * the operator actually has some dependency information in it, complain.
1.1 deraadt 327: */
328: if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
1.40 espie 329: !OP_NOP(gn->type) && !OP_NOP(op)) {
330: Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
331: return 0;
1.1 deraadt 332: }
333:
334: if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
335: /*
336: * If the node was the object of a :: operator, we need to create a
337: * new instance of it for the children and commands on this dependency
338: * line. The new instance is placed on the 'cohorts' list of the
339: * initial one (note the initial one is not on its own cohorts list)
340: * and the new instance is linked to all parents of the initial
341: * instance.
342: */
343: register GNode *cohort;
344: LstNode ln;
1.11 millert 345:
1.1 deraadt 346: cohort = Targ_NewGN(gn->name);
347: /*
348: * Duplicate links to parents so graph traversal is simple. Perhaps
349: * some type bits should be duplicated?
350: *
351: * Make the cohort invisible as well to avoid duplicating it into
352: * other variables. True, parents of this target won't tend to do
353: * anything with their local variables, but better safe than
354: * sorry.
355: */
1.43 espie 356: Lst_ForEach(&gn->parents, ParseLinkSrc, cohort);
1.1 deraadt 357: cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
1.43 espie 358: Lst_AtEnd(&gn->cohorts, cohort);
1.1 deraadt 359:
360: /*
361: * Replace the node in the targets list with the new copy
362: */
1.45 espie 363: ln = Lst_Member(&targets, gn);
1.37 espie 364: Lst_Replace(ln, cohort);
1.1 deraadt 365: gn = cohort;
366: }
367: /*
368: * We don't want to nuke any previous flags (whatever they were) so we
1.11 millert 369: * just OR the new operator into the old
1.1 deraadt 370: */
371: gn->type |= op;
372:
1.40 espie 373: return 1;
1.1 deraadt 374: }
375:
1.11 millert 376: /*-
1.3 deraadt 377: *---------------------------------------------------------------------
378: * ParseAddDep --
379: * Check if the pair of GNodes given needs to be synchronized.
380: * This has to be when two nodes are on different sides of a
381: * .WAIT directive.
382: *
383: * Results:
1.40 espie 384: * Returns 0 if the two targets need to be ordered, 1 otherwise.
385: * If it returns 0, the search can stop
1.3 deraadt 386: *
387: * Side Effects:
388: * A dependency can be added between the two nodes.
1.11 millert 389: *
1.3 deraadt 390: *---------------------------------------------------------------------
391: */
1.13 millert 392: static int
1.3 deraadt 393: ParseAddDep(pp, sp)
1.42 espie 394: void *pp;
395: void *sp;
1.3 deraadt 396: {
397: GNode *p = (GNode *) pp;
398: GNode *s = (GNode *) sp;
399:
400: if (p->order < s->order) {
401: /*
402: * XXX: This can cause loops, and loops can cause unmade targets,
403: * but checking is tedious, and the debugging output can show the
404: * problem
405: */
1.43 espie 406: Lst_AtEnd(&p->successors, s);
407: Lst_AtEnd(&s->preds, p);
1.40 espie 408: return 1;
1.3 deraadt 409: }
410: else
1.40 espie 411: return 0;
1.3 deraadt 412: }
413:
414:
1.1 deraadt 415: /*-
416: *---------------------------------------------------------------------
417: * ParseDoSrc --
418: * Given the name of a source, figure out if it is an attribute
419: * and apply it to the targets if it is. Else decide if there is
420: * some attribute which should be applied *to* the source because
421: * of some special target and apply it if so. Otherwise, make the
422: * source be a child of the targets in the list 'targets'
423: *
424: * Results:
425: * None
426: *
427: * Side Effects:
428: * Operator bits may be added to the list of targets or to the source.
429: * The targets may have a new source added to their lists of children.
430: *---------------------------------------------------------------------
431: */
432: static void
1.3 deraadt 433: ParseDoSrc (tOp, src, allsrc)
1.1 deraadt 434: int tOp; /* operator (if any) from special targets */
435: char *src; /* name of the source to handle */
1.3 deraadt 436: Lst allsrc; /* List of all sources to wait for */
437:
1.1 deraadt 438: {
1.3 deraadt 439: GNode *gn = NULL;
1.1 deraadt 440:
441: if (*src == '.' && isupper (src[1])) {
442: int keywd = ParseFindKeyword(src);
443: if (keywd != -1) {
1.3 deraadt 444: int op = parseKeywords[keywd].op;
445: if (op != 0) {
1.45 espie 446: Lst_Find(&targets, ParseDoOp, &op);
1.3 deraadt 447: return;
448: }
449: if (parseKeywords[keywd].spec == Wait) {
450: waiting++;
451: return;
452: }
1.1 deraadt 453: }
454: }
1.3 deraadt 455:
456: switch (specType) {
457: case Main:
1.1 deraadt 458: /*
459: * If we have noted the existence of a .MAIN, it means we need
460: * to add the sources of said target to the list of things
461: * to create. The string 'src' is likely to be free, so we
462: * must make a new copy of it. Note that this will only be
463: * invoked if the user didn't specify a target on the command
464: * line. This is to allow #ifmake's to succeed, or something...
465: */
1.43 espie 466: Lst_AtEnd(&create, estrdup(src));
1.1 deraadt 467: /*
468: * Add the name to the .TARGETS variable as well, so the user cna
469: * employ that, if desired.
470: */
471: Var_Append(".TARGETS", src, VAR_GLOBAL);
1.3 deraadt 472: return;
473:
474: case Order:
1.1 deraadt 475: /*
476: * Create proper predecessor/successor links between the previous
477: * source and the current one.
478: */
479: gn = Targ_FindNode(src, TARG_CREATE);
1.33 espie 480: if (predecessor != NULL) {
1.43 espie 481: Lst_AtEnd(&predecessor->successors, gn);
482: Lst_AtEnd(&gn->preds, predecessor);
1.1 deraadt 483: }
484: /*
485: * The current source now becomes the predecessor for the next one.
486: */
487: predecessor = gn;
1.3 deraadt 488: break;
489:
490: default:
1.1 deraadt 491: /*
492: * If the source is not an attribute, we need to find/create
493: * a node for it. After that we can apply any operator to it
494: * from a special target or link it to its parents, as
495: * appropriate.
496: *
497: * In the case of a source that was the object of a :: operator,
498: * the attribute is applied to all of its instances (as kept in
499: * the 'cohorts' list of the node) or all the cohorts are linked
500: * to all the targets.
501: */
502: gn = Targ_FindNode (src, TARG_CREATE);
503: if (tOp) {
504: gn->type |= tOp;
505: } else {
1.45 espie 506: Lst_ForEach(&targets, ParseLinkSrc, gn);
1.1 deraadt 507: }
508: if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
509: register GNode *cohort;
510: register LstNode ln;
511:
1.46 espie 512: for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)){
1.1 deraadt 513: cohort = (GNode *)Lst_Datum(ln);
514: if (tOp) {
515: cohort->type |= tOp;
516: } else {
1.45 espie 517: Lst_ForEach(&targets, ParseLinkSrc, cohort);
1.1 deraadt 518: }
519: }
520: }
1.3 deraadt 521: break;
522: }
523:
524: gn->order = waiting;
1.37 espie 525: Lst_AtEnd(allsrc, gn);
1.40 espie 526: if (waiting)
527: Lst_Find(allsrc, ParseAddDep, gn);
1.1 deraadt 528: }
529:
530: /*-
531: *-----------------------------------------------------------------------
532: * ParseFindMain --
533: * Find a real target in the list and set it to be the main one.
534: * Called by ParseDoDependency when a main target hasn't been found
535: * yet.
536: *
537: * Results:
1.40 espie 538: * 1 if main not found yet, 0 if it is.
1.1 deraadt 539: *
540: * Side Effects:
541: * mainNode is changed and Targ_SetMain is called.
542: *
543: *-----------------------------------------------------------------------
544: */
545: static int
546: ParseFindMain(gnp, dummy)
1.54 ! espie 547: void *gnp; /* Node to examine */
! 548: void *dummy UNUSED;
1.1 deraadt 549: {
550: GNode *gn = (GNode *) gnp;
1.17 espie 551: if ((gn->type & OP_NOTARGET) == 0) {
1.1 deraadt 552: mainNode = gn;
553: Targ_SetMain(gn);
1.54 ! espie 554: return 0;
! 555: } else
! 556: return 1;
1.1 deraadt 557: }
558:
559: /*-
560: *-----------------------------------------------------------------------
561: * ParseAddDir --
562: * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
563: *
564: * Side Effects:
565: * See Dir_AddDir.
566: *
567: *-----------------------------------------------------------------------
568: */
1.41 espie 569: static void
1.1 deraadt 570: ParseAddDir(path, name)
1.42 espie 571: void *path;
572: void *name;
1.1 deraadt 573: {
1.41 espie 574: Dir_AddDir((Lst)path, (char *)name);
1.1 deraadt 575: }
576:
577: /*-
578: *-----------------------------------------------------------------------
579: * ParseClearPath --
580: * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
581: *
582: * Side Effects:
583: * See Dir_ClearPath
584: *
585: *-----------------------------------------------------------------------
586: */
1.41 espie 587: static void
588: ParseClearPath(path)
1.42 espie 589: void *path;
1.1 deraadt 590: {
1.41 espie 591: Dir_ClearPath((Lst)path);
1.1 deraadt 592: }
593:
594: /*-
595: *---------------------------------------------------------------------
596: * ParseDoDependency --
597: * Parse the dependency line in line.
598: *
599: * Results:
600: * None
601: *
602: * Side Effects:
603: * The nodes of the sources are linked as children to the nodes of the
604: * targets. Some nodes may be created.
605: *
606: * We parse a dependency line by first extracting words from the line and
607: * finding nodes in the list of all targets with that name. This is done
608: * until a character is encountered which is an operator character. Currently
609: * these are only ! and :. At this point the operator is parsed and the
610: * pointer into the line advanced until the first source is encountered.
611: * The parsed operator is applied to each node in the 'targets' list,
612: * which is where the nodes found for the targets are kept, by means of
613: * the ParseDoOp function.
614: * The sources are read in much the same way as the targets were except
615: * that now they are expanded using the wildcarding scheme of the C-Shell
616: * and all instances of the resulting words in the list of all targets
617: * are found. Each of the resulting nodes is then linked to each of the
618: * targets as one of its children.
619: * Certain targets are handled specially. These are the ones detailed
620: * by the specType variable.
621: * The storing of transformation rules is also taken care of here.
622: * A target is recognized as a transformation rule by calling
623: * Suff_IsTransform. If it is a transformation rule, its node is gotten
624: * from the suffix module via Suff_AddTransform rather than the standard
625: * Targ_FindNode in the target module.
626: *---------------------------------------------------------------------
627: */
628: static void
629: ParseDoDependency (line)
630: char *line; /* the line to parse */
631: {
632: char *cp; /* our current position */
633: GNode *gn; /* a general purpose temporary node */
634: int op; /* the operator on the line */
635: char savec; /* a place to save a character */
1.45 espie 636: LIST paths; /* List of search paths to alter when parsing
1.1 deraadt 637: * a list of .PATH targets */
638: int tOp; /* operator from special target */
1.43 espie 639: LIST curTargs; /* list of target names to be found and added
1.1 deraadt 640: * to the targets list */
1.43 espie 641: LIST curSrcs; /* list of sources in order */
1.1 deraadt 642:
643: tOp = 0;
644:
645: specType = Not;
1.3 deraadt 646: waiting = 0;
1.45 espie 647: Lst_Init(&paths);
1.1 deraadt 648:
1.43 espie 649: Lst_Init(&curTargs);
650: Lst_Init(&curSrcs);
1.11 millert 651:
1.1 deraadt 652: do {
653: for (cp = line;
1.18 millert 654: *cp && !isspace (*cp) && (*cp != '(');
1.1 deraadt 655: cp++)
656: {
1.19 millert 657: /*
658: * We don't want to end a word on ':' or '!' if there is a
659: * better match later on in the string. By "better" I mean
660: * one that is followed by whitespace. This allows the user
661: * to have targets like:
662: * fie::fi:fo: fum
663: * where "fie::fi:fo" is the target. In real life this is used
664: * for perl5 library man pages where "::" separates an object
665: * from its class. Ie: "File::Spec::Unix". This behaviour
666: * is also consistent with other versions of make.
667: */
1.18 millert 668: if (*cp == '!' || *cp == ':') {
669: char *p = cp + 1;
670:
671: if (*p == '\0')
672: break; /* no chance, not enough room */
673: /*
674: * Only end the word on ':' or '!' if there is not
1.19 millert 675: * a match later on followed by whitespace.
1.18 millert 676: */
677: while ((p = strchr(p + 1, *cp)) && !isspace(*(p + 1)))
678: ;
679: if (!p || !isspace(*(p + 1)))
680: break;
681: } else if (*cp == '$') {
1.1 deraadt 682: /*
683: * Must be a dynamic source (would have been expanded
684: * otherwise), so call the Var module to parse the puppy
685: * so we can safely advance beyond it...There should be
686: * no errors in this, as they would have been discovered
687: * in the initial Var_Subst and we wouldn't be here.
688: */
1.36 espie 689: size_t length;
1.1 deraadt 690: Boolean freeIt;
691: char *result;
692:
1.48 espie 693: result=Var_Parse(cp, NULL, TRUE, &length, &freeIt);
1.1 deraadt 694:
695: if (freeIt) {
696: free(result);
697: }
698: cp += length-1;
699: }
700: continue;
701: }
702: if (*cp == '(') {
703: /*
704: * Archives must be handled specially to make sure the OP_ARCHV
705: * flag is set in their 'type' field, for one thing, and because
706: * things like "archive(file1.o file2.o file3.o)" are permissible.
707: * Arch_ParseArchive will set 'line' to be the first non-blank
708: * after the archive-spec. It creates/finds nodes for the members
709: * and places them on the given list, returning SUCCESS if all
710: * went well and FAILURE if there was an error in the
711: * specification. On error, line should remain untouched.
712: */
1.48 espie 713: if (Arch_ParseArchive(&line, &targets, NULL) != SUCCESS) {
1.1 deraadt 714: Parse_Error (PARSE_FATAL,
715: "Error in archive specification: \"%s\"", line);
716: return;
717: } else {
718: continue;
719: }
720: }
721: savec = *cp;
1.11 millert 722:
1.1 deraadt 723: if (!*cp) {
724: /*
725: * Ending a dependency line without an operator is a Bozo
1.11 millert 726: * no-no
1.1 deraadt 727: */
728: Parse_Error (PARSE_FATAL, "Need an operator");
729: return;
730: }
731: *cp = '\0';
732: /*
733: * Have a word in line. See if it's a special target and set
734: * specType to match it.
735: */
736: if (*line == '.' && isupper (line[1])) {
737: /*
738: * See if the target is a special target that must have it
1.11 millert 739: * or its sources handled specially.
1.1 deraadt 740: */
741: int keywd = ParseFindKeyword(line);
742: if (keywd != -1) {
743: if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
744: Parse_Error(PARSE_FATAL, "Mismatched special targets");
745: return;
746: }
1.11 millert 747:
1.1 deraadt 748: specType = parseKeywords[keywd].spec;
749: tOp = parseKeywords[keywd].op;
750:
751: /*
752: * Certain special targets have special semantics:
753: * .PATH Have to set the dirSearchPath
754: * variable too
755: * .MAIN Its sources are only used if
756: * nothing has been specified to
757: * create.
758: * .DEFAULT Need to create a node to hang
759: * commands on, but we don't want
760: * it in the graph, nor do we want
761: * it to be the Main Target, so we
762: * create it, set OP_NOTMAIN and
763: * add it to the list, setting
764: * DEFAULT to the new node for
765: * later use. We claim the node is
766: * A transformation rule to make
767: * life easier later, when we'll
768: * use Make_HandleUse to actually
769: * apply the .DEFAULT commands.
1.7 niklas 770: * .PHONY The list of targets
1.17 espie 771: * .NOPATH Don't search for file in the path
1.1 deraadt 772: * .BEGIN
773: * .END
774: * .INTERRUPT Are not to be considered the
775: * main target.
776: * .NOTPARALLEL Make only one target at a time.
777: * .SINGLESHELL Create a shell for each command.
1.33 espie 778: * .ORDER Must set initial predecessor to NULL
1.1 deraadt 779: */
780: switch (specType) {
781: case ExPath:
1.45 espie 782: Lst_AtEnd(&paths, &dirSearchPath);
1.1 deraadt 783: break;
784: case Main:
1.43 espie 785: if (!Lst_IsEmpty(&create)) {
1.1 deraadt 786: specType = Not;
787: }
788: break;
789: case Begin:
790: case End:
791: case Interrupt:
792: gn = Targ_FindNode(line, TARG_CREATE);
793: gn->type |= OP_NOTMAIN;
1.45 espie 794: Lst_AtEnd(&targets, gn);
1.1 deraadt 795: break;
796: case Default:
797: gn = Targ_NewGN(".DEFAULT");
798: gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
1.45 espie 799: Lst_AtEnd(&targets, gn);
1.1 deraadt 800: DEFAULT = gn;
801: break;
802: case NotParallel:
803: {
804: extern int maxJobs;
1.11 millert 805:
1.1 deraadt 806: maxJobs = 1;
807: break;
808: }
809: case SingleShell:
810: compatMake = 1;
811: break;
812: case Order:
1.33 espie 813: predecessor = NULL;
1.1 deraadt 814: break;
815: default:
816: break;
817: }
818: } else if (strncmp (line, ".PATH", 5) == 0) {
819: /*
820: * .PATH<suffix> has to be handled specially.
821: * Call on the suffix module to give us a path to
822: * modify.
823: */
824: Lst path;
1.11 millert 825:
1.1 deraadt 826: specType = ExPath;
1.45 espie 827: path = Suff_GetPath(&line[5]);
1.33 espie 828: if (path == NULL) {
1.45 espie 829: Parse_Error(PARSE_FATAL,
1.1 deraadt 830: "Suffix '%s' not defined (yet)",
831: &line[5]);
832: return;
1.45 espie 833: } else
834: Lst_AtEnd(&paths, path);
1.1 deraadt 835: }
836: }
1.11 millert 837:
1.1 deraadt 838: /*
839: * Have word in line. Get or create its node and stick it at
1.11 millert 840: * the end of the targets list
1.1 deraadt 841: */
842: if ((specType == Not) && (*line != '\0')) {
1.34 espie 843: char *targName;
844:
1.1 deraadt 845: if (Dir_HasWildcards(line)) {
846: /*
847: * Targets are to be sought only in the current directory,
848: * so create an empty path for the thing. Note we need to
849: * use Dir_Destroy in the destruction of the path as the
850: * Dir module could have added a directory to the path...
851: */
1.43 espie 852: LIST emptyPath;
853:
854: Lst_Init(&emptyPath);
1.11 millert 855:
1.43 espie 856: Dir_Expand(line, &emptyPath, &curTargs);
1.11 millert 857:
1.43 espie 858: Lst_Destroy(&emptyPath, Dir_Destroy);
1.1 deraadt 859: } else {
860: /*
861: * No wildcards, but we want to avoid code duplication,
862: * so create a list with the word on it.
863: */
1.43 espie 864: Lst_AtEnd(&curTargs, line);
1.1 deraadt 865: }
1.11 millert 866:
1.43 espie 867: while((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) {
1.1 deraadt 868: if (!Suff_IsTransform (targName)) {
869: gn = Targ_FindNode (targName, TARG_CREATE);
870: } else {
871: gn = Suff_AddTransform (targName);
872: }
1.11 millert 873:
1.16 millert 874: if (gn != NULL)
1.45 espie 875: Lst_AtEnd(&targets, gn);
1.1 deraadt 876: }
877: } else if (specType == ExPath && *line != '.' && *line != '\0') {
878: Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
879: }
1.11 millert 880:
1.1 deraadt 881: *cp = savec;
882: /*
883: * If it is a special type and not .PATH, it's the only target we
884: * allow on this line...
885: */
886: if (specType != Not && specType != ExPath) {
887: Boolean warn = FALSE;
1.11 millert 888:
1.1 deraadt 889: while ((*cp != '!') && (*cp != ':') && *cp) {
890: if (*cp != ' ' && *cp != '\t') {
891: warn = TRUE;
892: }
893: cp++;
894: }
895: if (warn) {
896: Parse_Error(PARSE_WARNING, "Extra target ignored");
897: }
898: } else {
899: while (*cp && isspace (*cp)) {
900: cp++;
901: }
902: }
903: line = cp;
904: } while ((*line != '!') && (*line != ':') && *line);
905:
1.43 espie 906: /* Don't need the list of target names any more */
907: Lst_Destroy(&curTargs, NOFREE);
1.1 deraadt 908:
1.45 espie 909: if (!Lst_IsEmpty(&targets)) {
1.1 deraadt 910: switch(specType) {
911: default:
912: Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
913: break;
914: case Default:
915: case Begin:
916: case End:
917: case Interrupt:
918: /*
919: * These four create nodes on which to hang commands, so
920: * targets shouldn't be empty...
921: */
922: case Not:
923: /*
924: * Nothing special here -- targets can be empty if it wants.
925: */
926: break;
927: }
928: }
929:
930: /*
931: * Have now parsed all the target names. Must parse the operator next. The
932: * result is left in op .
933: */
934: if (*cp == '!') {
935: op = OP_FORCE;
936: } else if (*cp == ':') {
937: if (cp[1] == ':') {
938: op = OP_DOUBLEDEP;
939: cp++;
940: } else {
941: op = OP_DEPENDS;
942: }
943: } else {
944: Parse_Error (PARSE_FATAL, "Missing dependency operator");
945: return;
946: }
947:
948: cp++; /* Advance beyond operator */
949:
1.45 espie 950: Lst_Find(&targets, ParseDoOp, &op);
1.1 deraadt 951:
952: /*
1.11 millert 953: * Get to the first source
1.1 deraadt 954: */
955: while (*cp && isspace (*cp)) {
956: cp++;
957: }
958: line = cp;
959:
960: /*
961: * Several special targets take different actions if present with no
962: * sources:
963: * a .SUFFIXES line with no sources clears out all old suffixes
964: * a .PRECIOUS line makes all targets precious
965: * a .IGNORE line ignores errors for all targets
966: * a .SILENT line creates silence when making all targets
967: * a .PATH removes all directories from the search path(s).
968: */
969: if (!*line) {
970: switch (specType) {
971: case Suffixes:
972: Suff_ClearSuffixes ();
973: break;
974: case Precious:
975: allPrecious = TRUE;
976: break;
977: case Ignore:
978: ignoreErrors = TRUE;
979: break;
980: case Silent:
981: beSilent = TRUE;
982: break;
983: case ExPath:
1.45 espie 984: Lst_Every(&paths, ParseClearPath);
1.1 deraadt 985: break;
986: default:
987: break;
988: }
989: } else if (specType == MFlags) {
990: /*
991: * Call on functions in main.c to deal with these arguments and
992: * set the initial character to a null-character so the loop to
993: * get sources won't get anything
994: */
995: Main_ParseArgLine (line);
996: *line = '\0';
997: } else if (specType == ExShell) {
998: if (Job_ParseShell (line) != SUCCESS) {
999: Parse_Error (PARSE_FATAL, "improper shell specification");
1000: return;
1001: }
1002: *line = '\0';
1003: } else if ((specType == NotParallel) || (specType == SingleShell)) {
1004: *line = '\0';
1005: }
1.11 millert 1006:
1.1 deraadt 1007: /*
1.11 millert 1008: * NOW GO FOR THE SOURCES
1.1 deraadt 1009: */
1010: if ((specType == Suffixes) || (specType == ExPath) ||
1011: (specType == Includes) || (specType == Libs) ||
1012: (specType == Null))
1013: {
1014: while (*line) {
1015: /*
1016: * If the target was one that doesn't take files as its sources
1017: * but takes something like suffixes, we take each
1018: * space-separated word on the line as a something and deal
1019: * with it accordingly.
1020: *
1021: * If the target was .SUFFIXES, we take each source as a
1022: * suffix and add it to the list of suffixes maintained by the
1023: * Suff module.
1024: *
1025: * If the target was a .PATH, we add the source as a directory
1026: * to search on the search path.
1027: *
1028: * If it was .INCLUDES, the source is taken to be the suffix of
1029: * files which will be #included and whose search path should
1030: * be present in the .INCLUDES variable.
1031: *
1032: * If it was .LIBS, the source is taken to be the suffix of
1033: * files which are considered libraries and whose search path
1034: * should be present in the .LIBS variable.
1035: *
1036: * If it was .NULL, the source is the suffix to use when a file
1037: * has no valid suffix.
1038: */
1039: char savec;
1040: while (*cp && !isspace (*cp)) {
1041: cp++;
1042: }
1043: savec = *cp;
1044: *cp = '\0';
1045: switch (specType) {
1046: case Suffixes:
1047: Suff_AddSuffix (line);
1048: break;
1049: case ExPath:
1.45 espie 1050: Lst_ForEach(&paths, ParseAddDir, line);
1.1 deraadt 1051: break;
1052: case Includes:
1053: Suff_AddInclude (line);
1054: break;
1055: case Libs:
1056: Suff_AddLib (line);
1057: break;
1058: case Null:
1059: Suff_SetNull (line);
1060: break;
1061: default:
1062: break;
1063: }
1064: *cp = savec;
1065: if (savec != '\0') {
1066: cp++;
1067: }
1068: while (*cp && isspace (*cp)) {
1069: cp++;
1070: }
1071: line = cp;
1072: }
1.45 espie 1073: Lst_Destroy(&paths, NOFREE);
1.1 deraadt 1074: } else {
1075: while (*line) {
1076: /*
1077: * The targets take real sources, so we must beware of archive
1078: * specifications (i.e. things with left parentheses in them)
1079: * and handle them accordingly.
1080: */
1081: while (*cp && !isspace (*cp)) {
1082: if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
1083: /*
1084: * Only stop for a left parenthesis if it isn't at the
1085: * start of a word (that'll be for variable changes
1086: * later) and isn't preceded by a dollar sign (a dynamic
1087: * source).
1088: */
1089: break;
1090: } else {
1091: cp++;
1092: }
1093: }
1094:
1095: if (*cp == '(') {
1096: GNode *gn;
1.43 espie 1097: LIST sources; /* list of archive source names after
1098: * expansion */
1.1 deraadt 1099:
1.43 espie 1100: Lst_Init(&sources);
1.48 espie 1101: if (Arch_ParseArchive(&line, &sources, NULL) != SUCCESS) {
1.1 deraadt 1102: Parse_Error (PARSE_FATAL,
1103: "Error in source archive spec \"%s\"", line);
1104: return;
1105: }
1106:
1.43 espie 1107: while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL)
1108: ParseDoSrc(tOp, gn->name, &curSrcs);
1109: Lst_Destroy(&sources, NOFREE);
1.1 deraadt 1110: cp = line;
1111: } else {
1112: if (*cp) {
1113: *cp = '\0';
1114: cp += 1;
1115: }
1116:
1.43 espie 1117: ParseDoSrc(tOp, line, &curSrcs);
1.1 deraadt 1118: }
1119: while (*cp && isspace (*cp)) {
1120: cp++;
1121: }
1122: line = cp;
1123: }
1124: }
1.11 millert 1125:
1.33 espie 1126: if (mainNode == NULL) {
1.1 deraadt 1127: /*
1128: * If we have yet to decide on a main target to make, in the
1129: * absence of any user input, we want the first target on
1130: * the first dependency line that is actually a real target
1131: * (i.e. isn't a .USE or .EXEC rule) to be made.
1132: */
1.45 espie 1133: Lst_Find(&targets, ParseFindMain, NULL);
1.1 deraadt 1134: }
1135:
1.43 espie 1136: /* Finally, destroy the list of sources. */
1137: Lst_Destroy(&curSrcs, NOFREE);
1.1 deraadt 1138: }
1139:
1140: /*-
1141: *---------------------------------------------------------------------
1142: * Parse_IsVar --
1143: * Return TRUE if the passed line is a variable assignment. A variable
1144: * assignment consists of a single word followed by optional whitespace
1145: * followed by either a += or an = operator.
1146: * This function is used both by the Parse_File function and main when
1147: * parsing the command-line arguments.
1148: *
1149: * Results:
1150: * TRUE if it is. FALSE if it ain't
1151: *
1152: * Side Effects:
1153: * none
1154: *---------------------------------------------------------------------
1155: */
1156: Boolean
1157: Parse_IsVar (line)
1158: register char *line; /* the line to check */
1159: {
1160: register Boolean wasSpace = FALSE; /* set TRUE if found a space */
1161: register Boolean haveName = FALSE; /* Set TRUE if have a variable name */
1162: int level = 0;
1163: #define ISEQOPERATOR(c) \
1164: (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1165:
1166: /*
1167: * Skip to variable name
1168: */
1.11 millert 1169: for (;(*line == ' ') || (*line == '\t'); line++)
1.1 deraadt 1170: continue;
1171:
1172: for (; *line != '=' || level != 0; line++)
1173: switch (*line) {
1174: case '\0':
1175: /*
1176: * end-of-line -- can't be a variable assignment.
1177: */
1178: return FALSE;
1179:
1180: case ' ':
1181: case '\t':
1182: /*
1183: * there can be as much white space as desired so long as there is
1.11 millert 1184: * only one word before the operator
1.1 deraadt 1185: */
1186: wasSpace = TRUE;
1187: break;
1188:
1189: case '(':
1190: case '{':
1191: level++;
1192: break;
1193:
1194: case '}':
1195: case ')':
1196: level--;
1197: break;
1.11 millert 1198:
1.1 deraadt 1199: default:
1200: if (wasSpace && haveName) {
1201: if (ISEQOPERATOR(*line)) {
1202: /*
1.9 briggs 1203: * We must have a finished word
1204: */
1205: if (level != 0)
1206: return FALSE;
1207:
1208: /*
1.1 deraadt 1209: * When an = operator [+?!:] is found, the next
1.9 briggs 1210: * character must be an = or it ain't a valid
1.1 deraadt 1211: * assignment.
1212: */
1.9 briggs 1213: if (line[1] == '=')
1.1 deraadt 1214: return haveName;
1.9 briggs 1215: #ifdef SUNSHCMD
1.1 deraadt 1216: /*
1.9 briggs 1217: * This is a shell command
1.1 deraadt 1218: */
1.9 briggs 1219: if (strncmp(line, ":sh", 3) == 0)
1220: return haveName;
1221: #endif
1.1 deraadt 1222: }
1.9 briggs 1223: /*
1224: * This is the start of another word, so not assignment.
1225: */
1226: return FALSE;
1.1 deraadt 1227: }
1228: else {
1.11 millert 1229: haveName = TRUE;
1.1 deraadt 1230: wasSpace = FALSE;
1231: }
1232: break;
1233: }
1234:
1235: return haveName;
1236: }
1237:
1238: /*-
1239: *---------------------------------------------------------------------
1240: * Parse_DoVar --
1241: * Take the variable assignment in the passed line and do it in the
1242: * global context.
1243: *
1244: * Note: There is a lexical ambiguity with assignment modifier characters
1245: * in variable names. This routine interprets the character before the =
1246: * as a modifier. Therefore, an assignment like
1247: * C++=/usr/bin/CC
1248: * is interpreted as "C+ +=" instead of "C++ =".
1249: *
1250: * Results:
1251: * none
1252: *
1253: * Side Effects:
1254: * the variable structure of the given variable name is altered in the
1255: * global context.
1256: *---------------------------------------------------------------------
1257: */
1258: void
1259: Parse_DoVar (line, ctxt)
1260: char *line; /* a line guaranteed to be a variable
1261: * assignment. This reduces error checks */
1.49 espie 1262: GSymT *ctxt; /* Context in which to do the assignment */
1.1 deraadt 1263: {
1264: char *cp; /* pointer into line */
1265: enum {
1266: VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1267: } type; /* Type of assignment */
1.11 millert 1268: char *opc; /* ptr to operator character to
1.1 deraadt 1269: * null-terminate the variable name */
1.11 millert 1270: /*
1.1 deraadt 1271: * Avoid clobbered variable warnings by forcing the compiler
1272: * to ``unregister'' variables
1273: */
1274: #if __GNUC__
1275: (void) &cp;
1276: (void) &line;
1277: #endif
1278:
1279: /*
1280: * Skip to variable name
1281: */
1282: while ((*line == ' ') || (*line == '\t')) {
1283: line++;
1284: }
1285:
1286: /*
1287: * Skip to operator character, nulling out whitespace as we go
1288: */
1289: for (cp = line + 1; *cp != '='; cp++) {
1290: if (isspace (*cp)) {
1291: *cp = '\0';
1292: }
1293: }
1294: opc = cp-1; /* operator is the previous character */
1295: *cp++ = '\0'; /* nuke the = */
1296:
1297: /*
1298: * Check operator type
1299: */
1300: switch (*opc) {
1301: case '+':
1302: type = VAR_APPEND;
1303: *opc = '\0';
1304: break;
1305:
1306: case '?':
1307: /*
1308: * If the variable already has a value, we don't do anything.
1309: */
1310: *opc = '\0';
1311: if (Var_Exists(line, ctxt)) {
1312: return;
1313: } else {
1314: type = VAR_NORMAL;
1315: }
1316: break;
1317:
1318: case ':':
1319: type = VAR_SUBST;
1320: *opc = '\0';
1321: break;
1322:
1323: case '!':
1324: type = VAR_SHELL;
1325: *opc = '\0';
1326: break;
1327:
1328: default:
1.9 briggs 1329: #ifdef SUNSHCMD
1330: while (*opc != ':')
1331: if (--opc < line)
1332: break;
1333:
1334: if (strncmp(opc, ":sh", 3) == 0) {
1335: type = VAR_SHELL;
1336: *opc = '\0';
1337: break;
1338: }
1339: #endif
1.1 deraadt 1340: type = VAR_NORMAL;
1341: break;
1342: }
1343:
1344: while (isspace (*cp)) {
1345: cp++;
1346: }
1347:
1348: if (type == VAR_APPEND) {
1349: Var_Append (line, cp, ctxt);
1350: } else if (type == VAR_SUBST) {
1351: /*
1352: * Allow variables in the old value to be undefined, but leave their
1353: * invocation alone -- this is done by forcing oldVars to be false.
1354: * XXX: This can cause recursive variables, but that's not hard to do,
1355: * and this allows someone to do something like
1356: *
1357: * CFLAGS = $(.INCLUDES)
1358: * CFLAGS := -I.. $(CFLAGS)
1359: *
1360: * And not get an error.
1361: */
1362: Boolean oldOldVars = oldVars;
1363:
1364: oldVars = FALSE;
1.49 espie 1365: cp = Var_Subst(cp, (SymTable *)ctxt, FALSE);
1.1 deraadt 1366: oldVars = oldOldVars;
1367:
1368: Var_Set(line, cp, ctxt);
1369: free(cp);
1370: } else if (type == VAR_SHELL) {
1.9 briggs 1371: Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
1372: * if any variable expansion was performed */
1373: char *res, *err;
1.1 deraadt 1374:
1.9 briggs 1375: if (strchr(cp, '$') != NULL) {
1.1 deraadt 1376: /*
1377: * There's a dollar sign in the command, so perform variable
1378: * expansion on the whole thing. The resulting string will need
1379: * freeing when we're done, so set freeCmd to TRUE.
1380: */
1.48 espie 1381: cp = Var_Subst(cp, NULL, TRUE);
1.1 deraadt 1382: freeCmd = TRUE;
1383: }
1384:
1.9 briggs 1385: res = Cmd_Exec(cp, &err);
1386: Var_Set(line, res, ctxt);
1387: free(res);
1.1 deraadt 1388:
1.9 briggs 1389: if (err)
1390: Parse_Error(PARSE_WARNING, err, cp);
1.1 deraadt 1391:
1.9 briggs 1392: if (freeCmd)
1393: free(cp);
1.1 deraadt 1394: } else {
1395: /*
1396: * Normal assignment -- just do it.
1397: */
1.9 briggs 1398: Var_Set(line, cp, ctxt);
1.1 deraadt 1399: }
1400: }
1401:
1.9 briggs 1402:
1.1 deraadt 1403: /*-
1404: * ParseAddCmd --
1405: * Lst_ForEach function to add a command line to all targets
1406: *
1407: * Side Effects:
1408: * A new element is added to the commands list of the node.
1409: */
1.41 espie 1410: static void
1.1 deraadt 1411: ParseAddCmd(gnp, cmd)
1.42 espie 1412: void *gnp; /* the node to which the command is to be added */
1413: void *cmd; /* the command to add */
1.1 deraadt 1414: {
1.41 espie 1415: GNode *gn = (GNode *)gnp;
1.1 deraadt 1416: /* if target already supplied, ignore commands */
1.39 espie 1417: if (!(gn->type & OP_HAS_COMMANDS)) {
1.43 espie 1418: Lst_AtEnd(&gn->commands, cmd);
1.39 espie 1419: if (!gn->lineno) {
1420: gn->lineno = Parse_Getlineno();
1421: gn->fname = Parse_Getfilename();
1422: }
1423: }
1.1 deraadt 1424: }
1425:
1426: /*-
1427: *-----------------------------------------------------------------------
1428: * ParseHasCommands --
1429: * Callback procedure for Parse_File when destroying the list of
1430: * targets on the last dependency line. Marks a target as already
1431: * having commands if it does, to keep from having shell commands
1432: * on multiple dependency lines.
1433: *
1434: * Results:
1435: * None
1436: *
1437: * Side Effects:
1438: * OP_HAS_COMMANDS may be set for the target.
1439: *
1440: *-----------------------------------------------------------------------
1441: */
1442: static void
1443: ParseHasCommands(gnp)
1.42 espie 1444: void *gnp; /* Node to examine */
1.1 deraadt 1445: {
1446: GNode *gn = (GNode *) gnp;
1.43 espie 1447: if (!Lst_IsEmpty(&gn->commands)) {
1.1 deraadt 1448: gn->type |= OP_HAS_COMMANDS;
1449: }
1450: }
1451:
1452: /*-
1453: *-----------------------------------------------------------------------
1454: * Parse_AddIncludeDir --
1455: * Add a directory to the path searched for included makefiles
1456: * bracketed by double-quotes. Used by functions in main.c
1457: *
1458: * Results:
1459: * None.
1460: *
1461: * Side Effects:
1462: * The directory is appended to the list.
1463: *
1464: *-----------------------------------------------------------------------
1465: */
1466: void
1.43 espie 1467: Parse_AddIncludeDir(dir)
1.1 deraadt 1468: char *dir; /* The name of the directory to add */
1469: {
1.43 espie 1470: Dir_AddDir(&parseIncPath, dir);
1.1 deraadt 1471: }
1472:
1473: /*-
1474: *---------------------------------------------------------------------
1475: * ParseDoInclude --
1476: * Push to another file.
1.11 millert 1477: *
1.1 deraadt 1478: * The input is the line minus the #include. A file spec is a string
1479: * enclosed in <> or "". The former is looked for only in sysIncPath.
1480: * The latter in . and the directories specified by -I command line
1481: * options
1482: *
1483: * Side Effects:
1.50 espie 1484: * old parse context is pushed on the stack, new file becomes
1485: * current context.
1.1 deraadt 1486: *---------------------------------------------------------------------
1487: */
1488: static void
1.50 espie 1489: ParseDoInclude(file)
1.1 deraadt 1490: char *file; /* file specification */
1491: {
1492: char endc; /* the character which ends the file spec */
1493: char *cp; /* current position in file spec */
1494: Boolean isSystem; /* TRUE if makefile is a system makefile */
1495:
1.50 espie 1496: /* Skip to delimiter character so we know where to look */
1497: while (*file == ' ' || *file == '\t')
1.1 deraadt 1498: file++;
1499:
1.50 espie 1500: if (*file != '"' && *file != '<') {
1.1 deraadt 1501: Parse_Error (PARSE_FATAL,
1502: ".include filename must be delimited by '\"' or '<'");
1503: return;
1504: }
1505:
1.50 espie 1506: /* Set the search path on which to find the include file based on the
1.1 deraadt 1507: * characters which bracket its name. Angle-brackets imply it's
1.50 espie 1508: * a system Makefile while double-quotes imply it's a user makefile */
1.1 deraadt 1509: if (*file == '<') {
1510: isSystem = TRUE;
1511: endc = '>';
1512: } else {
1513: isSystem = FALSE;
1514: endc = '"';
1515: }
1516:
1.50 espie 1517: /* Skip to matching delimiter */
1.1 deraadt 1518: for (cp = ++file; *cp && *cp != endc; cp++) {
1.50 espie 1519: if (*cp == '\0') {
1520: Parse_Error(PARSE_FATAL,
1.1 deraadt 1521: "Unclosed %cinclude filename. '%c' expected",
1522: '.', endc);
1.50 espie 1523: return;
1.1 deraadt 1524: }
1525: }
1.50 espie 1526: ParseLookupIncludeFile(file, cp, isSystem);
1.1 deraadt 1527: }
1528:
1529: #ifdef SYSVINCLUDE
1530: /*-
1531: *---------------------------------------------------------------------
1532: * ParseTraditionalInclude --
1533: * Push to another file.
1.11 millert 1534: *
1.1 deraadt 1535: * The input is the line minus the "include". The file name is
1536: * the string following the "include".
1537: *
1538: * Side Effects:
1.50 espie 1539: * old parse context is pushed on the stack, new file becomes
1540: * current context.
1.1 deraadt 1541: *---------------------------------------------------------------------
1542: */
1543: static void
1.50 espie 1544: ParseTraditionalInclude(file)
1.1 deraadt 1545: char *file; /* file specification */
1546: {
1547: char *cp; /* current position in file spec */
1548:
1.50 espie 1549: /* Skip over whitespace */
1550: while (*file == ' ' || *file == '\t')
1.1 deraadt 1551: file++;
1552:
1553: if (*file == '\0') {
1554: Parse_Error (PARSE_FATAL,
1555: "Filename missing from \"include\"");
1556: return;
1557: }
1558:
1.50 espie 1559: /* Skip to end of line or next whitespace */
1560: for (cp = file; *cp != '\0' && !isspace(*cp);)
1561: cp++;
1.1 deraadt 1562:
1.50 espie 1563: ParseLookupIncludeFile(file, cp, TRUE);
1564: }
1565: #endif
1.1 deraadt 1566:
1.50 espie 1567: /* Common part to lookup and read an include file. */
1568: static void
1569: ParseLookupIncludeFile(spec, endSpec, isSystem)
1570: char *spec;
1571: char *endSpec;
1572: Boolean isSystem;
1573: {
1574: char *file;
1575: char *fullname;
1576: char endc;
1577:
1578: /* Substitute for any variables in the file name before trying to
1579: * find the thing. */
1580: endc = *endSpec;
1581: *endSpec = '\0';
1582: file = Var_Subst(spec, NULL, FALSE);
1583: *endSpec = endc;
1584:
1585: /* Now that we know the file name and its search path, we attempt to
1586: * find the durn thing. NULL indicates the file still hasn't been
1587: * found. */
1588: fullname = NULL;
1589:
1590: /* Handle non-system non-absolute files... */
1591: if (!isSystem && file[0] != '/') {
1592: /* ... by first searching relative to the including file's
1593: * location. We don't want to cd there, of course, so we
1594: * just tack on the old file's leading path components
1595: * and call Dir_FindFile to see if we can locate the beast. */
1596: char *slash;
1597:
1598: slash = strrchr(Parse_Getfilename(), '/');
1599: if (slash != NULL) {
1600: char *base, *newName;
1601:
1602: base = interval_dup(Parse_Getfilename(), slash);
1.52 espie 1603: newName = str_concat(base, file, '/');
1.50 espie 1604: free(base);
1605: fullname = Dir_FindFile(newName, &parseIncPath);
1606: if (fullname == NULL)
1607: fullname = Dir_FindFile(newName, &dirSearchPath);
1608: free(newName);
1609: }
1.1 deraadt 1610: }
1611:
1.50 espie 1612: /* Now look first on the -I search path, then on the .PATH
1613: * search path, if not found in a -I directory.
1614: * XXX: Suffix specific? */
1615: if (fullname == NULL)
1.43 espie 1616: fullname = Dir_FindFile(file, &parseIncPath);
1.50 espie 1617: if (fullname == NULL)
1618: fullname = Dir_FindFile(file, &dirSearchPath);
1.1 deraadt 1619:
1.50 espie 1620: /* Still haven't found the makefile. Look for it on the system
1621: * path as a last resort. */
1622: if (fullname == NULL)
1.43 espie 1623: fullname = Dir_FindFile(file, &sysIncPath);
1.1 deraadt 1624:
1.50 espie 1625: if (fullname == NULL)
1626: Parse_Error(PARSE_FATAL, "Could not find %s", file);
1.1 deraadt 1627:
1.50 espie 1628: free(file);
1.1 deraadt 1629:
1.50 espie 1630: if (fullname != NULL) {
1631: FILE *f;
1.1 deraadt 1632:
1.50 espie 1633: f = fopen(fullname, "r");
1634: if (f == NULL) {
1635: Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1636: } else {
1637: /* Once we find the absolute path to the file, we push the current
1638: * stream to the includes stack, and start reading from the new
1639: * file. We set up the file name to be its absolute name so that
1640: * error messages are informative. */
1641: Parse_FromFile(fullname, f);
1642: }
1.1 deraadt 1643: }
1644: }
1645:
1646: /*-
1647: *-----------------------------------------------------------------------
1648: * ParseFinishLine --
1649: * Handle the end of a dependency group.
1650: *
1651: * Side Effects:
1652: * inLine set FALSE. 'targets' list destroyed.
1653: *
1654: *-----------------------------------------------------------------------
1655: */
1656: static void
1657: ParseFinishLine()
1658: {
1659: if (inLine) {
1.45 espie 1660: Lst_Every(&targets, Suff_EndTransform);
1661: Lst_Destroy(&targets, ParseHasCommands);
1662: Lst_Init(&targets);
1.1 deraadt 1663: inLine = FALSE;
1664: }
1665: }
1.11 millert 1666:
1.1 deraadt 1667:
1668: /*-
1669: *---------------------------------------------------------------------
1670: * Parse_File --
1671: * Parse a file into its component parts, incorporating it into the
1672: * current dependency graph. This is the main function and controls
1673: * almost every other function in this module
1674: *
1675: * Results:
1676: * None
1677: *
1678: * Side Effects:
1679: * Loads. Nodes are added to the list of all targets, nodes and links
1680: * are added to the dependency graph. etc. etc. etc.
1681: *---------------------------------------------------------------------
1682: */
1683: void
1684: Parse_File(name, stream)
1685: char *name; /* the name of the file being read */
1686: FILE * stream; /* Stream open to makefile to parse */
1687: {
1688: register char *cp, /* pointer into the line */
1689: *line; /* the line we're working on */
1690:
1691: inLine = FALSE;
1.50 espie 1692: Parse_FromFile(name, stream);
1.1 deraadt 1693: do {
1694: while ((line = ParseReadLine ()) != NULL) {
1695: if (*line == '.') {
1696: /*
1697: * Lines that begin with the special character are either
1698: * include or undef directives.
1699: */
1700: for (cp = line + 1; isspace (*cp); cp++) {
1701: continue;
1702: }
1703: if (strncmp (cp, "include", 7) == 0) {
1704: ParseDoInclude (cp + 7);
1705: goto nextLine;
1706: } else if (strncmp(cp, "undef", 5) == 0) {
1707: char *cp2;
1708: for (cp += 5; isspace((unsigned char) *cp); cp++) {
1709: continue;
1710: }
1711:
1712: for (cp2 = cp; !isspace((unsigned char) *cp2) &&
1713: (*cp2 != '\0'); cp2++) {
1714: continue;
1715: }
1716:
1717: *cp2 = '\0';
1718:
1719: Var_Delete(cp, VAR_GLOBAL);
1720: goto nextLine;
1721: }
1722: }
1.11 millert 1723: if (*line == '#') {
1724: /* If we're this far, the line must be a comment. */
1.1 deraadt 1725: goto nextLine;
1726: }
1.11 millert 1727:
1.1 deraadt 1728: if (*line == '\t') {
1729: /*
1730: * If a line starts with a tab, it can only hope to be
1731: * a creation command.
1732: */
1733: #ifndef POSIX
1734: shellCommand:
1735: #endif
1736: for (cp = line + 1; isspace (*cp); cp++) {
1737: continue;
1738: }
1739: if (*cp) {
1740: if (inLine) {
1741: /*
1742: * So long as it's not a blank line and we're actually
1743: * in a dependency spec, add the command to the list of
1.11 millert 1744: * commands of all targets in the dependency spec
1.1 deraadt 1745: */
1.45 espie 1746: Lst_ForEach(&targets, ParseAddCmd, cp);
1.20 espie 1747: #ifdef CLEANUP
1.43 espie 1748: Lst_AtEnd(&targCmds, line);
1.20 espie 1749: #endif
1.1 deraadt 1750: continue;
1751: } else {
1752: Parse_Error (PARSE_FATAL,
1.10 briggs 1753: "Unassociated shell command \"%s\"",
1.1 deraadt 1754: cp);
1755: }
1756: }
1757: #ifdef SYSVINCLUDE
1.11 millert 1758: } else if (strncmp (line, "include", 7) == 0 &&
1.6 tholo 1759: isspace((unsigned char) line[7]) &&
1.1 deraadt 1760: strchr(line, ':') == NULL) {
1761: /*
1762: * It's an S3/S5-style "include".
1763: */
1764: ParseTraditionalInclude (line + 7);
1765: goto nextLine;
1766: #endif
1767: } else if (Parse_IsVar (line)) {
1768: ParseFinishLine();
1769: Parse_DoVar (line, VAR_GLOBAL);
1770: } else {
1771: /*
1772: * We now know it's a dependency line so it needs to have all
1773: * variables expanded before being parsed. Tell the variable
1774: * module to complain if some variable is undefined...
1775: * To make life easier on novices, if the line is indented we
1776: * first make sure the line has a dependency operator in it.
1777: * If it doesn't have an operator and we're in a dependency
1778: * line's script, we assume it's actually a shell command
1779: * and add it to the current list of targets.
1780: */
1781: #ifndef POSIX
1782: Boolean nonSpace = FALSE;
1783: #endif
1.11 millert 1784:
1.1 deraadt 1785: cp = line;
1786: if (isspace((unsigned char) line[0])) {
1787: while ((*cp != '\0') && isspace((unsigned char) *cp)) {
1788: cp++;
1789: }
1790: if (*cp == '\0') {
1791: goto nextLine;
1792: }
1793: #ifndef POSIX
1794: while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
1795: nonSpace = TRUE;
1796: cp++;
1797: }
1798: #endif
1799: }
1.11 millert 1800:
1.1 deraadt 1801: #ifndef POSIX
1802: if (*cp == '\0') {
1803: if (inLine) {
1804: Parse_Error (PARSE_WARNING,
1805: "Shell command needs a leading tab");
1806: goto shellCommand;
1807: } else if (nonSpace) {
1808: Parse_Error (PARSE_FATAL, "Missing operator");
1809: }
1810: } else {
1811: #endif
1812: ParseFinishLine();
1813:
1.48 espie 1814: cp = Var_Subst(line, NULL, TRUE);
1.1 deraadt 1815: free (line);
1816: line = cp;
1.11 millert 1817:
1.45 espie 1818: /* Need a new list for the target nodes */
1819: Lst_Destroy(&targets, NOFREE);
1820: Lst_Init(&targets);
1.1 deraadt 1821: inLine = TRUE;
1.11 millert 1822:
1.1 deraadt 1823: ParseDoDependency (line);
1824: #ifndef POSIX
1825: }
1826: #endif
1827: }
1828:
1829: nextLine:
1830:
1831: free (line);
1832: }
1.50 espie 1833: } while (Parse_NextFile());
1.1 deraadt 1834:
1.50 espie 1835: /* Make sure conditionals are clean */
1.1 deraadt 1836: Cond_End();
1837:
1.50 espie 1838: Finish_Errors();
1.1 deraadt 1839: }
1840:
1841: /*-
1842: *---------------------------------------------------------------------
1843: * Parse_Init --
1844: * initialize the parsing module
1845: *
1846: * Side Effects:
1847: * the parseIncPath list is initialized...
1848: *---------------------------------------------------------------------
1849: */
1850: void
1.43 espie 1851: Parse_Init()
1.1 deraadt 1852: {
1.33 espie 1853: mainNode = NULL;
1.43 espie 1854: Lst_Init(&parseIncPath);
1855: Lst_Init(&sysIncPath);
1.45 espie 1856: Lst_Init(&targets);
1.20 espie 1857: #ifdef CLEANUP
1.50 espie 1858: LowParse_Init();
1.43 espie 1859: Lst_Init(&targCmds);
1860: Lst_Init(&fileNames);
1.20 espie 1861: #endif
1.1 deraadt 1862: }
1863:
1864: void
1865: Parse_End()
1866: {
1.20 espie 1867: #ifdef CLEANUP
1.43 espie 1868: Lst_Destroy(&targCmds, (SimpleProc)free);
1869: Lst_Destroy(&fileNames, (void (*) __P((ClientData))) free);
1.45 espie 1870: Lst_Delete(&targets, NOFREE);
1.43 espie 1871: Lst_Destroy(&sysIncPath, Dir_Destroy);
1872: Lst_Destroy(&parseIncPath, Dir_Destroy);
1.50 espie 1873: LowParse_End();
1.20 espie 1874: #endif
1.1 deraadt 1875: }
1.11 millert 1876:
1.1 deraadt 1877:
1878: /*-
1879: *-----------------------------------------------------------------------
1880: * Parse_MainName --
1881: * Return a Lst of the main target to create for main()'s sake. If
1882: * no such target exists, we Punt with an obnoxious error message.
1883: *
1884: * Side Effects:
1.44 espie 1885: * Add the node to create to the list.
1.1 deraadt 1886: *
1887: *-----------------------------------------------------------------------
1888: */
1.44 espie 1889: void
1890: Parse_MainName(listmain)
1891: Lst listmain; /* result list */
1.1 deraadt 1892: {
1893:
1.44 espie 1894: if (mainNode == NULL)
1.8 deraadt 1895: Punt ("no target to make.");
1.1 deraadt 1896: /*NOTREACHED*/
1.44 espie 1897: else if (mainNode->type & OP_DOUBLEDEP) {
1.37 espie 1898: Lst_AtEnd(listmain, mainNode);
1.45 espie 1899: Lst_Concat(listmain, &mainNode->cohorts);
1.1 deraadt 1900: }
1901: else
1.37 espie 1902: Lst_AtEnd(listmain, mainNode);
1.1 deraadt 1903: }