parse.c revision 143100
1141104Sharti/*- 21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * This code is derived from software contributed to Berkeley by 81590Srgrimes * Adam de Boor. 91590Srgrimes * 101590Srgrimes * Redistribution and use in source and binary forms, with or without 111590Srgrimes * modification, are permitted provided that the following conditions 121590Srgrimes * are met: 131590Srgrimes * 1. Redistributions of source code must retain the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer. 151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161590Srgrimes * notice, this list of conditions and the following disclaimer in the 171590Srgrimes * documentation and/or other materials provided with the distribution. 181590Srgrimes * 3. All advertising materials mentioning features or use of this software 191590Srgrimes * must display the following acknowledgement: 201590Srgrimes * This product includes software developed by the University of 211590Srgrimes * California, Berkeley and its contributors. 221590Srgrimes * 4. Neither the name of the University nor the names of its contributors 231590Srgrimes * may be used to endorse or promote products derived from this software 241590Srgrimes * without specific prior written permission. 251590Srgrimes * 261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361590Srgrimes * SUCH DAMAGE. 3762833Swsanchez * 3862833Swsanchez * @(#)parse.c 8.3 (Berkeley) 3/19/94 391590Srgrimes */ 401590Srgrimes 4162833Swsanchez#include <sys/cdefs.h> 4294587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/parse.c 143100 2005-03-03 10:07:28Z harti $"); 431590Srgrimes 441590Srgrimes/*- 451590Srgrimes * parse.c -- 461590Srgrimes * Functions to parse a makefile. 471590Srgrimes * 481590Srgrimes * One function, Parse_Init, must be called before any functions 491590Srgrimes * in this module are used. After that, the function Parse_File is the 501590Srgrimes * main entry point and controls most of the other functions in this 511590Srgrimes * module. 521590Srgrimes * 531590Srgrimes * Most important structures are kept in Lsts. Directories for 541590Srgrimes * the #include "..." function are kept in the 'parseIncPath' Lst, while 551590Srgrimes * those for the #include <...> are kept in the 'sysIncPath' Lst. The 561590Srgrimes * targets currently being defined are kept in the 'targets' Lst. 571590Srgrimes * 58126824Sru * The variables 'curFile.fname' and 'curFile.lineno' are used to track 59126824Sru * the name of the current file and the line number in that file so that 60126824Sru * error messages can be more meaningful. 611590Srgrimes * 621590Srgrimes * Interface: 631590Srgrimes * Parse_Init Initialization function which must be 641590Srgrimes * called before anything else in this module 651590Srgrimes * is used. 661590Srgrimes * 671590Srgrimes * Parse_File Function used to parse a makefile. It must 681590Srgrimes * be given the name of the file, which should 691590Srgrimes * already have been opened, and a function 701590Srgrimes * to call to read a character from the file. 711590Srgrimes * 721590Srgrimes * Parse_IsVar Returns TRUE if the given line is a 731590Srgrimes * variable assignment. Used by MainParseArgs 741590Srgrimes * to determine if an argument is a target 751590Srgrimes * or a variable assignment. Used internally 761590Srgrimes * for pretty much the same thing... 771590Srgrimes * 781590Srgrimes * Parse_Error Function called when an error occurs in 791590Srgrimes * parsing. Used by the variable and 801590Srgrimes * conditional modules. 811590Srgrimes * Parse_MainName Returns a Lst of the main target to create. 821590Srgrimes */ 831590Srgrimes 84141104Sharti#include <ctype.h> 851590Srgrimes#include <stdarg.h> 86141104Sharti#include <string.h> 87141104Sharti#include <stdlib.h> 8827644Scharnier#include <err.h> 89141104Sharti 90141104Sharti#include "arch.h" 91141104Sharti#include "buf.h" 92141104Sharti#include "cond.h" 93141104Sharti#include "config.h" 941590Srgrimes#include "dir.h" 95141104Sharti#include "for.h" 96141104Sharti#include "globals.h" 97141104Sharti#include "GNode.h" 981590Srgrimes#include "job.h" 99141104Sharti#include "make.h" 100141104Sharti#include "nonints.h" 101141104Sharti#include "parse.h" 1021590Srgrimes#include "pathnames.h" 103141104Sharti#include "str.h" 104141104Sharti#include "suff.h" 105141104Sharti#include "targ.h" 106141104Sharti#include "util.h" 107141104Sharti#include "var.h" 1081590Srgrimes 1091590Srgrimes/* 1101590Srgrimes * These values are returned by ParseEOF to tell Parse_File whether to 1111590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file, 1121590Srgrimes * or if it's DONE. 1131590Srgrimes */ 1141590Srgrimes#define CONTINUE 1 1151590Srgrimes#define DONE 0 116138916Sharti 117138916Sharti/* targets we're working on */ 118138916Shartistatic Lst targets = Lst_Initializer(targets); 119138916Sharti 1201590Srgrimesstatic Boolean inLine; /* true if currently in a dependency 1211590Srgrimes * line or its commands */ 1221590Srgrimesstatic int fatals = 0; 1231590Srgrimes 1241590Srgrimesstatic GNode *mainNode; /* The main target to create. This is the 1251590Srgrimes * first target on the first dependency 1261590Srgrimes * line in the first makefile */ 1271590Srgrimes 128132439ShartiIFile curFile; /* current makefile */ 129126824Sru 130138916Sharti/* stack of IFiles generated by * #includes */ 131138916Shartistatic Lst includes = Lst_Initializer(includes); 1321590Srgrimes 133138916Sharti/* list of directories for "..." includes */ 134138916ShartiLst parseIncPath = Lst_Initializer(parseIncPath); 135138916Sharti 136138916Sharti/* list of directories for <...> includes */ 137138916ShartiLst sysIncPath = Lst_Initializer(sysIncPath); 138138916Sharti 1391590Srgrimes/*- 1401590Srgrimes * specType contains the SPECial TYPE of the current target. It is 1411590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children 1421590Srgrimes * are linked as children of the parent but not vice versa. This variable is 1431590Srgrimes * set in ParseDoDependency 1441590Srgrimes */ 1451590Srgrimestypedef enum { 1461590Srgrimes Begin, /* .BEGIN */ 1471590Srgrimes Default, /* .DEFAULT */ 1481590Srgrimes End, /* .END */ 1491590Srgrimes Ignore, /* .IGNORE */ 1501590Srgrimes Includes, /* .INCLUDES */ 1511590Srgrimes Interrupt, /* .INTERRUPT */ 1521590Srgrimes Libs, /* .LIBS */ 1531590Srgrimes MFlags, /* .MFLAGS or .MAKEFLAGS */ 1541590Srgrimes Main, /* .MAIN and we don't have anything user-specified to 1551590Srgrimes * make */ 1561590Srgrimes NoExport, /* .NOEXPORT */ 1571590Srgrimes Not, /* Not special */ 1581590Srgrimes NotParallel, /* .NOTPARALELL */ 1591590Srgrimes Null, /* .NULL */ 1601590Srgrimes Order, /* .ORDER */ 16118730Ssteve Parallel, /* .PARALLEL */ 1621590Srgrimes ExPath, /* .PATH */ 16318730Ssteve Phony, /* .PHONY */ 16419344Ssteve Posix, /* .POSIX */ 1651590Srgrimes Precious, /* .PRECIOUS */ 1661590Srgrimes ExShell, /* .SHELL */ 1671590Srgrimes Silent, /* .SILENT */ 1681590Srgrimes SingleShell, /* .SINGLESHELL */ 1691590Srgrimes Suffixes, /* .SUFFIXES */ 17018730Ssteve Wait, /* .WAIT */ 1711590Srgrimes Attribute /* Generic attribute */ 1721590Srgrimes} ParseSpecial; 1731590Srgrimes 1741590Srgrimesstatic ParseSpecial specType; 17518730Sstevestatic int waiting; 1761590Srgrimes 1771590Srgrimes/* 17869527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 1791590Srgrimes * seen, then set to each successive source on the line. 1801590Srgrimes */ 1811590Srgrimesstatic GNode *predecessor; 1821590Srgrimes 1831590Srgrimes/* 1841590Srgrimes * The parseKeywords table is searched using binary search when deciding 1851590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial 1861590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while 1871590Srgrimes * the 'op' field is the operator to apply to the list of targets if the 1881590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source) 1891590Srgrimes */ 1901590Srgrimesstatic struct { 191141252Sharti const char *name; /* Name of keyword */ 1921590Srgrimes ParseSpecial spec; /* Type when used as a target */ 1931590Srgrimes int op; /* Operator when used as a source */ 1941590Srgrimes} parseKeywords[] = { 1951590Srgrimes{ ".BEGIN", Begin, 0 }, 1961590Srgrimes{ ".DEFAULT", Default, 0 }, 1971590Srgrimes{ ".END", End, 0 }, 1981590Srgrimes{ ".EXEC", Attribute, OP_EXEC }, 1991590Srgrimes{ ".IGNORE", Ignore, OP_IGNORE }, 2001590Srgrimes{ ".INCLUDES", Includes, 0 }, 2011590Srgrimes{ ".INTERRUPT", Interrupt, 0 }, 2021590Srgrimes{ ".INVISIBLE", Attribute, OP_INVISIBLE }, 2031590Srgrimes{ ".JOIN", Attribute, OP_JOIN }, 2041590Srgrimes{ ".LIBS", Libs, 0 }, 2051590Srgrimes{ ".MAIN", Main, 0 }, 2061590Srgrimes{ ".MAKE", Attribute, OP_MAKE }, 2071590Srgrimes{ ".MAKEFLAGS", MFlags, 0 }, 2081590Srgrimes{ ".MFLAGS", MFlags, 0 }, 2091590Srgrimes{ ".NOTMAIN", Attribute, OP_NOTMAIN }, 2101590Srgrimes{ ".NOTPARALLEL", NotParallel, 0 }, 21118730Ssteve{ ".NO_PARALLEL", NotParallel, 0 }, 2121590Srgrimes{ ".NULL", Null, 0 }, 2139254Sache{ ".OPTIONAL", Attribute, OP_OPTIONAL }, 2141590Srgrimes{ ".ORDER", Order, 0 }, 21518730Ssteve{ ".PARALLEL", Parallel, 0 }, 2161590Srgrimes{ ".PATH", ExPath, 0 }, 21718730Ssteve{ ".PHONY", Phony, OP_PHONY }, 21819344Ssteve{ ".POSIX", Posix, 0 }, 2191590Srgrimes{ ".PRECIOUS", Precious, OP_PRECIOUS }, 2201590Srgrimes{ ".RECURSIVE", Attribute, OP_MAKE }, 2211590Srgrimes{ ".SHELL", ExShell, 0 }, 2221590Srgrimes{ ".SILENT", Silent, OP_SILENT }, 2231590Srgrimes{ ".SINGLESHELL", SingleShell, 0 }, 2241590Srgrimes{ ".SUFFIXES", Suffixes, 0 }, 2251590Srgrimes{ ".USE", Attribute, OP_USE }, 22618730Ssteve{ ".WAIT", Wait, 0 }, 2271590Srgrimes}; 2281590Srgrimes 22992921Simpstatic int ParseFindKeyword(char *); 23092921Simpstatic int ParseDoOp(void *, void *); 23192921Simpstatic int ParseAddDep(void *, void *); 232138512Shartistatic void ParseDoSrc(int, char *, Lst *); 23392921Simpstatic int ParseFindMain(void *, void *); 23492921Simpstatic int ParseAddDir(void *, void *); 23592921Simpstatic int ParseClearPath(void *, void *); 23692921Simpstatic void ParseDoDependency(char *); 23792921Simpstatic int ParseAddCmd(void *, void *); 23892921Simpstatic int ParseReadc(void); 23992921Simpstatic void ParseUnreadc(int); 24092921Simpstatic void ParseHasCommands(void *); 24192921Simpstatic void ParseDoInclude(char *); 24292921Simpstatic void ParseDoError(char *); 243128160Srustatic void ParseDoWarning(char *); 2441590Srgrimes#ifdef SYSVINCLUDE 24592921Simpstatic void ParseTraditionalInclude(char *); 2461590Srgrimes#endif 24792921Simpstatic int ParseEOF(int); 24892921Simpstatic char *ParseReadLine(void); 249126824Srustatic char *ParseSkipLine(int, int); 25092921Simpstatic void ParseFinishLine(void); 2511590Srgrimes 2521590Srgrimes/*- 2531590Srgrimes *---------------------------------------------------------------------- 2541590Srgrimes * ParseFindKeyword -- 2551590Srgrimes * Look in the table of keywords for one matching the given string. 2561590Srgrimes * 2571590Srgrimes * Results: 2581590Srgrimes * The index of the keyword, or -1 if it isn't there. 2591590Srgrimes * 2601590Srgrimes * Side Effects: 2611590Srgrimes * None 2621590Srgrimes *---------------------------------------------------------------------- 2631590Srgrimes */ 2641590Srgrimesstatic int 265138232ShartiParseFindKeyword(char *str) 2661590Srgrimes{ 26794584Sobrien int start, 2681590Srgrimes end, 2691590Srgrimes cur; 27094584Sobrien int diff; 2718874Srgrimes 2721590Srgrimes start = 0; 273138232Sharti end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1; 2741590Srgrimes 2751590Srgrimes do { 2761590Srgrimes cur = start + ((end - start) / 2); 277138232Sharti diff = strcmp(str, parseKeywords[cur].name); 2781590Srgrimes 2791590Srgrimes if (diff == 0) { 2801590Srgrimes return (cur); 2811590Srgrimes } else if (diff < 0) { 2821590Srgrimes end = cur - 1; 2831590Srgrimes } else { 2841590Srgrimes start = cur + 1; 2851590Srgrimes } 2861590Srgrimes } while (start <= end); 2871590Srgrimes return (-1); 2881590Srgrimes} 2891590Srgrimes 2901590Srgrimes/*- 2911590Srgrimes * Parse_Error -- 2921590Srgrimes * Error message abort function for parsing. Prints out the context 2931590Srgrimes * of the error (line number and file) as well as the message with 2941590Srgrimes * two optional arguments. 2951590Srgrimes * 2961590Srgrimes * Results: 2971590Srgrimes * None 2981590Srgrimes * 2991590Srgrimes * Side Effects: 3001590Srgrimes * "fatals" is incremented if the level is PARSE_FATAL. 3011590Srgrimes */ 3021590Srgrimes/* VARARGS */ 3031590Srgrimesvoid 30498136SjmallettParse_Error(int type, const char *fmt, ...) 3051590Srgrimes{ 3061590Srgrimes va_list ap; 30793056Simp 3081590Srgrimes va_start(ap, fmt); 309138232Sharti fprintf(stderr, "\"%s\", line %d: ", 310126824Sru curFile.fname, curFile.lineno); 3111590Srgrimes if (type == PARSE_WARNING) 312138232Sharti fprintf(stderr, "warning: "); 313138232Sharti vfprintf(stderr, fmt, ap); 3141590Srgrimes va_end(ap); 315138232Sharti fprintf(stderr, "\n"); 316138232Sharti fflush(stderr); 3171590Srgrimes if (type == PARSE_FATAL) 3181590Srgrimes fatals += 1; 3191590Srgrimes} 3201590Srgrimes 3211590Srgrimes/*- 3221590Srgrimes *--------------------------------------------------------------------- 3231590Srgrimes * ParseLinkSrc -- 324143100Sharti * Link the parent nodes to their new child. Used by 3251590Srgrimes * ParseDoDependency. If the specType isn't 'Not', the parent 3261590Srgrimes * isn't linked as a parent of the child. 3271590Srgrimes * 3281590Srgrimes * Side Effects: 329143100Sharti * New elements are added to the parents lists of cgn and the 3301590Srgrimes * children list of cgn. the unmade field of pgn is updated 3311590Srgrimes * to reflect the additional child. 3321590Srgrimes *--------------------------------------------------------------------- 3331590Srgrimes */ 334143027Shartistatic void 335143027ShartiParseLinkSrc(Lst *parents, GNode *cgn) 3361590Srgrimes{ 337143027Sharti LstNode *ln; 338143027Sharti GNode *pgn; 339138232Sharti 340143027Sharti LST_FOREACH(ln, parents) { 341143027Sharti pgn = Lst_Datum(ln); 342143027Sharti if (Lst_Member(&pgn->children, cgn) == NULL) { 343143027Sharti Lst_AtEnd(&pgn->children, cgn); 344143027Sharti if (specType == Not) { 345143027Sharti Lst_AtEnd(&cgn->parents, pgn); 346143027Sharti } 347143027Sharti pgn->unmade += 1; 348143027Sharti } 3491590Srgrimes } 3501590Srgrimes} 3511590Srgrimes 3521590Srgrimes/*- 3531590Srgrimes *--------------------------------------------------------------------- 3541590Srgrimes * ParseDoOp -- 3551590Srgrimes * Apply the parsed operator to the given target node. Used in a 3561590Srgrimes * Lst_ForEach call by ParseDoDependency once all targets have 3571590Srgrimes * been found and their operator parsed. If the previous and new 3581590Srgrimes * operators are incompatible, a major error is taken. 3591590Srgrimes * 3601590Srgrimes * Results: 3611590Srgrimes * Always 0 3621590Srgrimes * 3631590Srgrimes * Side Effects: 3641590Srgrimes * The type field of the node is altered to reflect any new bits in 3651590Srgrimes * the op. 3661590Srgrimes *--------------------------------------------------------------------- 3671590Srgrimes */ 3681590Srgrimesstatic int 369138232ShartiParseDoOp(void *gnp, void *opp) 3701590Srgrimes{ 371138264Sharti GNode *gn = gnp; 372138264Sharti int op = *(int *)opp; 373138232Sharti 3741590Srgrimes /* 3751590Srgrimes * If the dependency mask of the operator and the node don't match and 3761590Srgrimes * the node has actually had an operator applied to it before, and 3778874Srgrimes * the operator actually has some dependency information in it, complain. 3781590Srgrimes */ 3791590Srgrimes if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 3801590Srgrimes !OP_NOP(gn->type) && !OP_NOP(op)) 3811590Srgrimes { 382138232Sharti Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); 3831590Srgrimes return (1); 3841590Srgrimes } 3851590Srgrimes 3861590Srgrimes if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 3871590Srgrimes /* 3881590Srgrimes * If the node was the object of a :: operator, we need to create a 3891590Srgrimes * new instance of it for the children and commands on this dependency 3901590Srgrimes * line. The new instance is placed on the 'cohorts' list of the 3911590Srgrimes * initial one (note the initial one is not on its own cohorts list) 3921590Srgrimes * and the new instance is linked to all parents of the initial 3931590Srgrimes * instance. 3941590Srgrimes */ 395138512Sharti GNode *cohort; 396138512Sharti LstNode *ln; 3978874Srgrimes 3981590Srgrimes cohort = Targ_NewGN(gn->name); 3991590Srgrimes /* 4001590Srgrimes * Duplicate links to parents so graph traversal is simple. Perhaps 4011590Srgrimes * some type bits should be duplicated? 4021590Srgrimes * 4031590Srgrimes * Make the cohort invisible as well to avoid duplicating it into 4041590Srgrimes * other variables. True, parents of this target won't tend to do 4051590Srgrimes * anything with their local variables, but better safe than 4061590Srgrimes * sorry. 4071590Srgrimes */ 408143027Sharti ParseLinkSrc(&gn->parents, cohort); 4091590Srgrimes cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 410138916Sharti Lst_AtEnd(&gn->cohorts, cohort); 4111590Srgrimes 4121590Srgrimes /* 4131590Srgrimes * Replace the node in the targets list with the new copy 4141590Srgrimes */ 415138916Sharti ln = Lst_Member(&targets, gn); 416138264Sharti Lst_Replace(ln, cohort); 4171590Srgrimes gn = cohort; 4181590Srgrimes } 4191590Srgrimes /* 4201590Srgrimes * We don't want to nuke any previous flags (whatever they were) so we 4218874Srgrimes * just OR the new operator into the old 4221590Srgrimes */ 4231590Srgrimes gn->type |= op; 4241590Srgrimes 4251590Srgrimes return (0); 4261590Srgrimes} 4271590Srgrimes 4281590Srgrimes/*- 4291590Srgrimes *--------------------------------------------------------------------- 43018730Ssteve * ParseAddDep -- 43118730Ssteve * Check if the pair of GNodes given needs to be synchronized. 43218730Ssteve * This has to be when two nodes are on different sides of a 43318730Ssteve * .WAIT directive. 43418730Ssteve * 43518730Ssteve * Results: 43618730Ssteve * Returns 1 if the two targets need to be ordered, 0 otherwise. 43718730Ssteve * If it returns 1, the search can stop 43818730Ssteve * 43918730Ssteve * Side Effects: 44018730Ssteve * A dependency can be added between the two nodes. 44118730Ssteve * 44218730Ssteve *--------------------------------------------------------------------- 44318730Ssteve */ 44449938Shoekstatic int 445104696SjmallettParseAddDep(void *pp, void *sp) 44618730Ssteve{ 447138264Sharti GNode *p = pp; 448138264Sharti GNode *s = sp; 44918730Ssteve 45018730Ssteve if (p->order < s->order) { 45118730Ssteve /* 45218730Ssteve * XXX: This can cause loops, and loops can cause unmade targets, 45318730Ssteve * but checking is tedious, and the debugging output can show the 45418730Ssteve * problem 45518730Ssteve */ 456138916Sharti Lst_AtEnd(&p->successors, s); 457138916Sharti Lst_AtEnd(&s->preds, p); 458138232Sharti return (0); 45918730Ssteve } 46018730Ssteve else 461138232Sharti return (1); 46218730Ssteve} 46318730Ssteve 46418730Ssteve 46518730Ssteve/*- 46618730Ssteve *--------------------------------------------------------------------- 4671590Srgrimes * ParseDoSrc -- 4681590Srgrimes * Given the name of a source, figure out if it is an attribute 4691590Srgrimes * and apply it to the targets if it is. Else decide if there is 4701590Srgrimes * some attribute which should be applied *to* the source because 4711590Srgrimes * of some special target and apply it if so. Otherwise, make the 4721590Srgrimes * source be a child of the targets in the list 'targets' 4731590Srgrimes * 4741590Srgrimes * Results: 4751590Srgrimes * None 4761590Srgrimes * 4771590Srgrimes * Side Effects: 4781590Srgrimes * Operator bits may be added to the list of targets or to the source. 4791590Srgrimes * The targets may have a new source added to their lists of children. 4801590Srgrimes *--------------------------------------------------------------------- 4811590Srgrimes */ 4821590Srgrimesstatic void 483138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc) 4841590Srgrimes{ 48518730Ssteve GNode *gn = NULL; 4861590Srgrimes 48798508Sjmallett if (*src == '.' && isupper ((unsigned char) src[1])) { 4881590Srgrimes int keywd = ParseFindKeyword(src); 4891590Srgrimes if (keywd != -1) { 49018730Ssteve int op = parseKeywords[keywd].op; 49118730Ssteve if (op != 0) { 492138916Sharti Lst_ForEach(&targets, ParseDoOp, &op); 49318730Ssteve return; 49418730Ssteve } 49518730Ssteve if (parseKeywords[keywd].spec == Wait) { 49618730Ssteve waiting++; 49718730Ssteve return; 49818730Ssteve } 4991590Srgrimes } 5001590Srgrimes } 50118730Ssteve 50218730Ssteve switch (specType) { 50318730Ssteve case Main: 5041590Srgrimes /* 5051590Srgrimes * If we have noted the existence of a .MAIN, it means we need 5061590Srgrimes * to add the sources of said target to the list of things 5071590Srgrimes * to create. The string 'src' is likely to be free, so we 5081590Srgrimes * must make a new copy of it. Note that this will only be 5091590Srgrimes * invoked if the user didn't specify a target on the command 5101590Srgrimes * line. This is to allow #ifmake's to succeed, or something... 5111590Srgrimes */ 512138916Sharti Lst_AtEnd(&create, estrdup(src)); 5131590Srgrimes /* 5141590Srgrimes * Add the name to the .TARGETS variable as well, so the user cna 5151590Srgrimes * employ that, if desired. 5161590Srgrimes */ 5171590Srgrimes Var_Append(".TARGETS", src, VAR_GLOBAL); 51818730Ssteve return; 51918730Ssteve 52018730Ssteve case Order: 5211590Srgrimes /* 5221590Srgrimes * Create proper predecessor/successor links between the previous 5231590Srgrimes * source and the current one. 5241590Srgrimes */ 5251590Srgrimes gn = Targ_FindNode(src, TARG_CREATE); 52669527Swill if (predecessor != NULL) { 527138916Sharti Lst_AtEnd(&predecessor->successors, gn); 528138916Sharti Lst_AtEnd(&gn->preds, predecessor); 5291590Srgrimes } 5301590Srgrimes /* 5311590Srgrimes * The current source now becomes the predecessor for the next one. 5321590Srgrimes */ 5331590Srgrimes predecessor = gn; 53418730Ssteve break; 53518730Ssteve 53618730Ssteve default: 5371590Srgrimes /* 5381590Srgrimes * If the source is not an attribute, we need to find/create 5391590Srgrimes * a node for it. After that we can apply any operator to it 5401590Srgrimes * from a special target or link it to its parents, as 5411590Srgrimes * appropriate. 5421590Srgrimes * 5431590Srgrimes * In the case of a source that was the object of a :: operator, 5441590Srgrimes * the attribute is applied to all of its instances (as kept in 5451590Srgrimes * the 'cohorts' list of the node) or all the cohorts are linked 5461590Srgrimes * to all the targets. 5471590Srgrimes */ 548138232Sharti gn = Targ_FindNode(src, TARG_CREATE); 5491590Srgrimes if (tOp) { 5501590Srgrimes gn->type |= tOp; 5511590Srgrimes } else { 552143027Sharti ParseLinkSrc(&targets, gn); 5531590Srgrimes } 5541590Srgrimes if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 55594584Sobrien GNode *cohort; 556138512Sharti LstNode *ln; 5571590Srgrimes 558138916Sharti for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Succ(ln)) { 559138264Sharti cohort = Lst_Datum(ln); 5601590Srgrimes if (tOp) { 5611590Srgrimes cohort->type |= tOp; 5621590Srgrimes } else { 563143027Sharti ParseLinkSrc(&targets, cohort); 5641590Srgrimes } 5651590Srgrimes } 5661590Srgrimes } 56718730Ssteve break; 5681590Srgrimes } 56918730Ssteve 57018730Ssteve gn->order = waiting; 571138264Sharti Lst_AtEnd(allsrc, gn); 57218730Ssteve if (waiting) { 573138264Sharti Lst_ForEach(allsrc, ParseAddDep, gn); 57418730Ssteve } 5751590Srgrimes} 5761590Srgrimes 5771590Srgrimes/*- 5781590Srgrimes *----------------------------------------------------------------------- 5791590Srgrimes * ParseFindMain -- 5801590Srgrimes * Find a real target in the list and set it to be the main one. 5811590Srgrimes * Called by ParseDoDependency when a main target hasn't been found 5821590Srgrimes * yet. 5831590Srgrimes * 5841590Srgrimes * Results: 5851590Srgrimes * 0 if main not found yet, 1 if it is. 5861590Srgrimes * 5871590Srgrimes * Side Effects: 5881590Srgrimes * mainNode is changed and Targ_SetMain is called. 5891590Srgrimes * 5901590Srgrimes *----------------------------------------------------------------------- 5911590Srgrimes */ 5921590Srgrimesstatic int 593104696SjmallettParseFindMain(void *gnp, void *dummy __unused) 5941590Srgrimes{ 595138264Sharti GNode *gn = gnp; 596138264Sharti 597138232Sharti if ((gn->type & (OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM)) == 0) { 5981590Srgrimes mainNode = gn; 5991590Srgrimes Targ_SetMain(gn); 600104696Sjmallett return (1); 6011590Srgrimes } else { 602104696Sjmallett return (0); 6031590Srgrimes } 6041590Srgrimes} 6051590Srgrimes 6061590Srgrimes/*- 6071590Srgrimes *----------------------------------------------------------------------- 6081590Srgrimes * ParseAddDir -- 6091590Srgrimes * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 6101590Srgrimes * 6111590Srgrimes * Results: 6121590Srgrimes * === 0 6131590Srgrimes * 6141590Srgrimes * Side Effects: 6151590Srgrimes * See Dir_AddDir. 6161590Srgrimes * 6171590Srgrimes *----------------------------------------------------------------------- 6181590Srgrimes */ 6191590Srgrimesstatic int 620104696SjmallettParseAddDir(void *path, void *name) 6211590Srgrimes{ 622138232Sharti 623138264Sharti Dir_AddDir(path, name); 6241590Srgrimes return(0); 6251590Srgrimes} 6261590Srgrimes 6271590Srgrimes/*- 6281590Srgrimes *----------------------------------------------------------------------- 6291590Srgrimes * ParseClearPath -- 6301590Srgrimes * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going 6311590Srgrimes * 6321590Srgrimes * Results: 6331590Srgrimes * === 0 6341590Srgrimes * 6351590Srgrimes * Side Effects: 6361590Srgrimes * See Dir_ClearPath 6371590Srgrimes * 6381590Srgrimes *----------------------------------------------------------------------- 6391590Srgrimes */ 6401590Srgrimesstatic int 641104696SjmallettParseClearPath(void *path, void *dummy __unused) 6421590Srgrimes{ 643138232Sharti 644138264Sharti Dir_ClearPath(path); 645104696Sjmallett return (0); 6461590Srgrimes} 6471590Srgrimes 6481590Srgrimes/*- 6491590Srgrimes *--------------------------------------------------------------------- 6501590Srgrimes * ParseDoDependency -- 6511590Srgrimes * Parse the dependency line in line. 6521590Srgrimes * 6531590Srgrimes * Results: 6541590Srgrimes * None 6551590Srgrimes * 6561590Srgrimes * Side Effects: 6571590Srgrimes * The nodes of the sources are linked as children to the nodes of the 6581590Srgrimes * targets. Some nodes may be created. 6591590Srgrimes * 6601590Srgrimes * We parse a dependency line by first extracting words from the line and 6611590Srgrimes * finding nodes in the list of all targets with that name. This is done 6621590Srgrimes * until a character is encountered which is an operator character. Currently 6631590Srgrimes * these are only ! and :. At this point the operator is parsed and the 6641590Srgrimes * pointer into the line advanced until the first source is encountered. 6651590Srgrimes * The parsed operator is applied to each node in the 'targets' list, 6661590Srgrimes * which is where the nodes found for the targets are kept, by means of 6671590Srgrimes * the ParseDoOp function. 6681590Srgrimes * The sources are read in much the same way as the targets were except 6691590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell 6701590Srgrimes * and all instances of the resulting words in the list of all targets 6711590Srgrimes * are found. Each of the resulting nodes is then linked to each of the 6721590Srgrimes * targets as one of its children. 6731590Srgrimes * Certain targets are handled specially. These are the ones detailed 6741590Srgrimes * by the specType variable. 6751590Srgrimes * The storing of transformation rules is also taken care of here. 6761590Srgrimes * A target is recognized as a transformation rule by calling 6771590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten 6781590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard 6791590Srgrimes * Targ_FindNode in the target module. 6801590Srgrimes *--------------------------------------------------------------------- 6811590Srgrimes */ 6821590Srgrimesstatic void 683141270ShartiParseDoDependency(char *line) 6841590Srgrimes{ 6855814Sjkh char *cp; /* our current position */ 6865814Sjkh GNode *gn; /* a general purpose temporary node */ 6875814Sjkh int op; /* the operator on the line */ 6881590Srgrimes char savec; /* a place to save a character */ 689138916Sharti Lst paths; /* Search paths to alter when parsing a list of .PATH targets */ 6901590Srgrimes int tOp; /* operator from special target */ 6911590Srgrimes 6921590Srgrimes tOp = 0; 6931590Srgrimes 6941590Srgrimes specType = Not; 69518730Ssteve waiting = 0; 696138916Sharti Lst_Init(&paths); 6971590Srgrimes 6981590Srgrimes do { 6991590Srgrimes for (cp = line; 700138264Sharti *cp && !isspace((unsigned char)*cp) && *cp != '('; 701138264Sharti cp++) 7021590Srgrimes { 7031590Srgrimes if (*cp == '$') { 7041590Srgrimes /* 7051590Srgrimes * Must be a dynamic source (would have been expanded 7061590Srgrimes * otherwise), so call the Var module to parse the puppy 7071590Srgrimes * so we can safely advance beyond it...There should be 7081590Srgrimes * no errors in this, as they would have been discovered 7091590Srgrimes * in the initial Var_Subst and we wouldn't be here. 7101590Srgrimes */ 711142937Sharti size_t length = 0; 7121590Srgrimes Boolean freeIt; 7131590Srgrimes char *result; 7141590Srgrimes 715138232Sharti result = Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt); 7161590Srgrimes 7171590Srgrimes if (freeIt) { 7181590Srgrimes free(result); 7191590Srgrimes } 720138232Sharti cp += length - 1; 721102178Sru } else if (*cp == '!' || *cp == ':') { 722102178Sru /* 723102178Sru * We don't want to end a word on ':' or '!' if there is a 724107373Sru * better match later on in the string (greedy matching). 725107373Sru * This allows the user to have targets like: 726102178Sru * fie::fi:fo: fum 727107373Sru * foo::bar: 728107373Sru * where "fie::fi:fo" and "foo::bar" are the targets. In 729107373Sru * real life this is used for perl5 library man pages where 730107373Sru * "::" separates an object from its class. 731107373Sru * Ie: "File::Spec::Unix". This behaviour is also consistent 732107373Sru * with other versions of make. 733102178Sru */ 734102178Sru char *p = cp + 1; 735102178Sru 736103991Sjmallett if (*cp == ':' && *p == ':') 737102178Sru p++; 738102178Sru 739102178Sru /* Found the best match already. */ 740102178Sru if (*p == '\0' || isspace(*p)) 741102178Sru break; 742102178Sru 743107373Sru p += strcspn(p, "!:"); 744102178Sru 745102178Sru /* No better match later on... */ 746102178Sru if (*p == '\0') 747102178Sru break; 7481590Srgrimes } 7491590Srgrimes continue; 7501590Srgrimes } 7511590Srgrimes if (*cp == '(') { 7521590Srgrimes /* 7531590Srgrimes * Archives must be handled specially to make sure the OP_ARCHV 7541590Srgrimes * flag is set in their 'type' field, for one thing, and because 7551590Srgrimes * things like "archive(file1.o file2.o file3.o)" are permissible. 7561590Srgrimes * Arch_ParseArchive will set 'line' to be the first non-blank 7571590Srgrimes * after the archive-spec. It creates/finds nodes for the members 7581590Srgrimes * and places them on the given list, returning SUCCESS if all 7591590Srgrimes * went well and FAILURE if there was an error in the 7601590Srgrimes * specification. On error, line should remain untouched. 7611590Srgrimes */ 762138916Sharti if (Arch_ParseArchive(&line, &targets, VAR_CMD) != SUCCESS) { 763138232Sharti Parse_Error(PARSE_FATAL, 7641590Srgrimes "Error in archive specification: \"%s\"", line); 7651590Srgrimes return; 7661590Srgrimes } else { 7671590Srgrimes continue; 7681590Srgrimes } 7691590Srgrimes } 7701590Srgrimes savec = *cp; 7718874Srgrimes 7721590Srgrimes if (!*cp) { 7731590Srgrimes /* 7741590Srgrimes * Ending a dependency line without an operator is a Bozo 77598506Sjmallett * no-no. As a heuristic, this is also often triggered by 77698506Sjmallett * undetected conflicts from cvs/rcs merges. 7771590Srgrimes */ 77898506Sjmallett if ((strncmp(line, "<<<<<<", 6) == 0) || 77998506Sjmallett (strncmp(line, "======", 6) == 0) || 78098506Sjmallett (strncmp(line, ">>>>>>", 6) == 0)) 781138232Sharti Parse_Error(PARSE_FATAL, 78298506Sjmallett "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); 78398506Sjmallett else 784138232Sharti Parse_Error(PARSE_FATAL, "Need an operator"); 7851590Srgrimes return; 7861590Srgrimes } 7871590Srgrimes *cp = '\0'; 7881590Srgrimes /* 7891590Srgrimes * Have a word in line. See if it's a special target and set 7901590Srgrimes * specType to match it. 7911590Srgrimes */ 792138264Sharti if (*line == '.' && isupper((unsigned char)line[1])) { 7931590Srgrimes /* 7941590Srgrimes * See if the target is a special target that must have it 7958874Srgrimes * or its sources handled specially. 7961590Srgrimes */ 7971590Srgrimes int keywd = ParseFindKeyword(line); 7981590Srgrimes if (keywd != -1) { 7991590Srgrimes if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 8001590Srgrimes Parse_Error(PARSE_FATAL, "Mismatched special targets"); 8011590Srgrimes return; 8021590Srgrimes } 8038874Srgrimes 8041590Srgrimes specType = parseKeywords[keywd].spec; 8051590Srgrimes tOp = parseKeywords[keywd].op; 8061590Srgrimes 8071590Srgrimes /* 8081590Srgrimes * Certain special targets have special semantics: 8091590Srgrimes * .PATH Have to set the dirSearchPath 8101590Srgrimes * variable too 8111590Srgrimes * .MAIN Its sources are only used if 8121590Srgrimes * nothing has been specified to 8131590Srgrimes * create. 8141590Srgrimes * .DEFAULT Need to create a node to hang 8151590Srgrimes * commands on, but we don't want 8161590Srgrimes * it in the graph, nor do we want 8171590Srgrimes * it to be the Main Target, so we 8181590Srgrimes * create it, set OP_NOTMAIN and 8191590Srgrimes * add it to the list, setting 8201590Srgrimes * DEFAULT to the new node for 8211590Srgrimes * later use. We claim the node is 8221590Srgrimes * A transformation rule to make 8231590Srgrimes * life easier later, when we'll 8241590Srgrimes * use Make_HandleUse to actually 8251590Srgrimes * apply the .DEFAULT commands. 82618730Ssteve * .PHONY The list of targets 8271590Srgrimes * .BEGIN 8281590Srgrimes * .END 8291590Srgrimes * .INTERRUPT Are not to be considered the 8301590Srgrimes * main target. 8311590Srgrimes * .NOTPARALLEL Make only one target at a time. 8321590Srgrimes * .SINGLESHELL Create a shell for each command. 83369527Swill * .ORDER Must set initial predecessor to NULL 8341590Srgrimes */ 8351590Srgrimes switch (specType) { 8361590Srgrimes case ExPath: 837138916Sharti Lst_AtEnd(&paths, &dirSearchPath); 8381590Srgrimes break; 8391590Srgrimes case Main: 840138916Sharti if (!Lst_IsEmpty(&create)) { 8411590Srgrimes specType = Not; 8421590Srgrimes } 8431590Srgrimes break; 8441590Srgrimes case Begin: 8451590Srgrimes case End: 8461590Srgrimes case Interrupt: 8471590Srgrimes gn = Targ_FindNode(line, TARG_CREATE); 8481590Srgrimes gn->type |= OP_NOTMAIN; 849138916Sharti Lst_AtEnd(&targets, gn); 8501590Srgrimes break; 8511590Srgrimes case Default: 8521590Srgrimes gn = Targ_NewGN(".DEFAULT"); 8531590Srgrimes gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 854138916Sharti Lst_AtEnd(&targets, gn); 8551590Srgrimes DEFAULT = gn; 8561590Srgrimes break; 8571590Srgrimes case NotParallel: 8581590Srgrimes { 8591590Srgrimes maxJobs = 1; 8601590Srgrimes break; 8611590Srgrimes } 8621590Srgrimes case SingleShell: 8631590Srgrimes compatMake = 1; 8641590Srgrimes break; 8651590Srgrimes case Order: 86669527Swill predecessor = NULL; 8671590Srgrimes break; 8681590Srgrimes default: 8691590Srgrimes break; 8701590Srgrimes } 871138232Sharti } else if (strncmp(line, ".PATH", 5) == 0) { 8721590Srgrimes /* 8731590Srgrimes * .PATH<suffix> has to be handled specially. 8741590Srgrimes * Call on the suffix module to give us a path to 8751590Srgrimes * modify. 8761590Srgrimes */ 877138512Sharti Lst *path; 8788874Srgrimes 8791590Srgrimes specType = ExPath; 880138232Sharti path = Suff_GetPath(&line[5]); 88169527Swill if (path == NULL) { 882138232Sharti Parse_Error(PARSE_FATAL, 8831590Srgrimes "Suffix '%s' not defined (yet)", 8841590Srgrimes &line[5]); 8851590Srgrimes return; 886138916Sharti } else 887138916Sharti Lst_AtEnd(&paths, path); 8881590Srgrimes } 8891590Srgrimes } 8908874Srgrimes 8911590Srgrimes /* 8921590Srgrimes * Have word in line. Get or create its node and stick it at 8938874Srgrimes * the end of the targets list 8941590Srgrimes */ 8951590Srgrimes if ((specType == Not) && (*line != '\0')) { 896138916Sharti /* target names to be found and added to targets list */ 897138916Sharti Lst curTargs = Lst_Initializer(curTargs); 898138916Sharti 8991590Srgrimes if (Dir_HasWildcards(line)) { 9001590Srgrimes /* 9011590Srgrimes * Targets are to be sought only in the current directory, 9021590Srgrimes * so create an empty path for the thing. Note we need to 9031590Srgrimes * use Dir_Destroy in the destruction of the path as the 9041590Srgrimes * Dir module could have added a directory to the path... 9051590Srgrimes */ 906138916Sharti Lst emptyPath = Lst_Initializer(emptyPath); 9078874Srgrimes 908138916Sharti Dir_Expand(line, &emptyPath, &curTargs); 9098874Srgrimes 910138916Sharti Lst_Destroy(&emptyPath, Dir_Destroy); 9111590Srgrimes } else { 9121590Srgrimes /* 9131590Srgrimes * No wildcards, but we want to avoid code duplication, 9141590Srgrimes * so create a list with the word on it. 9151590Srgrimes */ 916138916Sharti Lst_AtEnd(&curTargs, line); 9171590Srgrimes } 9188874Srgrimes 919138916Sharti while (!Lst_IsEmpty(&curTargs)) { 920138916Sharti char *targName = Lst_DeQueue(&curTargs); 9218874Srgrimes 9221590Srgrimes if (!Suff_IsTransform (targName)) { 923138232Sharti gn = Targ_FindNode(targName, TARG_CREATE); 9241590Srgrimes } else { 925138232Sharti gn = Suff_AddTransform(targName); 9261590Srgrimes } 9278874Srgrimes 928138916Sharti Lst_AtEnd(&targets, gn); 9291590Srgrimes } 9301590Srgrimes } else if (specType == ExPath && *line != '.' && *line != '\0') { 9311590Srgrimes Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 9321590Srgrimes } 9338874Srgrimes 9341590Srgrimes *cp = savec; 9351590Srgrimes /* 9361590Srgrimes * If it is a special type and not .PATH, it's the only target we 9371590Srgrimes * allow on this line... 9381590Srgrimes */ 9391590Srgrimes if (specType != Not && specType != ExPath) { 940141252Sharti Boolean warnFlag = FALSE; 9418874Srgrimes 9421590Srgrimes while ((*cp != '!') && (*cp != ':') && *cp) { 9431590Srgrimes if (*cp != ' ' && *cp != '\t') { 944141252Sharti warnFlag = TRUE; 9451590Srgrimes } 9461590Srgrimes cp++; 9471590Srgrimes } 948141252Sharti if (warnFlag) { 9491590Srgrimes Parse_Error(PARSE_WARNING, "Extra target ignored"); 9501590Srgrimes } 9511590Srgrimes } else { 952138264Sharti while (*cp && isspace((unsigned char)*cp)) { 9531590Srgrimes cp++; 9541590Srgrimes } 9551590Srgrimes } 9561590Srgrimes line = cp; 9571590Srgrimes } while ((*line != '!') && (*line != ':') && *line); 9581590Srgrimes 959138916Sharti if (!Lst_IsEmpty(&targets)) { 960138264Sharti switch (specType) { 9611590Srgrimes default: 9621590Srgrimes Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 9631590Srgrimes break; 9641590Srgrimes case Default: 9651590Srgrimes case Begin: 9661590Srgrimes case End: 9671590Srgrimes case Interrupt: 9681590Srgrimes /* 9691590Srgrimes * These four create nodes on which to hang commands, so 9701590Srgrimes * targets shouldn't be empty... 9711590Srgrimes */ 9721590Srgrimes case Not: 9731590Srgrimes /* 9741590Srgrimes * Nothing special here -- targets can be empty if it wants. 9751590Srgrimes */ 9761590Srgrimes break; 9771590Srgrimes } 9781590Srgrimes } 9791590Srgrimes 9801590Srgrimes /* 9811590Srgrimes * Have now parsed all the target names. Must parse the operator next. The 9821590Srgrimes * result is left in op . 9831590Srgrimes */ 9841590Srgrimes if (*cp == '!') { 9851590Srgrimes op = OP_FORCE; 9861590Srgrimes } else if (*cp == ':') { 9871590Srgrimes if (cp[1] == ':') { 9881590Srgrimes op = OP_DOUBLEDEP; 9891590Srgrimes cp++; 9901590Srgrimes } else { 9911590Srgrimes op = OP_DEPENDS; 9921590Srgrimes } 9931590Srgrimes } else { 994138232Sharti Parse_Error(PARSE_FATAL, "Missing dependency operator"); 9951590Srgrimes return; 9961590Srgrimes } 9971590Srgrimes 9981590Srgrimes cp++; /* Advance beyond operator */ 9991590Srgrimes 1000138916Sharti Lst_ForEach(&targets, ParseDoOp, &op); 10011590Srgrimes 10021590Srgrimes /* 10038874Srgrimes * Get to the first source 10041590Srgrimes */ 1005138264Sharti while (*cp && isspace((unsigned char)*cp)) { 10061590Srgrimes cp++; 10071590Srgrimes } 10081590Srgrimes line = cp; 10091590Srgrimes 10101590Srgrimes /* 10111590Srgrimes * Several special targets take different actions if present with no 10121590Srgrimes * sources: 10131590Srgrimes * a .SUFFIXES line with no sources clears out all old suffixes 10141590Srgrimes * a .PRECIOUS line makes all targets precious 10151590Srgrimes * a .IGNORE line ignores errors for all targets 10161590Srgrimes * a .SILENT line creates silence when making all targets 10171590Srgrimes * a .PATH removes all directories from the search path(s). 10181590Srgrimes */ 10191590Srgrimes if (!*line) { 10201590Srgrimes switch (specType) { 10211590Srgrimes case Suffixes: 1022138232Sharti Suff_ClearSuffixes(); 10231590Srgrimes break; 10241590Srgrimes case Precious: 10251590Srgrimes allPrecious = TRUE; 10261590Srgrimes break; 10271590Srgrimes case Ignore: 10281590Srgrimes ignoreErrors = TRUE; 10291590Srgrimes break; 10301590Srgrimes case Silent: 10311590Srgrimes beSilent = TRUE; 10321590Srgrimes break; 10331590Srgrimes case ExPath: 1034138916Sharti Lst_ForEach(&paths, ParseClearPath, NULL); 10351590Srgrimes break; 103619344Ssteve case Posix: 103719344Ssteve Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 103819344Ssteve break; 10391590Srgrimes default: 10401590Srgrimes break; 10411590Srgrimes } 10421590Srgrimes } else if (specType == MFlags) { 10431590Srgrimes /* 10441590Srgrimes * Call on functions in main.c to deal with these arguments and 10451590Srgrimes * set the initial character to a null-character so the loop to 10461590Srgrimes * get sources won't get anything 10471590Srgrimes */ 1048140870Sharti Main_ParseArgLine(line, 0); 10491590Srgrimes *line = '\0'; 10501590Srgrimes } else if (specType == ExShell) { 1051138232Sharti if (Job_ParseShell(line) != SUCCESS) { 1052138232Sharti Parse_Error(PARSE_FATAL, "improper shell specification"); 10531590Srgrimes return; 10541590Srgrimes } 10551590Srgrimes *line = '\0'; 10561590Srgrimes } else if ((specType == NotParallel) || (specType == SingleShell)) { 10571590Srgrimes *line = '\0'; 10581590Srgrimes } 10598874Srgrimes 10601590Srgrimes /* 10618874Srgrimes * NOW GO FOR THE SOURCES 10621590Srgrimes */ 10631590Srgrimes if ((specType == Suffixes) || (specType == ExPath) || 10641590Srgrimes (specType == Includes) || (specType == Libs) || 10651590Srgrimes (specType == Null)) 10661590Srgrimes { 10671590Srgrimes while (*line) { 10681590Srgrimes /* 10691590Srgrimes * If the target was one that doesn't take files as its sources 10701590Srgrimes * but takes something like suffixes, we take each 10711590Srgrimes * space-separated word on the line as a something and deal 10721590Srgrimes * with it accordingly. 10731590Srgrimes * 10741590Srgrimes * If the target was .SUFFIXES, we take each source as a 10751590Srgrimes * suffix and add it to the list of suffixes maintained by the 10761590Srgrimes * Suff module. 10771590Srgrimes * 10781590Srgrimes * If the target was a .PATH, we add the source as a directory 10791590Srgrimes * to search on the search path. 10801590Srgrimes * 10811590Srgrimes * If it was .INCLUDES, the source is taken to be the suffix of 10821590Srgrimes * files which will be #included and whose search path should 10831590Srgrimes * be present in the .INCLUDES variable. 10841590Srgrimes * 10851590Srgrimes * If it was .LIBS, the source is taken to be the suffix of 10861590Srgrimes * files which are considered libraries and whose search path 10871590Srgrimes * should be present in the .LIBS variable. 10881590Srgrimes * 10891590Srgrimes * If it was .NULL, the source is the suffix to use when a file 10901590Srgrimes * has no valid suffix. 10911590Srgrimes */ 1092104121Sjmallett char savech; 1093138264Sharti while (*cp && !isspace((unsigned char)*cp)) { 10941590Srgrimes cp++; 10951590Srgrimes } 1096104121Sjmallett savech = *cp; 10971590Srgrimes *cp = '\0'; 10981590Srgrimes switch (specType) { 10991590Srgrimes case Suffixes: 1100138232Sharti Suff_AddSuffix(line); 11011590Srgrimes break; 11021590Srgrimes case ExPath: 1103138916Sharti Lst_ForEach(&paths, ParseAddDir, line); 11041590Srgrimes break; 11051590Srgrimes case Includes: 1106138232Sharti Suff_AddInclude(line); 11071590Srgrimes break; 11081590Srgrimes case Libs: 1109138232Sharti Suff_AddLib(line); 11101590Srgrimes break; 11111590Srgrimes case Null: 1112138232Sharti Suff_SetNull(line); 11131590Srgrimes break; 11141590Srgrimes default: 11151590Srgrimes break; 11161590Srgrimes } 1117104121Sjmallett *cp = savech; 1118104121Sjmallett if (savech != '\0') { 11191590Srgrimes cp++; 11201590Srgrimes } 1121138264Sharti while (*cp && isspace((unsigned char)*cp)) { 11221590Srgrimes cp++; 11231590Srgrimes } 11241590Srgrimes line = cp; 11251590Srgrimes } 1126138916Sharti Lst_Destroy(&paths, NOFREE); 1127138916Sharti 11281590Srgrimes } else { 1129138916Sharti Lst curSrcs = Lst_Initializer(curSrc); /* list of sources in order */ 1130141270Sharti 11311590Srgrimes while (*line) { 11321590Srgrimes /* 11331590Srgrimes * The targets take real sources, so we must beware of archive 11341590Srgrimes * specifications (i.e. things with left parentheses in them) 11351590Srgrimes * and handle them accordingly. 11361590Srgrimes */ 1137138264Sharti while (*cp && !isspace((unsigned char)*cp)) { 11381590Srgrimes if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) { 11391590Srgrimes /* 11401590Srgrimes * Only stop for a left parenthesis if it isn't at the 11411590Srgrimes * start of a word (that'll be for variable changes 11421590Srgrimes * later) and isn't preceded by a dollar sign (a dynamic 11431590Srgrimes * source). 11441590Srgrimes */ 11451590Srgrimes break; 11461590Srgrimes } else { 11471590Srgrimes cp++; 11481590Srgrimes } 11491590Srgrimes } 11501590Srgrimes 11511590Srgrimes if (*cp == '(') { 1152104121Sjmallett GNode *gnp; 1153138916Sharti /* list of archive source names after expansion */ 1154138916Sharti Lst sources = Lst_Initializer(sources); 11551590Srgrimes 1156138916Sharti if (Arch_ParseArchive(&line, &sources, VAR_CMD) != SUCCESS) { 1157138232Sharti Parse_Error(PARSE_FATAL, 11581590Srgrimes "Error in source archive spec \"%s\"", line); 11591590Srgrimes return; 11601590Srgrimes } 11611590Srgrimes 1162138916Sharti while (!Lst_IsEmpty(&sources)) { 1163138916Sharti gnp = Lst_DeQueue(&sources); 1164138916Sharti ParseDoSrc(tOp, gnp->name, &curSrcs); 11651590Srgrimes } 11661590Srgrimes cp = line; 11671590Srgrimes } else { 11681590Srgrimes if (*cp) { 11691590Srgrimes *cp = '\0'; 11701590Srgrimes cp += 1; 11711590Srgrimes } 11721590Srgrimes 1173138916Sharti ParseDoSrc(tOp, line, &curSrcs); 11741590Srgrimes } 1175138264Sharti while (*cp && isspace((unsigned char)*cp)) { 11761590Srgrimes cp++; 11771590Srgrimes } 11781590Srgrimes line = cp; 11791590Srgrimes } 1180138916Sharti Lst_Destroy(&curSrcs, NOFREE); 11811590Srgrimes } 11828874Srgrimes 118369527Swill if (mainNode == NULL) { 11841590Srgrimes /* 11851590Srgrimes * If we have yet to decide on a main target to make, in the 11861590Srgrimes * absence of any user input, we want the first target on 11871590Srgrimes * the first dependency line that is actually a real target 11881590Srgrimes * (i.e. isn't a .USE or .EXEC rule) to be made. 11891590Srgrimes */ 1190138916Sharti Lst_ForEach(&targets, ParseFindMain, NULL); 11911590Srgrimes } 11921590Srgrimes} 11931590Srgrimes 11941590Srgrimes/*- 11951590Srgrimes *--------------------------------------------------------------------- 11961590Srgrimes * Parse_IsVar -- 11971590Srgrimes * Return TRUE if the passed line is a variable assignment. A variable 11981590Srgrimes * assignment consists of a single word followed by optional whitespace 11991590Srgrimes * followed by either a += or an = operator. 12001590Srgrimes * This function is used both by the Parse_File function and main when 12011590Srgrimes * parsing the command-line arguments. 12021590Srgrimes * 12031590Srgrimes * Results: 12041590Srgrimes * TRUE if it is. FALSE if it ain't 12051590Srgrimes * 12061590Srgrimes * Side Effects: 12071590Srgrimes * none 12081590Srgrimes *--------------------------------------------------------------------- 12091590Srgrimes */ 12101590SrgrimesBoolean 1211138232ShartiParse_IsVar(char *line) 12121590Srgrimes{ 121394584Sobrien Boolean wasSpace = FALSE; /* set TRUE if found a space */ 121494584Sobrien Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1215138232Sharti 121618730Ssteve int level = 0; 1217103503Sjmallett#define ISEQOPERATOR(c) \ 121818730Ssteve (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) 12191590Srgrimes 12201590Srgrimes /* 12211590Srgrimes * Skip to variable name 12221590Srgrimes */ 1223138232Sharti for (; (*line == ' ') || (*line == '\t'); line++) 122418730Ssteve continue; 12251590Srgrimes 122618730Ssteve for (; *line != '=' || level != 0; line++) 122718730Ssteve switch (*line) { 122818730Ssteve case '\0': 12291590Srgrimes /* 12301590Srgrimes * end-of-line -- can't be a variable assignment. 12311590Srgrimes */ 1232138232Sharti return (FALSE); 123318730Ssteve 123418730Ssteve case ' ': 123518730Ssteve case '\t': 12361590Srgrimes /* 12371590Srgrimes * there can be as much white space as desired so long as there is 12388874Srgrimes * only one word before the operator 12391590Srgrimes */ 12401590Srgrimes wasSpace = TRUE; 124118730Ssteve break; 124218730Ssteve 124318730Ssteve case '(': 124418730Ssteve case '{': 124518730Ssteve level++; 124618730Ssteve break; 124718730Ssteve 124818730Ssteve case '}': 124918730Ssteve case ')': 125018730Ssteve level--; 125118730Ssteve break; 125218730Ssteve 125318730Ssteve default: 125418730Ssteve if (wasSpace && haveName) { 125518730Ssteve if (ISEQOPERATOR(*line)) { 125618730Ssteve /* 125718730Ssteve * We must have a finished word 125818730Ssteve */ 125918730Ssteve if (level != 0) 1260138232Sharti return (FALSE); 126118730Ssteve 126218730Ssteve /* 126318730Ssteve * When an = operator [+?!:] is found, the next 126418730Ssteve * character must be an = or it ain't a valid 126518730Ssteve * assignment. 126618730Ssteve */ 126718730Ssteve if (line[1] == '=') 1268138232Sharti return (haveName); 126918730Ssteve#ifdef SUNSHCMD 127018730Ssteve /* 127118730Ssteve * This is a shell command 127218730Ssteve */ 127318730Ssteve if (strncmp(line, ":sh", 3) == 0) 1274138232Sharti return (haveName); 127518730Ssteve#endif 127618730Ssteve } 127718730Ssteve /* 127818730Ssteve * This is the start of another word, so not assignment. 127918730Ssteve */ 1280138232Sharti return (FALSE); 12811590Srgrimes } 128218730Ssteve else { 128318730Ssteve haveName = TRUE; 128418730Ssteve wasSpace = FALSE; 128518730Ssteve } 128618730Ssteve break; 12871590Srgrimes } 12881590Srgrimes 1289138232Sharti return (haveName); 12901590Srgrimes} 12911590Srgrimes 12921590Srgrimes/*- 12931590Srgrimes *--------------------------------------------------------------------- 12941590Srgrimes * Parse_DoVar -- 12951590Srgrimes * Take the variable assignment in the passed line and do it in the 12961590Srgrimes * global context. 12971590Srgrimes * 12981590Srgrimes * Note: There is a lexical ambiguity with assignment modifier characters 12991590Srgrimes * in variable names. This routine interprets the character before the = 13001590Srgrimes * as a modifier. Therefore, an assignment like 13011590Srgrimes * C++=/usr/bin/CC 13021590Srgrimes * is interpreted as "C+ +=" instead of "C++ =". 13031590Srgrimes * 13041590Srgrimes * Results: 13051590Srgrimes * none 13061590Srgrimes * 13071590Srgrimes * Side Effects: 13081590Srgrimes * the variable structure of the given variable name is altered in the 13091590Srgrimes * global context. 13101590Srgrimes *--------------------------------------------------------------------- 13111590Srgrimes */ 13121590Srgrimesvoid 1313138232ShartiParse_DoVar(char *line, GNode *ctxt) 13141590Srgrimes{ 13155814Sjkh char *cp; /* pointer into line */ 13161590Srgrimes enum { 13171590Srgrimes VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL 13181590Srgrimes } type; /* Type of assignment */ 13198874Srgrimes char *opc; /* ptr to operator character to 13201590Srgrimes * null-terminate the variable name */ 1321142457Sharti Buffer *buf; 1322142457Sharti 13238874Srgrimes /* 13241590Srgrimes * Avoid clobbered variable warnings by forcing the compiler 13251590Srgrimes * to ``unregister'' variables 13265814Sjkh */ 13271590Srgrimes#if __GNUC__ 1328138232Sharti (void)&cp; 1329138232Sharti (void)&line; 13305814Sjkh#endif 13311590Srgrimes 13321590Srgrimes /* 13331590Srgrimes * Skip to variable name 13341590Srgrimes */ 13351590Srgrimes while ((*line == ' ') || (*line == '\t')) { 13361590Srgrimes line++; 13371590Srgrimes } 13381590Srgrimes 13391590Srgrimes /* 13401590Srgrimes * Skip to operator character, nulling out whitespace as we go 13411590Srgrimes */ 13421590Srgrimes for (cp = line + 1; *cp != '='; cp++) { 1343138264Sharti if (isspace((unsigned char)*cp)) { 13441590Srgrimes *cp = '\0'; 13451590Srgrimes } 13461590Srgrimes } 1347138232Sharti opc = cp - 1; /* operator is the previous character */ 13481590Srgrimes *cp++ = '\0'; /* nuke the = */ 13491590Srgrimes 13501590Srgrimes /* 13511590Srgrimes * Check operator type 13521590Srgrimes */ 13531590Srgrimes switch (*opc) { 13541590Srgrimes case '+': 13551590Srgrimes type = VAR_APPEND; 13561590Srgrimes *opc = '\0'; 13571590Srgrimes break; 13581590Srgrimes 13591590Srgrimes case '?': 13601590Srgrimes /* 13611590Srgrimes * If the variable already has a value, we don't do anything. 13621590Srgrimes */ 13631590Srgrimes *opc = '\0'; 13641590Srgrimes if (Var_Exists(line, ctxt)) { 13651590Srgrimes return; 13661590Srgrimes } else { 13671590Srgrimes type = VAR_NORMAL; 13681590Srgrimes } 13691590Srgrimes break; 13701590Srgrimes 13711590Srgrimes case ':': 13721590Srgrimes type = VAR_SUBST; 13731590Srgrimes *opc = '\0'; 13741590Srgrimes break; 13751590Srgrimes 13761590Srgrimes case '!': 13771590Srgrimes type = VAR_SHELL; 13781590Srgrimes *opc = '\0'; 13791590Srgrimes break; 13801590Srgrimes 13811590Srgrimes default: 138218730Ssteve#ifdef SUNSHCMD 138318730Ssteve while (*opc != ':') 138442409Sjkh if (opc == line) 138518730Ssteve break; 138642409Sjkh else 138742409Sjkh --opc; 138818730Ssteve 138918730Ssteve if (strncmp(opc, ":sh", 3) == 0) { 139018730Ssteve type = VAR_SHELL; 139118730Ssteve *opc = '\0'; 139218730Ssteve break; 139318730Ssteve } 139418730Ssteve#endif 13951590Srgrimes type = VAR_NORMAL; 13961590Srgrimes break; 13971590Srgrimes } 13981590Srgrimes 1399138264Sharti while (isspace((unsigned char)*cp)) { 14001590Srgrimes cp++; 14011590Srgrimes } 14021590Srgrimes 14031590Srgrimes if (type == VAR_APPEND) { 1404138232Sharti Var_Append(line, cp, ctxt); 14051590Srgrimes } else if (type == VAR_SUBST) { 14061590Srgrimes /* 14071590Srgrimes * Allow variables in the old value to be undefined, but leave their 14081590Srgrimes * invocation alone -- this is done by forcing oldVars to be false. 14091590Srgrimes * XXX: This can cause recursive variables, but that's not hard to do, 14101590Srgrimes * and this allows someone to do something like 14111590Srgrimes * 14121590Srgrimes * CFLAGS = $(.INCLUDES) 14131590Srgrimes * CFLAGS := -I.. $(CFLAGS) 14141590Srgrimes * 14151590Srgrimes * And not get an error. 14161590Srgrimes */ 14171590Srgrimes Boolean oldOldVars = oldVars; 14181590Srgrimes 14191590Srgrimes oldVars = FALSE; 142098509Sjmallett 142198509Sjmallett /* 142298509Sjmallett * make sure that we set the variable the first time to nothing 142398509Sjmallett * so that it gets substituted! 142498509Sjmallett */ 142598509Sjmallett if (!Var_Exists(line, ctxt)) 142698509Sjmallett Var_Set(line, "", ctxt); 142798509Sjmallett 1428142457Sharti buf = Var_Subst(NULL, cp, ctxt, FALSE); 1429142457Sharti cp = Buf_GetAll(buf, NULL); 1430142457Sharti Buf_Destroy(buf, FALSE); 1431142457Sharti 14321590Srgrimes oldVars = oldOldVars; 14331590Srgrimes 14341590Srgrimes Var_Set(line, cp, ctxt); 14351590Srgrimes free(cp); 14361590Srgrimes } else if (type == VAR_SHELL) { 143718730Ssteve Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e. 143818730Ssteve * if any variable expansion was performed */ 1439141454Sharti Buffer *buf; 1440141252Sharti const char *error; 14411590Srgrimes 144218730Ssteve if (strchr(cp, '$') != NULL) { 14431590Srgrimes /* 14441590Srgrimes * There's a dollar sign in the command, so perform variable 14451590Srgrimes * expansion on the whole thing. The resulting string will need 14461590Srgrimes * freeing when we're done, so set freeCmd to TRUE. 14471590Srgrimes */ 1448142457Sharti buf = Var_Subst(NULL, cp, VAR_CMD, TRUE); 1449142457Sharti cp = Buf_GetAll(buf, NULL); 1450142457Sharti Buf_Destroy(buf, FALSE); 14511590Srgrimes freeCmd = TRUE; 14521590Srgrimes } 14531590Srgrimes 1454141454Sharti buf = Cmd_Exec(cp, &error); 1455141454Sharti Var_Set(line, Buf_GetAll(buf, NULL), ctxt); 1456141454Sharti Buf_Destroy(buf, TRUE); 14571590Srgrimes 1458104121Sjmallett if (error) 1459104121Sjmallett Parse_Error(PARSE_WARNING, error, cp); 14601590Srgrimes 146118730Ssteve if (freeCmd) 146218730Ssteve free(cp); 14631590Srgrimes } else { 14641590Srgrimes /* 14651590Srgrimes * Normal assignment -- just do it. 14661590Srgrimes */ 146718730Ssteve Var_Set(line, cp, ctxt); 14681590Srgrimes } 14691590Srgrimes} 14701590Srgrimes 14711590Srgrimes/*- 14721590Srgrimes * ParseAddCmd -- 14731590Srgrimes * Lst_ForEach function to add a command line to all targets 14741590Srgrimes * 14751590Srgrimes * Results: 14761590Srgrimes * Always 0 14771590Srgrimes * 14781590Srgrimes * Side Effects: 14791590Srgrimes * A new element is added to the commands list of the node. 14801590Srgrimes */ 14811590Srgrimesstatic int 1482104696SjmallettParseAddCmd(void *gnp, void *cmd) 14831590Srgrimes{ 1484138264Sharti GNode *gn = gnp; 1485138232Sharti 14865814Sjkh /* if target already supplied, ignore commands */ 14875814Sjkh if (!(gn->type & OP_HAS_COMMANDS)) 1488138916Sharti Lst_AtEnd(&gn->commands, cmd); 1489100792Sjmallett else 1490100792Sjmallett Parse_Error(PARSE_WARNING, 1491100792Sjmallett "duplicate script for target \"%s\" ignored", 1492100792Sjmallett gn->name); 1493138232Sharti return (0); 14941590Srgrimes} 14951590Srgrimes 14961590Srgrimes/*- 14971590Srgrimes *----------------------------------------------------------------------- 14981590Srgrimes * ParseHasCommands -- 14991590Srgrimes * Callback procedure for Parse_File when destroying the list of 15001590Srgrimes * targets on the last dependency line. Marks a target as already 15011590Srgrimes * having commands if it does, to keep from having shell commands 15021590Srgrimes * on multiple dependency lines. 15031590Srgrimes * 15041590Srgrimes * Results: 15055814Sjkh * None 15061590Srgrimes * 15071590Srgrimes * Side Effects: 15081590Srgrimes * OP_HAS_COMMANDS may be set for the target. 15091590Srgrimes * 15101590Srgrimes *----------------------------------------------------------------------- 15111590Srgrimes */ 15125814Sjkhstatic void 1513104696SjmallettParseHasCommands(void *gnp) 15141590Srgrimes{ 1515138264Sharti GNode *gn = gnp; 1516138232Sharti 1517138916Sharti if (!Lst_IsEmpty(&gn->commands)) { 15181590Srgrimes gn->type |= OP_HAS_COMMANDS; 15191590Srgrimes } 15201590Srgrimes} 15211590Srgrimes 15221590Srgrimes/*- 15231590Srgrimes *----------------------------------------------------------------------- 15241590Srgrimes * Parse_AddIncludeDir -- 15251590Srgrimes * Add a directory to the path searched for included makefiles 15261590Srgrimes * bracketed by double-quotes. Used by functions in main.c 15271590Srgrimes * 15281590Srgrimes * Results: 15291590Srgrimes * None. 15301590Srgrimes * 15311590Srgrimes * Side Effects: 15321590Srgrimes * The directory is appended to the list. 15331590Srgrimes * 15341590Srgrimes *----------------------------------------------------------------------- 15351590Srgrimes */ 15361590Srgrimesvoid 1537138232ShartiParse_AddIncludeDir(char *dir) 15381590Srgrimes{ 1539138232Sharti 1540138916Sharti Dir_AddDir(&parseIncPath, dir); 15411590Srgrimes} 15421590Srgrimes 154336347Ssteve/*--------------------------------------------------------------------- 154436347Ssteve * ParseDoError -- 154536347Ssteve * Handle error directive 154636347Ssteve * 154736347Ssteve * The input is the line minus the ".error". We substitute variables, 154836347Ssteve * print the message and exit(1) or just print a warning if the ".error" 154936347Ssteve * directive is malformed. 155036347Ssteve * 155136347Ssteve *--------------------------------------------------------------------- 155236347Ssteve */ 155336347Sstevestatic void 1554104696SjmallettParseDoError(char *errmsg) 155536347Ssteve{ 1556142457Sharti Buffer *buf; 1557138232Sharti 1558138232Sharti if (!isspace((unsigned char)*errmsg)) { 155936347Ssteve Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg); 156036347Ssteve return; 156136347Ssteve } 1562138232Sharti 1563138232Sharti while (isspace((unsigned char)*errmsg)) 156436347Ssteve errmsg++; 1565138232Sharti 1566142457Sharti buf = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE); 1567142457Sharti errmsg = Buf_GetAll(buf, NULL); 156836347Ssteve 1569128160Sru Parse_Error(PARSE_FATAL, "%s", errmsg); 1570142457Sharti Buf_Destroy(buf, TRUE); 1571142457Sharti 1572128160Sru /* Terminate immediately. */ 157336347Ssteve exit(1); 157436347Ssteve} 157536347Ssteve 1576128160Sru/*--------------------------------------------------------------------- 1577128160Sru * ParseDoWarning -- 1578128160Sru * Handle warning directive 1579128160Sru * 1580128160Sru * The input is the line minus the ".warning". We substitute variables 1581128160Sru * and print the message or just print a warning if the ".warning" 1582128160Sru * directive is malformed. 1583128160Sru * 1584128160Sru *--------------------------------------------------------------------- 1585128160Sru */ 1586128160Srustatic void 1587128160SruParseDoWarning(char *warnmsg) 1588128160Sru{ 1589142457Sharti Buffer *buf; 1590138232Sharti 1591138232Sharti if (!isspace((unsigned char)*warnmsg)) { 1592128160Sru Parse_Error(PARSE_WARNING, "invalid syntax: .warning%s", 1593128160Sru warnmsg); 1594128160Sru return; 1595128160Sru } 1596138232Sharti 1597138232Sharti while (isspace((unsigned char)*warnmsg)) 1598128160Sru warnmsg++; 1599138232Sharti 1600142457Sharti buf = Var_Subst(NULL, warnmsg, VAR_GLOBAL, FALSE); 1601142457Sharti warnmsg = Buf_GetAll(buf, NULL); 1602128160Sru 1603128160Sru Parse_Error(PARSE_WARNING, "%s", warnmsg); 1604142457Sharti Buf_Destroy(buf, TRUE); 1605128160Sru} 1606128160Sru 16071590Srgrimes/*- 16081590Srgrimes *--------------------------------------------------------------------- 16091590Srgrimes * ParseDoInclude -- 16101590Srgrimes * Push to another file. 16118874Srgrimes * 16121590Srgrimes * The input is the line minus the #include. A file spec is a string 16131590Srgrimes * enclosed in <> or "". The former is looked for only in sysIncPath. 16141590Srgrimes * The latter in . and the directories specified by -I command line 16151590Srgrimes * options 16161590Srgrimes * 16171590Srgrimes * Results: 16181590Srgrimes * None 16191590Srgrimes * 16201590Srgrimes * Side Effects: 1621126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1622126824Sru * curFile.fname and curFile.F are altered for the new file 16231590Srgrimes *--------------------------------------------------------------------- 16241590Srgrimes */ 16251590Srgrimesstatic void 1626141270ShartiParseDoInclude(char *file) 16271590Srgrimes{ 16281590Srgrimes char *fullname; /* full pathname of file */ 16291590Srgrimes IFile *oldFile; /* state associated with current file */ 16301590Srgrimes char endc; /* the character which ends the file spec */ 16311590Srgrimes char *cp; /* current position in file spec */ 16321590Srgrimes Boolean isSystem; /* TRUE if makefile is a system makefile */ 1633142457Sharti Buffer *buf; 16341590Srgrimes 16351590Srgrimes /* 16361590Srgrimes * Skip to delimiter character so we know where to look 16371590Srgrimes */ 16381590Srgrimes while ((*file == ' ') || (*file == '\t')) { 16391590Srgrimes file++; 16401590Srgrimes } 16411590Srgrimes 16421590Srgrimes if ((*file != '"') && (*file != '<')) { 1643138232Sharti Parse_Error(PARSE_FATAL, 16441590Srgrimes ".include filename must be delimited by '\"' or '<'"); 16451590Srgrimes return; 16461590Srgrimes } 16471590Srgrimes 16481590Srgrimes /* 16491590Srgrimes * Set the search path on which to find the include file based on the 16501590Srgrimes * characters which bracket its name. Angle-brackets imply it's 16511590Srgrimes * a system Makefile while double-quotes imply it's a user makefile 16521590Srgrimes */ 16531590Srgrimes if (*file == '<') { 16541590Srgrimes isSystem = TRUE; 16551590Srgrimes endc = '>'; 16561590Srgrimes } else { 16571590Srgrimes isSystem = FALSE; 16581590Srgrimes endc = '"'; 16591590Srgrimes } 16601590Srgrimes 16611590Srgrimes /* 16621590Srgrimes * Skip to matching delimiter 16631590Srgrimes */ 16641590Srgrimes for (cp = ++file; *cp && *cp != endc; cp++) { 16651590Srgrimes continue; 16661590Srgrimes } 16671590Srgrimes 16681590Srgrimes if (*cp != endc) { 1669138232Sharti Parse_Error(PARSE_FATAL, 16701590Srgrimes "Unclosed %cinclude filename. '%c' expected", 16711590Srgrimes '.', endc); 16721590Srgrimes return; 16731590Srgrimes } 16741590Srgrimes *cp = '\0'; 16751590Srgrimes 16761590Srgrimes /* 16771590Srgrimes * Substitute for any variables in the file name before trying to 16781590Srgrimes * find the thing. 16791590Srgrimes */ 1680142457Sharti buf = Var_Subst(NULL, file, VAR_CMD, FALSE); 1681142457Sharti file = Buf_GetAll(buf, NULL); 1682142457Sharti Buf_Destroy(buf, FALSE); 16831590Srgrimes 16841590Srgrimes /* 16851590Srgrimes * Now we know the file's name and its search path, we attempt to 16861590Srgrimes * find the durn thing. A return of NULL indicates the file don't 16871590Srgrimes * exist. 16881590Srgrimes */ 16891590Srgrimes if (!isSystem) { 16901590Srgrimes /* 16911590Srgrimes * Include files contained in double-quotes are first searched for 16921590Srgrimes * relative to the including file's location. We don't want to 16931590Srgrimes * cd there, of course, so we just tack on the old file's 16941590Srgrimes * leading path components and call Dir_FindFile to see if 16951590Srgrimes * we can locate the beast. 16961590Srgrimes */ 169718730Ssteve char *prefEnd, *Fname; 16981590Srgrimes 169918730Ssteve /* Make a temporary copy of this, to be safe. */ 1700126824Sru Fname = estrdup(curFile.fname); 170118730Ssteve 1702138232Sharti prefEnd = strrchr(Fname, '/'); 17031590Srgrimes if (prefEnd != (char *)NULL) { 17041590Srgrimes char *newName; 17058874Srgrimes 17061590Srgrimes *prefEnd = '\0'; 17075814Sjkh if (file[0] == '/') 170818730Ssteve newName = estrdup(file); 17095814Sjkh else 1710138232Sharti newName = str_concat(Fname, file, STR_ADDSLASH); 1711138916Sharti fullname = Dir_FindFile(newName, &parseIncPath); 1712138264Sharti if (fullname == NULL) { 1713138916Sharti fullname = Dir_FindFile(newName, &dirSearchPath); 17141590Srgrimes } 1715138232Sharti free(newName); 17161590Srgrimes *prefEnd = '/'; 17171590Srgrimes } else { 1718138264Sharti fullname = NULL; 17191590Srgrimes } 1720138232Sharti free(Fname); 17211590Srgrimes } else { 1722138264Sharti fullname = NULL; 17231590Srgrimes } 17241590Srgrimes 1725138264Sharti if (fullname == NULL) { 17261590Srgrimes /* 17271590Srgrimes * System makefile or makefile wasn't found in same directory as 17281590Srgrimes * included makefile. Search for it first on the -I search path, 17291590Srgrimes * then on the .PATH search path, if not found in a -I directory. 17301590Srgrimes * XXX: Suffix specific? 17311590Srgrimes */ 1732138916Sharti fullname = Dir_FindFile(file, &parseIncPath); 1733138264Sharti if (fullname == NULL) { 1734138916Sharti fullname = Dir_FindFile(file, &dirSearchPath); 17351590Srgrimes } 17361590Srgrimes } 17371590Srgrimes 1738138264Sharti if (fullname == NULL) { 17391590Srgrimes /* 17401590Srgrimes * Still haven't found the makefile. Look for it on the system 17411590Srgrimes * path as a last resort. 17421590Srgrimes */ 1743138916Sharti fullname = Dir_FindFile(file, &sysIncPath); 17441590Srgrimes } 17451590Srgrimes 1746138264Sharti if (fullname == NULL) { 17471590Srgrimes *cp = endc; 1748138232Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1749142457Sharti /* XXXHB free(file) */ 17501590Srgrimes return; 17511590Srgrimes } 17521590Srgrimes 17535814Sjkh free(file); 17545814Sjkh 17551590Srgrimes /* 17561590Srgrimes * Once we find the absolute path to the file, we get to save all the 17571590Srgrimes * state from the current file before we can start reading this 17581590Srgrimes * include file. The state is stored in an IFile structure which 17591590Srgrimes * is placed on a list with other IFile structures. The list makes 17601590Srgrimes * a very nice stack to track how we got here... 17611590Srgrimes */ 1762141270Sharti oldFile = emalloc(sizeof(IFile)); 1763138264Sharti memcpy(oldFile, &curFile, sizeof(IFile)); 17641590Srgrimes 1765138916Sharti Lst_AtFront(&includes, oldFile); 17661590Srgrimes 17671590Srgrimes /* 17681590Srgrimes * Once the previous state has been saved, we can get down to reading 17691590Srgrimes * the new file. We set up the name of the file to be the absolute 17701590Srgrimes * name of the include file so error messages refer to the right 17711590Srgrimes * place. Naturally enough, we start reading at line number 0. 17721590Srgrimes */ 1773126824Sru curFile.fname = fullname; 1774126824Sru curFile.lineno = 0; 17751590Srgrimes 1776138232Sharti curFile.F = fopen(fullname, "r"); 1777126824Sru curFile.p = NULL; 1778138264Sharti if (curFile.F == NULL) { 1779138232Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 17801590Srgrimes /* 17811590Srgrimes * Pop to previous file 17821590Srgrimes */ 1783138232Sharti ParseEOF(0); 1784131456Seik } else { 1785131456Seik Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 17861590Srgrimes } 17871590Srgrimes} 17881590Srgrimes 17891590Srgrimes/*- 17901590Srgrimes *--------------------------------------------------------------------- 17911590Srgrimes * Parse_FromString -- 17921590Srgrimes * Start Parsing from the given string 17938874Srgrimes * 17941590Srgrimes * Results: 17951590Srgrimes * None 17961590Srgrimes * 17971590Srgrimes * Side Effects: 1798126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1799126824Sru * curFile.fname and curFile.F are altered for the new file 18001590Srgrimes *--------------------------------------------------------------------- 18011590Srgrimes */ 18021590Srgrimesvoid 1803126824SruParse_FromString(char *str, int lineno) 18041590Srgrimes{ 18051590Srgrimes IFile *oldFile; /* state associated with this file */ 18061590Srgrimes 1807126824Sru DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 18081590Srgrimes 1809138264Sharti oldFile = emalloc(sizeof(IFile)); 1810138232Sharti memcpy(oldFile, &curFile, sizeof(IFile)); 18118874Srgrimes 1812138916Sharti Lst_AtFront(&includes, oldFile); 18131590Srgrimes 1814126824Sru curFile.F = NULL; 1815141270Sharti curFile.p = emalloc(sizeof(PTR)); 1816126824Sru curFile.p->str = curFile.p->ptr = str; 1817126824Sru curFile.lineno = lineno; 1818126824Sru curFile.fname = estrdup(curFile.fname); 18191590Srgrimes} 18201590Srgrimes 18211590Srgrimes#ifdef SYSVINCLUDE 18221590Srgrimes/*- 18231590Srgrimes *--------------------------------------------------------------------- 18241590Srgrimes * ParseTraditionalInclude -- 18251590Srgrimes * Push to another file. 18268874Srgrimes * 18271590Srgrimes * The input is the line minus the "include". The file name is 18281590Srgrimes * the string following the "include". 18291590Srgrimes * 18301590Srgrimes * Results: 18311590Srgrimes * None 18321590Srgrimes * 18331590Srgrimes * Side Effects: 1834126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1835126824Sru * curFile.fname and curFile.F are altered for the new file 18361590Srgrimes *--------------------------------------------------------------------- 18371590Srgrimes */ 18381590Srgrimesstatic void 1839141270ShartiParseTraditionalInclude(char *file) 18401590Srgrimes{ 18411590Srgrimes char *fullname; /* full pathname of file */ 18421590Srgrimes IFile *oldFile; /* state associated with current file */ 18431590Srgrimes char *cp; /* current position in file spec */ 1844142457Sharti Buffer *buf; 18451590Srgrimes 18461590Srgrimes /* 18471590Srgrimes * Skip over whitespace 18481590Srgrimes */ 18491590Srgrimes while ((*file == ' ') || (*file == '\t')) { 18501590Srgrimes file++; 18511590Srgrimes } 18521590Srgrimes 18531590Srgrimes if (*file == '\0') { 1854138232Sharti Parse_Error(PARSE_FATAL, 18551590Srgrimes "Filename missing from \"include\""); 18561590Srgrimes return; 18571590Srgrimes } 18581590Srgrimes 18591590Srgrimes /* 18601590Srgrimes * Skip to end of line or next whitespace 18611590Srgrimes */ 18621590Srgrimes for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 18631590Srgrimes continue; 18641590Srgrimes } 18651590Srgrimes 18661590Srgrimes *cp = '\0'; 18671590Srgrimes 18681590Srgrimes /* 18691590Srgrimes * Substitute for any variables in the file name before trying to 18701590Srgrimes * find the thing. 18711590Srgrimes */ 1872142457Sharti buf = Var_Subst(NULL, file, VAR_CMD, FALSE); 1873142457Sharti file = Buf_GetAll(buf, NULL); 1874142457Sharti Buf_Destroy(buf, FALSE); 18751590Srgrimes 18761590Srgrimes /* 18771590Srgrimes * Now we know the file's name, we attempt to find the durn thing. 1878105754Sjmallett * Search for it first on the -I search path, then on the .PATH 1879105754Sjmallett * search path, if not found in a -I directory. 18801590Srgrimes */ 1881138916Sharti fullname = Dir_FindFile(file, &parseIncPath); 1882138264Sharti if (fullname == NULL) { 1883138916Sharti fullname = Dir_FindFile(file, &dirSearchPath); 18841590Srgrimes } 18851590Srgrimes 1886138264Sharti if (fullname == NULL) { 18871590Srgrimes /* 18881590Srgrimes * Still haven't found the makefile. Look for it on the system 18891590Srgrimes * path as a last resort. 18901590Srgrimes */ 1891138916Sharti fullname = Dir_FindFile(file, &sysIncPath); 18921590Srgrimes } 18931590Srgrimes 1894138264Sharti if (fullname == NULL) { 1895138232Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1896142457Sharti /* XXXHB free(file) */ 18971590Srgrimes return; 18981590Srgrimes } 18991590Srgrimes 1900142457Sharti /* XXXHB free(file) */ 1901142457Sharti 19021590Srgrimes /* 19031590Srgrimes * Once we find the absolute path to the file, we get to save all the 19041590Srgrimes * state from the current file before we can start reading this 19051590Srgrimes * include file. The state is stored in an IFile structure which 19061590Srgrimes * is placed on a list with other IFile structures. The list makes 19071590Srgrimes * a very nice stack to track how we got here... 19081590Srgrimes */ 1909138264Sharti oldFile = emalloc(sizeof(IFile)); 1910138232Sharti memcpy(oldFile, &curFile, sizeof(IFile)); 19111590Srgrimes 1912138916Sharti Lst_AtFront(&includes, oldFile); 19131590Srgrimes 19141590Srgrimes /* 19151590Srgrimes * Once the previous state has been saved, we can get down to reading 19161590Srgrimes * the new file. We set up the name of the file to be the absolute 19171590Srgrimes * name of the include file so error messages refer to the right 19181590Srgrimes * place. Naturally enough, we start reading at line number 0. 19191590Srgrimes */ 1920126824Sru curFile.fname = fullname; 1921126824Sru curFile.lineno = 0; 19221590Srgrimes 1923138232Sharti curFile.F = fopen(fullname, "r"); 1924126824Sru curFile.p = NULL; 1925138264Sharti if (curFile.F == NULL) { 1926138232Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 19271590Srgrimes /* 19281590Srgrimes * Pop to previous file 19291590Srgrimes */ 1930138232Sharti ParseEOF(1); 1931131456Seik } else { 1932131456Seik Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 19331590Srgrimes } 19341590Srgrimes} 19351590Srgrimes#endif 19361590Srgrimes 19371590Srgrimes/*- 19381590Srgrimes *--------------------------------------------------------------------- 19391590Srgrimes * ParseEOF -- 19401590Srgrimes * Called when EOF is reached in the current file. If we were reading 19411590Srgrimes * an include file, the includes stack is popped and things set up 19421590Srgrimes * to go back to reading the previous file at the previous location. 19431590Srgrimes * 19441590Srgrimes * Results: 19451590Srgrimes * CONTINUE if there's more to do. DONE if not. 19461590Srgrimes * 19471590Srgrimes * Side Effects: 1948126824Sru * The old curFile.F is closed. The includes list is shortened. 1949126824Sru * curFile.lineno, curFile.F, and curFile.fname are changed if 1950126824Sru * CONTINUE is returned. 19511590Srgrimes *--------------------------------------------------------------------- 19521590Srgrimes */ 19531590Srgrimesstatic int 1954138232ShartiParseEOF(int opened) 19551590Srgrimes{ 19561590Srgrimes IFile *ifile; /* the state on the top of the includes stack */ 19571590Srgrimes 1958138916Sharti if (Lst_IsEmpty(&includes)) { 1959131456Seik Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 19601590Srgrimes return (DONE); 19611590Srgrimes } 19621590Srgrimes 1963138916Sharti ifile = Lst_DeQueue(&includes); 1964138232Sharti free(curFile.fname); 1965131456Seik if (opened && curFile.F) { 1966138232Sharti fclose(curFile.F); 1967131456Seik Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 1968131456Seik } 1969126824Sru if (curFile.p) { 1970126824Sru free(curFile.p->str); 1971126824Sru free(curFile.p); 19721590Srgrimes } 1973138232Sharti memcpy(&curFile, ifile, sizeof(IFile)); 1974138232Sharti free(ifile); 19751590Srgrimes return (CONTINUE); 19761590Srgrimes} 19771590Srgrimes 19781590Srgrimes/*- 19791590Srgrimes *--------------------------------------------------------------------- 19801590Srgrimes * ParseReadc -- 19818874Srgrimes * Read a character from the current file 19821590Srgrimes * 19831590Srgrimes * Results: 19841590Srgrimes * The character that was read 19851590Srgrimes * 19861590Srgrimes * Side Effects: 19871590Srgrimes *--------------------------------------------------------------------- 19881590Srgrimes */ 19891590Srgrimesstatic int 1990104696SjmallettParseReadc(void) 19911590Srgrimes{ 1992138232Sharti 1993126824Sru if (curFile.F) 1994138232Sharti return (fgetc(curFile.F)); 19958874Srgrimes 1996126824Sru if (curFile.p && *curFile.p->ptr) 1997138232Sharti return (*curFile.p->ptr++); 1998138232Sharti return (EOF); 19991590Srgrimes} 20001590Srgrimes 20011590Srgrimes 20021590Srgrimes/*- 20031590Srgrimes *--------------------------------------------------------------------- 20041590Srgrimes * ParseUnreadc -- 20058874Srgrimes * Put back a character to the current file 20061590Srgrimes * 20071590Srgrimes * Results: 20081590Srgrimes * None. 20091590Srgrimes * 20101590Srgrimes * Side Effects: 20111590Srgrimes *--------------------------------------------------------------------- 20121590Srgrimes */ 20131590Srgrimesstatic void 2014104696SjmallettParseUnreadc(int c) 20151590Srgrimes{ 2016138232Sharti 2017126824Sru if (curFile.F) { 2018126824Sru ungetc(c, curFile.F); 20191590Srgrimes return; 20201590Srgrimes } 2021126824Sru if (curFile.p) { 2022126824Sru *--(curFile.p->ptr) = c; 20231590Srgrimes return; 20241590Srgrimes } 20251590Srgrimes} 20261590Srgrimes 20271590Srgrimes 20281590Srgrimes/* ParseSkipLine(): 2029104696Sjmallett * Grab the next line unless it begins with a dot (`.') and we're told to 2030104696Sjmallett * ignore such lines. 20311590Srgrimes */ 20321590Srgrimesstatic char * 2033126824SruParseSkipLine(int skip, int keep_newline) 20341590Srgrimes{ 20351590Srgrimes char *line; 2036138346Sharti int c, lastc; 2037141133Sharti Buffer *buf; 20381590Srgrimes 203918456Ssteve buf = Buf_Init(MAKE_BSIZE); 20401590Srgrimes 204118456Ssteve do { 2042141275Sharti Buf_Clear(buf); 204318456Ssteve lastc = '\0'; 20448874Srgrimes 204518456Ssteve while (((c = ParseReadc()) != '\n' || lastc == '\\') 204618456Ssteve && c != EOF) { 2047132540Sharti if (skip && c == '#' && lastc != '\\') { 2048132540Sharti /* let a comment be terminated even by an escaped \n. 2049132540Sharti * This is consistent to comment handling in ParseReadLine */ 2050132540Sharti while ((c = ParseReadc()) != '\n' && c != EOF) 2051132540Sharti ; 2052132540Sharti break; 2053132540Sharti } 205474293Swill if (c == '\n') { 2055126824Sru if (keep_newline) 2056126824Sru Buf_AddByte(buf, (Byte)c); 2057126824Sru else 2058126824Sru Buf_ReplaceLastByte(buf, (Byte)' '); 2059126824Sru curFile.lineno++; 20608874Srgrimes 2061104108Sjmallett while ((c = ParseReadc()) == ' ' || c == '\t') 2062104108Sjmallett continue; 20638874Srgrimes 206474293Swill if (c == EOF) 206574293Swill break; 206674293Swill } 206774272Swill 206874293Swill Buf_AddByte(buf, (Byte)c); 206974293Swill lastc = c; 207018456Ssteve } 207118456Ssteve 207218456Ssteve if (c == EOF) { 207318456Ssteve Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop"); 207418456Ssteve Buf_Destroy(buf, TRUE); 2075138264Sharti return (NULL); 207618456Ssteve } 207718456Ssteve 2078126824Sru curFile.lineno++; 207918456Ssteve Buf_AddByte(buf, (Byte)'\0'); 2080141291Sharti line = (char *)Buf_GetAll(buf, NULL); 208118456Ssteve } while (skip == 1 && line[0] != '.'); 208218456Ssteve 208318456Ssteve Buf_Destroy(buf, FALSE); 2084138232Sharti return (line); 20851590Srgrimes} 20861590Srgrimes 20871590Srgrimes 20881590Srgrimes/*- 20891590Srgrimes *--------------------------------------------------------------------- 20901590Srgrimes * ParseReadLine -- 20911590Srgrimes * Read an entire line from the input file. Called only by Parse_File. 20921590Srgrimes * To facilitate escaped newlines and what have you, a character is 20931590Srgrimes * buffered in 'lastc', which is '\0' when no characters have been 20941590Srgrimes * read. When we break out of the loop, c holds the terminating 20951590Srgrimes * character and lastc holds a character that should be added to 20961590Srgrimes * the line (unless we don't read anything but a terminator). 20971590Srgrimes * 20981590Srgrimes * Results: 20991590Srgrimes * A line w/o its newline 21001590Srgrimes * 21011590Srgrimes * Side Effects: 21021590Srgrimes * Only those associated with reading a character 21031590Srgrimes *--------------------------------------------------------------------- 21041590Srgrimes */ 21051590Srgrimesstatic char * 2106138232ShartiParseReadLine(void) 21071590Srgrimes{ 2108141133Sharti Buffer *buf; /* Buffer for current line */ 210994584Sobrien int c; /* the current character */ 211094584Sobrien int lastc; /* The most-recent character */ 21111590Srgrimes Boolean semiNL; /* treat semi-colons as newlines */ 21121590Srgrimes Boolean ignDepOp; /* TRUE if should ignore dependency operators 21131590Srgrimes * for the purposes of setting semiNL */ 21141590Srgrimes Boolean ignComment; /* TRUE if should ignore comments (in a 21151590Srgrimes * shell command */ 21165814Sjkh char *line; /* Result */ 21175814Sjkh char *ep; /* to strip trailing blanks */ 2118126824Sru int lineno; /* Saved line # */ 21191590Srgrimes 21201590Srgrimes semiNL = FALSE; 21211590Srgrimes ignDepOp = FALSE; 21221590Srgrimes ignComment = FALSE; 21231590Srgrimes 21241590Srgrimes /* 21251590Srgrimes * Handle special-characters at the beginning of the line. Either a 21261590Srgrimes * leading tab (shell command) or pound-sign (possible conditional) 21271590Srgrimes * forces us to ignore comments and dependency operators and treat 21281590Srgrimes * semi-colons as semi-colons (by leaving semiNL FALSE). This also 21291590Srgrimes * discards completely blank lines. 21301590Srgrimes */ 21311590Srgrimes for (;;) { 21321590Srgrimes c = ParseReadc(); 21331590Srgrimes 21341590Srgrimes if (c == '\t') { 21351590Srgrimes ignComment = ignDepOp = TRUE; 21361590Srgrimes break; 21371590Srgrimes } else if (c == '\n') { 2138126824Sru curFile.lineno++; 21391590Srgrimes } else if (c == '#') { 21401590Srgrimes ParseUnreadc(c); 21411590Srgrimes break; 21421590Srgrimes } else { 21431590Srgrimes /* 21441590Srgrimes * Anything else breaks out without doing anything 21451590Srgrimes */ 21461590Srgrimes break; 21471590Srgrimes } 21481590Srgrimes } 21498874Srgrimes 21501590Srgrimes if (c != EOF) { 21511590Srgrimes lastc = c; 21521590Srgrimes buf = Buf_Init(MAKE_BSIZE); 21538874Srgrimes 2154138232Sharti while (((c = ParseReadc()) != '\n' || (lastc == '\\')) && 21551590Srgrimes (c != EOF)) 21561590Srgrimes { 21571590Srgrimestest_char: 2158138232Sharti switch (c) { 21591590Srgrimes case '\n': 21601590Srgrimes /* 21611590Srgrimes * Escaped newline: read characters until a non-space or an 21621590Srgrimes * unescaped newline and replace them all by a single space. 21631590Srgrimes * This is done by storing the space over the backslash and 21641590Srgrimes * dropping through with the next nonspace. If it is a 21651590Srgrimes * semi-colon and semiNL is TRUE, it will be recognized as a 21661590Srgrimes * newline in the code below this... 21671590Srgrimes */ 2168126824Sru curFile.lineno++; 21691590Srgrimes lastc = ' '; 2170138232Sharti while ((c = ParseReadc()) == ' ' || c == '\t') { 21711590Srgrimes continue; 21721590Srgrimes } 21731590Srgrimes if (c == EOF || c == '\n') { 21741590Srgrimes goto line_read; 21751590Srgrimes } else { 21761590Srgrimes /* 21771590Srgrimes * Check for comments, semiNL's, etc. -- easier than 21781590Srgrimes * ParseUnreadc(c); continue; 21791590Srgrimes */ 21801590Srgrimes goto test_char; 21811590Srgrimes } 21821590Srgrimes /*NOTREACHED*/ 21831590Srgrimes break; 21841590Srgrimes 21851590Srgrimes case ';': 21861590Srgrimes /* 21871590Srgrimes * Semi-colon: Need to see if it should be interpreted as a 21881590Srgrimes * newline 21891590Srgrimes */ 21901590Srgrimes if (semiNL) { 21911590Srgrimes /* 21921590Srgrimes * To make sure the command that may be following this 21931590Srgrimes * semi-colon begins with a tab, we push one back into the 21941590Srgrimes * input stream. This will overwrite the semi-colon in the 21951590Srgrimes * buffer. If there is no command following, this does no 21961590Srgrimes * harm, since the newline remains in the buffer and the 21971590Srgrimes * whole line is ignored. 21981590Srgrimes */ 21991590Srgrimes ParseUnreadc('\t'); 22001590Srgrimes goto line_read; 22018874Srgrimes } 22021590Srgrimes break; 22031590Srgrimes case '=': 22041590Srgrimes if (!semiNL) { 22051590Srgrimes /* 22061590Srgrimes * Haven't seen a dependency operator before this, so this 22071590Srgrimes * must be a variable assignment -- don't pay attention to 22081590Srgrimes * dependency operators after this. 22091590Srgrimes */ 22101590Srgrimes ignDepOp = TRUE; 22111590Srgrimes } else if (lastc == ':' || lastc == '!') { 22121590Srgrimes /* 22131590Srgrimes * Well, we've seen a dependency operator already, but it 22141590Srgrimes * was the previous character, so this is really just an 22151590Srgrimes * expanded variable assignment. Revert semi-colons to 22161590Srgrimes * being just semi-colons again and ignore any more 22171590Srgrimes * dependency operators. 22181590Srgrimes * 22191590Srgrimes * XXX: Note that a line like "foo : a:=b" will blow up, 22201590Srgrimes * but who'd write a line like that anyway? 22211590Srgrimes */ 2222138232Sharti ignDepOp = TRUE; 2223138232Sharti semiNL = FALSE; 22241590Srgrimes } 22251590Srgrimes break; 22261590Srgrimes case '#': 22271590Srgrimes if (!ignComment) { 2228104374Sjmallett if (lastc != '\\') { 22291590Srgrimes /* 22301590Srgrimes * If the character is a hash mark and it isn't escaped 22311590Srgrimes * (or we're being compatible), the thing is a comment. 22321590Srgrimes * Skip to the end of the line. 22331590Srgrimes */ 22341590Srgrimes do { 22351590Srgrimes c = ParseReadc(); 22361590Srgrimes } while ((c != '\n') && (c != EOF)); 22371590Srgrimes goto line_read; 22381590Srgrimes } else { 22391590Srgrimes /* 22401590Srgrimes * Don't add the backslash. Just let the # get copied 22411590Srgrimes * over. 22421590Srgrimes */ 22431590Srgrimes lastc = c; 22441590Srgrimes continue; 22451590Srgrimes } 22461590Srgrimes } 22471590Srgrimes break; 22481590Srgrimes case ':': 22491590Srgrimes case '!': 22501590Srgrimes if (!ignDepOp && (c == ':' || c == '!')) { 22511590Srgrimes /* 22521590Srgrimes * A semi-colon is recognized as a newline only on 22531590Srgrimes * dependency lines. Dependency lines are lines with a 22541590Srgrimes * colon or an exclamation point. Ergo... 22551590Srgrimes */ 22561590Srgrimes semiNL = TRUE; 22571590Srgrimes } 22581590Srgrimes break; 2259104108Sjmallett default: 2260104108Sjmallett break; 22611590Srgrimes } 22621590Srgrimes /* 22631590Srgrimes * Copy in the previous character and save this one in lastc. 22641590Srgrimes */ 2265138232Sharti Buf_AddByte(buf, (Byte)lastc); 22661590Srgrimes lastc = c; 22678874Srgrimes 22681590Srgrimes } 22691590Srgrimes line_read: 2270126824Sru curFile.lineno++; 22718874Srgrimes 22721590Srgrimes if (lastc != '\0') { 2273138232Sharti Buf_AddByte(buf, (Byte)lastc); 22741590Srgrimes } 2275138232Sharti Buf_AddByte(buf, (Byte)'\0'); 2276141291Sharti line = (char *)Buf_GetAll(buf, NULL); 2277138232Sharti Buf_Destroy(buf, FALSE); 22785814Sjkh 22795814Sjkh /* 22805814Sjkh * Strip trailing blanks and tabs from the line. 228172645Sasmodai * Do not strip a blank or tab that is preceded by 22825814Sjkh * a '\' 22835814Sjkh */ 22845814Sjkh ep = line; 22855814Sjkh while (*ep) 22865814Sjkh ++ep; 22879298Sache while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 228818730Ssteve if (ep > line + 1 && ep[-2] == '\\') 22895814Sjkh break; 22905814Sjkh --ep; 22915814Sjkh } 22925814Sjkh *ep = 0; 22938874Srgrimes 22941590Srgrimes if (line[0] == '.') { 22951590Srgrimes /* 22961590Srgrimes * The line might be a conditional. Ask the conditional module 22971590Srgrimes * about it and act accordingly 22981590Srgrimes */ 2299138232Sharti switch (Cond_Eval(line)) { 23001590Srgrimes case COND_SKIP: 23011590Srgrimes /* 23021590Srgrimes * Skip to next conditional that evaluates to COND_PARSE. 23031590Srgrimes */ 23041590Srgrimes do { 2305138232Sharti free(line); 2306126824Sru line = ParseSkipLine(1, 0); 23071590Srgrimes } while (line && Cond_Eval(line) != COND_PARSE); 23081590Srgrimes if (line == NULL) 23091590Srgrimes break; 23101590Srgrimes /*FALLTHRU*/ 23111590Srgrimes case COND_PARSE: 2312138232Sharti free(line); 23131590Srgrimes line = ParseReadLine(); 23141590Srgrimes break; 23151590Srgrimes case COND_INVALID: 23161590Srgrimes if (For_Eval(line)) { 23171590Srgrimes int ok; 23181590Srgrimes free(line); 2319126824Sru lineno = curFile.lineno; 23201590Srgrimes do { 23211590Srgrimes /* 23221590Srgrimes * Skip after the matching end 23231590Srgrimes */ 2324126824Sru line = ParseSkipLine(0, 1); 23251590Srgrimes if (line == NULL) { 2326138232Sharti Parse_Error(PARSE_FATAL, 23271590Srgrimes "Unexpected end of file in for loop.\n"); 23281590Srgrimes break; 23291590Srgrimes } 23301590Srgrimes ok = For_Eval(line); 23311590Srgrimes free(line); 23321590Srgrimes } 23331590Srgrimes while (ok); 23341590Srgrimes if (line != NULL) 2335126824Sru For_Run(lineno); 23361590Srgrimes line = ParseReadLine(); 23371590Srgrimes } 23381590Srgrimes break; 2339104108Sjmallett default: 2340104108Sjmallett break; 23411590Srgrimes } 23421590Srgrimes } 23431590Srgrimes return (line); 23441590Srgrimes 23451590Srgrimes } else { 23461590Srgrimes /* 23471590Srgrimes * Hit end-of-file, so return a NULL line to indicate this. 23481590Srgrimes */ 2349138264Sharti return (NULL); 23501590Srgrimes } 23511590Srgrimes} 23521590Srgrimes 23531590Srgrimes/*- 23541590Srgrimes *----------------------------------------------------------------------- 23551590Srgrimes * ParseFinishLine -- 23561590Srgrimes * Handle the end of a dependency group. 23571590Srgrimes * 23581590Srgrimes * Results: 23591590Srgrimes * Nothing. 23601590Srgrimes * 23611590Srgrimes * Side Effects: 23621590Srgrimes * inLine set FALSE. 'targets' list destroyed. 23631590Srgrimes * 23641590Srgrimes *----------------------------------------------------------------------- 23651590Srgrimes */ 23661590Srgrimesstatic void 2367104696SjmallettParseFinishLine(void) 23681590Srgrimes{ 2369138232Sharti 23701590Srgrimes if (inLine) { 2371138916Sharti Lst_ForEach(&targets, Suff_EndTransform, NULL); 2372138916Sharti Lst_Destroy(&targets, ParseHasCommands); 23731590Srgrimes inLine = FALSE; 23741590Srgrimes } 23751590Srgrimes} 23761590Srgrimes 23778874Srgrimes 23781590Srgrimes/*- 23791590Srgrimes *--------------------------------------------------------------------- 23801590Srgrimes * Parse_File -- 23811590Srgrimes * Parse a file into its component parts, incorporating it into the 23821590Srgrimes * current dependency graph. This is the main function and controls 23831590Srgrimes * almost every other function in this module 23841590Srgrimes * 23851590Srgrimes * Results: 23861590Srgrimes * None 23871590Srgrimes * 23881590Srgrimes * Side Effects: 23891590Srgrimes * Loads. Nodes are added to the list of all targets, nodes and links 23901590Srgrimes * are added to the dependency graph. etc. etc. etc. 23911590Srgrimes *--------------------------------------------------------------------- 23921590Srgrimes */ 23931590Srgrimesvoid 2394104696SjmallettParse_File(char *name, FILE *stream) 23951590Srgrimes{ 239694584Sobrien char *cp, /* pointer into the line */ 23971590Srgrimes *line; /* the line we're working on */ 2398142457Sharti Buffer *buf; 23991590Srgrimes 24001590Srgrimes inLine = FALSE; 2401126824Sru curFile.fname = name; 2402126824Sru curFile.F = stream; 2403126824Sru curFile.lineno = 0; 24041590Srgrimes fatals = 0; 24051590Srgrimes 2406131456Seik Var_Append(".MAKEFILE_LIST", name, VAR_GLOBAL); 2407131456Seik 24081590Srgrimes do { 2409138232Sharti while ((line = ParseReadLine()) != NULL) { 24101590Srgrimes if (*line == '.') { 24111590Srgrimes /* 24121590Srgrimes * Lines that begin with the special character are either 24131590Srgrimes * include or undef directives. 24141590Srgrimes */ 2415138232Sharti for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 24161590Srgrimes continue; 24171590Srgrimes } 2418138232Sharti if (strncmp(cp, "include", 7) == 0) { 2419141270Sharti ParseDoInclude(cp + 7); 24201590Srgrimes goto nextLine; 2421138232Sharti } else if (strncmp(cp, "error", 5) == 0) { 242236347Ssteve ParseDoError(cp + 5); 2423138232Sharti goto nextLine; 2424138232Sharti } else if (strncmp(cp, "warning", 7) == 0) { 2425128160Sru ParseDoWarning(cp + 7); 2426138232Sharti goto nextLine; 24271590Srgrimes } else if (strncmp(cp, "undef", 5) == 0) { 24281590Srgrimes char *cp2; 2429138232Sharti for (cp += 5; isspace((unsigned char)*cp); cp++) { 24301590Srgrimes continue; 24311590Srgrimes } 24321590Srgrimes 2433138232Sharti for (cp2 = cp; !isspace((unsigned char)*cp2) && 24345814Sjkh (*cp2 != '\0'); cp2++) { 24351590Srgrimes continue; 24361590Srgrimes } 24371590Srgrimes 24381590Srgrimes *cp2 = '\0'; 24391590Srgrimes 2440142457Sharti buf = Var_Subst(NULL, cp, VAR_CMD, FALSE); 2441142457Sharti cp = Buf_GetAll(buf, NULL); 2442142457Sharti Buf_Destroy(buf, FALSE); 2443142457Sharti 24441590Srgrimes Var_Delete(cp, VAR_GLOBAL); 24451590Srgrimes goto nextLine; 24461590Srgrimes } 24471590Srgrimes } 24489298Sache if (*line == '#') { 24491590Srgrimes /* If we're this far, the line must be a comment. */ 24501590Srgrimes goto nextLine; 24511590Srgrimes } 24528874Srgrimes 24535814Sjkh if (*line == '\t') { 24541590Srgrimes /* 24555814Sjkh * If a line starts with a tab, it can only hope to be 24565814Sjkh * a creation command. 24571590Srgrimes */ 2458138232Sharti for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 24591590Srgrimes continue; 24601590Srgrimes } 24611590Srgrimes if (*cp) { 24621590Srgrimes if (inLine) { 24631590Srgrimes /* 24641590Srgrimes * So long as it's not a blank line and we're actually 24651590Srgrimes * in a dependency spec, add the command to the list of 24668874Srgrimes * commands of all targets in the dependency spec 24671590Srgrimes */ 2468138916Sharti Lst_ForEach(&targets, ParseAddCmd, cp); 24691590Srgrimes continue; 24701590Srgrimes } else { 2471138232Sharti Parse_Error(PARSE_FATAL, 247218730Ssteve "Unassociated shell command \"%s\"", 24731590Srgrimes cp); 24741590Srgrimes } 24751590Srgrimes } 24761590Srgrimes#ifdef SYSVINCLUDE 2477138232Sharti } else if (strncmp(line, "include", 7) == 0 && 2478138232Sharti isspace((unsigned char)line[7]) && 24791590Srgrimes strchr(line, ':') == NULL) { 24801590Srgrimes /* 24811590Srgrimes * It's an S3/S5-style "include". 24821590Srgrimes */ 2483138232Sharti ParseTraditionalInclude(line + 7); 24841590Srgrimes goto nextLine; 24851590Srgrimes#endif 2486138232Sharti } else if (Parse_IsVar(line)) { 24871590Srgrimes ParseFinishLine(); 2488138232Sharti Parse_DoVar(line, VAR_GLOBAL); 24891590Srgrimes } else { 24901590Srgrimes /* 24911590Srgrimes * We now know it's a dependency line so it needs to have all 24921590Srgrimes * variables expanded before being parsed. Tell the variable 24931590Srgrimes * module to complain if some variable is undefined... 24941590Srgrimes * To make life easier on novices, if the line is indented we 24951590Srgrimes * first make sure the line has a dependency operator in it. 24961590Srgrimes * If it doesn't have an operator and we're in a dependency 24971590Srgrimes * line's script, we assume it's actually a shell command 24981590Srgrimes * and add it to the current list of targets. 24991590Srgrimes */ 25001590Srgrimes cp = line; 2501138232Sharti if (isspace((unsigned char)line[0])) { 2502138232Sharti while ((*cp != '\0') && isspace((unsigned char)*cp)) { 25035814Sjkh cp++; 25045814Sjkh } 25055814Sjkh if (*cp == '\0') { 25065814Sjkh goto nextLine; 25075814Sjkh } 25081590Srgrimes } 25098874Srgrimes 2510137810Sharti ParseFinishLine(); 25111590Srgrimes 2512142457Sharti buf = Var_Subst(NULL, line, VAR_CMD, TRUE); 2513142457Sharti cp = Buf_GetAll(buf, NULL); 2514142457Sharti Buf_Destroy(buf, FALSE); 2515142457Sharti 2516138232Sharti free(line); 2517137810Sharti line = cp; 25188874Srgrimes 2519137810Sharti /* 2520137810Sharti * Need a non-circular list for the target nodes 2521137810Sharti */ 2522138916Sharti Lst_Destroy(&targets, NOFREE); 2523137810Sharti inLine = TRUE; 25248874Srgrimes 2525141270Sharti ParseDoDependency(line); 25261590Srgrimes } 25271590Srgrimes 25281590Srgrimes nextLine: 25291590Srgrimes 2530138232Sharti free(line); 25311590Srgrimes } 25321590Srgrimes /* 25338874Srgrimes * Reached EOF, but it may be just EOF of an include file... 25341590Srgrimes */ 25351590Srgrimes } while (ParseEOF(1) == CONTINUE); 25361590Srgrimes 25371590Srgrimes /* 25381590Srgrimes * Make sure conditionals are clean 25391590Srgrimes */ 25401590Srgrimes Cond_End(); 25411590Srgrimes 254227644Scharnier if (fatals) 254327644Scharnier errx(1, "fatal errors encountered -- cannot continue"); 25441590Srgrimes} 25451590Srgrimes 25461590Srgrimes/*- 25471590Srgrimes *--------------------------------------------------------------------- 25481590Srgrimes * Parse_Init -- 25491590Srgrimes * initialize the parsing module 25501590Srgrimes * 25511590Srgrimes * Results: 25521590Srgrimes * none 25531590Srgrimes * 25541590Srgrimes * Side Effects: 25551590Srgrimes * the parseIncPath list is initialized... 25561590Srgrimes *--------------------------------------------------------------------- 25571590Srgrimes */ 25581590Srgrimesvoid 2559138232ShartiParse_Init(void) 25601590Srgrimes{ 2561138232Sharti 256269527Swill mainNode = NULL; 25631590Srgrimes} 25641590Srgrimes 25651590Srgrimes/*- 25661590Srgrimes *----------------------------------------------------------------------- 25671590Srgrimes * Parse_MainName -- 25681590Srgrimes * Return a Lst of the main target to create for main()'s sake. If 25691590Srgrimes * no such target exists, we Punt with an obnoxious error message. 25701590Srgrimes * 25711590Srgrimes * Results: 25721590Srgrimes * A Lst of the single node to create. 25731590Srgrimes * 25741590Srgrimes * Side Effects: 25751590Srgrimes * None. 25761590Srgrimes * 25771590Srgrimes *----------------------------------------------------------------------- 25781590Srgrimes */ 2579138916Shartivoid 2580138916ShartiParse_MainName(Lst *listmain) 25811590Srgrimes{ 25821590Srgrimes 258369527Swill if (mainNode == NULL) { 2584138232Sharti Punt("no target to make."); 25851590Srgrimes /*NOTREACHED*/ 25861590Srgrimes } else if (mainNode->type & OP_DOUBLEDEP) { 2587138264Sharti Lst_AtEnd(listmain, mainNode); 2588138916Sharti Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 25891590Srgrimes } 25901590Srgrimes else 2591138264Sharti Lst_AtEnd(listmain, mainNode); 25921590Srgrimes} 2593