parse.c revision 92921
167754Smsmith/* 267754Smsmith * Copyright (c) 1988, 1989, 1990, 1993 367754Smsmith * The Regents of the University of California. All rights reserved. 4102550Siwasaki * Copyright (c) 1989 by Berkeley Softworks 567754Smsmith * All rights reserved. 667754Smsmith * 767754Smsmith * This code is derived from software contributed to Berkeley by 867754Smsmith * Adam de Boor. 967754Smsmith * 1067754Smsmith * Redistribution and use in source and binary forms, with or without 1167754Smsmith * modification, are permitted provided that the following conditions 1291116Smsmith * are met: 1370243Smsmith * 1. Redistributions of source code must retain the above copyright 1467754Smsmith * notice, this list of conditions and the following disclaimer. 1567754Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1667754Smsmith * notice, this list of conditions and the following disclaimer in the 1767754Smsmith * documentation and/or other materials provided with the distribution. 1867754Smsmith * 3. All advertising materials mentioning features or use of this software 1967754Smsmith * must display the following acknowledgement: 2067754Smsmith * This product includes software developed by the University of 2167754Smsmith * California, Berkeley and its contributors. 2267754Smsmith * 4. Neither the name of the University nor the names of its contributors 2367754Smsmith * may be used to endorse or promote products derived from this software 2467754Smsmith * without specific prior written permission. 2567754Smsmith * 2667754Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2767754Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2867754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2967754Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3067754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3167754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3267754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3367754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3467754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3567754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3667754Smsmith * SUCH DAMAGE. 3767754Smsmith * 3867754Smsmith * @(#)parse.c 8.3 (Berkeley) 3/19/94 3967754Smsmith */ 4067754Smsmith 4167754Smsmith#ifndef lint 4267754Smsmith#include <sys/cdefs.h> 4367754Smsmith__RCSID("$FreeBSD: head/usr.bin/make/parse.c 92921 2002-03-22 01:33:25Z imp $"); 4467754Smsmith#endif /* not lint */ 4567754Smsmith 4667754Smsmith/*- 4767754Smsmith * parse.c -- 4867754Smsmith * Functions to parse a makefile. 4967754Smsmith * 5067754Smsmith * One function, Parse_Init, must be called before any functions 5167754Smsmith * in this module are used. After that, the function Parse_File is the 5267754Smsmith * main entry point and controls most of the other functions in this 5367754Smsmith * module. 5467754Smsmith * 5567754Smsmith * Most important structures are kept in Lsts. Directories for 5667754Smsmith * the #include "..." function are kept in the 'parseIncPath' Lst, while 5767754Smsmith * those for the #include <...> are kept in the 'sysIncPath' Lst. The 5867754Smsmith * targets currently being defined are kept in the 'targets' Lst. 5967754Smsmith * 6067754Smsmith * The variables 'fname' and 'lineno' are used to track the name 6167754Smsmith * of the current file and the line number in that file so that error 6267754Smsmith * messages can be more meaningful. 6367754Smsmith * 6467754Smsmith * Interface: 6567754Smsmith * Parse_Init Initialization function which must be 6667754Smsmith * called before anything else in this module 6767754Smsmith * is used. 6867754Smsmith * 6967754Smsmith * Parse_End Cleanup the module 7067754Smsmith * 7167754Smsmith * Parse_File Function used to parse a makefile. It must 7267754Smsmith * be given the name of the file, which should 7367754Smsmith * already have been opened, and a function 7467754Smsmith * to call to read a character from the file. 7567754Smsmith * 7667754Smsmith * Parse_IsVar Returns TRUE if the given line is a 7767754Smsmith * variable assignment. Used by MainParseArgs 7867754Smsmith * to determine if an argument is a target 7967754Smsmith * or a variable assignment. Used internally 8067754Smsmith * for pretty much the same thing... 8167754Smsmith * 8267754Smsmith * Parse_Error Function called when an error occurs in 8367754Smsmith * parsing. Used by the variable and 8467754Smsmith * conditional modules. 8567754Smsmith * Parse_MainName Returns a Lst of the main target to create. 8667754Smsmith */ 8767754Smsmith 8867754Smsmith#ifdef __STDC__ 8967754Smsmith#include <stdarg.h> 9067754Smsmith#else 9167754Smsmith#include <varargs.h> 9267754Smsmith#endif 9367754Smsmith#include <ctype.h> 9467754Smsmith#include <err.h> 9567754Smsmith#include <stdio.h> 9667754Smsmith#include "make.h" 9767754Smsmith#include "hash.h" 9867754Smsmith#include "dir.h" 9967754Smsmith#include "job.h" 10067754Smsmith#include "buf.h" 10167754Smsmith#include "pathnames.h" 10267754Smsmith 10367754Smsmith/* 10467754Smsmith * These values are returned by ParseEOF to tell Parse_File whether to 10567754Smsmith * CONTINUE parsing, i.e. it had only reached the end of an include file, 10667754Smsmith * or if it's DONE. 10767754Smsmith */ 10867754Smsmith#define CONTINUE 1 10967754Smsmith#define DONE 0 11067754Smsmithstatic Lst targets; /* targets we're working on */ 11167754Smsmithstatic Lst targCmds; /* command lines for targets */ 11267754Smsmithstatic Boolean inLine; /* true if currently in a dependency 11367754Smsmith * line or its commands */ 11467754Smsmithtypedef struct { 11567754Smsmith char *str; 11667754Smsmith char *ptr; 11767754Smsmith} PTR; 11867754Smsmith 11967754Smsmithstatic char *fname; /* name of current file (for errors) */ 12067754Smsmithstatic int lineno; /* line number in current file */ 12167754Smsmithstatic FILE *curFILE = NULL; /* current makefile */ 122102550Siwasaki 12367754Smsmithstatic PTR *curPTR = NULL; /* current makefile */ 124102550Siwasaki 12591116Smsmithstatic int fatals = 0; 12667754Smsmith 12767754Smsmithstatic GNode *mainNode; /* The main target to create. This is the 12867754Smsmith * first target on the first dependency 12967754Smsmith * line in the first makefile */ 13099679Siwasaki/* 13167754Smsmith * Definitions for handling #include specifications 13267754Smsmith */ 13367754Smsmithtypedef struct IFile { 13467754Smsmith char *fname; /* name of previous file */ 13567754Smsmith int lineno; /* saved line number */ 13667754Smsmith FILE * F; /* the open stream */ 13767754Smsmith PTR * p; /* the char pointer */ 13883174Smsmith} IFile; 13967754Smsmith 14067754Smsmithstatic Lst includes; /* stack of IFiles generated by 14167754Smsmith * #includes */ 14299679SiwasakiLst parseIncPath; /* list of directories for "..." includes */ 14399679SiwasakiLst sysIncPath; /* list of directories for <...> includes */ 14499679Siwasaki 14599679Siwasaki/*- 14699679Siwasaki * specType contains the SPECial TYPE of the current target. It is 14799679Siwasaki * Not if the target is unspecial. If it *is* special, however, the children 14899679Siwasaki * are linked as children of the parent but not vice versa. This variable is 14967754Smsmith * set in ParseDoDependency 15067754Smsmith */ 15167754Smsmithtypedef enum { 15267754Smsmith Begin, /* .BEGIN */ 15367754Smsmith Default, /* .DEFAULT */ 15467754Smsmith End, /* .END */ 15567754Smsmith Ignore, /* .IGNORE */ 15667754Smsmith Includes, /* .INCLUDES */ 15767754Smsmith Interrupt, /* .INTERRUPT */ 15867754Smsmith Libs, /* .LIBS */ 15967754Smsmith MFlags, /* .MFLAGS or .MAKEFLAGS */ 16091116Smsmith Main, /* .MAIN and we don't have anything user-specified to 16191116Smsmith * make */ 16267754Smsmith NoExport, /* .NOEXPORT */ 16367754Smsmith Not, /* Not special */ 16467754Smsmith NotParallel, /* .NOTPARALELL */ 16567754Smsmith Null, /* .NULL */ 16667754Smsmith Order, /* .ORDER */ 16767754Smsmith Parallel, /* .PARALLEL */ 16867754Smsmith ExPath, /* .PATH */ 16967754Smsmith Phony, /* .PHONY */ 17067754Smsmith#ifdef POSIX 17167754Smsmith Posix, /* .POSIX */ 17267754Smsmith#endif 17367754Smsmith Precious, /* .PRECIOUS */ 17467754Smsmith ExShell, /* .SHELL */ 17567754Smsmith Silent, /* .SILENT */ 17667754Smsmith SingleShell, /* .SINGLESHELL */ 17767754Smsmith Suffixes, /* .SUFFIXES */ 17867754Smsmith Wait, /* .WAIT */ 17967754Smsmith Attribute /* Generic attribute */ 18083174Smsmith} ParseSpecial; 18167754Smsmith 18299679Siwasakistatic ParseSpecial specType; 18367754Smsmithstatic int waiting; 18467754Smsmith 18567754Smsmith/* 18667754Smsmith * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 18767754Smsmith * seen, then set to each successive source on the line. 18899679Siwasaki */ 18967754Smsmithstatic GNode *predecessor; 19067754Smsmith 19167754Smsmith/* 19267754Smsmith * The parseKeywords table is searched using binary search when deciding 19399679Siwasaki * if a target or source is special. The 'spec' field is the ParseSpecial 19467754Smsmith * type of the keyword ("Not" if the keyword isn't special as a target) while 19567754Smsmith * the 'op' field is the operator to apply to the list of targets if the 19691116Smsmith * keyword is used as a source ("0" if the keyword isn't special as a source) 19767754Smsmith */ 19867754Smsmithstatic struct { 19967754Smsmith char *name; /* Name of keyword */ 20067754Smsmith ParseSpecial spec; /* Type when used as a target */ 20167754Smsmith int op; /* Operator when used as a source */ 20267754Smsmith} parseKeywords[] = { 20367754Smsmith{ ".BEGIN", Begin, 0 }, 20467754Smsmith{ ".DEFAULT", Default, 0 }, 20567754Smsmith{ ".END", End, 0 }, 20667754Smsmith{ ".EXEC", Attribute, OP_EXEC }, 20767754Smsmith{ ".IGNORE", Ignore, OP_IGNORE }, 20887031Smsmith{ ".INCLUDES", Includes, 0 }, 20991116Smsmith{ ".INTERRUPT", Interrupt, 0 }, 21087031Smsmith{ ".INVISIBLE", Attribute, OP_INVISIBLE }, 21191116Smsmith{ ".JOIN", Attribute, OP_JOIN }, 21287031Smsmith{ ".LIBS", Libs, 0 }, 21387031Smsmith{ ".MAIN", Main, 0 }, 21487031Smsmith{ ".MAKE", Attribute, OP_MAKE }, 21567754Smsmith{ ".MAKEFLAGS", MFlags, 0 }, 21691116Smsmith{ ".MFLAGS", MFlags, 0 }, 21767754Smsmith{ ".NOTMAIN", Attribute, OP_NOTMAIN }, 21867754Smsmith{ ".NOTPARALLEL", NotParallel, 0 }, 21967754Smsmith{ ".NO_PARALLEL", NotParallel, 0 }, 22067754Smsmith{ ".NULL", Null, 0 }, 22167754Smsmith{ ".OPTIONAL", Attribute, OP_OPTIONAL }, 22267754Smsmith{ ".ORDER", Order, 0 }, 22367754Smsmith{ ".PARALLEL", Parallel, 0 }, 22467754Smsmith{ ".PATH", ExPath, 0 }, 22567754Smsmith{ ".PHONY", Phony, OP_PHONY }, 22667754Smsmith#ifdef POSIX 22767754Smsmith{ ".POSIX", Posix, 0 }, 22867754Smsmith#endif 22967754Smsmith{ ".PRECIOUS", Precious, OP_PRECIOUS }, 23067754Smsmith{ ".RECURSIVE", Attribute, OP_MAKE }, 23167754Smsmith{ ".SHELL", ExShell, 0 }, 23267754Smsmith{ ".SILENT", Silent, OP_SILENT }, 23367754Smsmith{ ".SINGLESHELL", SingleShell, 0 }, 23467754Smsmith{ ".SUFFIXES", Suffixes, 0 }, 23567754Smsmith{ ".USE", Attribute, OP_USE }, 23699679Siwasaki{ ".WAIT", Wait, 0 }, 23799679Siwasaki}; 23899679Siwasaki 23967754Smsmithstatic int ParseFindKeyword(char *); 24067754Smsmithstatic int ParseLinkSrc(void *, void *); 24167754Smsmithstatic int ParseDoOp(void *, void *); 24267754Smsmithstatic int ParseAddDep(void *, void *); 24367754Smsmithstatic void ParseDoSrc(int, char *, Lst); 24467754Smsmithstatic int ParseFindMain(void *, void *); 24567754Smsmithstatic int ParseAddDir(void *, void *); 24667754Smsmithstatic int ParseClearPath(void *, void *); 24767754Smsmithstatic void ParseDoDependency(char *); 24867754Smsmithstatic int ParseAddCmd(void *, void *); 24967754Smsmithstatic int ParseReadc(void); 25067754Smsmithstatic void ParseUnreadc(int); 25167754Smsmithstatic void ParseHasCommands(void *); 25267754Smsmithstatic void ParseDoInclude(char *); 25367754Smsmithstatic void ParseDoError(char *); 25467754Smsmith#ifdef SYSVINCLUDE 25567754Smsmithstatic void ParseTraditionalInclude(char *); 25667754Smsmith#endif 25767754Smsmithstatic int ParseEOF(int); 25867754Smsmithstatic char *ParseReadLine(void); 25967754Smsmithstatic char *ParseSkipLine(int); 26067754Smsmithstatic void ParseFinishLine(void); 26167754Smsmith 26267754Smsmith/*- 26367754Smsmith *---------------------------------------------------------------------- 26467754Smsmith * ParseFindKeyword -- 26567754Smsmith * Look in the table of keywords for one matching the given string. 26667754Smsmith * 26767754Smsmith * Results: 26883174Smsmith * The index of the keyword, or -1 if it isn't there. 26967754Smsmith * 27067754Smsmith * Side Effects: 27187031Smsmith * None 27267754Smsmith *---------------------------------------------------------------------- 27367754Smsmith */ 27467754Smsmithstatic int 27567754SmsmithParseFindKeyword (str) 27683174Smsmith char *str; /* String to find */ 27767754Smsmith{ 27867754Smsmith register int start, 27967754Smsmith end, 28067754Smsmith cur; 28167754Smsmith register int diff; 28267754Smsmith 28367754Smsmith start = 0; 28467754Smsmith end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1; 28567754Smsmith 28667754Smsmith do { 28767754Smsmith cur = start + ((end - start) / 2); 28867754Smsmith diff = strcmp (str, parseKeywords[cur].name); 28967754Smsmith 29067754Smsmith if (diff == 0) { 29167754Smsmith return (cur); 29267754Smsmith } else if (diff < 0) { 29367754Smsmith end = cur - 1; 29467754Smsmith } else { 29567754Smsmith start = cur + 1; 29667754Smsmith } 29767754Smsmith } while (start <= end); 29867754Smsmith return (-1); 29967754Smsmith} 30067754Smsmith 30167754Smsmith/*- 30267754Smsmith * Parse_Error -- 30367754Smsmith * Error message abort function for parsing. Prints out the context 30467754Smsmith * of the error (line number and file) as well as the message with 30567754Smsmith * two optional arguments. 30667754Smsmith * 30767754Smsmith * Results: 30867754Smsmith * None 30967754Smsmith * 31067754Smsmith * Side Effects: 31167754Smsmith * "fatals" is incremented if the level is PARSE_FATAL. 31267754Smsmith */ 31367754Smsmith/* VARARGS */ 31467754Smsmithvoid 31567754Smsmith#ifdef __STDC__ 31667754SmsmithParse_Error(int type, char *fmt, ...) 31767754Smsmith#else 31867754SmsmithParse_Error(va_alist) 31967754Smsmith va_dcl 32067754Smsmith#endif 32167754Smsmith{ 32267754Smsmith va_list ap; 32367754Smsmith#ifdef __STDC__ 32467754Smsmith va_start(ap, fmt); 32567754Smsmith#else 32699679Siwasaki int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ 32767754Smsmith char *fmt; 32867754Smsmith 32967754Smsmith va_start(ap); 33067754Smsmith type = va_arg(ap, int); 33167754Smsmith fmt = va_arg(ap, char *); 33267754Smsmith#endif 33383174Smsmith 33483174Smsmith (void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno); 33567754Smsmith if (type == PARSE_WARNING) 33667754Smsmith (void)fprintf(stderr, "warning: "); 33783174Smsmith (void)vfprintf(stderr, fmt, ap); 33867754Smsmith va_end(ap); 33967754Smsmith (void)fprintf(stderr, "\n"); 34067754Smsmith (void)fflush(stderr); 34167754Smsmith if (type == PARSE_FATAL) 34267754Smsmith fatals += 1; 34399679Siwasaki} 34467754Smsmith 34567754Smsmith/*- 34667754Smsmith *--------------------------------------------------------------------- 34767754Smsmith * ParseLinkSrc -- 34867754Smsmith * Link the parent node to its new child. Used in a Lst_ForEach by 34967754Smsmith * ParseDoDependency. If the specType isn't 'Not', the parent 35067754Smsmith * isn't linked as a parent of the child. 35167754Smsmith * 35267754Smsmith * Results: 35367754Smsmith * Always = 0 35467754Smsmith * 35567754Smsmith * Side Effects: 35667754Smsmith * New elements are added to the parents list of cgn and the 35767754Smsmith * children list of cgn. the unmade field of pgn is updated 35867754Smsmith * to reflect the additional child. 35967754Smsmith *--------------------------------------------------------------------- 36067754Smsmith */ 36167754Smsmithstatic int 36267754SmsmithParseLinkSrc (pgnp, cgnp) 36367754Smsmith void * pgnp; /* The parent node */ 36467754Smsmith void * cgnp; /* The child node */ 36567754Smsmith{ 36691116Smsmith GNode *pgn = (GNode *) pgnp; 36791116Smsmith GNode *cgn = (GNode *) cgnp; 36882367Smsmith if (Lst_Member (pgn->children, (void *)cgn) == NULL) { 36991116Smsmith (void)Lst_AtEnd (pgn->children, (void *)cgn); 37067754Smsmith if (specType == Not) { 37167754Smsmith (void)Lst_AtEnd (cgn->parents, (void *)pgn); 37267754Smsmith } 37367754Smsmith pgn->unmade += 1; 37467754Smsmith } 37567754Smsmith return (0); 37667754Smsmith} 37767754Smsmith 37867754Smsmith/*- 37967754Smsmith *--------------------------------------------------------------------- 38067754Smsmith * ParseDoOp -- 38167754Smsmith * Apply the parsed operator to the given target node. Used in a 38267754Smsmith * Lst_ForEach call by ParseDoDependency once all targets have 38391116Smsmith * been found and their operator parsed. If the previous and new 38467754Smsmith * operators are incompatible, a major error is taken. 38567754Smsmith * 38667754Smsmith * Results: 38767754Smsmith * Always 0 38867754Smsmith * 38967754Smsmith * Side Effects: 39067754Smsmith * The type field of the node is altered to reflect any new bits in 39167754Smsmith * the op. 39267754Smsmith *--------------------------------------------------------------------- 39367754Smsmith */ 39499679Siwasakistatic int 39580062SmsmithParseDoOp (gnp, opp) 39677424Smsmith void * gnp; /* The node to which the operator is to be 39780062Smsmith * applied */ 39867754Smsmith void * opp; /* The operator to apply */ 39967754Smsmith{ 40099679Siwasaki GNode *gn = (GNode *) gnp; 40167754Smsmith int op = *(int *) opp; 40267754Smsmith /* 40367754Smsmith * If the dependency mask of the operator and the node don't match and 40467754Smsmith * the node has actually had an operator applied to it before, and 40569746Smsmith * the operator actually has some dependency information in it, complain. 40667754Smsmith */ 40767754Smsmith if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 40867754Smsmith !OP_NOP(gn->type) && !OP_NOP(op)) 40999679Siwasaki { 41067754Smsmith Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name); 41183174Smsmith return (1); 41283174Smsmith } 41367754Smsmith 41467754Smsmith if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 41567754Smsmith /* 41667754Smsmith * If the node was the object of a :: operator, we need to create a 41767754Smsmith * new instance of it for the children and commands on this dependency 41867754Smsmith * line. The new instance is placed on the 'cohorts' list of the 41977424Smsmith * initial one (note the initial one is not on its own cohorts list) 42067754Smsmith * and the new instance is linked to all parents of the initial 42167754Smsmith * instance. 42267754Smsmith */ 42367754Smsmith register GNode *cohort; 42467754Smsmith LstNode ln; 42567754Smsmith 42683174Smsmith cohort = Targ_NewGN(gn->name); 42767754Smsmith /* 42867754Smsmith * Duplicate links to parents so graph traversal is simple. Perhaps 42999679Siwasaki * some type bits should be duplicated? 43067754Smsmith * 43182367Smsmith * Make the cohort invisible as well to avoid duplicating it into 43282367Smsmith * other variables. True, parents of this target won't tend to do 43367754Smsmith * anything with their local variables, but better safe than 43482367Smsmith * sorry. 43582367Smsmith */ 43682367Smsmith Lst_ForEach(gn->parents, ParseLinkSrc, (void *)cohort); 43767754Smsmith cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 43882367Smsmith (void)Lst_AtEnd(gn->cohorts, (void *)cohort); 43982367Smsmith 44083174Smsmith /* 44182367Smsmith * Replace the node in the targets list with the new copy 44283174Smsmith */ 44382367Smsmith ln = Lst_Member(targets, (void *)gn); 44482367Smsmith Lst_Replace(ln, (void *)cohort); 44582367Smsmith gn = cohort; 44683174Smsmith } 44782367Smsmith /* 44883174Smsmith * We don't want to nuke any previous flags (whatever they were) so we 44982367Smsmith * just OR the new operator into the old 45083174Smsmith */ 45182367Smsmith gn->type |= op; 45282367Smsmith 45383174Smsmith return (0); 45483174Smsmith} 45582367Smsmith 45682367Smsmith/*- 45782367Smsmith *--------------------------------------------------------------------- 45882367Smsmith * ParseAddDep -- 45991116Smsmith * Check if the pair of GNodes given needs to be synchronized. 46082367Smsmith * This has to be when two nodes are on different sides of a 46182367Smsmith * .WAIT directive. 46282367Smsmith * 46391116Smsmith * Results: 46482367Smsmith * Returns 1 if the two targets need to be ordered, 0 otherwise. 46582367Smsmith * If it returns 1, the search can stop 46683174Smsmith * 46782367Smsmith * Side Effects: 46882367Smsmith * A dependency can be added between the two nodes. 46982367Smsmith * 47082367Smsmith *--------------------------------------------------------------------- 47182367Smsmith */ 47282367Smsmithstatic int 47367754SmsmithParseAddDep(pp, sp) 47467754Smsmith void * pp; 47599679Siwasaki void * sp; 47667754Smsmith{ 47767754Smsmith GNode *p = (GNode *) pp; 47867754Smsmith GNode *s = (GNode *) sp; 47967754Smsmith 48067754Smsmith if (p->order < s->order) { 48167754Smsmith /* 48267754Smsmith * XXX: This can cause loops, and loops can cause unmade targets, 48367754Smsmith * but checking is tedious, and the debugging output can show the 48467754Smsmith * problem 48567754Smsmith */ 48677424Smsmith (void)Lst_AtEnd(p->successors, (void *)s); 48767754Smsmith (void)Lst_AtEnd(s->preds, (void *)p); 48867754Smsmith return 0; 48967754Smsmith } 49067754Smsmith else 49199679Siwasaki return 1; 49267754Smsmith} 49367754Smsmith 49467754Smsmith 49567754Smsmith/*- 49671867Smsmith *--------------------------------------------------------------------- 49767754Smsmith * ParseDoSrc -- 49867754Smsmith * Given the name of a source, figure out if it is an attribute 49967754Smsmith * and apply it to the targets if it is. Else decide if there is 50077424Smsmith * some attribute which should be applied *to* the source because 50167754Smsmith * of some special target and apply it if so. Otherwise, make the 50267754Smsmith * source be a child of the targets in the list 'targets' 50367754Smsmith * 50467754Smsmith * Results: 50567754Smsmith * None 50667754Smsmith * 50767754Smsmith * Side Effects: 50867754Smsmith * Operator bits may be added to the list of targets or to the source. 50977424Smsmith * The targets may have a new source added to their lists of children. 51067754Smsmith *--------------------------------------------------------------------- 51167754Smsmith */ 51267754Smsmithstatic void 51367754SmsmithParseDoSrc (tOp, src, allsrc) 51467754Smsmith int tOp; /* operator (if any) from special targets */ 51567754Smsmith char *src; /* name of the source to handle */ 51687031Smsmith Lst allsrc; /* List of all sources to wait for */ 51767754Smsmith{ 51867754Smsmith GNode *gn = NULL; 51967754Smsmith 52099679Siwasaki if (*src == '.' && isupper (src[1])) { 52199679Siwasaki int keywd = ParseFindKeyword(src); 52299679Siwasaki if (keywd != -1) { 52367754Smsmith int op = parseKeywords[keywd].op; 52467754Smsmith if (op != 0) { 52567754Smsmith Lst_ForEach (targets, ParseDoOp, (void *)&op); 52667754Smsmith return; 52767754Smsmith } 52883174Smsmith if (parseKeywords[keywd].spec == Wait) { 52999679Siwasaki waiting++; 530102550Siwasaki return; 53183174Smsmith } 53299679Siwasaki } 53383174Smsmith } 53483174Smsmith 53583174Smsmith switch (specType) { 53683174Smsmith case Main: 53783174Smsmith /* 53883174Smsmith * If we have noted the existence of a .MAIN, it means we need 53999679Siwasaki * to add the sources of said target to the list of things 54083174Smsmith * to create. The string 'src' is likely to be free, so we 54199679Siwasaki * must make a new copy of it. Note that this will only be 54299679Siwasaki * invoked if the user didn't specify a target on the command 54399679Siwasaki * line. This is to allow #ifmake's to succeed, or something... 54467754Smsmith */ 54567754Smsmith (void) Lst_AtEnd (create, (void *)estrdup(src)); 54667754Smsmith /* 54767754Smsmith * Add the name to the .TARGETS variable as well, so the user cna 54867754Smsmith * employ that, if desired. 54967754Smsmith */ 55067754Smsmith Var_Append(".TARGETS", src, VAR_GLOBAL); 551102550Siwasaki return; 552 553 case Order: 554 /* 555 * Create proper predecessor/successor links between the previous 556 * source and the current one. 557 */ 558 gn = Targ_FindNode(src, TARG_CREATE); 559 if (predecessor != NULL) { 560 (void)Lst_AtEnd(predecessor->successors, (void *)gn); 561 (void)Lst_AtEnd(gn->preds, (void *)predecessor); 562 } 563 /* 564 * The current source now becomes the predecessor for the next one. 565 */ 566 predecessor = gn; 567 break; 568 569 default: 570 /* 571 * If the source is not an attribute, we need to find/create 572 * a node for it. After that we can apply any operator to it 573 * from a special target or link it to its parents, as 574 * appropriate. 575 * 576 * In the case of a source that was the object of a :: operator, 577 * the attribute is applied to all of its instances (as kept in 578 * the 'cohorts' list of the node) or all the cohorts are linked 579 * to all the targets. 580 */ 581 gn = Targ_FindNode (src, TARG_CREATE); 582 if (tOp) { 583 gn->type |= tOp; 584 } else { 585 Lst_ForEach (targets, ParseLinkSrc, (void *)gn); 586 } 587 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 588 register GNode *cohort; 589 register LstNode ln; 590 591 for (ln=Lst_First(gn->cohorts); ln != NULL; ln = Lst_Succ(ln)){ 592 cohort = (GNode *)Lst_Datum(ln); 593 if (tOp) { 594 cohort->type |= tOp; 595 } else { 596 Lst_ForEach(targets, ParseLinkSrc, (void *)cohort); 597 } 598 } 599 } 600 break; 601 } 602 603 gn->order = waiting; 604 (void)Lst_AtEnd(allsrc, (void *)gn); 605 if (waiting) { 606 Lst_ForEach(allsrc, ParseAddDep, (void *)gn); 607 } 608} 609 610/*- 611 *----------------------------------------------------------------------- 612 * ParseFindMain -- 613 * Find a real target in the list and set it to be the main one. 614 * Called by ParseDoDependency when a main target hasn't been found 615 * yet. 616 * 617 * Results: 618 * 0 if main not found yet, 1 if it is. 619 * 620 * Side Effects: 621 * mainNode is changed and Targ_SetMain is called. 622 * 623 *----------------------------------------------------------------------- 624 */ 625static int 626ParseFindMain(gnp, dummy) 627 void * gnp; /* Node to examine */ 628 void * dummy; 629{ 630 GNode *gn = (GNode *) gnp; 631 if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) { 632 mainNode = gn; 633 Targ_SetMain(gn); 634 return (dummy ? 1 : 1); 635 } else { 636 return (dummy ? 0 : 0); 637 } 638} 639 640/*- 641 *----------------------------------------------------------------------- 642 * ParseAddDir -- 643 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 644 * 645 * Results: 646 * === 0 647 * 648 * Side Effects: 649 * See Dir_AddDir. 650 * 651 *----------------------------------------------------------------------- 652 */ 653static int 654ParseAddDir(path, name) 655 void * path; 656 void * name; 657{ 658 Dir_AddDir((Lst) path, (char *) name); 659 return(0); 660} 661 662/*- 663 *----------------------------------------------------------------------- 664 * ParseClearPath -- 665 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going 666 * 667 * Results: 668 * === 0 669 * 670 * Side Effects: 671 * See Dir_ClearPath 672 * 673 *----------------------------------------------------------------------- 674 */ 675static int 676ParseClearPath(path, dummy) 677 void * path; 678 void * dummy; 679{ 680 Dir_ClearPath((Lst) path); 681 return(dummy ? 0 : 0); 682} 683 684/*- 685 *--------------------------------------------------------------------- 686 * ParseDoDependency -- 687 * Parse the dependency line in line. 688 * 689 * Results: 690 * None 691 * 692 * Side Effects: 693 * The nodes of the sources are linked as children to the nodes of the 694 * targets. Some nodes may be created. 695 * 696 * We parse a dependency line by first extracting words from the line and 697 * finding nodes in the list of all targets with that name. This is done 698 * until a character is encountered which is an operator character. Currently 699 * these are only ! and :. At this point the operator is parsed and the 700 * pointer into the line advanced until the first source is encountered. 701 * The parsed operator is applied to each node in the 'targets' list, 702 * which is where the nodes found for the targets are kept, by means of 703 * the ParseDoOp function. 704 * The sources are read in much the same way as the targets were except 705 * that now they are expanded using the wildcarding scheme of the C-Shell 706 * and all instances of the resulting words in the list of all targets 707 * are found. Each of the resulting nodes is then linked to each of the 708 * targets as one of its children. 709 * Certain targets are handled specially. These are the ones detailed 710 * by the specType variable. 711 * The storing of transformation rules is also taken care of here. 712 * A target is recognized as a transformation rule by calling 713 * Suff_IsTransform. If it is a transformation rule, its node is gotten 714 * from the suffix module via Suff_AddTransform rather than the standard 715 * Targ_FindNode in the target module. 716 *--------------------------------------------------------------------- 717 */ 718static void 719ParseDoDependency (line) 720 char *line; /* the line to parse */ 721{ 722 char *cp; /* our current position */ 723 GNode *gn; /* a general purpose temporary node */ 724 int op; /* the operator on the line */ 725 char savec; /* a place to save a character */ 726 Lst paths; /* List of search paths to alter when parsing 727 * a list of .PATH targets */ 728 int tOp; /* operator from special target */ 729 Lst sources; /* list of archive source names after 730 * expansion */ 731 Lst curTargs; /* list of target names to be found and added 732 * to the targets list */ 733 Lst curSrcs; /* list of sources in order */ 734 735 tOp = 0; 736 737 specType = Not; 738 waiting = 0; 739 paths = (Lst)NULL; 740 741 curTargs = Lst_Init(FALSE); 742 curSrcs = Lst_Init(FALSE); 743 744 do { 745 for (cp = line; 746 *cp && !isspace (*cp) && 747 (*cp != '!') && (*cp != ':') && (*cp != '('); 748 cp++) 749 { 750 if (*cp == '$') { 751 /* 752 * Must be a dynamic source (would have been expanded 753 * otherwise), so call the Var module to parse the puppy 754 * so we can safely advance beyond it...There should be 755 * no errors in this, as they would have been discovered 756 * in the initial Var_Subst and we wouldn't be here. 757 */ 758 int length; 759 Boolean freeIt; 760 char *result; 761 762 result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt); 763 764 if (freeIt) { 765 free(result); 766 } 767 cp += length-1; 768 } 769 continue; 770 } 771 if (*cp == '(') { 772 /* 773 * Archives must be handled specially to make sure the OP_ARCHV 774 * flag is set in their 'type' field, for one thing, and because 775 * things like "archive(file1.o file2.o file3.o)" are permissible. 776 * Arch_ParseArchive will set 'line' to be the first non-blank 777 * after the archive-spec. It creates/finds nodes for the members 778 * and places them on the given list, returning SUCCESS if all 779 * went well and FAILURE if there was an error in the 780 * specification. On error, line should remain untouched. 781 */ 782 if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) { 783 Parse_Error (PARSE_FATAL, 784 "Error in archive specification: \"%s\"", line); 785 return; 786 } else { 787 continue; 788 } 789 } 790 savec = *cp; 791 792 if (!*cp) { 793 /* 794 * Ending a dependency line without an operator is a Bozo 795 * no-no 796 */ 797 Parse_Error (PARSE_FATAL, "Need an operator"); 798 return; 799 } 800 *cp = '\0'; 801 /* 802 * Have a word in line. See if it's a special target and set 803 * specType to match it. 804 */ 805 if (*line == '.' && isupper (line[1])) { 806 /* 807 * See if the target is a special target that must have it 808 * or its sources handled specially. 809 */ 810 int keywd = ParseFindKeyword(line); 811 if (keywd != -1) { 812 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 813 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 814 return; 815 } 816 817 specType = parseKeywords[keywd].spec; 818 tOp = parseKeywords[keywd].op; 819 820 /* 821 * Certain special targets have special semantics: 822 * .PATH Have to set the dirSearchPath 823 * variable too 824 * .MAIN Its sources are only used if 825 * nothing has been specified to 826 * create. 827 * .DEFAULT Need to create a node to hang 828 * commands on, but we don't want 829 * it in the graph, nor do we want 830 * it to be the Main Target, so we 831 * create it, set OP_NOTMAIN and 832 * add it to the list, setting 833 * DEFAULT to the new node for 834 * later use. We claim the node is 835 * A transformation rule to make 836 * life easier later, when we'll 837 * use Make_HandleUse to actually 838 * apply the .DEFAULT commands. 839 * .PHONY The list of targets 840 * .BEGIN 841 * .END 842 * .INTERRUPT Are not to be considered the 843 * main target. 844 * .NOTPARALLEL Make only one target at a time. 845 * .SINGLESHELL Create a shell for each command. 846 * .ORDER Must set initial predecessor to NULL 847 */ 848 switch (specType) { 849 case ExPath: 850 if (paths == NULL) { 851 paths = Lst_Init(FALSE); 852 } 853 (void)Lst_AtEnd(paths, (void *)dirSearchPath); 854 break; 855 case Main: 856 if (!Lst_IsEmpty(create)) { 857 specType = Not; 858 } 859 break; 860 case Begin: 861 case End: 862 case Interrupt: 863 gn = Targ_FindNode(line, TARG_CREATE); 864 gn->type |= OP_NOTMAIN; 865 (void)Lst_AtEnd(targets, (void *)gn); 866 break; 867 case Default: 868 gn = Targ_NewGN(".DEFAULT"); 869 gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 870 (void)Lst_AtEnd(targets, (void *)gn); 871 DEFAULT = gn; 872 break; 873 case NotParallel: 874 { 875 extern int maxJobs; 876 877 maxJobs = 1; 878 break; 879 } 880 case SingleShell: 881 compatMake = 1; 882 break; 883 case Order: 884 predecessor = NULL; 885 break; 886 default: 887 break; 888 } 889 } else if (strncmp (line, ".PATH", 5) == 0) { 890 /* 891 * .PATH<suffix> has to be handled specially. 892 * Call on the suffix module to give us a path to 893 * modify. 894 */ 895 Lst path; 896 897 specType = ExPath; 898 path = Suff_GetPath (&line[5]); 899 if (path == NULL) { 900 Parse_Error (PARSE_FATAL, 901 "Suffix '%s' not defined (yet)", 902 &line[5]); 903 return; 904 } else { 905 if (paths == (Lst)NULL) { 906 paths = Lst_Init(FALSE); 907 } 908 (void)Lst_AtEnd(paths, (void *)path); 909 } 910 } 911 } 912 913 /* 914 * Have word in line. Get or create its node and stick it at 915 * the end of the targets list 916 */ 917 if ((specType == Not) && (*line != '\0')) { 918 if (Dir_HasWildcards(line)) { 919 /* 920 * Targets are to be sought only in the current directory, 921 * so create an empty path for the thing. Note we need to 922 * use Dir_Destroy in the destruction of the path as the 923 * Dir module could have added a directory to the path... 924 */ 925 Lst emptyPath = Lst_Init(FALSE); 926 927 Dir_Expand(line, emptyPath, curTargs); 928 929 Lst_Destroy(emptyPath, Dir_Destroy); 930 } else { 931 /* 932 * No wildcards, but we want to avoid code duplication, 933 * so create a list with the word on it. 934 */ 935 (void)Lst_AtEnd(curTargs, (void *)line); 936 } 937 938 while(!Lst_IsEmpty(curTargs)) { 939 char *targName = (char *)Lst_DeQueue(curTargs); 940 941 if (!Suff_IsTransform (targName)) { 942 gn = Targ_FindNode (targName, TARG_CREATE); 943 } else { 944 gn = Suff_AddTransform (targName); 945 } 946 947 (void)Lst_AtEnd (targets, (void *)gn); 948 } 949 } else if (specType == ExPath && *line != '.' && *line != '\0') { 950 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 951 } 952 953 *cp = savec; 954 /* 955 * If it is a special type and not .PATH, it's the only target we 956 * allow on this line... 957 */ 958 if (specType != Not && specType != ExPath) { 959 Boolean warn = FALSE; 960 961 while ((*cp != '!') && (*cp != ':') && *cp) { 962 if (*cp != ' ' && *cp != '\t') { 963 warn = TRUE; 964 } 965 cp++; 966 } 967 if (warn) { 968 Parse_Error(PARSE_WARNING, "Extra target ignored"); 969 } 970 } else { 971 while (*cp && isspace (*cp)) { 972 cp++; 973 } 974 } 975 line = cp; 976 } while ((*line != '!') && (*line != ':') && *line); 977 978 /* 979 * Don't need the list of target names anymore... 980 */ 981 Lst_Destroy(curTargs, NOFREE); 982 983 if (!Lst_IsEmpty(targets)) { 984 switch(specType) { 985 default: 986 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 987 break; 988 case Default: 989 case Begin: 990 case End: 991 case Interrupt: 992 /* 993 * These four create nodes on which to hang commands, so 994 * targets shouldn't be empty... 995 */ 996 case Not: 997 /* 998 * Nothing special here -- targets can be empty if it wants. 999 */ 1000 break; 1001 } 1002 } 1003 1004 /* 1005 * Have now parsed all the target names. Must parse the operator next. The 1006 * result is left in op . 1007 */ 1008 if (*cp == '!') { 1009 op = OP_FORCE; 1010 } else if (*cp == ':') { 1011 if (cp[1] == ':') { 1012 op = OP_DOUBLEDEP; 1013 cp++; 1014 } else { 1015 op = OP_DEPENDS; 1016 } 1017 } else { 1018 Parse_Error (PARSE_FATAL, "Missing dependency operator"); 1019 return; 1020 } 1021 1022 cp++; /* Advance beyond operator */ 1023 1024 Lst_ForEach (targets, ParseDoOp, (void *)&op); 1025 1026 /* 1027 * Get to the first source 1028 */ 1029 while (*cp && isspace (*cp)) { 1030 cp++; 1031 } 1032 line = cp; 1033 1034 /* 1035 * Several special targets take different actions if present with no 1036 * sources: 1037 * a .SUFFIXES line with no sources clears out all old suffixes 1038 * a .PRECIOUS line makes all targets precious 1039 * a .IGNORE line ignores errors for all targets 1040 * a .SILENT line creates silence when making all targets 1041 * a .PATH removes all directories from the search path(s). 1042 */ 1043 if (!*line) { 1044 switch (specType) { 1045 case Suffixes: 1046 Suff_ClearSuffixes (); 1047 break; 1048 case Precious: 1049 allPrecious = TRUE; 1050 break; 1051 case Ignore: 1052 ignoreErrors = TRUE; 1053 break; 1054 case Silent: 1055 beSilent = TRUE; 1056 break; 1057 case ExPath: 1058 Lst_ForEach(paths, ParseClearPath, (void *)NULL); 1059 break; 1060#ifdef POSIX 1061 case Posix: 1062 Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 1063 break; 1064#endif 1065 default: 1066 break; 1067 } 1068 } else if (specType == MFlags) { 1069 /* 1070 * Call on functions in main.c to deal with these arguments and 1071 * set the initial character to a null-character so the loop to 1072 * get sources won't get anything 1073 */ 1074 Main_ParseArgLine (line); 1075 *line = '\0'; 1076 } else if (specType == ExShell) { 1077 if (Job_ParseShell (line) != SUCCESS) { 1078 Parse_Error (PARSE_FATAL, "improper shell specification"); 1079 return; 1080 } 1081 *line = '\0'; 1082 } else if ((specType == NotParallel) || (specType == SingleShell)) { 1083 *line = '\0'; 1084 } 1085 1086 /* 1087 * NOW GO FOR THE SOURCES 1088 */ 1089 if ((specType == Suffixes) || (specType == ExPath) || 1090 (specType == Includes) || (specType == Libs) || 1091 (specType == Null)) 1092 { 1093 while (*line) { 1094 /* 1095 * If the target was one that doesn't take files as its sources 1096 * but takes something like suffixes, we take each 1097 * space-separated word on the line as a something and deal 1098 * with it accordingly. 1099 * 1100 * If the target was .SUFFIXES, we take each source as a 1101 * suffix and add it to the list of suffixes maintained by the 1102 * Suff module. 1103 * 1104 * If the target was a .PATH, we add the source as a directory 1105 * to search on the search path. 1106 * 1107 * If it was .INCLUDES, the source is taken to be the suffix of 1108 * files which will be #included and whose search path should 1109 * be present in the .INCLUDES variable. 1110 * 1111 * If it was .LIBS, the source is taken to be the suffix of 1112 * files which are considered libraries and whose search path 1113 * should be present in the .LIBS variable. 1114 * 1115 * If it was .NULL, the source is the suffix to use when a file 1116 * has no valid suffix. 1117 */ 1118 char savec; 1119 while (*cp && !isspace (*cp)) { 1120 cp++; 1121 } 1122 savec = *cp; 1123 *cp = '\0'; 1124 switch (specType) { 1125 case Suffixes: 1126 Suff_AddSuffix (line); 1127 break; 1128 case ExPath: 1129 Lst_ForEach(paths, ParseAddDir, (void *)line); 1130 break; 1131 case Includes: 1132 Suff_AddInclude (line); 1133 break; 1134 case Libs: 1135 Suff_AddLib (line); 1136 break; 1137 case Null: 1138 Suff_SetNull (line); 1139 break; 1140 default: 1141 break; 1142 } 1143 *cp = savec; 1144 if (savec != '\0') { 1145 cp++; 1146 } 1147 while (*cp && isspace (*cp)) { 1148 cp++; 1149 } 1150 line = cp; 1151 } 1152 if (paths) { 1153 Lst_Destroy(paths, NOFREE); 1154 } 1155 } else { 1156 while (*line) { 1157 /* 1158 * The targets take real sources, so we must beware of archive 1159 * specifications (i.e. things with left parentheses in them) 1160 * and handle them accordingly. 1161 */ 1162 while (*cp && !isspace (*cp)) { 1163 if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) { 1164 /* 1165 * Only stop for a left parenthesis if it isn't at the 1166 * start of a word (that'll be for variable changes 1167 * later) and isn't preceded by a dollar sign (a dynamic 1168 * source). 1169 */ 1170 break; 1171 } else { 1172 cp++; 1173 } 1174 } 1175 1176 if (*cp == '(') { 1177 GNode *gn; 1178 1179 sources = Lst_Init (FALSE); 1180 if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) { 1181 Parse_Error (PARSE_FATAL, 1182 "Error in source archive spec \"%s\"", line); 1183 return; 1184 } 1185 1186 while (!Lst_IsEmpty (sources)) { 1187 gn = (GNode *) Lst_DeQueue (sources); 1188 ParseDoSrc (tOp, gn->name, curSrcs); 1189 } 1190 Lst_Destroy (sources, NOFREE); 1191 cp = line; 1192 } else { 1193 if (*cp) { 1194 *cp = '\0'; 1195 cp += 1; 1196 } 1197 1198 ParseDoSrc (tOp, line, curSrcs); 1199 } 1200 while (*cp && isspace (*cp)) { 1201 cp++; 1202 } 1203 line = cp; 1204 } 1205 } 1206 1207 if (mainNode == NULL) { 1208 /* 1209 * If we have yet to decide on a main target to make, in the 1210 * absence of any user input, we want the first target on 1211 * the first dependency line that is actually a real target 1212 * (i.e. isn't a .USE or .EXEC rule) to be made. 1213 */ 1214 Lst_ForEach (targets, ParseFindMain, (void *)0); 1215 } 1216 1217 /* 1218 * Finally, destroy the list of sources 1219 */ 1220 Lst_Destroy(curSrcs, NOFREE); 1221} 1222 1223/*- 1224 *--------------------------------------------------------------------- 1225 * Parse_IsVar -- 1226 * Return TRUE if the passed line is a variable assignment. A variable 1227 * assignment consists of a single word followed by optional whitespace 1228 * followed by either a += or an = operator. 1229 * This function is used both by the Parse_File function and main when 1230 * parsing the command-line arguments. 1231 * 1232 * Results: 1233 * TRUE if it is. FALSE if it ain't 1234 * 1235 * Side Effects: 1236 * none 1237 *--------------------------------------------------------------------- 1238 */ 1239Boolean 1240Parse_IsVar (line) 1241 register char *line; /* the line to check */ 1242{ 1243 register Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1244 register Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1245 int level = 0; 1246#define ISEQOPERATOR(c) \ 1247 (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) 1248 1249 /* 1250 * Skip to variable name 1251 */ 1252 for (;(*line == ' ') || (*line == '\t'); line++) 1253 continue; 1254 1255 for (; *line != '=' || level != 0; line++) 1256 switch (*line) { 1257 case '\0': 1258 /* 1259 * end-of-line -- can't be a variable assignment. 1260 */ 1261 return FALSE; 1262 1263 case ' ': 1264 case '\t': 1265 /* 1266 * there can be as much white space as desired so long as there is 1267 * only one word before the operator 1268 */ 1269 wasSpace = TRUE; 1270 break; 1271 1272 case '(': 1273 case '{': 1274 level++; 1275 break; 1276 1277 case '}': 1278 case ')': 1279 level--; 1280 break; 1281 1282 default: 1283 if (wasSpace && haveName) { 1284 if (ISEQOPERATOR(*line)) { 1285 /* 1286 * We must have a finished word 1287 */ 1288 if (level != 0) 1289 return FALSE; 1290 1291 /* 1292 * When an = operator [+?!:] is found, the next 1293 * character must be an = or it ain't a valid 1294 * assignment. 1295 */ 1296 if (line[1] == '=') 1297 return haveName; 1298#ifdef SUNSHCMD 1299 /* 1300 * This is a shell command 1301 */ 1302 if (strncmp(line, ":sh", 3) == 0) 1303 return haveName; 1304#endif 1305 } 1306 /* 1307 * This is the start of another word, so not assignment. 1308 */ 1309 return FALSE; 1310 } 1311 else { 1312 haveName = TRUE; 1313 wasSpace = FALSE; 1314 } 1315 break; 1316 } 1317 1318 return haveName; 1319} 1320 1321/*- 1322 *--------------------------------------------------------------------- 1323 * Parse_DoVar -- 1324 * Take the variable assignment in the passed line and do it in the 1325 * global context. 1326 * 1327 * Note: There is a lexical ambiguity with assignment modifier characters 1328 * in variable names. This routine interprets the character before the = 1329 * as a modifier. Therefore, an assignment like 1330 * C++=/usr/bin/CC 1331 * is interpreted as "C+ +=" instead of "C++ =". 1332 * 1333 * Results: 1334 * none 1335 * 1336 * Side Effects: 1337 * the variable structure of the given variable name is altered in the 1338 * global context. 1339 *--------------------------------------------------------------------- 1340 */ 1341void 1342Parse_DoVar (line, ctxt) 1343 char *line; /* a line guaranteed to be a variable 1344 * assignment. This reduces error checks */ 1345 GNode *ctxt; /* Context in which to do the assignment */ 1346{ 1347 char *cp; /* pointer into line */ 1348 enum { 1349 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL 1350 } type; /* Type of assignment */ 1351 char *opc; /* ptr to operator character to 1352 * null-terminate the variable name */ 1353 /* 1354 * Avoid clobbered variable warnings by forcing the compiler 1355 * to ``unregister'' variables 1356 */ 1357#if __GNUC__ 1358 (void) &cp; 1359 (void) &line; 1360#endif 1361 1362 /* 1363 * Skip to variable name 1364 */ 1365 while ((*line == ' ') || (*line == '\t')) { 1366 line++; 1367 } 1368 1369 /* 1370 * Skip to operator character, nulling out whitespace as we go 1371 */ 1372 for (cp = line + 1; *cp != '='; cp++) { 1373 if (isspace (*cp)) { 1374 *cp = '\0'; 1375 } 1376 } 1377 opc = cp-1; /* operator is the previous character */ 1378 *cp++ = '\0'; /* nuke the = */ 1379 1380 /* 1381 * Check operator type 1382 */ 1383 switch (*opc) { 1384 case '+': 1385 type = VAR_APPEND; 1386 *opc = '\0'; 1387 break; 1388 1389 case '?': 1390 /* 1391 * If the variable already has a value, we don't do anything. 1392 */ 1393 *opc = '\0'; 1394 if (Var_Exists(line, ctxt)) { 1395 return; 1396 } else { 1397 type = VAR_NORMAL; 1398 } 1399 break; 1400 1401 case ':': 1402 type = VAR_SUBST; 1403 *opc = '\0'; 1404 break; 1405 1406 case '!': 1407 type = VAR_SHELL; 1408 *opc = '\0'; 1409 break; 1410 1411 default: 1412#ifdef SUNSHCMD 1413 while (*opc != ':') 1414 if (opc == line) 1415 break; 1416 else 1417 --opc; 1418 1419 if (strncmp(opc, ":sh", 3) == 0) { 1420 type = VAR_SHELL; 1421 *opc = '\0'; 1422 break; 1423 } 1424#endif 1425 type = VAR_NORMAL; 1426 break; 1427 } 1428 1429 while (isspace (*cp)) { 1430 cp++; 1431 } 1432 1433 if (type == VAR_APPEND) { 1434 Var_Append (line, cp, ctxt); 1435 } else if (type == VAR_SUBST) { 1436 /* 1437 * Allow variables in the old value to be undefined, but leave their 1438 * invocation alone -- this is done by forcing oldVars to be false. 1439 * XXX: This can cause recursive variables, but that's not hard to do, 1440 * and this allows someone to do something like 1441 * 1442 * CFLAGS = $(.INCLUDES) 1443 * CFLAGS := -I.. $(CFLAGS) 1444 * 1445 * And not get an error. 1446 */ 1447 Boolean oldOldVars = oldVars; 1448 1449 oldVars = FALSE; 1450 cp = Var_Subst(NULL, cp, ctxt, FALSE); 1451 oldVars = oldOldVars; 1452 1453 Var_Set(line, cp, ctxt); 1454 free(cp); 1455 } else if (type == VAR_SHELL) { 1456 Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e. 1457 * if any variable expansion was performed */ 1458 char *res, *err; 1459 1460 if (strchr(cp, '$') != NULL) { 1461 /* 1462 * There's a dollar sign in the command, so perform variable 1463 * expansion on the whole thing. The resulting string will need 1464 * freeing when we're done, so set freeCmd to TRUE. 1465 */ 1466 cp = Var_Subst(NULL, cp, VAR_CMD, TRUE); 1467 freeCmd = TRUE; 1468 } 1469 1470 res = Cmd_Exec(cp, &err); 1471 Var_Set(line, res, ctxt); 1472 free(res); 1473 1474 if (err) 1475 Parse_Error(PARSE_WARNING, err, cp); 1476 1477 if (freeCmd) 1478 free(cp); 1479 } else { 1480 /* 1481 * Normal assignment -- just do it. 1482 */ 1483 Var_Set(line, cp, ctxt); 1484 } 1485} 1486 1487 1488/*- 1489 * ParseAddCmd -- 1490 * Lst_ForEach function to add a command line to all targets 1491 * 1492 * Results: 1493 * Always 0 1494 * 1495 * Side Effects: 1496 * A new element is added to the commands list of the node. 1497 */ 1498static int 1499ParseAddCmd(gnp, cmd) 1500 void * gnp; /* the node to which the command is to be added */ 1501 void * cmd; /* the command to add */ 1502{ 1503 GNode *gn = (GNode *) gnp; 1504 /* if target already supplied, ignore commands */ 1505 if (!(gn->type & OP_HAS_COMMANDS)) 1506 (void)Lst_AtEnd(gn->commands, cmd); 1507 return(0); 1508} 1509 1510/*- 1511 *----------------------------------------------------------------------- 1512 * ParseHasCommands -- 1513 * Callback procedure for Parse_File when destroying the list of 1514 * targets on the last dependency line. Marks a target as already 1515 * having commands if it does, to keep from having shell commands 1516 * on multiple dependency lines. 1517 * 1518 * Results: 1519 * None 1520 * 1521 * Side Effects: 1522 * OP_HAS_COMMANDS may be set for the target. 1523 * 1524 *----------------------------------------------------------------------- 1525 */ 1526static void 1527ParseHasCommands(gnp) 1528 void * gnp; /* Node to examine */ 1529{ 1530 GNode *gn = (GNode *) gnp; 1531 if (!Lst_IsEmpty(gn->commands)) { 1532 gn->type |= OP_HAS_COMMANDS; 1533 } 1534} 1535 1536/*- 1537 *----------------------------------------------------------------------- 1538 * Parse_AddIncludeDir -- 1539 * Add a directory to the path searched for included makefiles 1540 * bracketed by double-quotes. Used by functions in main.c 1541 * 1542 * Results: 1543 * None. 1544 * 1545 * Side Effects: 1546 * The directory is appended to the list. 1547 * 1548 *----------------------------------------------------------------------- 1549 */ 1550void 1551Parse_AddIncludeDir (dir) 1552 char *dir; /* The name of the directory to add */ 1553{ 1554 Dir_AddDir (parseIncPath, dir); 1555} 1556 1557/*--------------------------------------------------------------------- 1558 * ParseDoError -- 1559 * Handle error directive 1560 * 1561 * The input is the line minus the ".error". We substitute variables, 1562 * print the message and exit(1) or just print a warning if the ".error" 1563 * directive is malformed. 1564 * 1565 *--------------------------------------------------------------------- 1566 */ 1567static void 1568ParseDoError(errmsg) 1569 char *errmsg; /* error message */ 1570{ 1571 if (!isspace(*errmsg)) { 1572 Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg); 1573 return; 1574 } 1575 1576 while (isspace(*errmsg)) 1577 errmsg++; 1578 1579 errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE); 1580 1581 /* use fprintf/exit instead of Parse_Error to terminate immediately */ 1582 fprintf(stderr, "\"%s\", line %d: %s\n", fname, lineno, errmsg); 1583 exit(1); 1584} 1585 1586/*- 1587 *--------------------------------------------------------------------- 1588 * ParseDoInclude -- 1589 * Push to another file. 1590 * 1591 * The input is the line minus the #include. A file spec is a string 1592 * enclosed in <> or "". The former is looked for only in sysIncPath. 1593 * The latter in . and the directories specified by -I command line 1594 * options 1595 * 1596 * Results: 1597 * None 1598 * 1599 * Side Effects: 1600 * A structure is added to the includes Lst and readProc, lineno, 1601 * fname and curFILE are altered for the new file 1602 *--------------------------------------------------------------------- 1603 */ 1604static void 1605ParseDoInclude (file) 1606 char *file; /* file specification */ 1607{ 1608 char *fullname; /* full pathname of file */ 1609 IFile *oldFile; /* state associated with current file */ 1610 char endc; /* the character which ends the file spec */ 1611 char *cp; /* current position in file spec */ 1612 Boolean isSystem; /* TRUE if makefile is a system makefile */ 1613 1614 /* 1615 * Skip to delimiter character so we know where to look 1616 */ 1617 while ((*file == ' ') || (*file == '\t')) { 1618 file++; 1619 } 1620 1621 if ((*file != '"') && (*file != '<')) { 1622 Parse_Error (PARSE_FATAL, 1623 ".include filename must be delimited by '\"' or '<'"); 1624 return; 1625 } 1626 1627 /* 1628 * Set the search path on which to find the include file based on the 1629 * characters which bracket its name. Angle-brackets imply it's 1630 * a system Makefile while double-quotes imply it's a user makefile 1631 */ 1632 if (*file == '<') { 1633 isSystem = TRUE; 1634 endc = '>'; 1635 } else { 1636 isSystem = FALSE; 1637 endc = '"'; 1638 } 1639 1640 /* 1641 * Skip to matching delimiter 1642 */ 1643 for (cp = ++file; *cp && *cp != endc; cp++) { 1644 continue; 1645 } 1646 1647 if (*cp != endc) { 1648 Parse_Error (PARSE_FATAL, 1649 "Unclosed %cinclude filename. '%c' expected", 1650 '.', endc); 1651 return; 1652 } 1653 *cp = '\0'; 1654 1655 /* 1656 * Substitute for any variables in the file name before trying to 1657 * find the thing. 1658 */ 1659 file = Var_Subst (NULL, file, VAR_CMD, FALSE); 1660 1661 /* 1662 * Now we know the file's name and its search path, we attempt to 1663 * find the durn thing. A return of NULL indicates the file don't 1664 * exist. 1665 */ 1666 if (!isSystem) { 1667 /* 1668 * Include files contained in double-quotes are first searched for 1669 * relative to the including file's location. We don't want to 1670 * cd there, of course, so we just tack on the old file's 1671 * leading path components and call Dir_FindFile to see if 1672 * we can locate the beast. 1673 */ 1674 char *prefEnd, *Fname; 1675 1676 /* Make a temporary copy of this, to be safe. */ 1677 Fname = estrdup(fname); 1678 1679 prefEnd = strrchr (Fname, '/'); 1680 if (prefEnd != (char *)NULL) { 1681 char *newName; 1682 1683 *prefEnd = '\0'; 1684 if (file[0] == '/') 1685 newName = estrdup(file); 1686 else 1687 newName = str_concat (Fname, file, STR_ADDSLASH); 1688 fullname = Dir_FindFile (newName, parseIncPath); 1689 if (fullname == (char *)NULL) { 1690 fullname = Dir_FindFile(newName, dirSearchPath); 1691 } 1692 free (newName); 1693 *prefEnd = '/'; 1694 } else { 1695 fullname = (char *)NULL; 1696 } 1697 free (Fname); 1698 } else { 1699 fullname = (char *)NULL; 1700 } 1701 1702 if (fullname == (char *)NULL) { 1703 /* 1704 * System makefile or makefile wasn't found in same directory as 1705 * included makefile. Search for it first on the -I search path, 1706 * then on the .PATH search path, if not found in a -I directory. 1707 * XXX: Suffix specific? 1708 */ 1709 fullname = Dir_FindFile (file, parseIncPath); 1710 if (fullname == (char *)NULL) { 1711 fullname = Dir_FindFile(file, dirSearchPath); 1712 } 1713 } 1714 1715 if (fullname == (char *)NULL) { 1716 /* 1717 * Still haven't found the makefile. Look for it on the system 1718 * path as a last resort. 1719 */ 1720 fullname = Dir_FindFile(file, sysIncPath); 1721 } 1722 1723 if (fullname == (char *) NULL) { 1724 *cp = endc; 1725 Parse_Error (PARSE_FATAL, "Could not find %s", file); 1726 return; 1727 } 1728 1729 free(file); 1730 1731 /* 1732 * Once we find the absolute path to the file, we get to save all the 1733 * state from the current file before we can start reading this 1734 * include file. The state is stored in an IFile structure which 1735 * is placed on a list with other IFile structures. The list makes 1736 * a very nice stack to track how we got here... 1737 */ 1738 oldFile = (IFile *) emalloc (sizeof (IFile)); 1739 oldFile->fname = fname; 1740 1741 oldFile->F = curFILE; 1742 oldFile->p = curPTR; 1743 oldFile->lineno = lineno; 1744 1745 (void) Lst_AtFront (includes, (void *)oldFile); 1746 1747 /* 1748 * Once the previous state has been saved, we can get down to reading 1749 * the new file. We set up the name of the file to be the absolute 1750 * name of the include file so error messages refer to the right 1751 * place. Naturally enough, we start reading at line number 0. 1752 */ 1753 fname = fullname; 1754 lineno = 0; 1755 1756 curFILE = fopen (fullname, "r"); 1757 curPTR = NULL; 1758 if (curFILE == (FILE * ) NULL) { 1759 Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); 1760 /* 1761 * Pop to previous file 1762 */ 1763 (void) ParseEOF(0); 1764 } 1765} 1766 1767 1768 1769/*- 1770 *--------------------------------------------------------------------- 1771 * Parse_FromString -- 1772 * Start Parsing from the given string 1773 * 1774 * Results: 1775 * None 1776 * 1777 * Side Effects: 1778 * A structure is added to the includes Lst and readProc, lineno, 1779 * fname and curFILE are altered for the new file 1780 *--------------------------------------------------------------------- 1781 */ 1782void 1783Parse_FromString(str) 1784 char *str; 1785{ 1786 IFile *oldFile; /* state associated with this file */ 1787 1788 if (DEBUG(FOR)) 1789 (void) fprintf(stderr, "%s\n----\n", str); 1790 1791 oldFile = (IFile *) emalloc (sizeof (IFile)); 1792 oldFile->lineno = lineno; 1793 oldFile->fname = fname; 1794 oldFile->F = curFILE; 1795 oldFile->p = curPTR; 1796 1797 (void) Lst_AtFront (includes, (void *)oldFile); 1798 1799 curFILE = NULL; 1800 curPTR = (PTR *) emalloc (sizeof (PTR)); 1801 curPTR->str = curPTR->ptr = str; 1802 lineno = 0; 1803 fname = estrdup(fname); 1804} 1805 1806 1807#ifdef SYSVINCLUDE 1808/*- 1809 *--------------------------------------------------------------------- 1810 * ParseTraditionalInclude -- 1811 * Push to another file. 1812 * 1813 * The input is the line minus the "include". The file name is 1814 * the string following the "include". 1815 * 1816 * Results: 1817 * None 1818 * 1819 * Side Effects: 1820 * A structure is added to the includes Lst and readProc, lineno, 1821 * fname and curFILE are altered for the new file 1822 *--------------------------------------------------------------------- 1823 */ 1824static void 1825ParseTraditionalInclude (file) 1826 char *file; /* file specification */ 1827{ 1828 char *fullname; /* full pathname of file */ 1829 IFile *oldFile; /* state associated with current file */ 1830 char *cp; /* current position in file spec */ 1831 char *prefEnd; 1832 1833 /* 1834 * Skip over whitespace 1835 */ 1836 while ((*file == ' ') || (*file == '\t')) { 1837 file++; 1838 } 1839 1840 if (*file == '\0') { 1841 Parse_Error (PARSE_FATAL, 1842 "Filename missing from \"include\""); 1843 return; 1844 } 1845 1846 /* 1847 * Skip to end of line or next whitespace 1848 */ 1849 for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1850 continue; 1851 } 1852 1853 *cp = '\0'; 1854 1855 /* 1856 * Substitute for any variables in the file name before trying to 1857 * find the thing. 1858 */ 1859 file = Var_Subst (NULL, file, VAR_CMD, FALSE); 1860 1861 /* 1862 * Now we know the file's name, we attempt to find the durn thing. 1863 * A return of NULL indicates the file don't exist. 1864 * 1865 * Include files are first searched for relative to the including 1866 * file's location. We don't want to cd there, of course, so we 1867 * just tack on the old file's leading path components and call 1868 * Dir_FindFile to see if we can locate the beast. 1869 * XXX - this *does* search in the current directory, right? 1870 */ 1871 1872 prefEnd = strrchr (fname, '/'); 1873 if (prefEnd != (char *)NULL) { 1874 char *newName; 1875 1876 *prefEnd = '\0'; 1877 newName = str_concat (fname, file, STR_ADDSLASH); 1878 fullname = Dir_FindFile (newName, parseIncPath); 1879 if (fullname == (char *)NULL) { 1880 fullname = Dir_FindFile(newName, dirSearchPath); 1881 } 1882 free (newName); 1883 *prefEnd = '/'; 1884 } else { 1885 fullname = (char *)NULL; 1886 } 1887 1888 if (fullname == (char *)NULL) { 1889 /* 1890 * System makefile or makefile wasn't found in same directory as 1891 * included makefile. Search for it first on the -I search path, 1892 * then on the .PATH search path, if not found in a -I directory. 1893 * XXX: Suffix specific? 1894 */ 1895 fullname = Dir_FindFile (file, parseIncPath); 1896 if (fullname == (char *)NULL) { 1897 fullname = Dir_FindFile(file, dirSearchPath); 1898 } 1899 } 1900 1901 if (fullname == (char *)NULL) { 1902 /* 1903 * Still haven't found the makefile. Look for it on the system 1904 * path as a last resort. 1905 */ 1906 fullname = Dir_FindFile(file, sysIncPath); 1907 } 1908 1909 if (fullname == (char *) NULL) { 1910 Parse_Error (PARSE_FATAL, "Could not find %s", file); 1911 return; 1912 } 1913 1914 /* 1915 * Once we find the absolute path to the file, we get to save all the 1916 * state from the current file before we can start reading this 1917 * include file. The state is stored in an IFile structure which 1918 * is placed on a list with other IFile structures. The list makes 1919 * a very nice stack to track how we got here... 1920 */ 1921 oldFile = (IFile *) emalloc (sizeof (IFile)); 1922 oldFile->fname = fname; 1923 1924 oldFile->F = curFILE; 1925 oldFile->p = curPTR; 1926 oldFile->lineno = lineno; 1927 1928 (void) Lst_AtFront (includes, (void *)oldFile); 1929 1930 /* 1931 * Once the previous state has been saved, we can get down to reading 1932 * the new file. We set up the name of the file to be the absolute 1933 * name of the include file so error messages refer to the right 1934 * place. Naturally enough, we start reading at line number 0. 1935 */ 1936 fname = fullname; 1937 lineno = 0; 1938 1939 curFILE = fopen (fullname, "r"); 1940 curPTR = NULL; 1941 if (curFILE == (FILE * ) NULL) { 1942 Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); 1943 /* 1944 * Pop to previous file 1945 */ 1946 (void) ParseEOF(1); 1947 } 1948} 1949#endif 1950 1951/*- 1952 *--------------------------------------------------------------------- 1953 * ParseEOF -- 1954 * Called when EOF is reached in the current file. If we were reading 1955 * an include file, the includes stack is popped and things set up 1956 * to go back to reading the previous file at the previous location. 1957 * 1958 * Results: 1959 * CONTINUE if there's more to do. DONE if not. 1960 * 1961 * Side Effects: 1962 * The old curFILE, is closed. The includes list is shortened. 1963 * lineno, curFILE, and fname are changed if CONTINUE is returned. 1964 *--------------------------------------------------------------------- 1965 */ 1966static int 1967ParseEOF (opened) 1968 int opened; 1969{ 1970 IFile *ifile; /* the state on the top of the includes stack */ 1971 1972 if (Lst_IsEmpty (includes)) { 1973 return (DONE); 1974 } 1975 1976 ifile = (IFile *) Lst_DeQueue (includes); 1977 free (fname); 1978 fname = ifile->fname; 1979 lineno = ifile->lineno; 1980 if (opened && curFILE) 1981 (void) fclose (curFILE); 1982 if (curPTR) { 1983 free(curPTR->str); 1984 free(curPTR); 1985 } 1986 curFILE = ifile->F; 1987 curPTR = ifile->p; 1988 free (ifile); 1989 return (CONTINUE); 1990} 1991 1992/*- 1993 *--------------------------------------------------------------------- 1994 * ParseReadc -- 1995 * Read a character from the current file 1996 * 1997 * Results: 1998 * The character that was read 1999 * 2000 * Side Effects: 2001 *--------------------------------------------------------------------- 2002 */ 2003static int 2004ParseReadc() 2005{ 2006 if (curFILE) 2007 return fgetc(curFILE); 2008 2009 if (curPTR && *curPTR->ptr) 2010 return *curPTR->ptr++; 2011 return EOF; 2012} 2013 2014 2015/*- 2016 *--------------------------------------------------------------------- 2017 * ParseUnreadc -- 2018 * Put back a character to the current file 2019 * 2020 * Results: 2021 * None. 2022 * 2023 * Side Effects: 2024 *--------------------------------------------------------------------- 2025 */ 2026static void 2027ParseUnreadc(c) 2028 int c; 2029{ 2030 if (curFILE) { 2031 ungetc(c, curFILE); 2032 return; 2033 } 2034 if (curPTR) { 2035 *--(curPTR->ptr) = c; 2036 return; 2037 } 2038} 2039 2040 2041/* ParseSkipLine(): 2042 * Grab the next line 2043 */ 2044static char * 2045ParseSkipLine(skip) 2046 int skip; /* Skip lines that don't start with . */ 2047{ 2048 char *line; 2049 int c, lastc, lineLength = 0; 2050 Buffer buf; 2051 2052 buf = Buf_Init(MAKE_BSIZE); 2053 2054 do { 2055 Buf_Discard(buf, lineLength); 2056 lastc = '\0'; 2057 2058 while (((c = ParseReadc()) != '\n' || lastc == '\\') 2059 && c != EOF) { 2060 if (c == '\n') { 2061 Buf_ReplaceLastByte(buf, (Byte)' '); 2062 lineno++; 2063 2064 while ((c = ParseReadc()) == ' ' || c == '\t'); 2065 2066 if (c == EOF) 2067 break; 2068 } 2069 2070 Buf_AddByte(buf, (Byte)c); 2071 lastc = c; 2072 } 2073 2074 if (c == EOF) { 2075 Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop"); 2076 Buf_Destroy(buf, TRUE); 2077 return((char *)NULL); 2078 } 2079 2080 lineno++; 2081 Buf_AddByte(buf, (Byte)'\0'); 2082 line = (char *)Buf_GetAll(buf, &lineLength); 2083 } while (skip == 1 && line[0] != '.'); 2084 2085 Buf_Destroy(buf, FALSE); 2086 return line; 2087} 2088 2089 2090/*- 2091 *--------------------------------------------------------------------- 2092 * ParseReadLine -- 2093 * Read an entire line from the input file. Called only by Parse_File. 2094 * To facilitate escaped newlines and what have you, a character is 2095 * buffered in 'lastc', which is '\0' when no characters have been 2096 * read. When we break out of the loop, c holds the terminating 2097 * character and lastc holds a character that should be added to 2098 * the line (unless we don't read anything but a terminator). 2099 * 2100 * Results: 2101 * A line w/o its newline 2102 * 2103 * Side Effects: 2104 * Only those associated with reading a character 2105 *--------------------------------------------------------------------- 2106 */ 2107static char * 2108ParseReadLine () 2109{ 2110 Buffer buf; /* Buffer for current line */ 2111 register int c; /* the current character */ 2112 register int lastc; /* The most-recent character */ 2113 Boolean semiNL; /* treat semi-colons as newlines */ 2114 Boolean ignDepOp; /* TRUE if should ignore dependency operators 2115 * for the purposes of setting semiNL */ 2116 Boolean ignComment; /* TRUE if should ignore comments (in a 2117 * shell command */ 2118 char *line; /* Result */ 2119 char *ep; /* to strip trailing blanks */ 2120 int lineLength; /* Length of result */ 2121 2122 semiNL = FALSE; 2123 ignDepOp = FALSE; 2124 ignComment = FALSE; 2125 2126 /* 2127 * Handle special-characters at the beginning of the line. Either a 2128 * leading tab (shell command) or pound-sign (possible conditional) 2129 * forces us to ignore comments and dependency operators and treat 2130 * semi-colons as semi-colons (by leaving semiNL FALSE). This also 2131 * discards completely blank lines. 2132 */ 2133 for (;;) { 2134 c = ParseReadc(); 2135 2136 if (c == '\t') { 2137 ignComment = ignDepOp = TRUE; 2138 break; 2139 } else if (c == '\n') { 2140 lineno++; 2141 } else if (c == '#') { 2142 ParseUnreadc(c); 2143 break; 2144 } else { 2145 /* 2146 * Anything else breaks out without doing anything 2147 */ 2148 break; 2149 } 2150 } 2151 2152 if (c != EOF) { 2153 lastc = c; 2154 buf = Buf_Init(MAKE_BSIZE); 2155 2156 while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) && 2157 (c != EOF)) 2158 { 2159test_char: 2160 switch(c) { 2161 case '\n': 2162 /* 2163 * Escaped newline: read characters until a non-space or an 2164 * unescaped newline and replace them all by a single space. 2165 * This is done by storing the space over the backslash and 2166 * dropping through with the next nonspace. If it is a 2167 * semi-colon and semiNL is TRUE, it will be recognized as a 2168 * newline in the code below this... 2169 */ 2170 lineno++; 2171 lastc = ' '; 2172 while ((c = ParseReadc ()) == ' ' || c == '\t') { 2173 continue; 2174 } 2175 if (c == EOF || c == '\n') { 2176 goto line_read; 2177 } else { 2178 /* 2179 * Check for comments, semiNL's, etc. -- easier than 2180 * ParseUnreadc(c); continue; 2181 */ 2182 goto test_char; 2183 } 2184 /*NOTREACHED*/ 2185 break; 2186 2187 case ';': 2188 /* 2189 * Semi-colon: Need to see if it should be interpreted as a 2190 * newline 2191 */ 2192 if (semiNL) { 2193 /* 2194 * To make sure the command that may be following this 2195 * semi-colon begins with a tab, we push one back into the 2196 * input stream. This will overwrite the semi-colon in the 2197 * buffer. If there is no command following, this does no 2198 * harm, since the newline remains in the buffer and the 2199 * whole line is ignored. 2200 */ 2201 ParseUnreadc('\t'); 2202 goto line_read; 2203 } 2204 break; 2205 case '=': 2206 if (!semiNL) { 2207 /* 2208 * Haven't seen a dependency operator before this, so this 2209 * must be a variable assignment -- don't pay attention to 2210 * dependency operators after this. 2211 */ 2212 ignDepOp = TRUE; 2213 } else if (lastc == ':' || lastc == '!') { 2214 /* 2215 * Well, we've seen a dependency operator already, but it 2216 * was the previous character, so this is really just an 2217 * expanded variable assignment. Revert semi-colons to 2218 * being just semi-colons again and ignore any more 2219 * dependency operators. 2220 * 2221 * XXX: Note that a line like "foo : a:=b" will blow up, 2222 * but who'd write a line like that anyway? 2223 */ 2224 ignDepOp = TRUE; semiNL = FALSE; 2225 } 2226 break; 2227 case '#': 2228 if (!ignComment) { 2229 if ( 2230#if 0 2231 compatMake && 2232#endif 2233 (lastc != '\\')) { 2234 /* 2235 * If the character is a hash mark and it isn't escaped 2236 * (or we're being compatible), the thing is a comment. 2237 * Skip to the end of the line. 2238 */ 2239 do { 2240 c = ParseReadc(); 2241 } while ((c != '\n') && (c != EOF)); 2242 goto line_read; 2243 } else { 2244 /* 2245 * Don't add the backslash. Just let the # get copied 2246 * over. 2247 */ 2248 lastc = c; 2249 continue; 2250 } 2251 } 2252 break; 2253 case ':': 2254 case '!': 2255 if (!ignDepOp && (c == ':' || c == '!')) { 2256 /* 2257 * A semi-colon is recognized as a newline only on 2258 * dependency lines. Dependency lines are lines with a 2259 * colon or an exclamation point. Ergo... 2260 */ 2261 semiNL = TRUE; 2262 } 2263 break; 2264 } 2265 /* 2266 * Copy in the previous character and save this one in lastc. 2267 */ 2268 Buf_AddByte (buf, (Byte)lastc); 2269 lastc = c; 2270 2271 } 2272 line_read: 2273 lineno++; 2274 2275 if (lastc != '\0') { 2276 Buf_AddByte (buf, (Byte)lastc); 2277 } 2278 Buf_AddByte (buf, (Byte)'\0'); 2279 line = (char *)Buf_GetAll (buf, &lineLength); 2280 Buf_Destroy (buf, FALSE); 2281 2282 /* 2283 * Strip trailing blanks and tabs from the line. 2284 * Do not strip a blank or tab that is preceded by 2285 * a '\' 2286 */ 2287 ep = line; 2288 while (*ep) 2289 ++ep; 2290 while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2291 if (ep > line + 1 && ep[-2] == '\\') 2292 break; 2293 --ep; 2294 } 2295 *ep = 0; 2296 2297 if (line[0] == '.') { 2298 /* 2299 * The line might be a conditional. Ask the conditional module 2300 * about it and act accordingly 2301 */ 2302 switch (Cond_Eval (line)) { 2303 case COND_SKIP: 2304 /* 2305 * Skip to next conditional that evaluates to COND_PARSE. 2306 */ 2307 do { 2308 free (line); 2309 line = ParseSkipLine(1); 2310 } while (line && Cond_Eval(line) != COND_PARSE); 2311 if (line == NULL) 2312 break; 2313 /*FALLTHRU*/ 2314 case COND_PARSE: 2315 free (line); 2316 line = ParseReadLine(); 2317 break; 2318 case COND_INVALID: 2319 if (For_Eval(line)) { 2320 int ok; 2321 free(line); 2322 do { 2323 /* 2324 * Skip after the matching end 2325 */ 2326 line = ParseSkipLine(0); 2327 if (line == NULL) { 2328 Parse_Error (PARSE_FATAL, 2329 "Unexpected end of file in for loop.\n"); 2330 break; 2331 } 2332 ok = For_Eval(line); 2333 free(line); 2334 } 2335 while (ok); 2336 if (line != NULL) 2337 For_Run(); 2338 line = ParseReadLine(); 2339 } 2340 break; 2341 } 2342 } 2343 return (line); 2344 2345 } else { 2346 /* 2347 * Hit end-of-file, so return a NULL line to indicate this. 2348 */ 2349 return((char *)NULL); 2350 } 2351} 2352 2353/*- 2354 *----------------------------------------------------------------------- 2355 * ParseFinishLine -- 2356 * Handle the end of a dependency group. 2357 * 2358 * Results: 2359 * Nothing. 2360 * 2361 * Side Effects: 2362 * inLine set FALSE. 'targets' list destroyed. 2363 * 2364 *----------------------------------------------------------------------- 2365 */ 2366static void 2367ParseFinishLine() 2368{ 2369 if (inLine) { 2370 Lst_ForEach(targets, Suff_EndTransform, (void *)NULL); 2371 Lst_Destroy (targets, ParseHasCommands); 2372 targets = NULL; 2373 inLine = FALSE; 2374 } 2375} 2376 2377 2378/*- 2379 *--------------------------------------------------------------------- 2380 * Parse_File -- 2381 * Parse a file into its component parts, incorporating it into the 2382 * current dependency graph. This is the main function and controls 2383 * almost every other function in this module 2384 * 2385 * Results: 2386 * None 2387 * 2388 * Side Effects: 2389 * Loads. Nodes are added to the list of all targets, nodes and links 2390 * are added to the dependency graph. etc. etc. etc. 2391 *--------------------------------------------------------------------- 2392 */ 2393void 2394Parse_File(name, stream) 2395 char *name; /* the name of the file being read */ 2396 FILE * stream; /* Stream open to makefile to parse */ 2397{ 2398 register char *cp, /* pointer into the line */ 2399 *line; /* the line we're working on */ 2400 2401 inLine = FALSE; 2402 fname = name; 2403 curFILE = stream; 2404 lineno = 0; 2405 fatals = 0; 2406 2407 do { 2408 while ((line = ParseReadLine ()) != NULL) { 2409 if (*line == '.') { 2410 /* 2411 * Lines that begin with the special character are either 2412 * include or undef directives. 2413 */ 2414 for (cp = line + 1; isspace (*cp); cp++) { 2415 continue; 2416 } 2417 if (strncmp (cp, "include", 7) == 0) { 2418 ParseDoInclude (cp + 7); 2419 goto nextLine; 2420 } else if (strncmp (cp, "error", 5) == 0) { 2421 ParseDoError(cp + 5); 2422 goto nextLine; 2423 } else if (strncmp(cp, "undef", 5) == 0) { 2424 char *cp2; 2425 for (cp += 5; isspace((unsigned char) *cp); cp++) { 2426 continue; 2427 } 2428 2429 for (cp2 = cp; !isspace((unsigned char) *cp2) && 2430 (*cp2 != '\0'); cp2++) { 2431 continue; 2432 } 2433 2434 *cp2 = '\0'; 2435 2436 Var_Delete(cp, VAR_GLOBAL); 2437 goto nextLine; 2438 } 2439 } 2440 if (*line == '#') { 2441 /* If we're this far, the line must be a comment. */ 2442 goto nextLine; 2443 } 2444 2445 if (*line == '\t') { 2446 /* 2447 * If a line starts with a tab, it can only hope to be 2448 * a creation command. 2449 */ 2450#ifndef POSIX 2451 shellCommand: 2452#endif 2453 for (cp = line + 1; isspace (*cp); cp++) { 2454 continue; 2455 } 2456 if (*cp) { 2457 if (inLine) { 2458 /* 2459 * So long as it's not a blank line and we're actually 2460 * in a dependency spec, add the command to the list of 2461 * commands of all targets in the dependency spec 2462 */ 2463 Lst_ForEach (targets, ParseAddCmd, cp); 2464 Lst_AtEnd(targCmds, (void *) line); 2465 continue; 2466 } else { 2467 Parse_Error (PARSE_FATAL, 2468 "Unassociated shell command \"%s\"", 2469 cp); 2470 } 2471 } 2472#ifdef SYSVINCLUDE 2473 } else if (strncmp (line, "include", 7) == 0 && 2474 isspace((unsigned char) line[7]) && 2475 strchr(line, ':') == NULL) { 2476 /* 2477 * It's an S3/S5-style "include". 2478 */ 2479 ParseTraditionalInclude (line + 7); 2480 goto nextLine; 2481#endif 2482 } else if (Parse_IsVar (line)) { 2483 ParseFinishLine(); 2484 Parse_DoVar (line, VAR_GLOBAL); 2485 } else { 2486 /* 2487 * We now know it's a dependency line so it needs to have all 2488 * variables expanded before being parsed. Tell the variable 2489 * module to complain if some variable is undefined... 2490 * To make life easier on novices, if the line is indented we 2491 * first make sure the line has a dependency operator in it. 2492 * If it doesn't have an operator and we're in a dependency 2493 * line's script, we assume it's actually a shell command 2494 * and add it to the current list of targets. 2495 */ 2496#ifndef POSIX 2497 Boolean nonSpace = FALSE; 2498#endif 2499 2500 cp = line; 2501 if (isspace((unsigned char) line[0])) { 2502 while ((*cp != '\0') && isspace((unsigned char) *cp)) { 2503 cp++; 2504 } 2505 if (*cp == '\0') { 2506 goto nextLine; 2507 } 2508#ifndef POSIX 2509 while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) { 2510 nonSpace = TRUE; 2511 cp++; 2512 } 2513#endif 2514 } 2515 2516#ifndef POSIX 2517 if (*cp == '\0') { 2518 if (inLine) { 2519 Parse_Error (PARSE_WARNING, 2520 "Shell command needs a leading tab"); 2521 goto shellCommand; 2522 } else if (nonSpace) { 2523 Parse_Error (PARSE_FATAL, "Missing operator"); 2524 } 2525 } else { 2526#endif 2527 ParseFinishLine(); 2528 2529 cp = Var_Subst (NULL, line, VAR_CMD, TRUE); 2530 free (line); 2531 line = cp; 2532 2533 /* 2534 * Need a non-circular list for the target nodes 2535 */ 2536 if (targets) 2537 Lst_Destroy(targets, NOFREE); 2538 2539 targets = Lst_Init (FALSE); 2540 inLine = TRUE; 2541 2542 ParseDoDependency (line); 2543#ifndef POSIX 2544 } 2545#endif 2546 } 2547 2548 nextLine: 2549 2550 free (line); 2551 } 2552 /* 2553 * Reached EOF, but it may be just EOF of an include file... 2554 */ 2555 } while (ParseEOF(1) == CONTINUE); 2556 2557 /* 2558 * Make sure conditionals are clean 2559 */ 2560 Cond_End(); 2561 2562 if (fatals) 2563 errx(1, "fatal errors encountered -- cannot continue"); 2564} 2565 2566/*- 2567 *--------------------------------------------------------------------- 2568 * Parse_Init -- 2569 * initialize the parsing module 2570 * 2571 * Results: 2572 * none 2573 * 2574 * Side Effects: 2575 * the parseIncPath list is initialized... 2576 *--------------------------------------------------------------------- 2577 */ 2578void 2579Parse_Init () 2580{ 2581 mainNode = NULL; 2582 parseIncPath = Lst_Init (FALSE); 2583 sysIncPath = Lst_Init (FALSE); 2584 includes = Lst_Init (FALSE); 2585 targCmds = Lst_Init (FALSE); 2586} 2587 2588void 2589Parse_End() 2590{ 2591 Lst_Destroy(targCmds, (void (*)(void *)) free); 2592 if (targets) 2593 Lst_Destroy(targets, NOFREE); 2594 Lst_Destroy(sysIncPath, Dir_Destroy); 2595 Lst_Destroy(parseIncPath, Dir_Destroy); 2596 Lst_Destroy(includes, NOFREE); /* Should be empty now */ 2597} 2598 2599 2600/*- 2601 *----------------------------------------------------------------------- 2602 * Parse_MainName -- 2603 * Return a Lst of the main target to create for main()'s sake. If 2604 * no such target exists, we Punt with an obnoxious error message. 2605 * 2606 * Results: 2607 * A Lst of the single node to create. 2608 * 2609 * Side Effects: 2610 * None. 2611 * 2612 *----------------------------------------------------------------------- 2613 */ 2614Lst 2615Parse_MainName() 2616{ 2617 Lst listmain; /* result list */ 2618 2619 listmain = Lst_Init (FALSE); 2620 2621 if (mainNode == NULL) { 2622 Punt ("no target to make."); 2623 /*NOTREACHED*/ 2624 } else if (mainNode->type & OP_DOUBLEDEP) { 2625 (void) Lst_AtEnd (listmain, (void *)mainNode); 2626 Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW); 2627 } 2628 else 2629 (void) Lst_AtEnd (listmain, (void *)mainNode); 2630 return (listmain); 2631} 2632