parse.c revision 144026
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 144026 2005-03-23 16:14:41Z 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: 63144026Sharti * Parse_Init Initialization function which must be 64144026Sharti * called before anything else in this module is used. 651590Srgrimes * 66144026Sharti * Parse_File Function used to parse a makefile. It must 67144026Sharti * be given the name of the file, which should 68144026Sharti * already have been opened, and a function 69144026Sharti * to call to read a character from the file. 701590Srgrimes * 71144026Sharti * Parse_IsVar Returns TRUE if the given line is a 72144026Sharti * variable assignment. Used by MainParseArgs 73144026Sharti * to determine if an argument is a target 74144026Sharti * or a variable assignment. Used internally 75144026Sharti * for pretty much the same thing... 761590Srgrimes * 77144026Sharti * Parse_Error Function called when an error occurs in 78144026Sharti * parsing. Used by the variable and 79144026Sharti * conditional modules. 80144026Sharti * 81144026Sharti * 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 120144026Sharti/* true if currently in a dependency line or its commands */ 121144026Shartistatic Boolean inLine; 1221590Srgrimes 123144026Shartistatic int fatals = 0; 1241590Srgrimes 125144026Sharti/* 126144026Sharti * The main target to create. This is the first target on the 127144026Sharti * first dependency line in the first makefile. 128144026Sharti */ 129144026Shartistatic GNode *mainNode; 130126824Sru 131144026ShartiIFile curFile; /* current makefile */ 132144026Sharti 133138916Sharti/* stack of IFiles generated by * #includes */ 134138916Shartistatic Lst includes = Lst_Initializer(includes); 1351590Srgrimes 136138916Sharti/* list of directories for "..." includes */ 137144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); 138138916Sharti 139138916Sharti/* list of directories for <...> includes */ 140144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); 141138916Sharti 142144026Sharti/* 1431590Srgrimes * specType contains the SPECial TYPE of the current target. It is 1441590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children 1451590Srgrimes * are linked as children of the parent but not vice versa. This variable is 1461590Srgrimes * set in ParseDoDependency 1471590Srgrimes */ 1481590Srgrimestypedef enum { 149144026Sharti Begin, /* .BEGIN */ 150144026Sharti Default, /* .DEFAULT */ 151144026Sharti End, /* .END */ 152144026Sharti Ignore, /* .IGNORE */ 153144026Sharti Includes, /* .INCLUDES */ 154144026Sharti Interrupt, /* .INTERRUPT */ 155144026Sharti Libs, /* .LIBS */ 156144026Sharti MFlags, /* .MFLAGS or .MAKEFLAGS */ 157144026Sharti Main, /* .MAIN and we don't have anyth. user-spec. to make */ 158144026Sharti NoExport, /* .NOEXPORT */ 159144026Sharti Not, /* Not special */ 160144026Sharti NotParallel, /* .NOTPARALELL */ 161144026Sharti Null, /* .NULL */ 162144026Sharti Order, /* .ORDER */ 163144026Sharti Parallel, /* .PARALLEL */ 164144026Sharti ExPath, /* .PATH */ 165144026Sharti Phony, /* .PHONY */ 166144026Sharti Posix, /* .POSIX */ 167144026Sharti Precious, /* .PRECIOUS */ 168144026Sharti ExShell, /* .SHELL */ 169144026Sharti Silent, /* .SILENT */ 170144026Sharti SingleShell, /* .SINGLESHELL */ 171144026Sharti Suffixes, /* .SUFFIXES */ 172144026Sharti Wait, /* .WAIT */ 173144026Sharti Attribute /* Generic attribute */ 1741590Srgrimes} ParseSpecial; 1751590Srgrimes 1761590Srgrimesstatic ParseSpecial specType; 17718730Sstevestatic int waiting; 1781590Srgrimes 1791590Srgrimes/* 18069527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 1811590Srgrimes * seen, then set to each successive source on the line. 1821590Srgrimes */ 183144026Shartistatic GNode *predecessor; 1841590Srgrimes 1851590Srgrimes/* 1861590Srgrimes * The parseKeywords table is searched using binary search when deciding 1871590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial 1881590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while 1891590Srgrimes * the 'op' field is the operator to apply to the list of targets if the 1901590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source) 1911590Srgrimes */ 1921590Srgrimesstatic struct { 193144026Sharti const char *name; /* Name of keyword */ 194144026Sharti ParseSpecial spec; /* Type when used as a target */ 195144026Sharti int op; /* Operator when used as a source */ 1961590Srgrimes} parseKeywords[] = { 197144026Sharti { ".BEGIN", Begin, 0 }, 198144026Sharti { ".DEFAULT", Default, 0 }, 199144026Sharti { ".END", End, 0 }, 200144026Sharti { ".EXEC", Attribute, OP_EXEC }, 201144026Sharti { ".IGNORE", Ignore, OP_IGNORE }, 202144026Sharti { ".INCLUDES", Includes, 0 }, 203144026Sharti { ".INTERRUPT", Interrupt, 0 }, 204144026Sharti { ".INVISIBLE", Attribute, OP_INVISIBLE }, 205144026Sharti { ".JOIN", Attribute, OP_JOIN }, 206144026Sharti { ".LIBS", Libs, 0 }, 207144026Sharti { ".MAIN", Main, 0 }, 208144026Sharti { ".MAKE", Attribute, OP_MAKE }, 209144026Sharti { ".MAKEFLAGS", MFlags, 0 }, 210144026Sharti { ".MFLAGS", MFlags, 0 }, 211144026Sharti { ".NOTMAIN", Attribute, OP_NOTMAIN }, 212144026Sharti { ".NOTPARALLEL", NotParallel, 0 }, 213144026Sharti { ".NO_PARALLEL", NotParallel, 0 }, 214144026Sharti { ".NULL", Null, 0 }, 215144026Sharti { ".OPTIONAL", Attribute, OP_OPTIONAL }, 216144026Sharti { ".ORDER", Order, 0 }, 217144026Sharti { ".PARALLEL", Parallel, 0 }, 218144026Sharti { ".PATH", ExPath, 0 }, 219144026Sharti { ".PHONY", Phony, OP_PHONY }, 220144026Sharti { ".POSIX", Posix, 0 }, 221144026Sharti { ".PRECIOUS", Precious, OP_PRECIOUS }, 222144026Sharti { ".RECURSIVE", Attribute, OP_MAKE }, 223144026Sharti { ".SHELL", ExShell, 0 }, 224144026Sharti { ".SILENT", Silent, OP_SILENT }, 225144026Sharti { ".SINGLESHELL", SingleShell, 0 }, 226144026Sharti { ".SUFFIXES", Suffixes, 0 }, 227144026Sharti { ".USE", Attribute, OP_USE }, 228144026Sharti { ".WAIT", Wait, 0 }, 2291590Srgrimes}; 2301590Srgrimes 23192921Simpstatic int ParseEOF(int); 2321590Srgrimes 2331590Srgrimes/*- 2341590Srgrimes *---------------------------------------------------------------------- 2351590Srgrimes * ParseFindKeyword -- 2361590Srgrimes * Look in the table of keywords for one matching the given string. 2371590Srgrimes * 2381590Srgrimes * Results: 2391590Srgrimes * The index of the keyword, or -1 if it isn't there. 2401590Srgrimes * 2411590Srgrimes * Side Effects: 2421590Srgrimes * None 2431590Srgrimes *---------------------------------------------------------------------- 2441590Srgrimes */ 2451590Srgrimesstatic int 246138232ShartiParseFindKeyword(char *str) 2471590Srgrimes{ 248144026Sharti int start; 249144026Sharti int end; 250144026Sharti int cur; 251144026Sharti int diff; 2528874Srgrimes 253144026Sharti start = 0; 254144026Sharti end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1; 2551590Srgrimes 256144026Sharti do { 257144026Sharti cur = start + (end - start) / 2; 258144026Sharti diff = strcmp(str, parseKeywords[cur].name); 259144026Sharti if (diff == 0) { 260144026Sharti return (cur); 261144026Sharti } else if (diff < 0) { 262144026Sharti end = cur - 1; 263144026Sharti } else { 264144026Sharti start = cur + 1; 265144026Sharti } 266144026Sharti } while (start <= end); 2671590Srgrimes 268144026Sharti return (-1); 2691590Srgrimes} 2701590Srgrimes 2711590Srgrimes/*- 2721590Srgrimes * Parse_Error -- 2731590Srgrimes * Error message abort function for parsing. Prints out the context 2741590Srgrimes * of the error (line number and file) as well as the message with 2751590Srgrimes * two optional arguments. 2761590Srgrimes * 2771590Srgrimes * Results: 2781590Srgrimes * None 2791590Srgrimes * 2801590Srgrimes * Side Effects: 2811590Srgrimes * "fatals" is incremented if the level is PARSE_FATAL. 2821590Srgrimes */ 2831590Srgrimes/* VARARGS */ 2841590Srgrimesvoid 28598136SjmallettParse_Error(int type, const char *fmt, ...) 2861590Srgrimes{ 2871590Srgrimes va_list ap; 28893056Simp 2891590Srgrimes va_start(ap, fmt); 290138232Sharti fprintf(stderr, "\"%s\", line %d: ", 291126824Sru curFile.fname, curFile.lineno); 2921590Srgrimes if (type == PARSE_WARNING) 293138232Sharti fprintf(stderr, "warning: "); 294138232Sharti vfprintf(stderr, fmt, ap); 2951590Srgrimes va_end(ap); 296138232Sharti fprintf(stderr, "\n"); 297138232Sharti fflush(stderr); 2981590Srgrimes if (type == PARSE_FATAL) 2991590Srgrimes fatals += 1; 3001590Srgrimes} 3011590Srgrimes 3021590Srgrimes/*- 3031590Srgrimes *--------------------------------------------------------------------- 3041590Srgrimes * ParseLinkSrc -- 305143100Sharti * Link the parent nodes to their new child. Used by 3061590Srgrimes * ParseDoDependency. If the specType isn't 'Not', the parent 3071590Srgrimes * isn't linked as a parent of the child. 3081590Srgrimes * 3091590Srgrimes * Side Effects: 310143100Sharti * New elements are added to the parents lists of cgn and the 3111590Srgrimes * children list of cgn. the unmade field of pgn is updated 3121590Srgrimes * to reflect the additional child. 3131590Srgrimes *--------------------------------------------------------------------- 3141590Srgrimes */ 315143027Shartistatic void 316143027ShartiParseLinkSrc(Lst *parents, GNode *cgn) 3171590Srgrimes{ 318143027Sharti LstNode *ln; 319143027Sharti GNode *pgn; 320138232Sharti 321143027Sharti LST_FOREACH(ln, parents) { 322143027Sharti pgn = Lst_Datum(ln); 323143027Sharti if (Lst_Member(&pgn->children, cgn) == NULL) { 324143027Sharti Lst_AtEnd(&pgn->children, cgn); 325143027Sharti if (specType == Not) { 326143027Sharti Lst_AtEnd(&cgn->parents, pgn); 327143027Sharti } 328143027Sharti pgn->unmade += 1; 329143027Sharti } 3301590Srgrimes } 3311590Srgrimes} 3321590Srgrimes 3331590Srgrimes/*- 3341590Srgrimes *--------------------------------------------------------------------- 3351590Srgrimes * ParseDoOp -- 336143684Sharti * Apply the parsed operator to all target nodes. Used in 337143684Sharti * ParseDoDependency once all targets have been found and their 338143684Sharti * operator parsed. If the previous and new operators are incompatible, 339143684Sharti * a major error is taken. 3401590Srgrimes * 3411590Srgrimes * Side Effects: 3421590Srgrimes * The type field of the node is altered to reflect any new bits in 3431590Srgrimes * the op. 3441590Srgrimes *--------------------------------------------------------------------- 3451590Srgrimes */ 346143684Shartistatic void 347143684ShartiParseDoOp(int op) 3481590Srgrimes{ 349143684Sharti GNode *cohort; 350143684Sharti LstNode *ln; 351143684Sharti GNode *gn; 352138232Sharti 353143684Sharti LST_FOREACH(ln, &targets) { 354143684Sharti gn = Lst_Datum(ln); 3551590Srgrimes 356143684Sharti /* 357143684Sharti * If the dependency mask of the operator and the node don't 358143684Sharti * match and the node has actually had an operator applied to 359143684Sharti * it before, and the operator actually has some dependency 360143684Sharti * information in it, complain. 361143684Sharti */ 362143684Sharti if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && 363143684Sharti !OP_NOP(gn->type) && !OP_NOP(op)) { 364143684Sharti Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 365143684Sharti gn->name); 366143684Sharti return; 367143684Sharti } 3688874Srgrimes 369143684Sharti if (op == OP_DOUBLEDEP && 370143684Sharti (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 371143684Sharti /* 372143684Sharti * If the node was the object of a :: operator, we need 373143684Sharti * to create a new instance of it for the children and 374143684Sharti * commands on this dependency line. The new instance 375143684Sharti * is placed on the 'cohorts' list of the initial one 376143684Sharti * (note the initial one is not on its own cohorts list) 377143684Sharti * and the new instance is linked to all parents of the 378143684Sharti * initial instance. 379143684Sharti */ 380143684Sharti cohort = Targ_NewGN(gn->name); 3811590Srgrimes 382143684Sharti /* 383143684Sharti * Duplicate links to parents so graph traversal is 384143684Sharti * simple. Perhaps some type bits should be duplicated? 385143684Sharti * 386143684Sharti * Make the cohort invisible as well to avoid 387143684Sharti * duplicating it into other variables. True, parents 388143684Sharti * of this target won't tend to do anything with their 389143684Sharti * local variables, but better safe than sorry. 390143684Sharti */ 391143684Sharti ParseLinkSrc(&gn->parents, cohort); 392143684Sharti cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 393143684Sharti Lst_AtEnd(&gn->cohorts, cohort); 3941590Srgrimes 395143684Sharti /* 396143684Sharti * Replace the node in the targets list with the 397143684Sharti * new copy 398143684Sharti */ 399143684Sharti Lst_Replace(ln, cohort); 400143684Sharti gn = cohort; 401143684Sharti } 402143684Sharti /* 403143684Sharti * We don't want to nuke any previous flags (whatever they were) 404143684Sharti * so we just OR the new operator into the old 405143684Sharti */ 406143684Sharti gn->type |= op; 407143684Sharti } 4081590Srgrimes} 4091590Srgrimes 4101590Srgrimes/*- 4111590Srgrimes *--------------------------------------------------------------------- 4121590Srgrimes * ParseDoSrc -- 4131590Srgrimes * Given the name of a source, figure out if it is an attribute 4141590Srgrimes * and apply it to the targets if it is. Else decide if there is 4151590Srgrimes * some attribute which should be applied *to* the source because 4161590Srgrimes * of some special target and apply it if so. Otherwise, make the 4171590Srgrimes * source be a child of the targets in the list 'targets' 4181590Srgrimes * 4191590Srgrimes * Results: 4201590Srgrimes * None 4211590Srgrimes * 4221590Srgrimes * Side Effects: 4231590Srgrimes * Operator bits may be added to the list of targets or to the source. 4241590Srgrimes * The targets may have a new source added to their lists of children. 4251590Srgrimes *--------------------------------------------------------------------- 4261590Srgrimes */ 4271590Srgrimesstatic void 428138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc) 4291590Srgrimes{ 430144026Sharti GNode *gn = NULL; 4311590Srgrimes 432144026Sharti if (*src == '.' && isupper ((unsigned char) src[1])) { 433144026Sharti int keywd = ParseFindKeyword(src); 434144026Sharti if (keywd != -1) { 435144026Sharti if(parseKeywords[keywd].op != 0) { 436144026Sharti ParseDoOp(parseKeywords[keywd].op); 437144026Sharti return; 438144026Sharti } 439144026Sharti if (parseKeywords[keywd].spec == Wait) { 440144026Sharti waiting++; 441144026Sharti return; 442144026Sharti } 443144026Sharti } 4441590Srgrimes } 44518730Ssteve 446144026Sharti switch (specType) { 447144026Sharti case Main: 448144026Sharti /* 449144026Sharti * If we have noted the existence of a .MAIN, it means we need 450144026Sharti * to add the sources of said target to the list of things 451144026Sharti * to create. The string 'src' is likely to be free, so we 452144026Sharti * must make a new copy of it. Note that this will only be 453144026Sharti * invoked if the user didn't specify a target on the command 454144026Sharti * line. This is to allow #ifmake's to succeed, or something... 455144026Sharti */ 456144026Sharti Lst_AtEnd(&create, estrdup(src)); 457144026Sharti /* 458144026Sharti * Add the name to the .TARGETS variable as well, so the user 459144026Sharti * can employ that, if desired. 460144026Sharti */ 461144026Sharti Var_Append(".TARGETS", src, VAR_GLOBAL); 462144026Sharti return; 46318730Ssteve 464144026Sharti case Order: 465144026Sharti /* 466144026Sharti * Create proper predecessor/successor links between the 467144026Sharti * previous source and the current one. 468144026Sharti */ 469144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 470144026Sharti if (predecessor != NULL) { 471144026Sharti Lst_AtEnd(&predecessor->successors, gn); 472144026Sharti Lst_AtEnd(&gn->preds, predecessor); 473144026Sharti } 474144026Sharti /* 475144026Sharti * The current source now becomes the predecessor for the next 476144026Sharti * one. 477144026Sharti */ 478144026Sharti predecessor = gn; 479144026Sharti break; 48018730Ssteve 481144026Sharti default: 482144026Sharti /* 483144026Sharti * If the source is not an attribute, we need to find/create 484144026Sharti * a node for it. After that we can apply any operator to it 485144026Sharti * from a special target or link it to its parents, as 486144026Sharti * appropriate. 487144026Sharti * 488144026Sharti * In the case of a source that was the object of a :: operator, 489144026Sharti * the attribute is applied to all of its instances (as kept in 490144026Sharti * the 'cohorts' list of the node) or all the cohorts are linked 491144026Sharti * to all the targets. 492144026Sharti */ 493144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 4941590Srgrimes if (tOp) { 495144026Sharti gn->type |= tOp; 4961590Srgrimes } else { 497144026Sharti ParseLinkSrc(&targets, gn); 4981590Srgrimes } 499144026Sharti if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 500144026Sharti GNode *cohort; 501144026Sharti LstNode *ln; 502144026Sharti 503144026Sharti for (ln = Lst_First(&gn->cohorts); ln != NULL; 504144026Sharti ln = Lst_Succ(ln)) { 505144026Sharti cohort = Lst_Datum(ln); 506144026Sharti if (tOp) { 507144026Sharti cohort->type |= tOp; 508144026Sharti } else { 509144026Sharti ParseLinkSrc(&targets, cohort); 510144026Sharti } 511144026Sharti } 512144026Sharti } 513144026Sharti break; 5141590Srgrimes } 51518730Ssteve 516144026Sharti gn->order = waiting; 517144026Sharti Lst_AtEnd(allsrc, gn); 518144026Sharti if (waiting) { 519144026Sharti LstNode *ln; 520144026Sharti GNode *p; 5211590Srgrimes 522143684Sharti /* 523144026Sharti * Check if GNodes needs to be synchronized. 524144026Sharti * This has to be when two nodes are on different sides of a 525144026Sharti * .WAIT directive. 526143684Sharti */ 527144026Sharti LST_FOREACH(ln, allsrc) { 528144026Sharti p = Lst_Datum(ln); 529144026Sharti 530144026Sharti if (p->order >= gn->order) 531144026Sharti break; 532144026Sharti /* 533144026Sharti * XXX: This can cause loops, and loops can cause 534144026Sharti * unmade targets, but checking is tedious, and the 535144026Sharti * debugging output can show the problem 536144026Sharti */ 537144026Sharti Lst_AtEnd(&p->successors, gn); 538144026Sharti Lst_AtEnd(&gn->preds, p); 539144026Sharti } 540143684Sharti } 5411590Srgrimes} 5421590Srgrimes 543138232Sharti 5441590Srgrimes/*- 5451590Srgrimes *--------------------------------------------------------------------- 5461590Srgrimes * ParseDoDependency -- 5471590Srgrimes * Parse the dependency line in line. 5481590Srgrimes * 5491590Srgrimes * Results: 5501590Srgrimes * None 5511590Srgrimes * 5521590Srgrimes * Side Effects: 5531590Srgrimes * The nodes of the sources are linked as children to the nodes of the 5541590Srgrimes * targets. Some nodes may be created. 5551590Srgrimes * 5561590Srgrimes * We parse a dependency line by first extracting words from the line and 5571590Srgrimes * finding nodes in the list of all targets with that name. This is done 5581590Srgrimes * until a character is encountered which is an operator character. Currently 5591590Srgrimes * these are only ! and :. At this point the operator is parsed and the 5601590Srgrimes * pointer into the line advanced until the first source is encountered. 561144026Sharti * The parsed operator is applied to each node in the 'targets' list, 5621590Srgrimes * which is where the nodes found for the targets are kept, by means of 5631590Srgrimes * the ParseDoOp function. 5641590Srgrimes * The sources are read in much the same way as the targets were except 5651590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell 5661590Srgrimes * and all instances of the resulting words in the list of all targets 5671590Srgrimes * are found. Each of the resulting nodes is then linked to each of the 5681590Srgrimes * targets as one of its children. 5691590Srgrimes * Certain targets are handled specially. These are the ones detailed 5701590Srgrimes * by the specType variable. 5711590Srgrimes * The storing of transformation rules is also taken care of here. 5721590Srgrimes * A target is recognized as a transformation rule by calling 5731590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten 5741590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard 5751590Srgrimes * Targ_FindNode in the target module. 5761590Srgrimes *--------------------------------------------------------------------- 5771590Srgrimes */ 5781590Srgrimesstatic void 579141270ShartiParseDoDependency(char *line) 5801590Srgrimes{ 581144026Sharti char *cp; /* our current position */ 582144026Sharti GNode *gn; /* a general purpose temporary node */ 583144026Sharti int op; /* the operator on the line */ 584144026Sharti char savec; /* a place to save a character */ 585144026Sharti Lst paths; /* Search paths to alter when parsing .PATH targets */ 586144026Sharti int tOp; /* operator from special target */ 587144026Sharti LstNode *ln; 5881590Srgrimes 589144026Sharti tOp = 0; 5901590Srgrimes 591144026Sharti specType = Not; 592144026Sharti waiting = 0; 593144026Sharti Lst_Init(&paths); 5941590Srgrimes 595144026Sharti do { 596144026Sharti for (cp = line; 597144026Sharti *cp && !isspace((unsigned char)*cp) && *cp != '('; 598144026Sharti cp++) { 599144026Sharti if (*cp == '$') { 600144026Sharti /* 601144026Sharti * Must be a dynamic source (would have been 602144026Sharti * expanded otherwise), so call the Var module 603144026Sharti * to parse the puppy so we can safely advance 604144026Sharti * beyond it...There should be no errors in this 605144026Sharti * as they would have been discovered in the 606144026Sharti * initial Var_Subst and we wouldn't be here. 607144026Sharti */ 608144026Sharti size_t length = 0; 609144026Sharti Boolean freeIt; 610144026Sharti char *result; 6111590Srgrimes 612144026Sharti result = Var_Parse(cp, VAR_CMD, TRUE, 613144026Sharti &length, &freeIt); 6141590Srgrimes 615144026Sharti if (freeIt) { 616144026Sharti free(result); 617144026Sharti } 618144026Sharti cp += length - 1; 619102178Sru 620144026Sharti } else if (*cp == '!' || *cp == ':') { 621144026Sharti /* 622144026Sharti * We don't want to end a word on ':' or '!' if 623144026Sharti * there is a better match later on in the 624144026Sharti * string (greedy matching). 625144026Sharti * This allows the user to have targets like: 626144026Sharti * fie::fi:fo: fum 627144026Sharti * foo::bar: 628144026Sharti * where "fie::fi:fo" and "foo::bar" are the 629144026Sharti * targets. In real life this is used for perl5 630144026Sharti * library man pages where "::" separates an 631144026Sharti * object from its class. Ie: 632144026Sharti * "File::Spec::Unix". This behaviour is also 633144026Sharti * consistent with other versions of make. 634144026Sharti */ 635144026Sharti char *p = cp + 1; 636102178Sru 637144026Sharti if (*cp == ':' && *p == ':') 638144026Sharti p++; 639102178Sru 640144026Sharti /* Found the best match already. */ 641144026Sharti if (*p == '\0' || isspace(*p)) 642144026Sharti break; 643102178Sru 644144026Sharti p += strcspn(p, "!:"); 6458874Srgrimes 646144026Sharti /* No better match later on... */ 647144026Sharti if (*p == '\0') 648144026Sharti break; 649144026Sharti } 650144026Sharti continue; 6511590Srgrimes } 652144026Sharti if (*cp == '(') { 653144026Sharti /* 654144026Sharti * Archives must be handled specially to make sure the 655144026Sharti * OP_ARCHV flag is set in their 'type' field, for one 656144026Sharti * thing, and because things like "archive(file1.o 657144026Sharti * file2.o file3.o)" are permissible. Arch_ParseArchive 658144026Sharti * will set 'line' to be the first non-blank after the 659144026Sharti * archive-spec. It creates/finds nodes for the members 660144026Sharti * and places them on the given list, returning SUCCESS 661144026Sharti * if all went well and FAILURE if there was an error in 662144026Sharti * the specification. On error, line should remain 663144026Sharti * untouched. 664144026Sharti */ 665144026Sharti if (Arch_ParseArchive(&line, &targets, VAR_CMD) != 666144026Sharti SUCCESS) { 667144026Sharti Parse_Error(PARSE_FATAL, 668144026Sharti "Error in archive specification: \"%s\"", 669144026Sharti line); 670144026Sharti return; 671144026Sharti } else { 672144026Sharti cp = line; 673144026Sharti continue; 674144026Sharti } 675144026Sharti } 676144026Sharti savec = *cp; 6778874Srgrimes 678144026Sharti if (!*cp) { 679144026Sharti /* 680144026Sharti * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often 681144026Sharti * triggered by undetected conflicts from cvs/rcs 682144026Sharti * merges. 683144026Sharti */ 684144026Sharti if (strncmp(line, "<<<<<<", 6) == 0 || 685144026Sharti strncmp(line, "======", 6) == 0 || 686144026Sharti strncmp(line, ">>>>>>", 6) == 0) { 687144026Sharti Parse_Error(PARSE_FATAL, "Makefile appears to " 688144026Sharti "contain unresolved cvs/rcs/??? merge " 689144026Sharti "conflicts"); 690144026Sharti } else 691144026Sharti Parse_Error(PARSE_FATAL, "Need an operator"); 692144026Sharti return; 693144026Sharti } 694144026Sharti *cp = '\0'; 6951590Srgrimes /* 696144026Sharti * Have a word in line. See if it's a special target and set 697144026Sharti * specType to match it. 6981590Srgrimes */ 699144026Sharti if (*line == '.' && isupper((unsigned char)line[1])) { 700144026Sharti /* 701144026Sharti * See if the target is a special target that must have 702144026Sharti * it or its sources handled specially. 703144026Sharti */ 704144026Sharti int keywd = ParseFindKeyword(line); 705144026Sharti 706144026Sharti if (keywd != -1) { 707144026Sharti if (specType == ExPath && 708144026Sharti parseKeywords[keywd].spec != ExPath) { 709144026Sharti Parse_Error(PARSE_FATAL, 710144026Sharti "Mismatched special targets"); 711144026Sharti return; 712144026Sharti } 713144026Sharti 714144026Sharti specType = parseKeywords[keywd].spec; 715144026Sharti tOp = parseKeywords[keywd].op; 716144026Sharti 717144026Sharti /* 718144026Sharti * Certain special targets have special 719144026Sharti * semantics: 720144026Sharti * .PATH Have to set the dirSearchPath 721144026Sharti * variable too 722144026Sharti * .MAIN Its sources are only used if 723144026Sharti * nothing has been specified to 724144026Sharti * create. 725144026Sharti * .DEFAULT Need to create a node to hang 726144026Sharti * commands on, but we don't want 727144026Sharti * it in the graph, nor do we want 728144026Sharti * it to be the Main Target, so we 729144026Sharti * create it, set OP_NOTMAIN and 730144026Sharti * add it to the list, setting 731144026Sharti * DEFAULT to the new node for 732144026Sharti * later use. We claim the node is 733144026Sharti * A transformation rule to make 734144026Sharti * life easier later, when we'll 735144026Sharti * use Make_HandleUse to actually 736144026Sharti * apply the .DEFAULT commands. 737144026Sharti * .PHONY The list of targets 738144026Sharti * .BEGIN 739144026Sharti * .END 740144026Sharti * .INTERRUPT Are not to be considered the 741144026Sharti * main target. 742144026Sharti * .NOTPARALLEL Make only one target at a time. 743144026Sharti * .SINGLESHELL Create a shell for each 744144026Sharti * command. 745144026Sharti * .ORDER Must set initial predecessor 746144026Sharti * to NULL 747144026Sharti */ 748144026Sharti switch (specType) { 749144026Sharti case ExPath: 750144026Sharti Lst_AtEnd(&paths, &dirSearchPath); 751144026Sharti break; 752144026Sharti case Main: 753144026Sharti if (!Lst_IsEmpty(&create)) { 754144026Sharti specType = Not; 755144026Sharti } 756144026Sharti break; 757144026Sharti case Begin: 758144026Sharti case End: 759144026Sharti case Interrupt: 760144026Sharti gn = Targ_FindNode(line, TARG_CREATE); 761144026Sharti gn->type |= OP_NOTMAIN; 762144026Sharti Lst_AtEnd(&targets, gn); 763144026Sharti break; 764144026Sharti case Default: 765144026Sharti gn = Targ_NewGN(".DEFAULT"); 766144026Sharti gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 767144026Sharti Lst_AtEnd(&targets, gn); 768144026Sharti DEFAULT = gn; 769144026Sharti break; 770144026Sharti case NotParallel: 771144026Sharti maxJobs = 1; 772144026Sharti break; 773144026Sharti case SingleShell: 774144026Sharti compatMake = 1; 775144026Sharti break; 776144026Sharti case Order: 777144026Sharti predecessor = NULL; 778144026Sharti break; 779144026Sharti default: 780144026Sharti break; 781144026Sharti } 782144026Sharti 783144026Sharti } else if (strncmp(line, ".PATH", 5) == 0) { 784144026Sharti /* 785144026Sharti * .PATH<suffix> has to be handled specially. 786144026Sharti * Call on the suffix module to give us a path 787144026Sharti * to modify. 788144026Sharti */ 789144026Sharti struct Path *path; 790144026Sharti 791144026Sharti specType = ExPath; 792144026Sharti path = Suff_GetPath(&line[5]); 793144026Sharti if (path == NULL) { 794144026Sharti Parse_Error(PARSE_FATAL, "Suffix '%s' " 795144026Sharti "not defined (yet)", &line[5]); 796144026Sharti return; 797144026Sharti } else 798144026Sharti Lst_AtEnd(&paths, path); 7991590Srgrimes } 8001590Srgrimes } 801144026Sharti 8021590Srgrimes /* 803144026Sharti * Have word in line. Get or create its node and stick it at 804144026Sharti * the end of the targets list 8051590Srgrimes */ 806144026Sharti if ((specType == Not) && (*line != '\0')) { 8078874Srgrimes 808144026Sharti /* target names to be found and added to targets list */ 809144026Sharti Lst curTargs = Lst_Initializer(curTargs); 8108874Srgrimes 811144026Sharti if (Dir_HasWildcards(line)) { 812144026Sharti /* 813144026Sharti * Targets are to be sought only in the current 814144026Sharti * directory, so create an empty path for the 815144026Sharti * thing. Note we need to use Path_Clear in the 816144026Sharti * destruction of the path as the Dir module 817144026Sharti * could have added a directory to the path... 818144026Sharti */ 819144026Sharti struct Path emptyPath = 820144026Sharti TAILQ_HEAD_INITIALIZER(emptyPath); 821138916Sharti 822144026Sharti Path_Expand(line, &emptyPath, &curTargs); 823144026Sharti Path_Clear(&emptyPath); 8248874Srgrimes 825144026Sharti } else { 826144026Sharti /* 827144026Sharti * No wildcards, but we want to avoid code 828144026Sharti * duplication, so create a list with the word 829144026Sharti * on it. 830144026Sharti */ 831144026Sharti Lst_AtEnd(&curTargs, line); 832144026Sharti } 8338874Srgrimes 834144026Sharti while (!Lst_IsEmpty(&curTargs)) { 835144026Sharti char *targName = Lst_DeQueue(&curTargs); 836144026Sharti 837144026Sharti if (!Suff_IsTransform (targName)) { 838144026Sharti gn = Targ_FindNode(targName, 839144026Sharti TARG_CREATE); 840144026Sharti } else { 841144026Sharti gn = Suff_AddTransform(targName); 842144026Sharti } 843144026Sharti 844144026Sharti Lst_AtEnd(&targets, gn); 845144026Sharti } 846144026Sharti } else if (specType == ExPath && *line != '.' && *line != '\0'){ 847144026Sharti Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 848144026Sharti line); 849144026Sharti } 850144026Sharti 851144026Sharti *cp = savec; 8521590Srgrimes /* 853144026Sharti * If it is a special type and not .PATH, it's the only 854144026Sharti * target we allow on this line... 8551590Srgrimes */ 856144026Sharti if (specType != Not && specType != ExPath) { 857144026Sharti Boolean warnFlag = FALSE; 8588874Srgrimes 859144026Sharti while ((*cp != '!') && (*cp != ':') && *cp) { 860144026Sharti if (*cp != ' ' && *cp != '\t') { 861144026Sharti warnFlag = TRUE; 862144026Sharti } 863144026Sharti cp++; 864144026Sharti } 865144026Sharti if (warnFlag) { 866144026Sharti Parse_Error(PARSE_WARNING, 867144026Sharti "Extra target ignored"); 868144026Sharti } 8691590Srgrimes } else { 870144026Sharti while (*cp && isspace((unsigned char)*cp)) { 871144026Sharti cp++; 872144026Sharti } 8731590Srgrimes } 874144026Sharti line = cp; 875144026Sharti } while ((*line != '!') && (*line != ':') && *line); 8768874Srgrimes 877144026Sharti if (!Lst_IsEmpty(&targets)) { 878144026Sharti switch (specType) { 879144026Sharti default: 880144026Sharti Parse_Error(PARSE_WARNING, "Special and mundane " 881144026Sharti "targets don't mix. Mundane ones ignored"); 882144026Sharti break; 883144026Sharti case Default: 884144026Sharti case Begin: 885144026Sharti case End: 886144026Sharti case Interrupt: 887144026Sharti /* 888144026Sharti * These four create nodes on which to hang commands, so 889144026Sharti * targets shouldn't be empty... 890144026Sharti */ 891144026Sharti case Not: 892144026Sharti /* 893144026Sharti * Nothing special here -- targets can be empty if it 894144026Sharti * wants. 895144026Sharti */ 896144026Sharti break; 897144026Sharti } 8981590Srgrimes } 8998874Srgrimes 9001590Srgrimes /* 901144026Sharti * Have now parsed all the target names. Must parse the operator next. 902144026Sharti * The result is left in op. 9031590Srgrimes */ 904144026Sharti if (*cp == '!') { 905144026Sharti op = OP_FORCE; 906144026Sharti } else if (*cp == ':') { 907144026Sharti if (cp[1] == ':') { 908144026Sharti op = OP_DOUBLEDEP; 909144026Sharti cp++; 910144026Sharti } else { 911144026Sharti op = OP_DEPENDS; 9121590Srgrimes } 9131590Srgrimes } else { 914144026Sharti Parse_Error(PARSE_FATAL, "Missing dependency operator"); 915144026Sharti return; 916144026Sharti } 917144026Sharti 918144026Sharti cp++; /* Advance beyond operator */ 919144026Sharti 920144026Sharti ParseDoOp(op); 921144026Sharti 922144026Sharti /* 923144026Sharti * Get to the first source 924144026Sharti */ 925144026Sharti while (*cp && isspace((unsigned char)*cp)) { 9261590Srgrimes cp++; 9271590Srgrimes } 9281590Srgrimes line = cp; 9291590Srgrimes 930144026Sharti /* 931144026Sharti * Several special targets take different actions if present with no 932144026Sharti * sources: 933144026Sharti * a .SUFFIXES line with no sources clears out all old suffixes 934144026Sharti * a .PRECIOUS line makes all targets precious 935144026Sharti * a .IGNORE line ignores errors for all targets 936144026Sharti * a .SILENT line creates silence when making all targets 937144026Sharti * a .PATH removes all directories from the search path(s). 938144026Sharti */ 939144026Sharti if (!*line) { 940144026Sharti switch (specType) { 941144026Sharti case Suffixes: 942144026Sharti Suff_ClearSuffixes(); 943144026Sharti break; 944144026Sharti case Precious: 945144026Sharti allPrecious = TRUE; 946144026Sharti break; 947144026Sharti case Ignore: 948144026Sharti ignoreErrors = TRUE; 949144026Sharti break; 950144026Sharti case Silent: 951144026Sharti beSilent = TRUE; 952144026Sharti break; 953144026Sharti case ExPath: 954144026Sharti LST_FOREACH(ln, &paths) 955144026Sharti Path_Clear(Lst_Datum(ln)); 956144026Sharti break; 957144026Sharti case Posix: 958144026Sharti Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 959144026Sharti break; 960144026Sharti default: 961144026Sharti break; 962144026Sharti } 963144026Sharti 964144026Sharti } else if (specType == MFlags) { 9651590Srgrimes /* 966144026Sharti * Call on functions in main.c to deal with these arguments and 967144026Sharti * set the initial character to a null-character so the loop to 968144026Sharti * get sources won't get anything 9691590Srgrimes */ 970144026Sharti Main_ParseArgLine(line, 0); 971144026Sharti *line = '\0'; 9721590Srgrimes 973144026Sharti } else if (specType == ExShell) { 974144026Sharti if (Job_ParseShell(line) != SUCCESS) { 975144026Sharti Parse_Error(PARSE_FATAL, 976144026Sharti "improper shell specification"); 977144026Sharti return; 978144026Sharti } 979144026Sharti *line = '\0'; 980144026Sharti 981144026Sharti } else if ((specType == NotParallel) || (specType == SingleShell)) { 982144026Sharti *line = '\0'; 9831590Srgrimes } 9841590Srgrimes 985144026Sharti /* 986144026Sharti * NOW GO FOR THE SOURCES 987144026Sharti */ 988144026Sharti if ((specType == Suffixes) || (specType == ExPath) || 989144026Sharti (specType == Includes) || (specType == Libs) || 990144026Sharti (specType == Null)) { 991144026Sharti while (*line) { 992144026Sharti /* 993144026Sharti * If the target was one that doesn't take files as its 994144026Sharti * sources but takes something like suffixes, we take 995144026Sharti * each space-separated word on the line as a something 996144026Sharti * and deal with it accordingly. 997144026Sharti * 998144026Sharti * If the target was .SUFFIXES, we take each source as 999144026Sharti * a suffix and add it to the list of suffixes 1000144026Sharti * maintained by the Suff module. 1001144026Sharti * 1002144026Sharti * If the target was a .PATH, we add the source as a 1003144026Sharti * directory to search on the search path. 1004144026Sharti * 1005144026Sharti * If it was .INCLUDES, the source is taken to be the 1006144026Sharti * suffix of files which will be #included and whose 1007144026Sharti * search path should be present in the .INCLUDES 1008144026Sharti * variable. 1009144026Sharti * 1010144026Sharti * If it was .LIBS, the source is taken to be the 1011144026Sharti * suffix of files which are considered libraries and 1012144026Sharti * whose search path should be present in the .LIBS 1013144026Sharti * variable. 1014144026Sharti * 1015144026Sharti * If it was .NULL, the source is the suffix to use 1016144026Sharti * when a file has no valid suffix. 1017144026Sharti */ 1018144026Sharti char savech; 1019144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1020144026Sharti cp++; 1021144026Sharti } 1022144026Sharti savech = *cp; 1023144026Sharti *cp = '\0'; 1024144026Sharti switch (specType) { 1025144026Sharti case Suffixes: 1026144026Sharti Suff_AddSuffix(line); 1027144026Sharti break; 1028144026Sharti case ExPath: 1029144026Sharti LST_FOREACH(ln, &paths) 1030144026Sharti Path_AddDir(Lst_Datum(ln), line); 1031144026Sharti break; 1032144026Sharti case Includes: 1033144026Sharti Suff_AddInclude(line); 1034144026Sharti break; 1035144026Sharti case Libs: 1036144026Sharti Suff_AddLib(line); 1037144026Sharti break; 1038144026Sharti case Null: 1039144026Sharti Suff_SetNull(line); 1040144026Sharti break; 1041144026Sharti default: 1042144026Sharti break; 1043144026Sharti } 1044144026Sharti *cp = savech; 1045144026Sharti if (savech != '\0') { 1046144026Sharti cp++; 1047144026Sharti } 1048144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1049144026Sharti cp++; 1050144026Sharti } 1051144026Sharti line = cp; 1052144026Sharti } 1053144026Sharti Lst_Destroy(&paths, NOFREE); 10541590Srgrimes 1055144026Sharti } else { 1056144026Sharti /* list of sources in order */ 1057144026Sharti Lst curSrcs = Lst_Initializer(curSrc); 10581590Srgrimes 1059144026Sharti while (*line) { 1060144026Sharti /* 1061144026Sharti * The targets take real sources, so we must beware of 1062144026Sharti * archive specifications (i.e. things with left 1063144026Sharti * parentheses in them) and handle them accordingly. 1064144026Sharti */ 1065144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1066144026Sharti if (*cp == '(' && cp > line && cp[-1] != '$') { 1067144026Sharti /* 1068144026Sharti * Only stop for a left parenthesis if 1069144026Sharti * it isn't at the start of a word 1070144026Sharti * (that'll be for variable changes 1071144026Sharti * later) and isn't preceded by a dollar 1072144026Sharti * sign (a dynamic source). 1073144026Sharti */ 1074144026Sharti break; 1075144026Sharti } else { 1076144026Sharti cp++; 1077144026Sharti } 1078144026Sharti } 10791590Srgrimes 1080144026Sharti if (*cp == '(') { 1081144026Sharti GNode *gnp; 10828874Srgrimes 1083144026Sharti /* list of archive source names after exp. */ 1084144026Sharti Lst sources = Lst_Initializer(sources); 1085138916Sharti 1086144026Sharti if (Arch_ParseArchive(&line, &sources, 1087144026Sharti VAR_CMD) != SUCCESS) { 1088144026Sharti Parse_Error(PARSE_FATAL, "Error in " 1089144026Sharti "source archive spec \"%s\"", line); 1090144026Sharti return; 1091144026Sharti } 1092141270Sharti 1093144026Sharti while (!Lst_IsEmpty(&sources)) { 1094144026Sharti gnp = Lst_DeQueue(&sources); 1095144026Sharti ParseDoSrc(tOp, gnp->name, &curSrcs); 1096144026Sharti } 1097144026Sharti cp = line; 1098144026Sharti } else { 1099144026Sharti if (*cp) { 1100144026Sharti *cp = '\0'; 1101144026Sharti cp += 1; 1102144026Sharti } 11031590Srgrimes 1104144026Sharti ParseDoSrc(tOp, line, &curSrcs); 1105144026Sharti } 1106144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1107144026Sharti cp++; 1108144026Sharti } 1109144026Sharti line = cp; 11101590Srgrimes } 1111144026Sharti Lst_Destroy(&curSrcs, NOFREE); 1112144026Sharti } 11131590Srgrimes 1114144026Sharti if (mainNode == NULL) { 1115144026Sharti /* 1116144026Sharti * If we have yet to decide on a main target to make, in the 1117144026Sharti * absence of any user input, we want the first target on 1118144026Sharti * the first dependency line that is actually a real target 1119144026Sharti * (i.e. isn't a .USE or .EXEC rule) to be made. 1120144026Sharti */ 1121144026Sharti LST_FOREACH(ln, &targets) { 1122144026Sharti gn = Lst_Datum(ln); 1123144026Sharti if ((gn->type & (OP_NOTMAIN | OP_USE | 1124144026Sharti OP_EXEC | OP_TRANSFORM)) == 0) { 1125144026Sharti mainNode = gn; 1126144026Sharti Targ_SetMain(gn); 1127144026Sharti break; 1128144026Sharti } 11291590Srgrimes } 11301590Srgrimes } 11311590Srgrimes} 11321590Srgrimes 11331590Srgrimes/*- 11341590Srgrimes *--------------------------------------------------------------------- 11351590Srgrimes * Parse_IsVar -- 11361590Srgrimes * Return TRUE if the passed line is a variable assignment. A variable 11371590Srgrimes * assignment consists of a single word followed by optional whitespace 11381590Srgrimes * followed by either a += or an = operator. 11391590Srgrimes * This function is used both by the Parse_File function and main when 11401590Srgrimes * parsing the command-line arguments. 11411590Srgrimes * 11421590Srgrimes * Results: 11431590Srgrimes * TRUE if it is. FALSE if it ain't 11441590Srgrimes * 11451590Srgrimes * Side Effects: 11461590Srgrimes * none 11471590Srgrimes *--------------------------------------------------------------------- 11481590Srgrimes */ 11491590SrgrimesBoolean 1150138232ShartiParse_IsVar(char *line) 11511590Srgrimes{ 1152144026Sharti Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1153144026Sharti Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1154138232Sharti 1155144026Sharti int level = 0; 1156103503Sjmallett#define ISEQOPERATOR(c) \ 115718730Ssteve (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) 11581590Srgrimes 1159144026Sharti /* 1160144026Sharti * Skip to variable name 1161144026Sharti */ 1162144026Sharti for (; (*line == ' ') || (*line == '\t'); line++) 1163144026Sharti continue; 11641590Srgrimes 1165144026Sharti for (; *line != '=' || level != 0; line++) { 1166144026Sharti switch (*line) { 1167144026Sharti case '\0': 1168144026Sharti /* 1169144026Sharti * end-of-line -- can't be a variable assignment. 1170144026Sharti */ 1171144026Sharti return (FALSE); 117218730Ssteve 1173144026Sharti case ' ': 1174144026Sharti case '\t': 1175144026Sharti /* 1176144026Sharti * there can be as much white space as desired so long 1177144026Sharti * as there is only one word before the operator 1178144026Sharti */ 1179144026Sharti wasSpace = TRUE; 1180144026Sharti break; 118118730Ssteve 1182144026Sharti case '(': 1183144026Sharti case '{': 1184144026Sharti level++; 1185144026Sharti break; 118618730Ssteve 1187144026Sharti case '}': 1188144026Sharti case ')': 1189144026Sharti level--; 1190144026Sharti break; 119118730Ssteve 1192144026Sharti default: 1193144026Sharti if (wasSpace && haveName) { 1194144026Sharti if (ISEQOPERATOR(*line)) { 1195144026Sharti /* 1196144026Sharti * We must have a finished word 1197144026Sharti */ 1198144026Sharti if (level != 0) 1199144026Sharti return (FALSE); 120018730Ssteve 1201144026Sharti /* 1202144026Sharti * When an = operator [+?!:] is found, 1203144026Sharti * the next character must be an = or 1204144026Sharti * it ain't a valid assignment. 1205144026Sharti */ 1206144026Sharti if (line[1] == '=') 1207144026Sharti return (haveName); 120818730Ssteve#ifdef SUNSHCMD 1209144026Sharti /* 1210144026Sharti * This is a shell command 1211144026Sharti */ 1212144026Sharti if (strncmp(line, ":sh", 3) == 0) 1213144026Sharti return (haveName); 121418730Ssteve#endif 1215144026Sharti } 1216144026Sharti /* 1217144026Sharti * This is the start of another word, so not 1218144026Sharti * assignment. 1219144026Sharti */ 1220144026Sharti return (FALSE); 1221144026Sharti 1222144026Sharti } else { 1223144026Sharti haveName = TRUE; 1224144026Sharti wasSpace = FALSE; 1225144026Sharti } 1226144026Sharti break; 1227144026Sharti } 12281590Srgrimes } 12291590Srgrimes 1230144026Sharti return (haveName); 12311590Srgrimes} 12321590Srgrimes 12331590Srgrimes/*- 12341590Srgrimes *--------------------------------------------------------------------- 12351590Srgrimes * Parse_DoVar -- 12361590Srgrimes * Take the variable assignment in the passed line and do it in the 12371590Srgrimes * global context. 12381590Srgrimes * 12391590Srgrimes * Note: There is a lexical ambiguity with assignment modifier characters 12401590Srgrimes * in variable names. This routine interprets the character before the = 12411590Srgrimes * as a modifier. Therefore, an assignment like 12421590Srgrimes * C++=/usr/bin/CC 12431590Srgrimes * is interpreted as "C+ +=" instead of "C++ =". 12441590Srgrimes * 12451590Srgrimes * Results: 12461590Srgrimes * none 12471590Srgrimes * 12481590Srgrimes * Side Effects: 12491590Srgrimes * the variable structure of the given variable name is altered in the 12501590Srgrimes * global context. 12511590Srgrimes *--------------------------------------------------------------------- 12521590Srgrimes */ 12531590Srgrimesvoid 1254138232ShartiParse_DoVar(char *line, GNode *ctxt) 12551590Srgrimes{ 1256144026Sharti char *cp; /* pointer into line */ 1257144026Sharti enum { 1258144026Sharti VAR_SUBST, 1259144026Sharti VAR_APPEND, 1260144026Sharti VAR_SHELL, 1261144026Sharti VAR_NORMAL 1262144026Sharti } type; /* Type of assignment */ 1263144026Sharti char *opc; /* ptr to operator character to 1264144026Sharti * null-terminate the variable name */ 1265144026Sharti 1266144026Sharti /* 1267144026Sharti * Avoid clobbered variable warnings by forcing the compiler 1268144026Sharti * to ``unregister'' variables 1269144026Sharti */ 12701590Srgrimes#if __GNUC__ 1271144026Sharti (void)&cp; 1272144026Sharti (void)&line; 12735814Sjkh#endif 12741590Srgrimes 1275144026Sharti /* 1276144026Sharti * Skip to variable name 1277144026Sharti */ 1278144026Sharti while ((*line == ' ') || (*line == '\t')) { 1279144026Sharti line++; 1280144026Sharti } 12811590Srgrimes 1282144026Sharti /* 1283144026Sharti * Skip to operator character, nulling out whitespace as we go 1284144026Sharti */ 1285144026Sharti for (cp = line + 1; *cp != '='; cp++) { 1286144026Sharti if (isspace((unsigned char)*cp)) { 1287144026Sharti *cp = '\0'; 1288144026Sharti } 12891590Srgrimes } 1290144026Sharti opc = cp - 1; /* operator is the previous character */ 1291144026Sharti *cp++ = '\0'; /* nuke the = */ 12921590Srgrimes 1293144026Sharti /* 1294144026Sharti * Check operator type 1295144026Sharti */ 1296144026Sharti switch (*opc) { 1297144026Sharti case '+': 1298144026Sharti type = VAR_APPEND; 1299144026Sharti *opc = '\0'; 1300144026Sharti break; 13011590Srgrimes 1302144026Sharti case '?': 1303144026Sharti /* 1304144026Sharti * If the variable already has a value, we don't do anything. 1305144026Sharti */ 1306144026Sharti *opc = '\0'; 1307144026Sharti if (Var_Exists(line, ctxt)) { 1308144026Sharti return; 1309144026Sharti } else { 1310144026Sharti type = VAR_NORMAL; 1311144026Sharti } 1312144026Sharti break; 13131590Srgrimes 1314144026Sharti case ':': 1315144026Sharti type = VAR_SUBST; 1316144026Sharti *opc = '\0'; 1317144026Sharti break; 13181590Srgrimes 1319144026Sharti case '!': 1320144026Sharti type = VAR_SHELL; 1321144026Sharti *opc = '\0'; 1322144026Sharti break; 13231590Srgrimes 1324144026Sharti default: 132518730Ssteve#ifdef SUNSHCMD 1326144026Sharti while (*opc != ':') { 1327144026Sharti if (opc == line) 1328144026Sharti break; 1329144026Sharti else 1330144026Sharti --opc; 1331144026Sharti } 133218730Ssteve 1333144026Sharti if (strncmp(opc, ":sh", 3) == 0) { 1334144026Sharti type = VAR_SHELL; 1335144026Sharti *opc = '\0'; 1336144026Sharti break; 1337144026Sharti } 1338144026Sharti#endif 1339144026Sharti type = VAR_NORMAL; 134018730Ssteve break; 1341144026Sharti } 13421590Srgrimes 1343144026Sharti while (isspace((unsigned char)*cp)) { 1344144026Sharti cp++; 1345144026Sharti } 13461590Srgrimes 1347144026Sharti if (type == VAR_APPEND) { 1348144026Sharti Var_Append(line, cp, ctxt); 13491590Srgrimes 1350144026Sharti } else if (type == VAR_SUBST) { 1351144026Sharti /* 1352144026Sharti * Allow variables in the old value to be undefined, but leave 1353144026Sharti * their invocation alone -- this is done by forcing oldVars 1354144026Sharti * to be false. 1355144026Sharti * XXX: This can cause recursive variables, but that's not 1356144026Sharti * hard to do, and this allows someone to do something like 1357144026Sharti * 1358144026Sharti * CFLAGS = $(.INCLUDES) 1359144026Sharti * CFLAGS := -I.. $(CFLAGS) 1360144026Sharti * 1361144026Sharti * And not get an error. 1362144026Sharti */ 1363144026Sharti Boolean oldOldVars = oldVars; 136498509Sjmallett 1365144026Sharti oldVars = FALSE; 136698509Sjmallett 1367144026Sharti /* 1368144026Sharti * make sure that we set the variable the first time to nothing 1369144026Sharti * so that it gets substituted! 1370144026Sharti */ 1371144026Sharti if (!Var_Exists(line, ctxt)) 1372144026Sharti Var_Set(line, "", ctxt); 1373142457Sharti 1374144026Sharti cp = Buf_Peel(Var_Subst(NULL, cp, ctxt, FALSE)); 13751590Srgrimes 1376144026Sharti oldVars = oldOldVars; 13771590Srgrimes 1378144026Sharti Var_Set(line, cp, ctxt); 1379144026Sharti free(cp); 13801590Srgrimes 1381144026Sharti } else if (type == VAR_SHELL) { 1382144026Sharti /* 1383144026Sharti * TRUE if the command needs to be freed, i.e. 1384144026Sharti * if any variable expansion was performed 1385144026Sharti */ 1386144026Sharti Boolean freeCmd = FALSE; 1387144026Sharti Buffer *buf; 1388144026Sharti const char *error; 13891590Srgrimes 1390144026Sharti if (strchr(cp, '$') != NULL) { 1391144026Sharti /* 1392144026Sharti * There's a dollar sign in the command, so perform 1393144026Sharti * variable expansion on the whole thing. The 1394144026Sharti * resulting string will need freeing when we're done, 1395144026Sharti * so set freeCmd to TRUE. 1396144026Sharti */ 1397144026Sharti cp = Buf_Peel(Var_Subst(NULL, cp, VAR_CMD, TRUE)); 1398144026Sharti freeCmd = TRUE; 1399144026Sharti } 14001590Srgrimes 1401144026Sharti buf = Cmd_Exec(cp, &error); 1402144026Sharti Var_Set(line, Buf_Data(buf), ctxt); 1403144026Sharti Buf_Destroy(buf, TRUE); 1404144026Sharti 1405144026Sharti if (error) 1406144026Sharti Parse_Error(PARSE_WARNING, error, cp); 1407144026Sharti 1408144026Sharti if (freeCmd) 1409144026Sharti free(cp); 1410144026Sharti 1411144026Sharti } else { 1412144026Sharti /* 1413144026Sharti * Normal assignment -- just do it. 1414144026Sharti */ 1415144026Sharti Var_Set(line, cp, ctxt); 1416144026Sharti } 14171590Srgrimes} 14181590Srgrimes 14191590Srgrimes/*- 14201590Srgrimes *----------------------------------------------------------------------- 14211590Srgrimes * ParseHasCommands -- 14221590Srgrimes * Callback procedure for Parse_File when destroying the list of 14231590Srgrimes * targets on the last dependency line. Marks a target as already 14241590Srgrimes * having commands if it does, to keep from having shell commands 14251590Srgrimes * on multiple dependency lines. 14261590Srgrimes * 14271590Srgrimes * Results: 14285814Sjkh * None 14291590Srgrimes * 14301590Srgrimes * Side Effects: 14311590Srgrimes * OP_HAS_COMMANDS may be set for the target. 14321590Srgrimes * 14331590Srgrimes *----------------------------------------------------------------------- 14341590Srgrimes */ 14355814Sjkhstatic void 1436104696SjmallettParseHasCommands(void *gnp) 14371590Srgrimes{ 1438144026Sharti GNode *gn = gnp; 1439138232Sharti 1440144026Sharti if (!Lst_IsEmpty(&gn->commands)) { 1441144026Sharti gn->type |= OP_HAS_COMMANDS; 1442144026Sharti } 14431590Srgrimes} 14441590Srgrimes 14451590Srgrimes/*- 14461590Srgrimes *----------------------------------------------------------------------- 14471590Srgrimes * Parse_AddIncludeDir -- 14481590Srgrimes * Add a directory to the path searched for included makefiles 14491590Srgrimes * bracketed by double-quotes. Used by functions in main.c 14501590Srgrimes * 14511590Srgrimes * Results: 14521590Srgrimes * None. 14531590Srgrimes * 14541590Srgrimes * Side Effects: 14551590Srgrimes * The directory is appended to the list. 14561590Srgrimes * 14571590Srgrimes *----------------------------------------------------------------------- 14581590Srgrimes */ 14591590Srgrimesvoid 1460138232ShartiParse_AddIncludeDir(char *dir) 14611590Srgrimes{ 1462138232Sharti 1463144026Sharti Path_AddDir(&parseIncPath, dir); 14641590Srgrimes} 14651590Srgrimes 146636347Ssteve/*--------------------------------------------------------------------- 146736347Ssteve * ParseDoError -- 146836347Ssteve * Handle error directive 146936347Ssteve * 147036347Ssteve * The input is the line minus the ".error". We substitute variables, 147136347Ssteve * print the message and exit(1) or just print a warning if the ".error" 147236347Ssteve * directive is malformed. 147336347Ssteve * 147436347Ssteve *--------------------------------------------------------------------- 147536347Ssteve */ 147636347Sstevestatic void 1477104696SjmallettParseDoError(char *errmsg) 147836347Ssteve{ 1479142457Sharti Buffer *buf; 1480138232Sharti 1481138232Sharti if (!isspace((unsigned char)*errmsg)) { 148236347Ssteve Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg); 148336347Ssteve return; 148436347Ssteve } 1485138232Sharti 1486138232Sharti while (isspace((unsigned char)*errmsg)) 148736347Ssteve errmsg++; 1488138232Sharti 1489142457Sharti buf = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE); 1490143959Sharti Parse_Error(PARSE_FATAL, "%s", Buf_Data(buf)); 1491142457Sharti Buf_Destroy(buf, TRUE); 1492142457Sharti 1493128160Sru /* Terminate immediately. */ 149436347Ssteve exit(1); 149536347Ssteve} 149636347Ssteve 1497128160Sru/*--------------------------------------------------------------------- 1498128160Sru * ParseDoWarning -- 1499128160Sru * Handle warning directive 1500128160Sru * 1501128160Sru * The input is the line minus the ".warning". We substitute variables 1502128160Sru * and print the message or just print a warning if the ".warning" 1503128160Sru * directive is malformed. 1504128160Sru * 1505128160Sru *--------------------------------------------------------------------- 1506128160Sru */ 1507128160Srustatic void 1508128160SruParseDoWarning(char *warnmsg) 1509128160Sru{ 1510142457Sharti Buffer *buf; 1511138232Sharti 1512138232Sharti if (!isspace((unsigned char)*warnmsg)) { 1513128160Sru Parse_Error(PARSE_WARNING, "invalid syntax: .warning%s", 1514128160Sru warnmsg); 1515128160Sru return; 1516128160Sru } 1517138232Sharti 1518138232Sharti while (isspace((unsigned char)*warnmsg)) 1519128160Sru warnmsg++; 1520138232Sharti 1521142457Sharti buf = Var_Subst(NULL, warnmsg, VAR_GLOBAL, FALSE); 1522143959Sharti Parse_Error(PARSE_WARNING, "%s", Buf_Data(buf)); 1523142457Sharti Buf_Destroy(buf, TRUE); 1524128160Sru} 1525128160Sru 15261590Srgrimes/*- 15271590Srgrimes *--------------------------------------------------------------------- 15281590Srgrimes * ParseDoInclude -- 15291590Srgrimes * Push to another file. 15308874Srgrimes * 15311590Srgrimes * The input is the line minus the #include. A file spec is a string 15321590Srgrimes * enclosed in <> or "". The former is looked for only in sysIncPath. 15331590Srgrimes * The latter in . and the directories specified by -I command line 15341590Srgrimes * options 15351590Srgrimes * 15361590Srgrimes * Results: 15371590Srgrimes * None 15381590Srgrimes * 15391590Srgrimes * Side Effects: 1540126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1541126824Sru * curFile.fname and curFile.F are altered for the new file 15421590Srgrimes *--------------------------------------------------------------------- 15431590Srgrimes */ 15441590Srgrimesstatic void 1545141270ShartiParseDoInclude(char *file) 15461590Srgrimes{ 1547144026Sharti char *fullname; /* full pathname of file */ 1548144026Sharti IFile *oldFile; /* state associated with current file */ 1549144026Sharti char endc; /* the character which ends the file spec */ 1550144026Sharti char *cp; /* current position in file spec */ 1551144026Sharti Boolean isSystem; /* TRUE if makefile is a system makefile */ 1552144026Sharti Buffer *buf; 15531590Srgrimes 1554144026Sharti /* 1555144026Sharti * Skip to delimiter character so we know where to look 1556144026Sharti */ 1557144026Sharti while ((*file == ' ') || (*file == '\t')) { 1558144026Sharti file++; 1559144026Sharti } 15601590Srgrimes 1561144026Sharti if ((*file != '"') && (*file != '<')) { 1562144026Sharti Parse_Error(PARSE_FATAL, 1563144026Sharti ".include filename must be delimited by '\"' or '<'"); 1564144026Sharti return; 1565144026Sharti } 15661590Srgrimes 1567144026Sharti /* 1568144026Sharti * Set the search path on which to find the include file based on the 1569144026Sharti * characters which bracket its name. Angle-brackets imply it's 1570144026Sharti * a system Makefile while double-quotes imply it's a user makefile 1571144026Sharti */ 1572144026Sharti if (*file == '<') { 1573144026Sharti isSystem = TRUE; 1574144026Sharti endc = '>'; 1575144026Sharti } else { 1576144026Sharti isSystem = FALSE; 1577144026Sharti endc = '"'; 1578144026Sharti } 15791590Srgrimes 1580144026Sharti /* 1581144026Sharti * Skip to matching delimiter 1582144026Sharti */ 1583144026Sharti for (cp = ++file; *cp && *cp != endc; cp++) { 1584144026Sharti continue; 1585144026Sharti } 15861590Srgrimes 1587144026Sharti if (*cp != endc) { 1588144026Sharti Parse_Error(PARSE_FATAL, 1589144026Sharti "Unclosed %cinclude filename. '%c' expected", '.', endc); 1590144026Sharti return; 1591144026Sharti } 1592144026Sharti *cp = '\0'; 15931590Srgrimes 1594144026Sharti /* 1595144026Sharti * Substitute for any variables in the file name before trying to 1596144026Sharti * find the thing. 1597144026Sharti */ 1598144026Sharti buf = Var_Subst(NULL, file, VAR_CMD, FALSE); 1599144026Sharti file = Buf_Peel(buf); 16001590Srgrimes 16011590Srgrimes /* 1602144026Sharti * Now we know the file's name and its search path, we attempt to 1603144026Sharti * find the durn thing. A return of NULL indicates the file don't 1604144026Sharti * exist. 16051590Srgrimes */ 1606144026Sharti if (!isSystem) { 1607144026Sharti /* 1608144026Sharti * Include files contained in double-quotes are first searched 1609144026Sharti * for relative to the including file's location. We don't want 1610144026Sharti * to cd there, of course, so we just tack on the old file's 1611144026Sharti * leading path components and call Dir_FindFile to see if 1612144026Sharti * we can locate the beast. 1613144026Sharti */ 1614144026Sharti char *prefEnd, *Fname; 16151590Srgrimes 1616144026Sharti /* Make a temporary copy of this, to be safe. */ 1617144026Sharti Fname = estrdup(curFile.fname); 161818730Ssteve 1619144026Sharti prefEnd = strrchr(Fname, '/'); 1620144026Sharti if (prefEnd != (char *)NULL) { 1621144026Sharti char *newName; 16228874Srgrimes 1623144026Sharti *prefEnd = '\0'; 1624144026Sharti if (file[0] == '/') 1625144026Sharti newName = estrdup(file); 1626144026Sharti else 1627144026Sharti newName = str_concat(Fname, file, STR_ADDSLASH); 1628144026Sharti fullname = Path_FindFile(newName, &parseIncPath); 1629144026Sharti if (fullname == NULL) { 1630144026Sharti fullname = Path_FindFile(newName, 1631144026Sharti &dirSearchPath); 1632144026Sharti } 1633144026Sharti free(newName); 1634144026Sharti *prefEnd = '/'; 1635144026Sharti } else { 1636144026Sharti fullname = NULL; 1637144026Sharti } 1638144026Sharti free(Fname); 16391590Srgrimes } else { 1640144026Sharti fullname = NULL; 16411590Srgrimes } 16421590Srgrimes 1643138264Sharti if (fullname == NULL) { 1644144026Sharti /* 1645144026Sharti * System makefile or makefile wasn't found in same directory as 1646144026Sharti * included makefile. Search for it first on the -I search path, 1647144026Sharti * then on the .PATH search path, if not found in a -I 1648144026Sharti * directory. 1649144026Sharti * XXX: Suffix specific? 1650144026Sharti */ 1651144026Sharti fullname = Path_FindFile(file, &parseIncPath); 1652144026Sharti if (fullname == NULL) { 1653144026Sharti fullname = Path_FindFile(file, &dirSearchPath); 1654144026Sharti } 16551590Srgrimes } 16561590Srgrimes 1657144026Sharti if (fullname == NULL) { 1658144026Sharti /* 1659144026Sharti * Still haven't found the makefile. Look for it on the system 1660144026Sharti * path as a last resort. 1661144026Sharti */ 1662144026Sharti fullname = Path_FindFile(file, &sysIncPath); 1663144026Sharti } 16641590Srgrimes 1665144026Sharti if (fullname == NULL) { 1666144026Sharti *cp = endc; 1667144026Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1668144026Sharti /* XXXHB free(file) */ 1669144026Sharti return; 1670144026Sharti } 16711590Srgrimes 1672144026Sharti free(file); 16735814Sjkh 1674144026Sharti /* 1675144026Sharti * Once we find the absolute path to the file, we get to save all the 1676144026Sharti * state from the current file before we can start reading this 1677144026Sharti * include file. The state is stored in an IFile structure which 1678144026Sharti * is placed on a list with other IFile structures. The list makes 1679144026Sharti * a very nice stack to track how we got here... 1680144026Sharti */ 1681144026Sharti oldFile = emalloc(sizeof(IFile)); 1682144026Sharti memcpy(oldFile, &curFile, sizeof(IFile)); 16831590Srgrimes 1684144026Sharti Lst_AtFront(&includes, oldFile); 16851590Srgrimes 16861590Srgrimes /* 1687144026Sharti * Once the previous state has been saved, we can get down to reading 1688144026Sharti * the new file. We set up the name of the file to be the absolute 1689144026Sharti * name of the include file so error messages refer to the right 1690144026Sharti * place. Naturally enough, we start reading at line number 0. 16911590Srgrimes */ 1692144026Sharti curFile.fname = fullname; 1693144026Sharti curFile.lineno = 0; 1694144026Sharti 1695144026Sharti curFile.F = fopen(fullname, "r"); 1696144026Sharti curFile.p = NULL; 1697144026Sharti if (curFile.F == NULL) { 1698144026Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 1699144026Sharti /* 1700144026Sharti * Pop to previous file 1701144026Sharti */ 1702144026Sharti ParseEOF(0); 1703144026Sharti } else { 1704144026Sharti Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 1705144026Sharti } 17061590Srgrimes} 17071590Srgrimes 17081590Srgrimes/*- 17091590Srgrimes *--------------------------------------------------------------------- 17101590Srgrimes * Parse_FromString -- 17111590Srgrimes * Start Parsing from the given string 17128874Srgrimes * 17131590Srgrimes * Results: 17141590Srgrimes * None 17151590Srgrimes * 17161590Srgrimes * Side Effects: 1717126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1718126824Sru * curFile.fname and curFile.F are altered for the new file 17191590Srgrimes *--------------------------------------------------------------------- 17201590Srgrimes */ 17211590Srgrimesvoid 1722126824SruParse_FromString(char *str, int lineno) 17231590Srgrimes{ 1724144026Sharti IFile *oldFile; /* state associated with this file */ 17251590Srgrimes 1726144026Sharti DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 17271590Srgrimes 1728144026Sharti oldFile = emalloc(sizeof(IFile)); 1729144026Sharti memcpy(oldFile, &curFile, sizeof(IFile)); 17308874Srgrimes 1731144026Sharti Lst_AtFront(&includes, oldFile); 17321590Srgrimes 1733144026Sharti curFile.F = NULL; 1734144026Sharti curFile.p = emalloc(sizeof(PTR)); 1735144026Sharti curFile.p->str = curFile.p->ptr = str; 1736144026Sharti curFile.lineno = lineno; 1737144026Sharti curFile.fname = estrdup(curFile.fname); 17381590Srgrimes} 17391590Srgrimes 17401590Srgrimes#ifdef SYSVINCLUDE 17411590Srgrimes/*- 17421590Srgrimes *--------------------------------------------------------------------- 17431590Srgrimes * ParseTraditionalInclude -- 17441590Srgrimes * Push to another file. 17458874Srgrimes * 17461590Srgrimes * The input is the line minus the "include". The file name is 17471590Srgrimes * the string following the "include". 17481590Srgrimes * 17491590Srgrimes * Results: 17501590Srgrimes * None 17511590Srgrimes * 17521590Srgrimes * Side Effects: 1753126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1754126824Sru * curFile.fname and curFile.F are altered for the new file 17551590Srgrimes *--------------------------------------------------------------------- 17561590Srgrimes */ 17571590Srgrimesstatic void 1758141270ShartiParseTraditionalInclude(char *file) 17591590Srgrimes{ 1760144026Sharti char *fullname; /* full pathname of file */ 1761144026Sharti IFile *oldFile; /* state associated with current file */ 1762144026Sharti char *cp; /* current position in file spec */ 1763144026Sharti Buffer *buf; 17641590Srgrimes 1765144026Sharti /* 1766144026Sharti * Skip over whitespace 1767144026Sharti */ 1768144026Sharti while ((*file == ' ') || (*file == '\t')) { 1769144026Sharti file++; 1770144026Sharti } 17711590Srgrimes 1772144026Sharti if (*file == '\0') { 1773144026Sharti Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); 1774144026Sharti return; 1775144026Sharti } 17761590Srgrimes 1777144026Sharti /* 1778144026Sharti * Skip to end of line or next whitespace 1779144026Sharti */ 1780144026Sharti for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1781144026Sharti continue; 1782144026Sharti } 17831590Srgrimes 1784144026Sharti *cp = '\0'; 17851590Srgrimes 1786144026Sharti /* 1787144026Sharti * Substitute for any variables in the file name before trying to 1788144026Sharti * find the thing. 1789144026Sharti */ 1790144026Sharti buf = Var_Subst(NULL, file, VAR_CMD, FALSE); 1791144026Sharti file = Buf_Peel(buf); 17921590Srgrimes 17931590Srgrimes /* 1794144026Sharti * Now we know the file's name, we attempt to find the durn thing. 1795144026Sharti * Search for it first on the -I search path, then on the .PATH 1796144026Sharti * search path, if not found in a -I directory. 17971590Srgrimes */ 1798144026Sharti fullname = Path_FindFile(file, &parseIncPath); 1799144026Sharti if (fullname == NULL) { 1800144026Sharti fullname = Path_FindFile(file, &dirSearchPath); 1801144026Sharti } 18021590Srgrimes 1803144026Sharti if (fullname == NULL) { 1804144026Sharti /* 1805144026Sharti * Still haven't found the makefile. Look for it on the system 1806144026Sharti * path as a last resort. 1807144026Sharti */ 1808144026Sharti fullname = Path_FindFile(file, &sysIncPath); 1809144026Sharti } 18101590Srgrimes 1811144026Sharti if (fullname == NULL) { 1812144026Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1813144026Sharti /* XXXHB free(file) */ 1814144026Sharti return; 1815144026Sharti } 1816142457Sharti 1817144026Sharti /* XXXHB free(file) */ 18181590Srgrimes 1819144026Sharti /* 1820144026Sharti * Once we find the absolute path to the file, we get to save all the 1821144026Sharti * state from the current file before we can start reading this 1822144026Sharti * include file. The state is stored in an IFile structure which 1823144026Sharti * is placed on a list with other IFile structures. The list makes 1824144026Sharti * a very nice stack to track how we got here... 1825144026Sharti */ 1826144026Sharti oldFile = emalloc(sizeof(IFile)); 1827144026Sharti memcpy(oldFile, &curFile, sizeof(IFile)); 18281590Srgrimes 1829144026Sharti Lst_AtFront(&includes, oldFile); 18301590Srgrimes 18311590Srgrimes /* 1832144026Sharti * Once the previous state has been saved, we can get down to reading 1833144026Sharti * the new file. We set up the name of the file to be the absolute 1834144026Sharti * name of the include file so error messages refer to the right 1835144026Sharti * place. Naturally enough, we start reading at line number 0. 18361590Srgrimes */ 1837144026Sharti curFile.fname = fullname; 1838144026Sharti curFile.lineno = 0; 1839144026Sharti 1840144026Sharti curFile.F = fopen(fullname, "r"); 1841144026Sharti curFile.p = NULL; 1842144026Sharti if (curFile.F == NULL) { 1843144026Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 1844144026Sharti /* 1845144026Sharti * Pop to previous file 1846144026Sharti */ 1847144026Sharti ParseEOF(1); 1848144026Sharti } else { 1849144026Sharti Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 1850144026Sharti } 18511590Srgrimes} 18521590Srgrimes#endif 18531590Srgrimes 18541590Srgrimes/*- 18551590Srgrimes *--------------------------------------------------------------------- 18561590Srgrimes * ParseEOF -- 18571590Srgrimes * Called when EOF is reached in the current file. If we were reading 18581590Srgrimes * an include file, the includes stack is popped and things set up 18591590Srgrimes * to go back to reading the previous file at the previous location. 18601590Srgrimes * 18611590Srgrimes * Results: 18621590Srgrimes * CONTINUE if there's more to do. DONE if not. 18631590Srgrimes * 18641590Srgrimes * Side Effects: 1865126824Sru * The old curFile.F is closed. The includes list is shortened. 1866126824Sru * curFile.lineno, curFile.F, and curFile.fname are changed if 1867126824Sru * CONTINUE is returned. 18681590Srgrimes *--------------------------------------------------------------------- 18691590Srgrimes */ 18701590Srgrimesstatic int 1871138232ShartiParseEOF(int opened) 18721590Srgrimes{ 1873144026Sharti IFile *ifile; /* the state on the top of the includes stack */ 18741590Srgrimes 1875144026Sharti if (Lst_IsEmpty(&includes)) { 1876144026Sharti Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 1877144026Sharti return (DONE); 1878144026Sharti } 18791590Srgrimes 1880144026Sharti ifile = Lst_DeQueue(&includes); 1881144026Sharti free(curFile.fname); 1882144026Sharti if (opened && curFile.F) { 1883144026Sharti fclose(curFile.F); 1884144026Sharti Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 1885144026Sharti } 1886144026Sharti if (curFile.p) { 1887144026Sharti free(curFile.p->str); 1888144026Sharti free(curFile.p); 1889144026Sharti } 1890144026Sharti memcpy(&curFile, ifile, sizeof(IFile)); 1891144026Sharti free(ifile); 1892144026Sharti return (CONTINUE); 18931590Srgrimes} 18941590Srgrimes 18951590Srgrimes/*- 18961590Srgrimes *--------------------------------------------------------------------- 18971590Srgrimes * ParseReadc -- 18988874Srgrimes * Read a character from the current file 18991590Srgrimes * 19001590Srgrimes * Results: 19011590Srgrimes * The character that was read 19021590Srgrimes * 19031590Srgrimes * Side Effects: 19041590Srgrimes *--------------------------------------------------------------------- 19051590Srgrimes */ 19061590Srgrimesstatic int 1907104696SjmallettParseReadc(void) 19081590Srgrimes{ 1909138232Sharti 1910144026Sharti if (curFile.F) 1911144026Sharti return (fgetc(curFile.F)); 19128874Srgrimes 1913144026Sharti if (curFile.p && *curFile.p->ptr) 1914144026Sharti return (*curFile.p->ptr++); 1915144026Sharti return (EOF); 19161590Srgrimes} 19171590Srgrimes 19181590Srgrimes 19191590Srgrimes/*- 19201590Srgrimes *--------------------------------------------------------------------- 19211590Srgrimes * ParseUnreadc -- 19228874Srgrimes * Put back a character to the current file 19231590Srgrimes * 19241590Srgrimes * Results: 19251590Srgrimes * None. 19261590Srgrimes * 19271590Srgrimes * Side Effects: 19281590Srgrimes *--------------------------------------------------------------------- 19291590Srgrimes */ 19301590Srgrimesstatic void 1931104696SjmallettParseUnreadc(int c) 19321590Srgrimes{ 1933138232Sharti 1934144026Sharti if (curFile.F) { 1935144026Sharti ungetc(c, curFile.F); 1936144026Sharti return; 1937144026Sharti } 1938144026Sharti if (curFile.p) { 1939144026Sharti *--(curFile.p->ptr) = c; 1940144026Sharti return; 1941144026Sharti } 19421590Srgrimes} 19431590Srgrimes 19441590Srgrimes/* ParseSkipLine(): 1945104696Sjmallett * Grab the next line unless it begins with a dot (`.') and we're told to 1946104696Sjmallett * ignore such lines. 19471590Srgrimes */ 19481590Srgrimesstatic char * 1949126824SruParseSkipLine(int skip, int keep_newline) 19501590Srgrimes{ 1951144026Sharti char *line; 1952144026Sharti int c, lastc; 1953144026Sharti Buffer *buf; 19541590Srgrimes 1955144026Sharti buf = Buf_Init(MAKE_BSIZE); 19561590Srgrimes 1957144026Sharti do { 1958144026Sharti Buf_Clear(buf); 1959144026Sharti lastc = '\0'; 19608874Srgrimes 1961144026Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') 1962144026Sharti && c != EOF) { 1963144026Sharti if (skip && c == '#' && lastc != '\\') { 1964144026Sharti /* 1965144026Sharti * let a comment be terminated even by an 1966144026Sharti * escaped \n. This is consistent to comment 1967144026Sharti * handling in ParseReadLine 1968144026Sharti */ 1969144026Sharti while ((c = ParseReadc()) != '\n' && c != EOF) 1970144026Sharti ; 1971144026Sharti break; 1972144026Sharti } 1973144026Sharti if (c == '\n') { 1974144026Sharti if (keep_newline) 1975144026Sharti Buf_AddByte(buf, (Byte)c); 1976144026Sharti else 1977144026Sharti Buf_ReplaceLastByte(buf, (Byte)' '); 1978144026Sharti curFile.lineno++; 19798874Srgrimes 1980144026Sharti while ((c = ParseReadc()) == ' ' || c == '\t') 1981144026Sharti continue; 19828874Srgrimes 1983144026Sharti if (c == EOF) 1984144026Sharti break; 1985144026Sharti } 198674272Swill 1987144026Sharti Buf_AddByte(buf, (Byte)c); 1988144026Sharti lastc = c; 1989144026Sharti } 199018456Ssteve 1991144026Sharti if (c == EOF) { 1992144026Sharti Parse_Error(PARSE_FATAL, 1993144026Sharti "Unclosed conditional/for loop"); 1994144026Sharti Buf_Destroy(buf, TRUE); 1995144026Sharti return (NULL); 1996144026Sharti } 199718456Ssteve 1998144026Sharti curFile.lineno++; 1999144026Sharti Buf_AddByte(buf, (Byte)'\0'); 2000144026Sharti line = Buf_Data(buf); 2001144026Sharti } while (skip == 1 && line[0] != '.'); 200218456Ssteve 2003144026Sharti Buf_Destroy(buf, FALSE); 2004144026Sharti return (line); 20051590Srgrimes} 20061590Srgrimes 20071590Srgrimes/*- 20081590Srgrimes *--------------------------------------------------------------------- 20091590Srgrimes * ParseReadLine -- 20101590Srgrimes * Read an entire line from the input file. Called only by Parse_File. 20111590Srgrimes * To facilitate escaped newlines and what have you, a character is 20121590Srgrimes * buffered in 'lastc', which is '\0' when no characters have been 20131590Srgrimes * read. When we break out of the loop, c holds the terminating 20141590Srgrimes * character and lastc holds a character that should be added to 20151590Srgrimes * the line (unless we don't read anything but a terminator). 20161590Srgrimes * 20171590Srgrimes * Results: 20181590Srgrimes * A line w/o its newline 20191590Srgrimes * 20201590Srgrimes * Side Effects: 20211590Srgrimes * Only those associated with reading a character 20221590Srgrimes *--------------------------------------------------------------------- 20231590Srgrimes */ 20241590Srgrimesstatic char * 2025138232ShartiParseReadLine(void) 20261590Srgrimes{ 2027144026Sharti Buffer *buf; /* Buffer for current line */ 2028144026Sharti int c; /* the current character */ 2029144026Sharti int lastc; /* The most-recent character */ 2030144026Sharti Boolean semiNL; /* treat semi-colons as newlines */ 2031144026Sharti Boolean ignDepOp; /* TRUE if should ignore dependency operators 20321590Srgrimes * for the purposes of setting semiNL */ 2033144026Sharti Boolean ignComment; /* TRUE if should ignore comments (in a 20341590Srgrimes * shell command */ 2035144026Sharti char *line; /* Result */ 2036144026Sharti char *ep; /* to strip trailing blanks */ 2037144026Sharti int lineno; /* Saved line # */ 20381590Srgrimes 2039144026Sharti semiNL = FALSE; 2040144026Sharti ignDepOp = FALSE; 2041144026Sharti ignComment = FALSE; 20421590Srgrimes 2043144026Sharti /* 2044144026Sharti * Handle special-characters at the beginning of the line. Either a 2045144026Sharti * leading tab (shell command) or pound-sign (possible conditional) 2046144026Sharti * forces us to ignore comments and dependency operators and treat 2047144026Sharti * semi-colons as semi-colons (by leaving semiNL FALSE). This also 2048144026Sharti * discards completely blank lines. 2049144026Sharti */ 2050144026Sharti for (;;) { 2051144026Sharti c = ParseReadc(); 20521590Srgrimes 2053144026Sharti if (c == '\t') { 2054144026Sharti ignComment = ignDepOp = TRUE; 2055144026Sharti break; 2056144026Sharti } else if (c == '\n') { 2057144026Sharti curFile.lineno++; 2058144026Sharti } else if (c == '#') { 2059144026Sharti ParseUnreadc(c); 2060144026Sharti break; 2061144026Sharti } else { 2062144026Sharti /* 2063144026Sharti * Anything else breaks out without doing anything 2064144026Sharti */ 2065144026Sharti break; 2066144026Sharti } 20671590Srgrimes } 20688874Srgrimes 2069144026Sharti if (c != EOF) { 2070144026Sharti lastc = c; 2071144026Sharti buf = Buf_Init(MAKE_BSIZE); 20728874Srgrimes 2073144026Sharti while (((c = ParseReadc()) != '\n' || (lastc == '\\')) && 2074144026Sharti (c != EOF)) { 2075144026Sharti test_char: 2076144026Sharti switch (c) { 2077144026Sharti case '\n': 2078144026Sharti /* 2079144026Sharti * Escaped newline: read characters until a 2080144026Sharti * non-space or an unescaped newline and 2081144026Sharti * replace them all by a single space. This is 2082144026Sharti * done by storing the space over the backslash 2083144026Sharti * and dropping through with the next nonspace. 2084144026Sharti * If it is a semi-colon and semiNL is TRUE, 2085144026Sharti * it will be recognized as a newline in the 2086144026Sharti * code below this... 2087144026Sharti */ 2088144026Sharti curFile.lineno++; 2089144026Sharti lastc = ' '; 2090144026Sharti while ((c = ParseReadc()) == ' ' || c == '\t') { 2091144026Sharti continue; 2092144026Sharti } 2093144026Sharti if (c == EOF || c == '\n') { 2094144026Sharti goto line_read; 2095144026Sharti } else { 2096144026Sharti /* 2097144026Sharti * Check for comments, semiNL's, etc. -- 2098144026Sharti * easier than ParseUnreadc(c); 2099144026Sharti * continue; 2100144026Sharti */ 2101144026Sharti goto test_char; 2102144026Sharti } 2103144026Sharti /*NOTREACHED*/ 2104144026Sharti break; 2105144026Sharti 2106144026Sharti case ';': 2107144026Sharti /* 2108144026Sharti * Semi-colon: Need to see if it should be 2109144026Sharti * interpreted as a newline 2110144026Sharti */ 2111144026Sharti if (semiNL) { 2112144026Sharti /* 2113144026Sharti * To make sure the command that may 2114144026Sharti * be following this semi-colon begins 2115144026Sharti * with a tab, we push one back into the 2116144026Sharti * input stream. This will overwrite the 2117144026Sharti * semi-colon in the buffer. If there is 2118144026Sharti * no command following, this does no 2119144026Sharti * harm, since the newline remains in 2120144026Sharti * the buffer and the 2121144026Sharti * whole line is ignored. 2122144026Sharti */ 2123144026Sharti ParseUnreadc('\t'); 2124144026Sharti goto line_read; 2125144026Sharti } 2126144026Sharti break; 2127144026Sharti case '=': 2128144026Sharti if (!semiNL) { 2129144026Sharti /* 2130144026Sharti * Haven't seen a dependency operator 2131144026Sharti * before this, so this must be a 2132144026Sharti * variable assignment -- don't pay 2133144026Sharti * attention to dependency operators 2134144026Sharti * after this. 2135144026Sharti */ 2136144026Sharti ignDepOp = TRUE; 2137144026Sharti } else if (lastc == ':' || lastc == '!') { 2138144026Sharti /* 2139144026Sharti * Well, we've seen a dependency 2140144026Sharti * operator already, but it was the 2141144026Sharti * previous character, so this is really 2142144026Sharti * just an expanded variable assignment. 2143144026Sharti * Revert semi-colons to being just 2144144026Sharti * semi-colons again and ignore any more 2145144026Sharti * dependency operators. 2146144026Sharti * 2147144026Sharti * XXX: Note that a line like 2148144026Sharti * "foo : a:=b" will blow up, but who'd 2149144026Sharti * write a line like that anyway? 2150144026Sharti */ 2151144026Sharti ignDepOp = TRUE; 2152144026Sharti semiNL = FALSE; 2153144026Sharti } 2154144026Sharti break; 2155144026Sharti case '#': 2156144026Sharti if (!ignComment) { 2157144026Sharti if (lastc != '\\') { 2158144026Sharti /* 2159144026Sharti * If the character is a hash 2160144026Sharti * mark and it isn't escaped 2161144026Sharti * (or we're being compatible), 2162144026Sharti * the thing is a comment. 2163144026Sharti * Skip to the end of the line. 2164144026Sharti */ 2165144026Sharti do { 2166144026Sharti c = ParseReadc(); 2167144026Sharti } while (c != '\n' && c != EOF); 2168144026Sharti goto line_read; 2169144026Sharti } else { 2170144026Sharti /* 2171144026Sharti * Don't add the backslash. 2172144026Sharti * Just let the # get copied 2173144026Sharti * over. 2174144026Sharti */ 2175144026Sharti lastc = c; 2176144026Sharti continue; 2177144026Sharti } 2178144026Sharti } 2179144026Sharti break; 2180144026Sharti 2181144026Sharti case ':': 2182144026Sharti case '!': 2183144026Sharti if (!ignDepOp && (c == ':' || c == '!')) { 2184144026Sharti /* 2185144026Sharti * A semi-colon is recognized as a 2186144026Sharti * newline only on dependency lines. 2187144026Sharti * Dependency lines are lines with a 2188144026Sharti * colon or an exclamation point. 2189144026Sharti * Ergo... 2190144026Sharti */ 2191144026Sharti semiNL = TRUE; 2192144026Sharti } 2193144026Sharti break; 2194144026Sharti 2195144026Sharti default: 2196144026Sharti break; 2197144026Sharti } 2198144026Sharti /* 2199144026Sharti * Copy in the previous character and save this one in 2200144026Sharti * lastc. 2201144026Sharti */ 2202144026Sharti Buf_AddByte(buf, (Byte)lastc); 2203144026Sharti lastc = c; 2204144026Sharti } 2205144026Sharti line_read: 2206126824Sru curFile.lineno++; 2207144026Sharti 2208144026Sharti if (lastc != '\0') { 2209144026Sharti Buf_AddByte(buf, (Byte)lastc); 22101590Srgrimes } 2211144026Sharti Buf_AddByte(buf, (Byte)'\0'); 2212144026Sharti line = Buf_Peel(buf); 22131590Srgrimes 22141590Srgrimes /* 2215144026Sharti * Strip trailing blanks and tabs from the line. 2216144026Sharti * Do not strip a blank or tab that is preceded by 2217144026Sharti * a '\' 22181590Srgrimes */ 2219144026Sharti ep = line; 2220144026Sharti while (*ep) 2221144026Sharti ++ep; 2222144026Sharti while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2223144026Sharti if (ep > line + 1 && ep[-2] == '\\') 2224144026Sharti break; 2225144026Sharti --ep; 22268874Srgrimes } 2227144026Sharti *ep = 0; 2228144026Sharti 2229144026Sharti if (line[0] == '.') { 22301590Srgrimes /* 2231144026Sharti * The line might be a conditional. Ask the 2232144026Sharti * conditional module about it and act accordingly 22331590Srgrimes */ 2234144026Sharti switch (Cond_Eval(line)) { 2235144026Sharti case COND_SKIP: 2236144026Sharti /* 2237144026Sharti * Skip to next conditional that evaluates to 2238144026Sharti * COND_PARSE. 2239144026Sharti */ 2240144026Sharti do { 2241144026Sharti free(line); 2242144026Sharti line = ParseSkipLine(1, 0); 2243144026Sharti } while (line && Cond_Eval(line) != COND_PARSE); 2244144026Sharti if (line == NULL) 2245144026Sharti break; 2246144026Sharti /*FALLTHRU*/ 22478874Srgrimes 2248144026Sharti case COND_PARSE: 2249144026Sharti free(line); 2250144026Sharti line = ParseReadLine(); 2251144026Sharti break; 22528874Srgrimes 2253144026Sharti case COND_INVALID: 2254144026Sharti if (For_Eval(line)) { 2255144026Sharti int ok; 2256144026Sharti free(line); 2257144026Sharti lineno = curFile.lineno; 2258144026Sharti do { 2259144026Sharti /* 2260144026Sharti * Skip after the matching end 2261144026Sharti */ 2262144026Sharti line = ParseSkipLine(0, 1); 2263144026Sharti if (line == NULL) { 2264144026Sharti Parse_Error(PARSE_FATAL, 2265144026Sharti "Unexpected end of" 2266144026Sharti " file in for " 2267144026Sharti "loop.\n"); 2268144026Sharti break; 2269144026Sharti } 2270144026Sharti ok = For_Eval(line); 2271144026Sharti free(line); 2272144026Sharti } while (ok); 2273144026Sharti if (line != NULL) 2274144026Sharti For_Run(lineno); 2275144026Sharti line = ParseReadLine(); 2276144026Sharti } 2277144026Sharti break; 22785814Sjkh 2279144026Sharti default: 2280144026Sharti break; 2281144026Sharti } 2282144026Sharti } 2283144026Sharti return (line); 22848874Srgrimes 2285144026Sharti } else { 22861590Srgrimes /* 2287144026Sharti * Hit end-of-file, so return a NULL line to indicate this. 22881590Srgrimes */ 2289144026Sharti return (NULL); 22901590Srgrimes } 22911590Srgrimes} 22921590Srgrimes 22931590Srgrimes/*- 22941590Srgrimes *----------------------------------------------------------------------- 22951590Srgrimes * ParseFinishLine -- 22961590Srgrimes * Handle the end of a dependency group. 22971590Srgrimes * 22981590Srgrimes * Results: 22991590Srgrimes * Nothing. 23001590Srgrimes * 23011590Srgrimes * Side Effects: 23021590Srgrimes * inLine set FALSE. 'targets' list destroyed. 23031590Srgrimes * 23041590Srgrimes *----------------------------------------------------------------------- 23051590Srgrimes */ 23061590Srgrimesstatic void 2307104696SjmallettParseFinishLine(void) 23081590Srgrimes{ 2309143372Sharti const LstNode *ln; 2310138232Sharti 2311143372Sharti if (inLine) { 2312143372Sharti LST_FOREACH(ln, &targets) { 2313143372Sharti if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) 2314143372Sharti Suff_EndTransform(Lst_Datum(ln)); 2315143372Sharti } 2316143372Sharti Lst_Destroy(&targets, ParseHasCommands); 2317143372Sharti inLine = FALSE; 2318143372Sharti } 23191590Srgrimes} 23201590Srgrimes 23218874Srgrimes 23221590Srgrimes/*- 23231590Srgrimes *--------------------------------------------------------------------- 23241590Srgrimes * Parse_File -- 23251590Srgrimes * Parse a file into its component parts, incorporating it into the 23261590Srgrimes * current dependency graph. This is the main function and controls 23271590Srgrimes * almost every other function in this module 23281590Srgrimes * 23291590Srgrimes * Results: 23301590Srgrimes * None 23311590Srgrimes * 23321590Srgrimes * Side Effects: 23331590Srgrimes * Loads. Nodes are added to the list of all targets, nodes and links 23341590Srgrimes * are added to the dependency graph. etc. etc. etc. 23351590Srgrimes *--------------------------------------------------------------------- 23361590Srgrimes */ 23371590Srgrimesvoid 2338104696SjmallettParse_File(char *name, FILE *stream) 23391590Srgrimes{ 2340144026Sharti char *cp; /* pointer into the line */ 2341144026Sharti char *line; /* the line we're working on */ 2342144026Sharti Buffer *buf; 23431590Srgrimes 2344144026Sharti inLine = FALSE; 2345144026Sharti curFile.fname = name; 2346144026Sharti curFile.F = stream; 2347144026Sharti curFile.lineno = 0; 2348144026Sharti fatals = 0; 23491590Srgrimes 2350144026Sharti Var_Append(".MAKEFILE_LIST", name, VAR_GLOBAL); 2351131456Seik 2352144026Sharti do { 2353144026Sharti while ((line = ParseReadLine()) != NULL) { 2354144026Sharti if (*line == '.') { 2355144026Sharti /* 2356144026Sharti * Lines that begin with the special character 2357144026Sharti * are either include or undef directives. 2358144026Sharti */ 2359144026Sharti for (cp = line + 1; isspace((unsigned char)*cp); 2360144026Sharti cp++) { 2361144026Sharti continue; 2362144026Sharti } 2363144026Sharti if (strncmp(cp, "include", 7) == 0) { 2364144026Sharti ParseDoInclude(cp + 7); 2365144026Sharti goto nextLine; 2366144026Sharti } else if (strncmp(cp, "error", 5) == 0) { 2367144026Sharti ParseDoError(cp + 5); 2368144026Sharti goto nextLine; 2369144026Sharti } else if (strncmp(cp, "warning", 7) == 0) { 2370144026Sharti ParseDoWarning(cp + 7); 2371144026Sharti goto nextLine; 2372144026Sharti } else if (strncmp(cp, "undef", 5) == 0) { 2373144026Sharti char *cp2; 2374144026Sharti for (cp += 5; 2375144026Sharti isspace((unsigned char)*cp); 2376144026Sharti cp++) { 2377144026Sharti continue; 2378144026Sharti } 23791590Srgrimes 2380144026Sharti for (cp2 = cp; 2381144026Sharti !isspace((unsigned char)*cp2) && 2382144026Sharti (*cp2 != '\0'); cp2++) { 2383144026Sharti continue; 2384144026Sharti } 23851590Srgrimes 2386144026Sharti *cp2 = '\0'; 23871590Srgrimes 2388144026Sharti buf = Var_Subst(NULL, cp, VAR_CMD, 2389144026Sharti FALSE); 2390144026Sharti cp = Buf_Peel(buf); 2391142457Sharti 2392144026Sharti Var_Delete(cp, VAR_GLOBAL); 2393144026Sharti goto nextLine; 2394144026Sharti } 2395144026Sharti } 2396144026Sharti if (*line == '#') { 2397144026Sharti /* 2398144026Sharti * If we're this far, the line must be 2399144026Sharti * a comment. 2400144026Sharti */ 2401144026Sharti goto nextLine; 2402144026Sharti } 24038874Srgrimes 2404144026Sharti if (*line == '\t') { 2405144026Sharti /* 2406144026Sharti * If a line starts with a tab, it can only 2407144026Sharti * hope to be a creation command. 2408144026Sharti */ 2409144026Sharti for (cp = line + 1; 2410144026Sharti isspace((unsigned char)*cp); cp++) { 2411144026Sharti continue; 2412144026Sharti } 2413144026Sharti if (*cp) { 2414144026Sharti if (inLine) { 2415144026Sharti LstNode *ln; 2416144026Sharti GNode *gn; 2417143684Sharti 2418144026Sharti /* 2419144026Sharti * So long as it's not a blank 2420144026Sharti * line and we're actually in a 2421144026Sharti * dependency spec, add the 2422144026Sharti * command to the list of 2423144026Sharti * commands of all targets in 2424144026Sharti * the dependency spec. 2425144026Sharti */ 2426144026Sharti LST_FOREACH(ln, &targets) { 2427144026Sharti gn = Lst_Datum(ln); 2428143684Sharti 2429144026Sharti /* 2430144026Sharti * if target already 2431144026Sharti * supplied, ignore 2432144026Sharti * commands 2433144026Sharti */ 2434144026Sharti if (!(gn->type & 2435144026Sharti OP_HAS_COMMANDS)) 2436144026Sharti Lst_AtEnd(&gn->commands, cp); 2437144026Sharti else 2438144026Sharti Parse_Error(PARSE_WARNING, "duplicate script " 2439144026Sharti "for target \"%s\" ignored", gn->name); 2440144026Sharti } 2441144026Sharti continue; 2442144026Sharti } else { 2443144026Sharti Parse_Error(PARSE_FATAL, 2444144026Sharti "Unassociated shell command \"%s\"", 2445144026Sharti cp); 2446144026Sharti } 2447144026Sharti } 24481590Srgrimes#ifdef SYSVINCLUDE 2449144026Sharti } else if (strncmp(line, "include", 7) == 0 && 2450144026Sharti isspace((unsigned char)line[7]) && 2451144026Sharti strchr(line, ':') == NULL) { 2452144026Sharti /* 2453144026Sharti * It's an S3/S5-style "include". 2454144026Sharti */ 2455144026Sharti ParseTraditionalInclude(line + 7); 2456144026Sharti goto nextLine; 24571590Srgrimes#endif 2458144026Sharti } else if (Parse_IsVar(line)) { 2459144026Sharti ParseFinishLine(); 2460144026Sharti Parse_DoVar(line, VAR_GLOBAL); 24618874Srgrimes 2462144026Sharti } else { 2463144026Sharti /* 2464144026Sharti * We now know it's a dependency line so it 2465144026Sharti * needs to have all variables expanded before 2466144026Sharti * being parsed. Tell the variable module to 2467144026Sharti * complain if some variable is undefined... 2468144026Sharti * To make life easier on novices, if the line 2469144026Sharti * is indented we first make sure the line has 2470144026Sharti * a dependency operator in it. If it doesn't 2471144026Sharti * have an operator and we're in a dependency 2472144026Sharti * line's script, we assume it's actually a 2473144026Sharti * shell command and add it to the current 2474144026Sharti * list of targets. 2475144026Sharti */ 2476144026Sharti cp = line; 2477144026Sharti if (isspace((unsigned char)line[0])) { 2478144026Sharti while ((*cp != '\0') && 2479144026Sharti isspace((unsigned char)*cp)) { 2480144026Sharti cp++; 2481144026Sharti } 2482144026Sharti if (*cp == '\0') { 2483144026Sharti goto nextLine; 2484144026Sharti } 2485144026Sharti } 24861590Srgrimes 2487144026Sharti ParseFinishLine(); 2488142457Sharti 2489144026Sharti buf = Var_Subst(NULL, line, VAR_CMD, TRUE); 2490144026Sharti cp = Buf_Peel(buf); 24918874Srgrimes 2492144026Sharti free(line); 2493144026Sharti line = cp; 2494144026Sharti 2495144026Sharti /* 2496144026Sharti * Need a non-circular list for the target nodes 2497144026Sharti */ 2498144026Sharti Lst_Destroy(&targets, NOFREE); 2499144026Sharti inLine = TRUE; 2500144026Sharti 2501144026Sharti ParseDoDependency(line); 2502144026Sharti } 2503144026Sharti 2504144026Sharti nextLine: 2505144026Sharti free(line); 2506144026Sharti } 2507144026Sharti 2508137810Sharti /* 2509144026Sharti * Reached EOF, but it may be just EOF of an include file... 2510137810Sharti */ 2511144026Sharti } while (ParseEOF(1) == CONTINUE); 25128874Srgrimes 2513144026Sharti ParseFinishLine(); 25141590Srgrimes 25151590Srgrimes /* 2516144026Sharti * Make sure conditionals are clean 25171590Srgrimes */ 2518144026Sharti Cond_End(); 25191590Srgrimes 2520144026Sharti if (fatals) 2521144026Sharti errx(1, "fatal errors encountered -- cannot continue"); 25221590Srgrimes} 25231590Srgrimes 25241590Srgrimes/*- 25251590Srgrimes *--------------------------------------------------------------------- 25261590Srgrimes * Parse_Init -- 25271590Srgrimes * initialize the parsing module 25281590Srgrimes * 25291590Srgrimes * Results: 25301590Srgrimes * none 25311590Srgrimes * 25321590Srgrimes * Side Effects: 25331590Srgrimes * the parseIncPath list is initialized... 25341590Srgrimes *--------------------------------------------------------------------- 25351590Srgrimes */ 25361590Srgrimesvoid 2537138232ShartiParse_Init(void) 25381590Srgrimes{ 2539138232Sharti 2540144026Sharti mainNode = NULL; 25411590Srgrimes} 25421590Srgrimes 25431590Srgrimes/*- 25441590Srgrimes *----------------------------------------------------------------------- 25451590Srgrimes * Parse_MainName -- 25461590Srgrimes * Return a Lst of the main target to create for main()'s sake. If 25471590Srgrimes * no such target exists, we Punt with an obnoxious error message. 25481590Srgrimes * 25491590Srgrimes * Results: 25501590Srgrimes * A Lst of the single node to create. 25511590Srgrimes * 25521590Srgrimes * Side Effects: 25531590Srgrimes * None. 25541590Srgrimes * 25551590Srgrimes *----------------------------------------------------------------------- 25561590Srgrimes */ 2557138916Shartivoid 2558138916ShartiParse_MainName(Lst *listmain) 25591590Srgrimes{ 25601590Srgrimes 2561144026Sharti if (mainNode == NULL) { 2562144026Sharti Punt("no target to make."); 2563144026Sharti /*NOTREACHED*/ 2564144026Sharti } else if (mainNode->type & OP_DOUBLEDEP) { 2565144026Sharti Lst_AtEnd(listmain, mainNode); 2566144026Sharti Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 2567144026Sharti } else 2568144026Sharti Lst_AtEnd(listmain, mainNode); 25691590Srgrimes} 2570