parse.c revision 144894
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 144894 2005-04-11 07:20:10Z 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 84144341Sharti#include <assert.h> 85141104Sharti#include <ctype.h> 861590Srgrimes#include <stdarg.h> 87141104Sharti#include <string.h> 88141104Sharti#include <stdlib.h> 8927644Scharnier#include <err.h> 90141104Sharti 91141104Sharti#include "arch.h" 92141104Sharti#include "buf.h" 93141104Sharti#include "cond.h" 94141104Sharti#include "config.h" 951590Srgrimes#include "dir.h" 96141104Sharti#include "for.h" 97141104Sharti#include "globals.h" 98141104Sharti#include "GNode.h" 991590Srgrimes#include "job.h" 100141104Sharti#include "make.h" 101141104Sharti#include "nonints.h" 102141104Sharti#include "parse.h" 1031590Srgrimes#include "pathnames.h" 104141104Sharti#include "str.h" 105141104Sharti#include "suff.h" 106141104Sharti#include "targ.h" 107141104Sharti#include "util.h" 108141104Sharti#include "var.h" 1091590Srgrimes 1101590Srgrimes/* 111144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to 1121590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file, 1131590Srgrimes * or if it's DONE. 1141590Srgrimes */ 1151590Srgrimes#define CONTINUE 1 1161590Srgrimes#define DONE 0 117138916Sharti 118138916Sharti/* targets we're working on */ 119138916Shartistatic Lst targets = Lst_Initializer(targets); 120138916Sharti 121144026Sharti/* true if currently in a dependency line or its commands */ 122144026Shartistatic Boolean inLine; 1231590Srgrimes 124144026Shartistatic int fatals = 0; 1251590Srgrimes 126144026Sharti/* 127144026Sharti * The main target to create. This is the first target on the 128144026Sharti * first dependency line in the first makefile. 129144026Sharti */ 130144026Shartistatic GNode *mainNode; 131126824Sru 132144341Sharti/* 133144341Sharti * Definitions for handling #include specifications 134144341Sharti */ 135144341Shartistruct IFile { 136144341Sharti char *fname; /* name of previous file */ 137144341Sharti int lineno; /* saved line number */ 138144341Sharti FILE *F; /* the open stream */ 139144341Sharti char *str; /* the string when parsing a string */ 140144341Sharti char *ptr; /* the current pointer when parsing a string */ 141144341Sharti TAILQ_ENTRY(IFile) link;/* stack the files */ 142144341Sharti}; 143144026Sharti 144138916Sharti/* stack of IFiles generated by * #includes */ 145144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); 1461590Srgrimes 147144341Sharti/* access current file */ 148144341Sharti#define CURFILE (TAILQ_FIRST(&includes)) 149144341Sharti 150138916Sharti/* list of directories for "..." includes */ 151144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); 152138916Sharti 153138916Sharti/* list of directories for <...> includes */ 154144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); 155138916Sharti 156144026Sharti/* 1571590Srgrimes * specType contains the SPECial TYPE of the current target. It is 1581590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children 1591590Srgrimes * are linked as children of the parent but not vice versa. This variable is 1601590Srgrimes * set in ParseDoDependency 1611590Srgrimes */ 1621590Srgrimestypedef enum { 163144026Sharti Begin, /* .BEGIN */ 164144026Sharti Default, /* .DEFAULT */ 165144026Sharti End, /* .END */ 166144026Sharti Ignore, /* .IGNORE */ 167144026Sharti Includes, /* .INCLUDES */ 168144026Sharti Interrupt, /* .INTERRUPT */ 169144026Sharti Libs, /* .LIBS */ 170144026Sharti MFlags, /* .MFLAGS or .MAKEFLAGS */ 171144026Sharti Main, /* .MAIN and we don't have anyth. user-spec. to make */ 172144026Sharti NoExport, /* .NOEXPORT */ 173144026Sharti Not, /* Not special */ 174144026Sharti NotParallel, /* .NOTPARALELL */ 175144026Sharti Null, /* .NULL */ 176144026Sharti Order, /* .ORDER */ 177144026Sharti Parallel, /* .PARALLEL */ 178144026Sharti ExPath, /* .PATH */ 179144026Sharti Phony, /* .PHONY */ 180144026Sharti Posix, /* .POSIX */ 181144026Sharti Precious, /* .PRECIOUS */ 182144026Sharti ExShell, /* .SHELL */ 183144026Sharti Silent, /* .SILENT */ 184144026Sharti SingleShell, /* .SINGLESHELL */ 185144026Sharti Suffixes, /* .SUFFIXES */ 186144026Sharti Wait, /* .WAIT */ 187144026Sharti Attribute /* Generic attribute */ 1881590Srgrimes} ParseSpecial; 1891590Srgrimes 1901590Srgrimesstatic ParseSpecial specType; 19118730Sstevestatic int waiting; 1921590Srgrimes 1931590Srgrimes/* 19469527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 1951590Srgrimes * seen, then set to each successive source on the line. 1961590Srgrimes */ 197144026Shartistatic GNode *predecessor; 1981590Srgrimes 1991590Srgrimes/* 2001590Srgrimes * The parseKeywords table is searched using binary search when deciding 2011590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial 2021590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while 2031590Srgrimes * the 'op' field is the operator to apply to the list of targets if the 2041590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source) 2051590Srgrimes */ 2061590Srgrimesstatic struct { 207144026Sharti const char *name; /* Name of keyword */ 208144026Sharti ParseSpecial spec; /* Type when used as a target */ 209144026Sharti int op; /* Operator when used as a source */ 2101590Srgrimes} parseKeywords[] = { 211144026Sharti { ".BEGIN", Begin, 0 }, 212144026Sharti { ".DEFAULT", Default, 0 }, 213144026Sharti { ".END", End, 0 }, 214144026Sharti { ".EXEC", Attribute, OP_EXEC }, 215144026Sharti { ".IGNORE", Ignore, OP_IGNORE }, 216144026Sharti { ".INCLUDES", Includes, 0 }, 217144026Sharti { ".INTERRUPT", Interrupt, 0 }, 218144026Sharti { ".INVISIBLE", Attribute, OP_INVISIBLE }, 219144026Sharti { ".JOIN", Attribute, OP_JOIN }, 220144026Sharti { ".LIBS", Libs, 0 }, 221144026Sharti { ".MAIN", Main, 0 }, 222144026Sharti { ".MAKE", Attribute, OP_MAKE }, 223144026Sharti { ".MAKEFLAGS", MFlags, 0 }, 224144026Sharti { ".MFLAGS", MFlags, 0 }, 225144026Sharti { ".NOTMAIN", Attribute, OP_NOTMAIN }, 226144026Sharti { ".NOTPARALLEL", NotParallel, 0 }, 227144026Sharti { ".NO_PARALLEL", NotParallel, 0 }, 228144026Sharti { ".NULL", Null, 0 }, 229144026Sharti { ".OPTIONAL", Attribute, OP_OPTIONAL }, 230144026Sharti { ".ORDER", Order, 0 }, 231144026Sharti { ".PARALLEL", Parallel, 0 }, 232144026Sharti { ".PATH", ExPath, 0 }, 233144026Sharti { ".PHONY", Phony, OP_PHONY }, 234144026Sharti { ".POSIX", Posix, 0 }, 235144026Sharti { ".PRECIOUS", Precious, OP_PRECIOUS }, 236144026Sharti { ".RECURSIVE", Attribute, OP_MAKE }, 237144026Sharti { ".SHELL", ExShell, 0 }, 238144026Sharti { ".SILENT", Silent, OP_SILENT }, 239144026Sharti { ".SINGLESHELL", SingleShell, 0 }, 240144026Sharti { ".SUFFIXES", Suffixes, 0 }, 241144026Sharti { ".USE", Attribute, OP_USE }, 242144026Sharti { ".WAIT", Wait, 0 }, 2431590Srgrimes}; 2441590Srgrimes 245144894Sharti/* 246144894Sharti * Directive table. We use a hash table. This hash table has been generated 247144894Sharti * with mph which can be found on the usual GNU mirrors. If you change the 248144894Sharti * directives (adding, deleting, reordering) you need to create a new table 249144894Sharti * and hash function (directive_hash). The command line to generate the 250144894Sharti * table is: 251144894Sharti * 252144894Sharti * mph -d2 -m1 <tab | emitc -l -s 253144894Sharti * 254144894Sharti * Where tab is a file containing just the directive strings, one per line. 255144894Sharti * 256144894Sharti * While inporting the result of this the following changes have been made 257144894Sharti * to the generated code: 258144894Sharti * 259144894Sharti * prefix the names of the g, T0 and T1 arrays with 'directive_'. 260144894Sharti * 261144894Sharti * make the type of the tables 'const [un]signed char'. 262144894Sharti * 263144894Sharti * make the hash function use the length for termination, 264144894Sharti * not the trailing '\0'. 265144894Sharti */ 266144894Shartistatic void parse_include(char *, int, int); 267144894Shartistatic void parse_message(char *, int, int); 268144894Shartistatic void parse_undef(char *, int, int); 269144894Shartistatic void parse_for(char *, int, int); 270144894Shartistatic void parse_endfor(char *, int, int); 271144894Sharti 272144894Shartistatic const signed char directive_g[] = { 273144894Sharti 16, 0, -1, 14, 5, 2, 2, -1, 0, 0, 274144894Sharti -1, -1, 16, 11, -1, 15, -1, 14, 7, -1, 275144894Sharti 8, 6, 1, -1, -1, 0, 4, 6, -1, 0, 276144894Sharti 0, 2, 0, 13, -1, 14, -1, 0, 277144894Sharti}; 278144894Sharti 279144894Shartistatic const unsigned char directive_T0[] = { 280144894Sharti 11, 25, 14, 30, 14, 26, 23, 15, 9, 37, 281144894Sharti 27, 32, 27, 1, 17, 27, 35, 13, 8, 22, 282144894Sharti 8, 28, 7, 283144894Sharti}; 284144894Sharti 285144894Shartistatic const unsigned char directive_T1[] = { 286144894Sharti 19, 20, 31, 17, 29, 2, 7, 12, 1, 31, 287144894Sharti 11, 18, 11, 20, 10, 2, 15, 19, 4, 10, 288144894Sharti 13, 36, 3, 289144894Sharti}; 290144894Sharti 291144894Shartistatic const struct directive { 292144894Sharti const char *name; 293144894Sharti int code; 294144894Sharti Boolean skip_flag; /* execute even when skipped */ 295144894Sharti void (*func)(char *, int, int); 296144894Sharti} directives[] = { 297144894Sharti { "elif", COND_ELIF, TRUE, Cond_If }, 298144894Sharti { "elifdef", COND_ELIFDEF, TRUE, Cond_If }, 299144894Sharti { "elifmake", COND_ELIFMAKE, TRUE, Cond_If }, 300144894Sharti { "elifndef", COND_ELIFNDEF, TRUE, Cond_If }, 301144894Sharti { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If }, 302144894Sharti { "else", COND_ELSE, TRUE, Cond_Else }, 303144894Sharti { "endfor", 0, FALSE, parse_endfor }, 304144894Sharti { "endif", COND_ENDIF, TRUE, Cond_Endif }, 305144894Sharti { "error", 1, FALSE, parse_message }, 306144894Sharti { "for", 0, FALSE, parse_for }, 307144894Sharti { "if", COND_IF, TRUE, Cond_If }, 308144894Sharti { "ifdef", COND_IFDEF, TRUE, Cond_If }, 309144894Sharti { "ifmake", COND_IFMAKE, TRUE, Cond_If }, 310144894Sharti { "ifndef", COND_IFNDEF, TRUE, Cond_If }, 311144894Sharti { "ifnmake", COND_IFNMAKE, TRUE, Cond_If }, 312144894Sharti { "include", 0, FALSE, parse_include }, 313144894Sharti { "undef", 0, FALSE, parse_undef }, 314144894Sharti { "warning", 0, FALSE, parse_message }, 315144894Sharti}; 316144894Sharti#define NDIRECTS (sizeof(directives) / sizeof(directives[0])) 317144894Sharti 3181590Srgrimes/*- 3191590Srgrimes *---------------------------------------------------------------------- 3201590Srgrimes * ParseFindKeyword -- 3211590Srgrimes * Look in the table of keywords for one matching the given string. 3221590Srgrimes * 3231590Srgrimes * Results: 3241590Srgrimes * The index of the keyword, or -1 if it isn't there. 3251590Srgrimes * 3261590Srgrimes * Side Effects: 3271590Srgrimes * None 3281590Srgrimes *---------------------------------------------------------------------- 3291590Srgrimes */ 3301590Srgrimesstatic int 331138232ShartiParseFindKeyword(char *str) 3321590Srgrimes{ 333144026Sharti int start; 334144026Sharti int end; 335144026Sharti int cur; 336144026Sharti int diff; 3378874Srgrimes 338144026Sharti start = 0; 339144026Sharti end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1; 3401590Srgrimes 341144026Sharti do { 342144026Sharti cur = start + (end - start) / 2; 343144026Sharti diff = strcmp(str, parseKeywords[cur].name); 344144026Sharti if (diff == 0) { 345144026Sharti return (cur); 346144026Sharti } else if (diff < 0) { 347144026Sharti end = cur - 1; 348144026Sharti } else { 349144026Sharti start = cur + 1; 350144026Sharti } 351144026Sharti } while (start <= end); 3521590Srgrimes 353144026Sharti return (-1); 3541590Srgrimes} 3551590Srgrimes 3561590Srgrimes/*- 3571590Srgrimes * Parse_Error -- 3581590Srgrimes * Error message abort function for parsing. Prints out the context 3591590Srgrimes * of the error (line number and file) as well as the message with 3601590Srgrimes * two optional arguments. 3611590Srgrimes * 3621590Srgrimes * Results: 3631590Srgrimes * None 3641590Srgrimes * 3651590Srgrimes * Side Effects: 3661590Srgrimes * "fatals" is incremented if the level is PARSE_FATAL. 3671590Srgrimes */ 3681590Srgrimes/* VARARGS */ 3691590Srgrimesvoid 37098136SjmallettParse_Error(int type, const char *fmt, ...) 3711590Srgrimes{ 3721590Srgrimes va_list ap; 37393056Simp 3741590Srgrimes va_start(ap, fmt); 375144745Sharti if (CURFILE != NULL) 376144745Sharti fprintf(stderr, "\"%s\", line %d: ", 377144745Sharti CURFILE->fname, CURFILE->lineno); 3781590Srgrimes if (type == PARSE_WARNING) 379138232Sharti fprintf(stderr, "warning: "); 380138232Sharti vfprintf(stderr, fmt, ap); 3811590Srgrimes va_end(ap); 382138232Sharti fprintf(stderr, "\n"); 383138232Sharti fflush(stderr); 3841590Srgrimes if (type == PARSE_FATAL) 3851590Srgrimes fatals += 1; 3861590Srgrimes} 3871590Srgrimes 388144341Sharti/** 389144341Sharti * ParsePushInput 390144341Sharti * 391144341Sharti * Push a new input source onto the input stack. If ptr is NULL 392144341Sharti * the fullname is used to fopen the file. If it is not NULL, 393144341Sharti * ptr is assumed to point to the string to be parsed. If opening the 394144341Sharti * file fails, the fullname is freed. 395144341Sharti */ 396144341Shartistatic void 397144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) 398144341Sharti{ 399144341Sharti struct IFile *nf; 400144341Sharti 401144341Sharti nf = emalloc(sizeof(*nf)); 402144341Sharti nf->fname = fullname; 403144341Sharti nf->lineno = lineno; 404144341Sharti 405144341Sharti if (ptr == NULL) { 406144341Sharti /* the input source is a file */ 407144341Sharti if ((nf->F = fp) == NULL) { 408144341Sharti nf->F = fopen(fullname, "r"); 409144341Sharti if (nf->F == NULL) { 410144341Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", 411144341Sharti fullname); 412144341Sharti free(fullname); 413144341Sharti free(nf); 414144341Sharti return; 415144341Sharti } 416144341Sharti } 417144341Sharti nf->str = nf->ptr = NULL; 418144341Sharti Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 419144341Sharti } else { 420144341Sharti nf->str = nf->ptr = ptr; 421144341Sharti nf->F = NULL; 422144341Sharti } 423144341Sharti TAILQ_INSERT_HEAD(&includes, nf, link); 424144341Sharti} 425144341Sharti 426144341Sharti/** 427144341Sharti * ParsePopInput 428144341Sharti * Called when EOF is reached in the current file. If we were reading 429144341Sharti * an include file, the includes stack is popped and things set up 430144341Sharti * to go back to reading the previous file at the previous location. 431144341Sharti * 432144341Sharti * Results: 433144341Sharti * CONTINUE if there's more to do. DONE if not. 434144341Sharti * 435144341Sharti * Side Effects: 436144341Sharti * The old curFile.F is closed. The includes list is shortened. 437144341Sharti * curFile.lineno, curFile.F, and curFile.fname are changed if 438144341Sharti * CONTINUE is returned. 439144341Sharti */ 440144341Shartistatic int 441144341ShartiParsePopInput(void) 442144341Sharti{ 443144341Sharti struct IFile *ifile; /* the state on the top of the includes stack */ 444144341Sharti 445144341Sharti assert(!TAILQ_EMPTY(&includes)); 446144341Sharti 447144341Sharti ifile = TAILQ_FIRST(&includes); 448144341Sharti TAILQ_REMOVE(&includes, ifile, link); 449144341Sharti 450144341Sharti free(ifile->fname); 451144341Sharti if (ifile->F != NULL) { 452144341Sharti fclose(ifile->F); 453144341Sharti Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 454144341Sharti } 455144341Sharti if (ifile->str != NULL) { 456144341Sharti free(ifile->str); 457144341Sharti } 458144341Sharti free(ifile); 459144341Sharti 460144341Sharti return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); 461144341Sharti} 462144341Sharti 4631590Srgrimes/*- 4641590Srgrimes *--------------------------------------------------------------------- 4651590Srgrimes * ParseLinkSrc -- 466143100Sharti * Link the parent nodes to their new child. Used by 4671590Srgrimes * ParseDoDependency. If the specType isn't 'Not', the parent 4681590Srgrimes * isn't linked as a parent of the child. 4691590Srgrimes * 4701590Srgrimes * Side Effects: 471143100Sharti * New elements are added to the parents lists of cgn and the 4721590Srgrimes * children list of cgn. the unmade field of pgn is updated 4731590Srgrimes * to reflect the additional child. 4741590Srgrimes *--------------------------------------------------------------------- 4751590Srgrimes */ 476143027Shartistatic void 477143027ShartiParseLinkSrc(Lst *parents, GNode *cgn) 4781590Srgrimes{ 479143027Sharti LstNode *ln; 480143027Sharti GNode *pgn; 481138232Sharti 482143027Sharti LST_FOREACH(ln, parents) { 483143027Sharti pgn = Lst_Datum(ln); 484143027Sharti if (Lst_Member(&pgn->children, cgn) == NULL) { 485143027Sharti Lst_AtEnd(&pgn->children, cgn); 486143027Sharti if (specType == Not) { 487143027Sharti Lst_AtEnd(&cgn->parents, pgn); 488143027Sharti } 489143027Sharti pgn->unmade += 1; 490143027Sharti } 4911590Srgrimes } 4921590Srgrimes} 4931590Srgrimes 4941590Srgrimes/*- 4951590Srgrimes *--------------------------------------------------------------------- 4961590Srgrimes * ParseDoOp -- 497143684Sharti * Apply the parsed operator to all target nodes. Used in 498143684Sharti * ParseDoDependency once all targets have been found and their 499143684Sharti * operator parsed. If the previous and new operators are incompatible, 500143684Sharti * a major error is taken. 5011590Srgrimes * 5021590Srgrimes * Side Effects: 5031590Srgrimes * The type field of the node is altered to reflect any new bits in 5041590Srgrimes * the op. 5051590Srgrimes *--------------------------------------------------------------------- 5061590Srgrimes */ 507143684Shartistatic void 508143684ShartiParseDoOp(int op) 5091590Srgrimes{ 510143684Sharti GNode *cohort; 511143684Sharti LstNode *ln; 512143684Sharti GNode *gn; 513138232Sharti 514143684Sharti LST_FOREACH(ln, &targets) { 515143684Sharti gn = Lst_Datum(ln); 5161590Srgrimes 517143684Sharti /* 518143684Sharti * If the dependency mask of the operator and the node don't 519143684Sharti * match and the node has actually had an operator applied to 520143684Sharti * it before, and the operator actually has some dependency 521143684Sharti * information in it, complain. 522143684Sharti */ 523143684Sharti if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && 524143684Sharti !OP_NOP(gn->type) && !OP_NOP(op)) { 525143684Sharti Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 526143684Sharti gn->name); 527143684Sharti return; 528143684Sharti } 5298874Srgrimes 530143684Sharti if (op == OP_DOUBLEDEP && 531143684Sharti (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 532143684Sharti /* 533143684Sharti * If the node was the object of a :: operator, we need 534143684Sharti * to create a new instance of it for the children and 535143684Sharti * commands on this dependency line. The new instance 536143684Sharti * is placed on the 'cohorts' list of the initial one 537143684Sharti * (note the initial one is not on its own cohorts list) 538143684Sharti * and the new instance is linked to all parents of the 539143684Sharti * initial instance. 540143684Sharti */ 541143684Sharti cohort = Targ_NewGN(gn->name); 5421590Srgrimes 543143684Sharti /* 544143684Sharti * Duplicate links to parents so graph traversal is 545143684Sharti * simple. Perhaps some type bits should be duplicated? 546143684Sharti * 547143684Sharti * Make the cohort invisible as well to avoid 548143684Sharti * duplicating it into other variables. True, parents 549143684Sharti * of this target won't tend to do anything with their 550143684Sharti * local variables, but better safe than sorry. 551143684Sharti */ 552143684Sharti ParseLinkSrc(&gn->parents, cohort); 553143684Sharti cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 554143684Sharti Lst_AtEnd(&gn->cohorts, cohort); 5551590Srgrimes 556143684Sharti /* 557143684Sharti * Replace the node in the targets list with the 558143684Sharti * new copy 559143684Sharti */ 560143684Sharti Lst_Replace(ln, cohort); 561143684Sharti gn = cohort; 562143684Sharti } 563143684Sharti /* 564143684Sharti * We don't want to nuke any previous flags (whatever they were) 565143684Sharti * so we just OR the new operator into the old 566143684Sharti */ 567143684Sharti gn->type |= op; 568143684Sharti } 5691590Srgrimes} 5701590Srgrimes 5711590Srgrimes/*- 5721590Srgrimes *--------------------------------------------------------------------- 5731590Srgrimes * ParseDoSrc -- 5741590Srgrimes * Given the name of a source, figure out if it is an attribute 5751590Srgrimes * and apply it to the targets if it is. Else decide if there is 5761590Srgrimes * some attribute which should be applied *to* the source because 5771590Srgrimes * of some special target and apply it if so. Otherwise, make the 5781590Srgrimes * source be a child of the targets in the list 'targets' 5791590Srgrimes * 5801590Srgrimes * Results: 5811590Srgrimes * None 5821590Srgrimes * 5831590Srgrimes * Side Effects: 5841590Srgrimes * Operator bits may be added to the list of targets or to the source. 5851590Srgrimes * The targets may have a new source added to their lists of children. 5861590Srgrimes *--------------------------------------------------------------------- 5871590Srgrimes */ 5881590Srgrimesstatic void 589138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc) 5901590Srgrimes{ 591144026Sharti GNode *gn = NULL; 5921590Srgrimes 593144026Sharti if (*src == '.' && isupper ((unsigned char) src[1])) { 594144026Sharti int keywd = ParseFindKeyword(src); 595144026Sharti if (keywd != -1) { 596144026Sharti if(parseKeywords[keywd].op != 0) { 597144026Sharti ParseDoOp(parseKeywords[keywd].op); 598144026Sharti return; 599144026Sharti } 600144026Sharti if (parseKeywords[keywd].spec == Wait) { 601144026Sharti waiting++; 602144026Sharti return; 603144026Sharti } 604144026Sharti } 6051590Srgrimes } 60618730Ssteve 607144026Sharti switch (specType) { 608144026Sharti case Main: 609144026Sharti /* 610144026Sharti * If we have noted the existence of a .MAIN, it means we need 611144026Sharti * to add the sources of said target to the list of things 612144026Sharti * to create. The string 'src' is likely to be free, so we 613144026Sharti * must make a new copy of it. Note that this will only be 614144026Sharti * invoked if the user didn't specify a target on the command 615144026Sharti * line. This is to allow #ifmake's to succeed, or something... 616144026Sharti */ 617144026Sharti Lst_AtEnd(&create, estrdup(src)); 618144026Sharti /* 619144026Sharti * Add the name to the .TARGETS variable as well, so the user 620144026Sharti * can employ that, if desired. 621144026Sharti */ 622144026Sharti Var_Append(".TARGETS", src, VAR_GLOBAL); 623144026Sharti return; 62418730Ssteve 625144026Sharti case Order: 626144026Sharti /* 627144026Sharti * Create proper predecessor/successor links between the 628144026Sharti * previous source and the current one. 629144026Sharti */ 630144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 631144026Sharti if (predecessor != NULL) { 632144026Sharti Lst_AtEnd(&predecessor->successors, gn); 633144026Sharti Lst_AtEnd(&gn->preds, predecessor); 634144026Sharti } 635144026Sharti /* 636144026Sharti * The current source now becomes the predecessor for the next 637144026Sharti * one. 638144026Sharti */ 639144026Sharti predecessor = gn; 640144026Sharti break; 64118730Ssteve 642144026Sharti default: 643144026Sharti /* 644144026Sharti * If the source is not an attribute, we need to find/create 645144026Sharti * a node for it. After that we can apply any operator to it 646144026Sharti * from a special target or link it to its parents, as 647144026Sharti * appropriate. 648144026Sharti * 649144026Sharti * In the case of a source that was the object of a :: operator, 650144026Sharti * the attribute is applied to all of its instances (as kept in 651144026Sharti * the 'cohorts' list of the node) or all the cohorts are linked 652144026Sharti * to all the targets. 653144026Sharti */ 654144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 6551590Srgrimes if (tOp) { 656144026Sharti gn->type |= tOp; 6571590Srgrimes } else { 658144026Sharti ParseLinkSrc(&targets, gn); 6591590Srgrimes } 660144026Sharti if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 661144026Sharti GNode *cohort; 662144026Sharti LstNode *ln; 663144026Sharti 664144026Sharti for (ln = Lst_First(&gn->cohorts); ln != NULL; 665144026Sharti ln = Lst_Succ(ln)) { 666144026Sharti cohort = Lst_Datum(ln); 667144026Sharti if (tOp) { 668144026Sharti cohort->type |= tOp; 669144026Sharti } else { 670144026Sharti ParseLinkSrc(&targets, cohort); 671144026Sharti } 672144026Sharti } 673144026Sharti } 674144026Sharti break; 6751590Srgrimes } 67618730Ssteve 677144026Sharti gn->order = waiting; 678144026Sharti Lst_AtEnd(allsrc, gn); 679144026Sharti if (waiting) { 680144026Sharti LstNode *ln; 681144026Sharti GNode *p; 6821590Srgrimes 683143684Sharti /* 684144026Sharti * Check if GNodes needs to be synchronized. 685144026Sharti * This has to be when two nodes are on different sides of a 686144026Sharti * .WAIT directive. 687143684Sharti */ 688144026Sharti LST_FOREACH(ln, allsrc) { 689144026Sharti p = Lst_Datum(ln); 690144026Sharti 691144026Sharti if (p->order >= gn->order) 692144026Sharti break; 693144026Sharti /* 694144026Sharti * XXX: This can cause loops, and loops can cause 695144026Sharti * unmade targets, but checking is tedious, and the 696144026Sharti * debugging output can show the problem 697144026Sharti */ 698144026Sharti Lst_AtEnd(&p->successors, gn); 699144026Sharti Lst_AtEnd(&gn->preds, p); 700144026Sharti } 701143684Sharti } 7021590Srgrimes} 7031590Srgrimes 704138232Sharti 7051590Srgrimes/*- 7061590Srgrimes *--------------------------------------------------------------------- 7071590Srgrimes * ParseDoDependency -- 7081590Srgrimes * Parse the dependency line in line. 7091590Srgrimes * 7101590Srgrimes * Results: 7111590Srgrimes * None 7121590Srgrimes * 7131590Srgrimes * Side Effects: 7141590Srgrimes * The nodes of the sources are linked as children to the nodes of the 7151590Srgrimes * targets. Some nodes may be created. 7161590Srgrimes * 7171590Srgrimes * We parse a dependency line by first extracting words from the line and 7181590Srgrimes * finding nodes in the list of all targets with that name. This is done 7191590Srgrimes * until a character is encountered which is an operator character. Currently 7201590Srgrimes * these are only ! and :. At this point the operator is parsed and the 7211590Srgrimes * pointer into the line advanced until the first source is encountered. 722144026Sharti * The parsed operator is applied to each node in the 'targets' list, 7231590Srgrimes * which is where the nodes found for the targets are kept, by means of 7241590Srgrimes * the ParseDoOp function. 7251590Srgrimes * The sources are read in much the same way as the targets were except 7261590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell 7271590Srgrimes * and all instances of the resulting words in the list of all targets 7281590Srgrimes * are found. Each of the resulting nodes is then linked to each of the 7291590Srgrimes * targets as one of its children. 7301590Srgrimes * Certain targets are handled specially. These are the ones detailed 7311590Srgrimes * by the specType variable. 7321590Srgrimes * The storing of transformation rules is also taken care of here. 7331590Srgrimes * A target is recognized as a transformation rule by calling 7341590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten 7351590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard 7361590Srgrimes * Targ_FindNode in the target module. 7371590Srgrimes *--------------------------------------------------------------------- 7381590Srgrimes */ 7391590Srgrimesstatic void 740141270ShartiParseDoDependency(char *line) 7411590Srgrimes{ 742144026Sharti char *cp; /* our current position */ 743144026Sharti GNode *gn; /* a general purpose temporary node */ 744144026Sharti int op; /* the operator on the line */ 745144026Sharti char savec; /* a place to save a character */ 746144026Sharti Lst paths; /* Search paths to alter when parsing .PATH targets */ 747144026Sharti int tOp; /* operator from special target */ 748144026Sharti LstNode *ln; 7491590Srgrimes 750144026Sharti tOp = 0; 7511590Srgrimes 752144026Sharti specType = Not; 753144026Sharti waiting = 0; 754144026Sharti Lst_Init(&paths); 7551590Srgrimes 756144026Sharti do { 757144026Sharti for (cp = line; 758144026Sharti *cp && !isspace((unsigned char)*cp) && *cp != '('; 759144026Sharti cp++) { 760144026Sharti if (*cp == '$') { 761144026Sharti /* 762144026Sharti * Must be a dynamic source (would have been 763144026Sharti * expanded otherwise), so call the Var module 764144026Sharti * to parse the puppy so we can safely advance 765144026Sharti * beyond it...There should be no errors in this 766144026Sharti * as they would have been discovered in the 767144026Sharti * initial Var_Subst and we wouldn't be here. 768144026Sharti */ 769144026Sharti size_t length = 0; 770144026Sharti Boolean freeIt; 771144026Sharti char *result; 7721590Srgrimes 773144026Sharti result = Var_Parse(cp, VAR_CMD, TRUE, 774144026Sharti &length, &freeIt); 7751590Srgrimes 776144026Sharti if (freeIt) { 777144026Sharti free(result); 778144026Sharti } 779144026Sharti cp += length - 1; 780102178Sru 781144026Sharti } else if (*cp == '!' || *cp == ':') { 782144026Sharti /* 783144026Sharti * We don't want to end a word on ':' or '!' if 784144026Sharti * there is a better match later on in the 785144026Sharti * string (greedy matching). 786144026Sharti * This allows the user to have targets like: 787144026Sharti * fie::fi:fo: fum 788144026Sharti * foo::bar: 789144026Sharti * where "fie::fi:fo" and "foo::bar" are the 790144026Sharti * targets. In real life this is used for perl5 791144026Sharti * library man pages where "::" separates an 792144026Sharti * object from its class. Ie: 793144026Sharti * "File::Spec::Unix". This behaviour is also 794144026Sharti * consistent with other versions of make. 795144026Sharti */ 796144026Sharti char *p = cp + 1; 797102178Sru 798144026Sharti if (*cp == ':' && *p == ':') 799144026Sharti p++; 800102178Sru 801144026Sharti /* Found the best match already. */ 802144026Sharti if (*p == '\0' || isspace(*p)) 803144026Sharti break; 804102178Sru 805144026Sharti p += strcspn(p, "!:"); 8068874Srgrimes 807144026Sharti /* No better match later on... */ 808144026Sharti if (*p == '\0') 809144026Sharti break; 810144026Sharti } 811144026Sharti continue; 8121590Srgrimes } 813144026Sharti if (*cp == '(') { 814144026Sharti /* 815144026Sharti * Archives must be handled specially to make sure the 816144026Sharti * OP_ARCHV flag is set in their 'type' field, for one 817144026Sharti * thing, and because things like "archive(file1.o 818144026Sharti * file2.o file3.o)" are permissible. Arch_ParseArchive 819144026Sharti * will set 'line' to be the first non-blank after the 820144026Sharti * archive-spec. It creates/finds nodes for the members 821144026Sharti * and places them on the given list, returning SUCCESS 822144026Sharti * if all went well and FAILURE if there was an error in 823144026Sharti * the specification. On error, line should remain 824144026Sharti * untouched. 825144026Sharti */ 826144026Sharti if (Arch_ParseArchive(&line, &targets, VAR_CMD) != 827144026Sharti SUCCESS) { 828144026Sharti Parse_Error(PARSE_FATAL, 829144026Sharti "Error in archive specification: \"%s\"", 830144026Sharti line); 831144026Sharti return; 832144026Sharti } else { 833144026Sharti cp = line; 834144026Sharti continue; 835144026Sharti } 836144026Sharti } 837144026Sharti savec = *cp; 8388874Srgrimes 839144026Sharti if (!*cp) { 840144026Sharti /* 841144026Sharti * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often 842144026Sharti * triggered by undetected conflicts from cvs/rcs 843144026Sharti * merges. 844144026Sharti */ 845144026Sharti if (strncmp(line, "<<<<<<", 6) == 0 || 846144026Sharti strncmp(line, "======", 6) == 0 || 847144026Sharti strncmp(line, ">>>>>>", 6) == 0) { 848144026Sharti Parse_Error(PARSE_FATAL, "Makefile appears to " 849144026Sharti "contain unresolved cvs/rcs/??? merge " 850144026Sharti "conflicts"); 851144026Sharti } else 852144026Sharti Parse_Error(PARSE_FATAL, "Need an operator"); 853144026Sharti return; 854144026Sharti } 855144026Sharti *cp = '\0'; 8561590Srgrimes /* 857144026Sharti * Have a word in line. See if it's a special target and set 858144026Sharti * specType to match it. 8591590Srgrimes */ 860144026Sharti if (*line == '.' && isupper((unsigned char)line[1])) { 861144026Sharti /* 862144026Sharti * See if the target is a special target that must have 863144026Sharti * it or its sources handled specially. 864144026Sharti */ 865144026Sharti int keywd = ParseFindKeyword(line); 866144026Sharti 867144026Sharti if (keywd != -1) { 868144026Sharti if (specType == ExPath && 869144026Sharti parseKeywords[keywd].spec != ExPath) { 870144026Sharti Parse_Error(PARSE_FATAL, 871144026Sharti "Mismatched special targets"); 872144026Sharti return; 873144026Sharti } 874144026Sharti 875144026Sharti specType = parseKeywords[keywd].spec; 876144026Sharti tOp = parseKeywords[keywd].op; 877144026Sharti 878144026Sharti /* 879144026Sharti * Certain special targets have special 880144026Sharti * semantics: 881144026Sharti * .PATH Have to set the dirSearchPath 882144026Sharti * variable too 883144026Sharti * .MAIN Its sources are only used if 884144026Sharti * nothing has been specified to 885144026Sharti * create. 886144026Sharti * .DEFAULT Need to create a node to hang 887144026Sharti * commands on, but we don't want 888144026Sharti * it in the graph, nor do we want 889144026Sharti * it to be the Main Target, so we 890144026Sharti * create it, set OP_NOTMAIN and 891144026Sharti * add it to the list, setting 892144026Sharti * DEFAULT to the new node for 893144026Sharti * later use. We claim the node is 894144026Sharti * A transformation rule to make 895144026Sharti * life easier later, when we'll 896144026Sharti * use Make_HandleUse to actually 897144026Sharti * apply the .DEFAULT commands. 898144026Sharti * .PHONY The list of targets 899144026Sharti * .BEGIN 900144026Sharti * .END 901144026Sharti * .INTERRUPT Are not to be considered the 902144026Sharti * main target. 903144026Sharti * .NOTPARALLEL Make only one target at a time. 904144026Sharti * .SINGLESHELL Create a shell for each 905144026Sharti * command. 906144026Sharti * .ORDER Must set initial predecessor 907144026Sharti * to NULL 908144026Sharti */ 909144026Sharti switch (specType) { 910144026Sharti case ExPath: 911144026Sharti Lst_AtEnd(&paths, &dirSearchPath); 912144026Sharti break; 913144026Sharti case Main: 914144026Sharti if (!Lst_IsEmpty(&create)) { 915144026Sharti specType = Not; 916144026Sharti } 917144026Sharti break; 918144026Sharti case Begin: 919144026Sharti case End: 920144026Sharti case Interrupt: 921144026Sharti gn = Targ_FindNode(line, TARG_CREATE); 922144026Sharti gn->type |= OP_NOTMAIN; 923144026Sharti Lst_AtEnd(&targets, gn); 924144026Sharti break; 925144026Sharti case Default: 926144026Sharti gn = Targ_NewGN(".DEFAULT"); 927144026Sharti gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 928144026Sharti Lst_AtEnd(&targets, gn); 929144026Sharti DEFAULT = gn; 930144026Sharti break; 931144026Sharti case NotParallel: 932144026Sharti maxJobs = 1; 933144026Sharti break; 934144026Sharti case SingleShell: 935144026Sharti compatMake = 1; 936144026Sharti break; 937144026Sharti case Order: 938144026Sharti predecessor = NULL; 939144026Sharti break; 940144026Sharti default: 941144026Sharti break; 942144026Sharti } 943144026Sharti 944144026Sharti } else if (strncmp(line, ".PATH", 5) == 0) { 945144026Sharti /* 946144026Sharti * .PATH<suffix> has to be handled specially. 947144026Sharti * Call on the suffix module to give us a path 948144026Sharti * to modify. 949144026Sharti */ 950144026Sharti struct Path *path; 951144026Sharti 952144026Sharti specType = ExPath; 953144026Sharti path = Suff_GetPath(&line[5]); 954144026Sharti if (path == NULL) { 955144026Sharti Parse_Error(PARSE_FATAL, "Suffix '%s' " 956144026Sharti "not defined (yet)", &line[5]); 957144026Sharti return; 958144026Sharti } else 959144026Sharti Lst_AtEnd(&paths, path); 9601590Srgrimes } 9611590Srgrimes } 962144026Sharti 9631590Srgrimes /* 964144026Sharti * Have word in line. Get or create its node and stick it at 965144026Sharti * the end of the targets list 9661590Srgrimes */ 967144029Sharti if (specType == Not && *line != '\0') { 9688874Srgrimes 969144026Sharti /* target names to be found and added to targets list */ 970144026Sharti Lst curTargs = Lst_Initializer(curTargs); 9718874Srgrimes 972144026Sharti if (Dir_HasWildcards(line)) { 973144026Sharti /* 974144026Sharti * Targets are to be sought only in the current 975144026Sharti * directory, so create an empty path for the 976144026Sharti * thing. Note we need to use Path_Clear in the 977144026Sharti * destruction of the path as the Dir module 978144026Sharti * could have added a directory to the path... 979144026Sharti */ 980144026Sharti struct Path emptyPath = 981144026Sharti TAILQ_HEAD_INITIALIZER(emptyPath); 982138916Sharti 983144026Sharti Path_Expand(line, &emptyPath, &curTargs); 984144026Sharti Path_Clear(&emptyPath); 9858874Srgrimes 986144026Sharti } else { 987144026Sharti /* 988144026Sharti * No wildcards, but we want to avoid code 989144026Sharti * duplication, so create a list with the word 990144026Sharti * on it. 991144026Sharti */ 992144026Sharti Lst_AtEnd(&curTargs, line); 993144026Sharti } 9948874Srgrimes 995144026Sharti while (!Lst_IsEmpty(&curTargs)) { 996144026Sharti char *targName = Lst_DeQueue(&curTargs); 997144026Sharti 998144026Sharti if (!Suff_IsTransform (targName)) { 999144026Sharti gn = Targ_FindNode(targName, 1000144026Sharti TARG_CREATE); 1001144026Sharti } else { 1002144026Sharti gn = Suff_AddTransform(targName); 1003144026Sharti } 1004144026Sharti 1005144026Sharti Lst_AtEnd(&targets, gn); 1006144026Sharti } 1007144026Sharti } else if (specType == ExPath && *line != '.' && *line != '\0'){ 1008144026Sharti Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 1009144026Sharti line); 1010144026Sharti } 1011144026Sharti 1012144026Sharti *cp = savec; 10131590Srgrimes /* 1014144026Sharti * If it is a special type and not .PATH, it's the only 1015144026Sharti * target we allow on this line... 10161590Srgrimes */ 1017144026Sharti if (specType != Not && specType != ExPath) { 1018144026Sharti Boolean warnFlag = FALSE; 10198874Srgrimes 1020144029Sharti while (*cp != '!' && *cp != ':' && *cp) { 1021144026Sharti if (*cp != ' ' && *cp != '\t') { 1022144026Sharti warnFlag = TRUE; 1023144026Sharti } 1024144026Sharti cp++; 1025144026Sharti } 1026144026Sharti if (warnFlag) { 1027144026Sharti Parse_Error(PARSE_WARNING, 1028144026Sharti "Extra target ignored"); 1029144026Sharti } 10301590Srgrimes } else { 1031144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1032144026Sharti cp++; 1033144026Sharti } 10341590Srgrimes } 1035144026Sharti line = cp; 1036144029Sharti } while (*line != '!' && *line != ':' && *line); 10378874Srgrimes 1038144026Sharti if (!Lst_IsEmpty(&targets)) { 1039144026Sharti switch (specType) { 1040144026Sharti default: 1041144026Sharti Parse_Error(PARSE_WARNING, "Special and mundane " 1042144026Sharti "targets don't mix. Mundane ones ignored"); 1043144026Sharti break; 1044144026Sharti case Default: 1045144026Sharti case Begin: 1046144026Sharti case End: 1047144026Sharti case Interrupt: 1048144026Sharti /* 1049144026Sharti * These four create nodes on which to hang commands, so 1050144026Sharti * targets shouldn't be empty... 1051144026Sharti */ 1052144026Sharti case Not: 1053144026Sharti /* 1054144026Sharti * Nothing special here -- targets can be empty if it 1055144026Sharti * wants. 1056144026Sharti */ 1057144026Sharti break; 1058144026Sharti } 10591590Srgrimes } 10608874Srgrimes 10611590Srgrimes /* 1062144026Sharti * Have now parsed all the target names. Must parse the operator next. 1063144026Sharti * The result is left in op. 10641590Srgrimes */ 1065144026Sharti if (*cp == '!') { 1066144026Sharti op = OP_FORCE; 1067144026Sharti } else if (*cp == ':') { 1068144026Sharti if (cp[1] == ':') { 1069144026Sharti op = OP_DOUBLEDEP; 1070144026Sharti cp++; 1071144026Sharti } else { 1072144026Sharti op = OP_DEPENDS; 10731590Srgrimes } 10741590Srgrimes } else { 1075144026Sharti Parse_Error(PARSE_FATAL, "Missing dependency operator"); 1076144026Sharti return; 1077144026Sharti } 1078144026Sharti 1079144026Sharti cp++; /* Advance beyond operator */ 1080144026Sharti 1081144026Sharti ParseDoOp(op); 1082144026Sharti 1083144026Sharti /* 1084144026Sharti * Get to the first source 1085144026Sharti */ 1086144026Sharti while (*cp && isspace((unsigned char)*cp)) { 10871590Srgrimes cp++; 10881590Srgrimes } 10891590Srgrimes line = cp; 10901590Srgrimes 1091144026Sharti /* 1092144026Sharti * Several special targets take different actions if present with no 1093144026Sharti * sources: 1094144026Sharti * a .SUFFIXES line with no sources clears out all old suffixes 1095144026Sharti * a .PRECIOUS line makes all targets precious 1096144026Sharti * a .IGNORE line ignores errors for all targets 1097144026Sharti * a .SILENT line creates silence when making all targets 1098144026Sharti * a .PATH removes all directories from the search path(s). 1099144026Sharti */ 1100144026Sharti if (!*line) { 1101144026Sharti switch (specType) { 1102144026Sharti case Suffixes: 1103144026Sharti Suff_ClearSuffixes(); 1104144026Sharti break; 1105144026Sharti case Precious: 1106144026Sharti allPrecious = TRUE; 1107144026Sharti break; 1108144026Sharti case Ignore: 1109144026Sharti ignoreErrors = TRUE; 1110144026Sharti break; 1111144026Sharti case Silent: 1112144026Sharti beSilent = TRUE; 1113144026Sharti break; 1114144026Sharti case ExPath: 1115144026Sharti LST_FOREACH(ln, &paths) 1116144026Sharti Path_Clear(Lst_Datum(ln)); 1117144026Sharti break; 1118144026Sharti case Posix: 1119144026Sharti Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 1120144026Sharti break; 1121144026Sharti default: 1122144026Sharti break; 1123144026Sharti } 1124144026Sharti 1125144026Sharti } else if (specType == MFlags) { 11261590Srgrimes /* 1127144026Sharti * Call on functions in main.c to deal with these arguments and 1128144026Sharti * set the initial character to a null-character so the loop to 1129144026Sharti * get sources won't get anything 11301590Srgrimes */ 1131144026Sharti Main_ParseArgLine(line, 0); 1132144026Sharti *line = '\0'; 11331590Srgrimes 1134144026Sharti } else if (specType == ExShell) { 1135144026Sharti if (Job_ParseShell(line) != SUCCESS) { 1136144026Sharti Parse_Error(PARSE_FATAL, 1137144026Sharti "improper shell specification"); 1138144026Sharti return; 1139144026Sharti } 1140144026Sharti *line = '\0'; 1141144026Sharti 1142144029Sharti } else if (specType == NotParallel || specType == SingleShell) { 1143144026Sharti *line = '\0'; 11441590Srgrimes } 11451590Srgrimes 1146144026Sharti /* 1147144026Sharti * NOW GO FOR THE SOURCES 1148144026Sharti */ 1149144029Sharti if (specType == Suffixes || specType == ExPath || 1150144029Sharti specType == Includes || specType == Libs || 1151144029Sharti specType == Null) { 1152144026Sharti while (*line) { 1153144026Sharti /* 1154144026Sharti * If the target was one that doesn't take files as its 1155144026Sharti * sources but takes something like suffixes, we take 1156144026Sharti * each space-separated word on the line as a something 1157144026Sharti * and deal with it accordingly. 1158144026Sharti * 1159144026Sharti * If the target was .SUFFIXES, we take each source as 1160144026Sharti * a suffix and add it to the list of suffixes 1161144026Sharti * maintained by the Suff module. 1162144026Sharti * 1163144026Sharti * If the target was a .PATH, we add the source as a 1164144026Sharti * directory to search on the search path. 1165144026Sharti * 1166144026Sharti * If it was .INCLUDES, the source is taken to be the 1167144026Sharti * suffix of files which will be #included and whose 1168144026Sharti * search path should be present in the .INCLUDES 1169144026Sharti * variable. 1170144026Sharti * 1171144026Sharti * If it was .LIBS, the source is taken to be the 1172144026Sharti * suffix of files which are considered libraries and 1173144026Sharti * whose search path should be present in the .LIBS 1174144026Sharti * variable. 1175144026Sharti * 1176144026Sharti * If it was .NULL, the source is the suffix to use 1177144026Sharti * when a file has no valid suffix. 1178144026Sharti */ 1179144026Sharti char savech; 1180144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1181144026Sharti cp++; 1182144026Sharti } 1183144026Sharti savech = *cp; 1184144026Sharti *cp = '\0'; 1185144026Sharti switch (specType) { 1186144026Sharti case Suffixes: 1187144026Sharti Suff_AddSuffix(line); 1188144026Sharti break; 1189144026Sharti case ExPath: 1190144026Sharti LST_FOREACH(ln, &paths) 1191144026Sharti Path_AddDir(Lst_Datum(ln), line); 1192144026Sharti break; 1193144026Sharti case Includes: 1194144026Sharti Suff_AddInclude(line); 1195144026Sharti break; 1196144026Sharti case Libs: 1197144026Sharti Suff_AddLib(line); 1198144026Sharti break; 1199144026Sharti case Null: 1200144026Sharti Suff_SetNull(line); 1201144026Sharti break; 1202144026Sharti default: 1203144026Sharti break; 1204144026Sharti } 1205144026Sharti *cp = savech; 1206144026Sharti if (savech != '\0') { 1207144026Sharti cp++; 1208144026Sharti } 1209144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1210144026Sharti cp++; 1211144026Sharti } 1212144026Sharti line = cp; 1213144026Sharti } 1214144026Sharti Lst_Destroy(&paths, NOFREE); 12151590Srgrimes 1216144026Sharti } else { 1217144026Sharti /* list of sources in order */ 1218144026Sharti Lst curSrcs = Lst_Initializer(curSrc); 12191590Srgrimes 1220144026Sharti while (*line) { 1221144026Sharti /* 1222144026Sharti * The targets take real sources, so we must beware of 1223144026Sharti * archive specifications (i.e. things with left 1224144026Sharti * parentheses in them) and handle them accordingly. 1225144026Sharti */ 1226144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1227144026Sharti if (*cp == '(' && cp > line && cp[-1] != '$') { 1228144026Sharti /* 1229144026Sharti * Only stop for a left parenthesis if 1230144026Sharti * it isn't at the start of a word 1231144026Sharti * (that'll be for variable changes 1232144026Sharti * later) and isn't preceded by a dollar 1233144026Sharti * sign (a dynamic source). 1234144026Sharti */ 1235144026Sharti break; 1236144026Sharti } else { 1237144026Sharti cp++; 1238144026Sharti } 1239144026Sharti } 12401590Srgrimes 1241144026Sharti if (*cp == '(') { 1242144026Sharti GNode *gnp; 12438874Srgrimes 1244144026Sharti /* list of archive source names after exp. */ 1245144026Sharti Lst sources = Lst_Initializer(sources); 1246138916Sharti 1247144026Sharti if (Arch_ParseArchive(&line, &sources, 1248144026Sharti VAR_CMD) != SUCCESS) { 1249144026Sharti Parse_Error(PARSE_FATAL, "Error in " 1250144026Sharti "source archive spec \"%s\"", line); 1251144026Sharti return; 1252144026Sharti } 1253141270Sharti 1254144026Sharti while (!Lst_IsEmpty(&sources)) { 1255144026Sharti gnp = Lst_DeQueue(&sources); 1256144026Sharti ParseDoSrc(tOp, gnp->name, &curSrcs); 1257144026Sharti } 1258144026Sharti cp = line; 1259144026Sharti } else { 1260144026Sharti if (*cp) { 1261144026Sharti *cp = '\0'; 1262144026Sharti cp += 1; 1263144026Sharti } 12641590Srgrimes 1265144026Sharti ParseDoSrc(tOp, line, &curSrcs); 1266144026Sharti } 1267144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1268144026Sharti cp++; 1269144026Sharti } 1270144026Sharti line = cp; 12711590Srgrimes } 1272144026Sharti Lst_Destroy(&curSrcs, NOFREE); 1273144026Sharti } 12741590Srgrimes 1275144026Sharti if (mainNode == NULL) { 1276144026Sharti /* 1277144026Sharti * If we have yet to decide on a main target to make, in the 1278144026Sharti * absence of any user input, we want the first target on 1279144026Sharti * the first dependency line that is actually a real target 1280144026Sharti * (i.e. isn't a .USE or .EXEC rule) to be made. 1281144026Sharti */ 1282144026Sharti LST_FOREACH(ln, &targets) { 1283144026Sharti gn = Lst_Datum(ln); 1284144026Sharti if ((gn->type & (OP_NOTMAIN | OP_USE | 1285144026Sharti OP_EXEC | OP_TRANSFORM)) == 0) { 1286144026Sharti mainNode = gn; 1287144026Sharti Targ_SetMain(gn); 1288144026Sharti break; 1289144026Sharti } 12901590Srgrimes } 12911590Srgrimes } 12921590Srgrimes} 12931590Srgrimes 12941590Srgrimes/*- 12951590Srgrimes *--------------------------------------------------------------------- 12961590Srgrimes * Parse_IsVar -- 12971590Srgrimes * Return TRUE if the passed line is a variable assignment. A variable 12981590Srgrimes * assignment consists of a single word followed by optional whitespace 12991590Srgrimes * followed by either a += or an = operator. 13001590Srgrimes * This function is used both by the Parse_File function and main when 13011590Srgrimes * parsing the command-line arguments. 13021590Srgrimes * 13031590Srgrimes * Results: 13041590Srgrimes * TRUE if it is. FALSE if it ain't 13051590Srgrimes * 13061590Srgrimes * Side Effects: 13071590Srgrimes * none 13081590Srgrimes *--------------------------------------------------------------------- 13091590Srgrimes */ 13101590SrgrimesBoolean 1311138232ShartiParse_IsVar(char *line) 13121590Srgrimes{ 1313144026Sharti Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1314144026Sharti Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1315138232Sharti 1316144026Sharti int level = 0; 1317103503Sjmallett#define ISEQOPERATOR(c) \ 1318144029Sharti ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') 13191590Srgrimes 1320144026Sharti /* 1321144026Sharti * Skip to variable name 1322144026Sharti */ 1323144029Sharti for (; *line == ' ' || *line == '\t'; line++) 1324144026Sharti continue; 13251590Srgrimes 1326144026Sharti for (; *line != '=' || level != 0; line++) { 1327144026Sharti switch (*line) { 1328144026Sharti case '\0': 1329144026Sharti /* 1330144026Sharti * end-of-line -- can't be a variable assignment. 1331144026Sharti */ 1332144026Sharti return (FALSE); 133318730Ssteve 1334144026Sharti case ' ': 1335144026Sharti case '\t': 1336144026Sharti /* 1337144026Sharti * there can be as much white space as desired so long 1338144026Sharti * as there is only one word before the operator 1339144026Sharti */ 1340144026Sharti wasSpace = TRUE; 1341144026Sharti break; 134218730Ssteve 1343144026Sharti case '(': 1344144026Sharti case '{': 1345144026Sharti level++; 1346144026Sharti break; 134718730Ssteve 1348144026Sharti case '}': 1349144026Sharti case ')': 1350144026Sharti level--; 1351144026Sharti break; 135218730Ssteve 1353144026Sharti default: 1354144026Sharti if (wasSpace && haveName) { 1355144026Sharti if (ISEQOPERATOR(*line)) { 1356144026Sharti /* 1357144026Sharti * We must have a finished word 1358144026Sharti */ 1359144026Sharti if (level != 0) 1360144026Sharti return (FALSE); 136118730Ssteve 1362144026Sharti /* 1363144026Sharti * When an = operator [+?!:] is found, 1364144026Sharti * the next character must be an = or 1365144026Sharti * it ain't a valid assignment. 1366144026Sharti */ 1367144026Sharti if (line[1] == '=') 1368144026Sharti return (haveName); 136918730Ssteve#ifdef SUNSHCMD 1370144026Sharti /* 1371144026Sharti * This is a shell command 1372144026Sharti */ 1373144026Sharti if (strncmp(line, ":sh", 3) == 0) 1374144026Sharti return (haveName); 137518730Ssteve#endif 1376144026Sharti } 1377144026Sharti /* 1378144026Sharti * This is the start of another word, so not 1379144026Sharti * assignment. 1380144026Sharti */ 1381144026Sharti return (FALSE); 1382144026Sharti 1383144026Sharti } else { 1384144026Sharti haveName = TRUE; 1385144026Sharti wasSpace = FALSE; 1386144026Sharti } 1387144026Sharti break; 1388144026Sharti } 13891590Srgrimes } 13901590Srgrimes 1391144026Sharti return (haveName); 13921590Srgrimes} 13931590Srgrimes 13941590Srgrimes/*- 13951590Srgrimes *--------------------------------------------------------------------- 13961590Srgrimes * Parse_DoVar -- 13971590Srgrimes * Take the variable assignment in the passed line and do it in the 13981590Srgrimes * global context. 13991590Srgrimes * 14001590Srgrimes * Note: There is a lexical ambiguity with assignment modifier characters 14011590Srgrimes * in variable names. This routine interprets the character before the = 14021590Srgrimes * as a modifier. Therefore, an assignment like 14031590Srgrimes * C++=/usr/bin/CC 14041590Srgrimes * is interpreted as "C+ +=" instead of "C++ =". 14051590Srgrimes * 14061590Srgrimes * Results: 14071590Srgrimes * none 14081590Srgrimes * 14091590Srgrimes * Side Effects: 14101590Srgrimes * the variable structure of the given variable name is altered in the 14111590Srgrimes * global context. 14121590Srgrimes *--------------------------------------------------------------------- 14131590Srgrimes */ 14141590Srgrimesvoid 1415138232ShartiParse_DoVar(char *line, GNode *ctxt) 14161590Srgrimes{ 1417144026Sharti char *cp; /* pointer into line */ 1418144026Sharti enum { 1419144026Sharti VAR_SUBST, 1420144026Sharti VAR_APPEND, 1421144026Sharti VAR_SHELL, 1422144026Sharti VAR_NORMAL 1423144026Sharti } type; /* Type of assignment */ 1424144026Sharti char *opc; /* ptr to operator character to 1425144026Sharti * null-terminate the variable name */ 1426144026Sharti 1427144026Sharti /* 1428144026Sharti * Avoid clobbered variable warnings by forcing the compiler 1429144026Sharti * to ``unregister'' variables 1430144026Sharti */ 14311590Srgrimes#if __GNUC__ 1432144026Sharti (void)&cp; 1433144026Sharti (void)&line; 14345814Sjkh#endif 14351590Srgrimes 1436144026Sharti /* 1437144026Sharti * Skip to variable name 1438144026Sharti */ 1439144029Sharti while (*line == ' ' || *line == '\t') { 1440144026Sharti line++; 1441144026Sharti } 14421590Srgrimes 1443144026Sharti /* 1444144026Sharti * Skip to operator character, nulling out whitespace as we go 1445144026Sharti */ 1446144026Sharti for (cp = line + 1; *cp != '='; cp++) { 1447144026Sharti if (isspace((unsigned char)*cp)) { 1448144026Sharti *cp = '\0'; 1449144026Sharti } 14501590Srgrimes } 1451144026Sharti opc = cp - 1; /* operator is the previous character */ 1452144026Sharti *cp++ = '\0'; /* nuke the = */ 14531590Srgrimes 1454144026Sharti /* 1455144026Sharti * Check operator type 1456144026Sharti */ 1457144026Sharti switch (*opc) { 1458144026Sharti case '+': 1459144026Sharti type = VAR_APPEND; 1460144026Sharti *opc = '\0'; 1461144026Sharti break; 14621590Srgrimes 1463144026Sharti case '?': 1464144026Sharti /* 1465144026Sharti * If the variable already has a value, we don't do anything. 1466144026Sharti */ 1467144026Sharti *opc = '\0'; 1468144026Sharti if (Var_Exists(line, ctxt)) { 1469144026Sharti return; 1470144026Sharti } else { 1471144026Sharti type = VAR_NORMAL; 1472144026Sharti } 1473144026Sharti break; 14741590Srgrimes 1475144026Sharti case ':': 1476144026Sharti type = VAR_SUBST; 1477144026Sharti *opc = '\0'; 1478144026Sharti break; 14791590Srgrimes 1480144026Sharti case '!': 1481144026Sharti type = VAR_SHELL; 1482144026Sharti *opc = '\0'; 1483144026Sharti break; 14841590Srgrimes 1485144026Sharti default: 148618730Ssteve#ifdef SUNSHCMD 1487144026Sharti while (*opc != ':') { 1488144026Sharti if (opc == line) 1489144026Sharti break; 1490144026Sharti else 1491144026Sharti --opc; 1492144026Sharti } 149318730Ssteve 1494144026Sharti if (strncmp(opc, ":sh", 3) == 0) { 1495144026Sharti type = VAR_SHELL; 1496144026Sharti *opc = '\0'; 1497144026Sharti break; 1498144026Sharti } 1499144026Sharti#endif 1500144026Sharti type = VAR_NORMAL; 150118730Ssteve break; 1502144026Sharti } 15031590Srgrimes 1504144026Sharti while (isspace((unsigned char)*cp)) { 1505144026Sharti cp++; 1506144026Sharti } 15071590Srgrimes 1508144026Sharti if (type == VAR_APPEND) { 1509144026Sharti Var_Append(line, cp, ctxt); 15101590Srgrimes 1511144026Sharti } else if (type == VAR_SUBST) { 1512144026Sharti /* 1513144026Sharti * Allow variables in the old value to be undefined, but leave 1514144026Sharti * their invocation alone -- this is done by forcing oldVars 1515144026Sharti * to be false. 1516144026Sharti * XXX: This can cause recursive variables, but that's not 1517144026Sharti * hard to do, and this allows someone to do something like 1518144026Sharti * 1519144026Sharti * CFLAGS = $(.INCLUDES) 1520144026Sharti * CFLAGS := -I.. $(CFLAGS) 1521144026Sharti * 1522144026Sharti * And not get an error. 1523144026Sharti */ 1524144026Sharti Boolean oldOldVars = oldVars; 152598509Sjmallett 1526144026Sharti oldVars = FALSE; 152798509Sjmallett 1528144026Sharti /* 1529144026Sharti * make sure that we set the variable the first time to nothing 1530144026Sharti * so that it gets substituted! 1531144026Sharti */ 1532144026Sharti if (!Var_Exists(line, ctxt)) 1533144026Sharti Var_Set(line, "", ctxt); 1534142457Sharti 1535144026Sharti cp = Buf_Peel(Var_Subst(NULL, cp, ctxt, FALSE)); 15361590Srgrimes 1537144026Sharti oldVars = oldOldVars; 15381590Srgrimes 1539144026Sharti Var_Set(line, cp, ctxt); 1540144026Sharti free(cp); 15411590Srgrimes 1542144026Sharti } else if (type == VAR_SHELL) { 1543144026Sharti /* 1544144026Sharti * TRUE if the command needs to be freed, i.e. 1545144026Sharti * if any variable expansion was performed 1546144026Sharti */ 1547144026Sharti Boolean freeCmd = FALSE; 1548144026Sharti Buffer *buf; 1549144026Sharti const char *error; 15501590Srgrimes 1551144026Sharti if (strchr(cp, '$') != NULL) { 1552144026Sharti /* 1553144026Sharti * There's a dollar sign in the command, so perform 1554144026Sharti * variable expansion on the whole thing. The 1555144026Sharti * resulting string will need freeing when we're done, 1556144026Sharti * so set freeCmd to TRUE. 1557144026Sharti */ 1558144026Sharti cp = Buf_Peel(Var_Subst(NULL, cp, VAR_CMD, TRUE)); 1559144026Sharti freeCmd = TRUE; 1560144026Sharti } 15611590Srgrimes 1562144026Sharti buf = Cmd_Exec(cp, &error); 1563144026Sharti Var_Set(line, Buf_Data(buf), ctxt); 1564144026Sharti Buf_Destroy(buf, TRUE); 1565144026Sharti 1566144026Sharti if (error) 1567144026Sharti Parse_Error(PARSE_WARNING, error, cp); 1568144026Sharti 1569144026Sharti if (freeCmd) 1570144026Sharti free(cp); 1571144026Sharti 1572144026Sharti } else { 1573144026Sharti /* 1574144026Sharti * Normal assignment -- just do it. 1575144026Sharti */ 1576144026Sharti Var_Set(line, cp, ctxt); 1577144026Sharti } 15781590Srgrimes} 15791590Srgrimes 15801590Srgrimes/*- 15811590Srgrimes *----------------------------------------------------------------------- 15821590Srgrimes * ParseHasCommands -- 15831590Srgrimes * Callback procedure for Parse_File when destroying the list of 15841590Srgrimes * targets on the last dependency line. Marks a target as already 15851590Srgrimes * having commands if it does, to keep from having shell commands 15861590Srgrimes * on multiple dependency lines. 15871590Srgrimes * 15881590Srgrimes * Results: 15895814Sjkh * None 15901590Srgrimes * 15911590Srgrimes * Side Effects: 15921590Srgrimes * OP_HAS_COMMANDS may be set for the target. 15931590Srgrimes * 15941590Srgrimes *----------------------------------------------------------------------- 15951590Srgrimes */ 15965814Sjkhstatic void 1597104696SjmallettParseHasCommands(void *gnp) 15981590Srgrimes{ 1599144026Sharti GNode *gn = gnp; 1600138232Sharti 1601144026Sharti if (!Lst_IsEmpty(&gn->commands)) { 1602144026Sharti gn->type |= OP_HAS_COMMANDS; 1603144026Sharti } 16041590Srgrimes} 16051590Srgrimes 16061590Srgrimes/*- 16071590Srgrimes *----------------------------------------------------------------------- 16081590Srgrimes * Parse_AddIncludeDir -- 16091590Srgrimes * Add a directory to the path searched for included makefiles 16101590Srgrimes * bracketed by double-quotes. Used by functions in main.c 16111590Srgrimes * 16121590Srgrimes * Results: 16131590Srgrimes * None. 16141590Srgrimes * 16151590Srgrimes * Side Effects: 16161590Srgrimes * The directory is appended to the list. 16171590Srgrimes * 16181590Srgrimes *----------------------------------------------------------------------- 16191590Srgrimes */ 16201590Srgrimesvoid 1621138232ShartiParse_AddIncludeDir(char *dir) 16221590Srgrimes{ 1623138232Sharti 1624144026Sharti Path_AddDir(&parseIncPath, dir); 16251590Srgrimes} 16261590Srgrimes 16271590Srgrimes/*- 16281590Srgrimes *--------------------------------------------------------------------- 16291590Srgrimes * Parse_FromString -- 16301590Srgrimes * Start Parsing from the given string 16318874Srgrimes * 16321590Srgrimes * Results: 16331590Srgrimes * None 16341590Srgrimes * 16351590Srgrimes * Side Effects: 1636126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1637126824Sru * curFile.fname and curFile.F are altered for the new file 16381590Srgrimes *--------------------------------------------------------------------- 16391590Srgrimes */ 16401590Srgrimesvoid 1641126824SruParse_FromString(char *str, int lineno) 16421590Srgrimes{ 16431590Srgrimes 1644144026Sharti DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 16451590Srgrimes 1646144341Sharti ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); 16471590Srgrimes} 16481590Srgrimes 16491590Srgrimes#ifdef SYSVINCLUDE 16501590Srgrimes/*- 16511590Srgrimes *--------------------------------------------------------------------- 16521590Srgrimes * ParseTraditionalInclude -- 16531590Srgrimes * Push to another file. 16548874Srgrimes * 16551590Srgrimes * The input is the line minus the "include". The file name is 16561590Srgrimes * the string following the "include". 16571590Srgrimes * 16581590Srgrimes * Results: 16591590Srgrimes * None 16601590Srgrimes * 16611590Srgrimes * Side Effects: 1662126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1663126824Sru * curFile.fname and curFile.F are altered for the new file 16641590Srgrimes *--------------------------------------------------------------------- 16651590Srgrimes */ 16661590Srgrimesstatic void 1667141270ShartiParseTraditionalInclude(char *file) 16681590Srgrimes{ 1669144026Sharti char *fullname; /* full pathname of file */ 1670144026Sharti char *cp; /* current position in file spec */ 16711590Srgrimes 1672144026Sharti /* 1673144026Sharti * Skip over whitespace 1674144026Sharti */ 1675144029Sharti while (*file == ' ' || *file == '\t') { 1676144026Sharti file++; 1677144026Sharti } 16781590Srgrimes 1679144026Sharti if (*file == '\0') { 1680144026Sharti Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); 1681144026Sharti return; 1682144026Sharti } 16831590Srgrimes 1684144026Sharti /* 1685144026Sharti * Skip to end of line or next whitespace 1686144026Sharti */ 1687144026Sharti for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1688144026Sharti continue; 1689144026Sharti } 16901590Srgrimes 1691144026Sharti *cp = '\0'; 16921590Srgrimes 1693144026Sharti /* 1694144026Sharti * Substitute for any variables in the file name before trying to 1695144026Sharti * find the thing. 1696144026Sharti */ 1697144894Sharti file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE)); 16981590Srgrimes 16991590Srgrimes /* 1700144026Sharti * Now we know the file's name, we attempt to find the durn thing. 1701144026Sharti * Search for it first on the -I search path, then on the .PATH 1702144026Sharti * search path, if not found in a -I directory. 17031590Srgrimes */ 1704144026Sharti fullname = Path_FindFile(file, &parseIncPath); 1705144026Sharti if (fullname == NULL) { 1706144026Sharti fullname = Path_FindFile(file, &dirSearchPath); 1707144026Sharti } 17081590Srgrimes 1709144026Sharti if (fullname == NULL) { 1710144026Sharti /* 1711144026Sharti * Still haven't found the makefile. Look for it on the system 1712144026Sharti * path as a last resort. 1713144026Sharti */ 1714144026Sharti fullname = Path_FindFile(file, &sysIncPath); 1715144026Sharti } 17161590Srgrimes 1717144026Sharti if (fullname == NULL) { 1718144026Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1719144026Sharti /* XXXHB free(file) */ 1720144026Sharti return; 1721144026Sharti } 1722142457Sharti 1723144026Sharti /* XXXHB free(file) */ 17241590Srgrimes 1725144026Sharti /* 1726144341Sharti * We set up the name of the file to be the absolute 1727144026Sharti * name of the include file so error messages refer to the right 1728144341Sharti * place. 17291590Srgrimes */ 1730144341Sharti ParsePushInput(fullname, NULL, NULL, 0); 17311590Srgrimes} 17321590Srgrimes#endif 17331590Srgrimes 17341590Srgrimes/*- 17351590Srgrimes *--------------------------------------------------------------------- 17361590Srgrimes * ParseReadc -- 17378874Srgrimes * Read a character from the current file 17381590Srgrimes * 17391590Srgrimes * Results: 17401590Srgrimes * The character that was read 17411590Srgrimes * 17421590Srgrimes * Side Effects: 17431590Srgrimes *--------------------------------------------------------------------- 17441590Srgrimes */ 17451590Srgrimesstatic int 1746104696SjmallettParseReadc(void) 17471590Srgrimes{ 1748138232Sharti 1749144341Sharti if (CURFILE->F != NULL) 1750144341Sharti return (fgetc(CURFILE->F)); 17518874Srgrimes 1752144341Sharti if (CURFILE->str != NULL && *CURFILE->ptr != '\0') 1753144341Sharti return (*CURFILE->ptr++); 1754144341Sharti 1755144026Sharti return (EOF); 17561590Srgrimes} 17571590Srgrimes 17581590Srgrimes 17591590Srgrimes/*- 17601590Srgrimes *--------------------------------------------------------------------- 17611590Srgrimes * ParseUnreadc -- 17628874Srgrimes * Put back a character to the current file 17631590Srgrimes * 17641590Srgrimes * Results: 17651590Srgrimes * None. 17661590Srgrimes * 17671590Srgrimes * Side Effects: 17681590Srgrimes *--------------------------------------------------------------------- 17691590Srgrimes */ 17701590Srgrimesstatic void 1771104696SjmallettParseUnreadc(int c) 17721590Srgrimes{ 1773138232Sharti 1774144341Sharti if (CURFILE->F != NULL) { 1775144341Sharti ungetc(c, CURFILE->F); 1776144026Sharti return; 1777144026Sharti } 1778144341Sharti if (CURFILE->str != NULL) { 1779144341Sharti *--(CURFILE->ptr) = c; 1780144026Sharti return; 1781144026Sharti } 17821590Srgrimes} 17831590Srgrimes 17841590Srgrimes/* ParseSkipLine(): 1785104696Sjmallett * Grab the next line unless it begins with a dot (`.') and we're told to 1786104696Sjmallett * ignore such lines. 17871590Srgrimes */ 17881590Srgrimesstatic char * 1789126824SruParseSkipLine(int skip, int keep_newline) 17901590Srgrimes{ 1791144026Sharti char *line; 1792144026Sharti int c, lastc; 1793144026Sharti Buffer *buf; 17941590Srgrimes 1795144026Sharti buf = Buf_Init(MAKE_BSIZE); 17961590Srgrimes 1797144026Sharti do { 1798144026Sharti Buf_Clear(buf); 1799144026Sharti lastc = '\0'; 18008874Srgrimes 1801144026Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') 1802144026Sharti && c != EOF) { 1803144026Sharti if (skip && c == '#' && lastc != '\\') { 1804144026Sharti /* 1805144026Sharti * let a comment be terminated even by an 1806144026Sharti * escaped \n. This is consistent to comment 1807144026Sharti * handling in ParseReadLine 1808144026Sharti */ 1809144026Sharti while ((c = ParseReadc()) != '\n' && c != EOF) 1810144026Sharti ; 1811144026Sharti break; 1812144026Sharti } 1813144026Sharti if (c == '\n') { 1814144026Sharti if (keep_newline) 1815144026Sharti Buf_AddByte(buf, (Byte)c); 1816144026Sharti else 1817144026Sharti Buf_ReplaceLastByte(buf, (Byte)' '); 1818144341Sharti CURFILE->lineno++; 18198874Srgrimes 1820144026Sharti while ((c = ParseReadc()) == ' ' || c == '\t') 1821144026Sharti continue; 18228874Srgrimes 1823144026Sharti if (c == EOF) 1824144026Sharti break; 1825144026Sharti } 182674272Swill 1827144026Sharti Buf_AddByte(buf, (Byte)c); 1828144026Sharti lastc = c; 1829144026Sharti } 183018456Ssteve 1831144026Sharti if (c == EOF) { 1832144026Sharti Parse_Error(PARSE_FATAL, 1833144026Sharti "Unclosed conditional/for loop"); 1834144026Sharti Buf_Destroy(buf, TRUE); 1835144026Sharti return (NULL); 1836144026Sharti } 183718456Ssteve 1838144341Sharti CURFILE->lineno++; 1839144026Sharti Buf_AddByte(buf, (Byte)'\0'); 1840144026Sharti line = Buf_Data(buf); 1841144026Sharti } while (skip == 1 && line[0] != '.'); 184218456Ssteve 1843144026Sharti Buf_Destroy(buf, FALSE); 1844144026Sharti return (line); 18451590Srgrimes} 18461590Srgrimes 18471590Srgrimes/*- 18481590Srgrimes *--------------------------------------------------------------------- 18491590Srgrimes * ParseReadLine -- 18501590Srgrimes * Read an entire line from the input file. Called only by Parse_File. 18511590Srgrimes * To facilitate escaped newlines and what have you, a character is 18521590Srgrimes * buffered in 'lastc', which is '\0' when no characters have been 18531590Srgrimes * read. When we break out of the loop, c holds the terminating 18541590Srgrimes * character and lastc holds a character that should be added to 18551590Srgrimes * the line (unless we don't read anything but a terminator). 18561590Srgrimes * 18571590Srgrimes * Results: 18581590Srgrimes * A line w/o its newline 18591590Srgrimes * 18601590Srgrimes * Side Effects: 18611590Srgrimes * Only those associated with reading a character 18621590Srgrimes *--------------------------------------------------------------------- 18631590Srgrimes */ 18641590Srgrimesstatic char * 1865138232ShartiParseReadLine(void) 18661590Srgrimes{ 1867144026Sharti Buffer *buf; /* Buffer for current line */ 1868144026Sharti int c; /* the current character */ 1869144026Sharti int lastc; /* The most-recent character */ 1870144026Sharti Boolean semiNL; /* treat semi-colons as newlines */ 1871144026Sharti Boolean ignDepOp; /* TRUE if should ignore dependency operators 18721590Srgrimes * for the purposes of setting semiNL */ 1873144026Sharti Boolean ignComment; /* TRUE if should ignore comments (in a 18741590Srgrimes * shell command */ 1875144026Sharti char *line; /* Result */ 1876144026Sharti char *ep; /* to strip trailing blanks */ 18771590Srgrimes 1878144742Sharti again: 1879144026Sharti semiNL = FALSE; 1880144026Sharti ignDepOp = FALSE; 1881144026Sharti ignComment = FALSE; 18821590Srgrimes 1883144742Sharti lastc = '\0'; 1884144742Sharti 1885144026Sharti /* 1886144742Sharti * Handle tab at the beginning of the line. A leading tab (shell 1887144742Sharti * command) forces us to ignore comments and dependency operators and 1888144742Sharti * treat semi-colons as semi-colons (by leaving semiNL FALSE). 1889144742Sharti * This also discards completely blank lines. 1890144026Sharti */ 1891144026Sharti for (;;) { 1892144026Sharti c = ParseReadc(); 1893144742Sharti if (c == EOF) { 1894144742Sharti if (ParsePopInput() == DONE) { 1895144742Sharti /* End of all inputs - return NULL */ 1896144742Sharti return (NULL); 1897144742Sharti } 1898144742Sharti continue; 1899144742Sharti } 19001590Srgrimes 1901144026Sharti if (c == '\t') { 1902144026Sharti ignComment = ignDepOp = TRUE; 1903144742Sharti lastc = c; 1904144026Sharti break; 1905144742Sharti } 1906144742Sharti if (c != '\n') { 1907144026Sharti ParseUnreadc(c); 1908144026Sharti break; 1909144026Sharti } 1910144742Sharti CURFILE->lineno++; 19111590Srgrimes } 19128874Srgrimes 1913144742Sharti buf = Buf_Init(MAKE_BSIZE); 19148874Srgrimes 1915144742Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { 1916144026Sharti test_char: 1917144742Sharti switch (c) { 1918144742Sharti case '\n': 1919144742Sharti /* 1920144742Sharti * Escaped newline: read characters until a 1921144742Sharti * non-space or an unescaped newline and 1922144742Sharti * replace them all by a single space. This is 1923144742Sharti * done by storing the space over the backslash 1924144742Sharti * and dropping through with the next nonspace. 1925144742Sharti * If it is a semi-colon and semiNL is TRUE, 1926144742Sharti * it will be recognized as a newline in the 1927144742Sharti * code below this... 1928144742Sharti */ 1929144742Sharti CURFILE->lineno++; 1930144742Sharti lastc = ' '; 1931144742Sharti while ((c = ParseReadc()) == ' ' || c == '\t') { 1932144742Sharti continue; 1933144742Sharti } 1934144742Sharti if (c == EOF || c == '\n') { 1935144742Sharti goto line_read; 1936144742Sharti } else { 1937144026Sharti /* 1938144742Sharti * Check for comments, semiNL's, etc. -- 1939144742Sharti * easier than ParseUnreadc(c); 1940144742Sharti * continue; 1941144026Sharti */ 1942144742Sharti goto test_char; 1943144742Sharti } 1944144742Sharti /*NOTREACHED*/ 1945144742Sharti break; 1946144026Sharti 1947144742Sharti case ';': 1948144742Sharti /* 1949144742Sharti * Semi-colon: Need to see if it should be 1950144742Sharti * interpreted as a newline 1951144742Sharti */ 1952144742Sharti if (semiNL) { 1953144026Sharti /* 1954144742Sharti * To make sure the command that may 1955144742Sharti * be following this semi-colon begins 1956144742Sharti * with a tab, we push one back into the 1957144742Sharti * input stream. This will overwrite the 1958144742Sharti * semi-colon in the buffer. If there is 1959144742Sharti * no command following, this does no 1960144742Sharti * harm, since the newline remains in 1961144742Sharti * the buffer and the 1962144742Sharti * whole line is ignored. 1963144026Sharti */ 1964144742Sharti ParseUnreadc('\t'); 1965144742Sharti goto line_read; 1966144742Sharti } 1967144742Sharti break; 1968144742Sharti case '=': 1969144742Sharti if (!semiNL) { 1970144742Sharti /* 1971144742Sharti * Haven't seen a dependency operator 1972144742Sharti * before this, so this must be a 1973144742Sharti * variable assignment -- don't pay 1974144742Sharti * attention to dependency operators 1975144742Sharti * after this. 1976144742Sharti */ 1977144742Sharti ignDepOp = TRUE; 1978144742Sharti } else if (lastc == ':' || lastc == '!') { 1979144742Sharti /* 1980144742Sharti * Well, we've seen a dependency 1981144742Sharti * operator already, but it was the 1982144742Sharti * previous character, so this is really 1983144742Sharti * just an expanded variable assignment. 1984144742Sharti * Revert semi-colons to being just 1985144742Sharti * semi-colons again and ignore any more 1986144742Sharti * dependency operators. 1987144742Sharti * 1988144742Sharti * XXX: Note that a line like 1989144742Sharti * "foo : a:=b" will blow up, but who'd 1990144742Sharti * write a line like that anyway? 1991144742Sharti */ 1992144742Sharti ignDepOp = TRUE; 1993144742Sharti semiNL = FALSE; 1994144742Sharti } 1995144742Sharti break; 1996144742Sharti case '#': 1997144742Sharti if (!ignComment) { 1998144742Sharti if (lastc != '\\') { 1999144026Sharti /* 2000144742Sharti * If the character is a hash 2001144742Sharti * mark and it isn't escaped 2002144742Sharti * (or we're being compatible), 2003144742Sharti * the thing is a comment. 2004144742Sharti * Skip to the end of the line. 2005144026Sharti */ 2006144742Sharti do { 2007144742Sharti c = ParseReadc(); 2008144742Sharti } while (c != '\n' && c != EOF); 2009144026Sharti goto line_read; 2010144742Sharti } else { 2011144026Sharti /* 2012144742Sharti * Don't add the backslash. 2013144742Sharti * Just let the # get copied 2014144742Sharti * over. 2015144026Sharti */ 2016144742Sharti lastc = c; 2017144742Sharti continue; 2018144026Sharti } 2019144742Sharti } 2020144742Sharti break; 2021144026Sharti 2022144742Sharti case ':': 2023144742Sharti case '!': 2024144742Sharti if (!ignDepOp) { 2025144742Sharti /* 2026144742Sharti * A semi-colon is recognized as a 2027144742Sharti * newline only on dependency lines. 2028144742Sharti * Dependency lines are lines with a 2029144742Sharti * colon or an exclamation point. 2030144742Sharti * Ergo... 2031144742Sharti */ 2032144742Sharti semiNL = TRUE; 2033144742Sharti } 2034144742Sharti break; 2035144026Sharti 2036144742Sharti default: 2037144742Sharti break; 2038144742Sharti } 2039144742Sharti /* 2040144742Sharti * Copy in the previous character (there may be none if this 2041144742Sharti * was the first character) and save this one in 2042144742Sharti * lastc. 2043144742Sharti */ 2044144742Sharti if (lastc != '\0') 2045144026Sharti Buf_AddByte(buf, (Byte)lastc); 2046144742Sharti lastc = c; 2047144742Sharti } 2048144026Sharti line_read: 2049144742Sharti CURFILE->lineno++; 2050144026Sharti 2051144742Sharti if (lastc != '\0') { 2052144742Sharti Buf_AddByte(buf, (Byte)lastc); 2053144742Sharti } 2054144742Sharti Buf_AddByte(buf, (Byte)'\0'); 2055144742Sharti line = Buf_Peel(buf); 20561590Srgrimes 2057144742Sharti /* 2058144742Sharti * Strip trailing blanks and tabs from the line. 2059144742Sharti * Do not strip a blank or tab that is preceded by 2060144742Sharti * a '\' 2061144742Sharti */ 2062144742Sharti ep = line; 2063144742Sharti while (*ep) 2064144742Sharti ++ep; 2065144742Sharti while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2066144742Sharti if (ep > line + 1 && ep[-2] == '\\') 2067144742Sharti break; 2068144742Sharti --ep; 2069144742Sharti } 2070144742Sharti *ep = 0; 2071144742Sharti 2072144742Sharti if (line[0] == '\0') { 2073144742Sharti /* empty line - just ignore */ 2074144742Sharti free(line); 2075144742Sharti goto again; 2076144742Sharti } 2077144742Sharti 2078144742Sharti return (line); 20791590Srgrimes} 20801590Srgrimes 20811590Srgrimes/*- 20821590Srgrimes *----------------------------------------------------------------------- 20831590Srgrimes * ParseFinishLine -- 20841590Srgrimes * Handle the end of a dependency group. 20851590Srgrimes * 20861590Srgrimes * Results: 20871590Srgrimes * Nothing. 20881590Srgrimes * 20891590Srgrimes * Side Effects: 20901590Srgrimes * inLine set FALSE. 'targets' list destroyed. 20911590Srgrimes * 20921590Srgrimes *----------------------------------------------------------------------- 20931590Srgrimes */ 20941590Srgrimesstatic void 2095104696SjmallettParseFinishLine(void) 20961590Srgrimes{ 2097143372Sharti const LstNode *ln; 2098138232Sharti 2099143372Sharti if (inLine) { 2100143372Sharti LST_FOREACH(ln, &targets) { 2101143372Sharti if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) 2102143372Sharti Suff_EndTransform(Lst_Datum(ln)); 2103143372Sharti } 2104143372Sharti Lst_Destroy(&targets, ParseHasCommands); 2105143372Sharti inLine = FALSE; 2106143372Sharti } 21071590Srgrimes} 21081590Srgrimes 2109144894Sharti/** 2110144894Sharti * parse_include 2111144894Sharti * Parse an .include directive and push the file onto the input stack. 2112144894Sharti * The input is the line minus the .include. A file spec is a string 2113144894Sharti * enclosed in <> or "". The former is looked for only in sysIncPath. 2114144894Sharti * The latter in . and the directories specified by -I command line 2115144894Sharti * options 2116144894Sharti */ 2117144894Shartistatic void 2118144894Shartiparse_include(char *file, int code __unused, int lineno __unused) 2119144894Sharti{ 2120144894Sharti char *fullname; /* full pathname of file */ 2121144894Sharti char endc; /* the character which ends the file spec */ 2122144894Sharti char *cp; /* current position in file spec */ 2123144894Sharti Boolean isSystem; /* TRUE if makefile is a system makefile */ 2124144894Sharti char *prefEnd, *Fname; 2125144894Sharti char *newName; 21268874Srgrimes 2127144894Sharti /* 2128144894Sharti * Skip to delimiter character so we know where to look 2129144894Sharti */ 2130144894Sharti while (*file == ' ' || *file == '\t') { 2131144894Sharti file++; 2132144894Sharti } 2133144894Sharti 2134144894Sharti if (*file != '"' && *file != '<') { 2135144894Sharti Parse_Error(PARSE_FATAL, 2136144894Sharti ".include filename must be delimited by '\"' or '<'"); 2137144894Sharti return; 2138144894Sharti } 2139144894Sharti 2140144894Sharti /* 2141144894Sharti * Set the search path on which to find the include file based on the 2142144894Sharti * characters which bracket its name. Angle-brackets imply it's 2143144894Sharti * a system Makefile while double-quotes imply it's a user makefile 2144144894Sharti */ 2145144894Sharti if (*file == '<') { 2146144894Sharti isSystem = TRUE; 2147144894Sharti endc = '>'; 2148144894Sharti } else { 2149144894Sharti isSystem = FALSE; 2150144894Sharti endc = '"'; 2151144894Sharti } 2152144894Sharti 2153144894Sharti /* 2154144894Sharti * Skip to matching delimiter 2155144894Sharti */ 2156144894Sharti for (cp = ++file; *cp != endc; cp++) { 2157144894Sharti if (*cp == '\0') { 2158144894Sharti Parse_Error(PARSE_FATAL, 2159144894Sharti "Unclosed .include filename. '%c' expected", endc); 2160144894Sharti return; 2161144894Sharti } 2162144894Sharti } 2163144894Sharti *cp = '\0'; 2164144894Sharti 2165144894Sharti /* 2166144894Sharti * Substitute for any variables in the file name before trying to 2167144894Sharti * find the thing. 2168144894Sharti */ 2169144894Sharti file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE)); 2170144894Sharti 2171144894Sharti /* 2172144894Sharti * Now we know the file's name and its search path, we attempt to 2173144894Sharti * find the durn thing. A return of NULL indicates the file don't 2174144894Sharti * exist. 2175144894Sharti */ 2176144894Sharti if (!isSystem) { 2177144894Sharti /* 2178144894Sharti * Include files contained in double-quotes are first searched 2179144894Sharti * for relative to the including file's location. We don't want 2180144894Sharti * to cd there, of course, so we just tack on the old file's 2181144894Sharti * leading path components and call Dir_FindFile to see if 2182144894Sharti * we can locate the beast. 2183144894Sharti */ 2184144894Sharti 2185144894Sharti /* Make a temporary copy of this, to be safe. */ 2186144894Sharti Fname = estrdup(CURFILE->fname); 2187144894Sharti 2188144894Sharti prefEnd = strrchr(Fname, '/'); 2189144894Sharti if (prefEnd != NULL) { 2190144894Sharti *prefEnd = '\0'; 2191144894Sharti if (file[0] == '/') 2192144894Sharti newName = estrdup(file); 2193144894Sharti else 2194144894Sharti newName = str_concat(Fname, file, STR_ADDSLASH); 2195144894Sharti fullname = Path_FindFile(newName, &parseIncPath); 2196144894Sharti if (fullname == NULL) { 2197144894Sharti fullname = Path_FindFile(newName, 2198144894Sharti &dirSearchPath); 2199144894Sharti } 2200144894Sharti free(newName); 2201144894Sharti *prefEnd = '/'; 2202144894Sharti } else { 2203144894Sharti fullname = NULL; 2204144894Sharti } 2205144894Sharti free(Fname); 2206144894Sharti } else { 2207144894Sharti fullname = NULL; 2208144894Sharti } 2209144894Sharti 2210144894Sharti if (fullname == NULL) { 2211144894Sharti /* 2212144894Sharti * System makefile or makefile wasn't found in same directory as 2213144894Sharti * included makefile. Search for it first on the -I search path, 2214144894Sharti * then on the .PATH search path, if not found in a -I 2215144894Sharti * directory. 2216144894Sharti * XXX: Suffix specific? 2217144894Sharti */ 2218144894Sharti fullname = Path_FindFile(file, &parseIncPath); 2219144894Sharti if (fullname == NULL) { 2220144894Sharti fullname = Path_FindFile(file, &dirSearchPath); 2221144894Sharti } 2222144894Sharti } 2223144894Sharti 2224144894Sharti if (fullname == NULL) { 2225144894Sharti /* 2226144894Sharti * Still haven't found the makefile. Look for it on the system 2227144894Sharti * path as a last resort. 2228144894Sharti */ 2229144894Sharti fullname = Path_FindFile(file, &sysIncPath); 2230144894Sharti } 2231144894Sharti 2232144894Sharti if (fullname == NULL) { 2233144894Sharti *cp = endc; 2234144894Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 2235144894Sharti free(file); 2236144894Sharti return; 2237144894Sharti } 2238144894Sharti free(file); 2239144894Sharti 2240144894Sharti /* 2241144894Sharti * We set up the name of the file to be the absolute 2242144894Sharti * name of the include file so error messages refer to the right 2243144894Sharti * place. 2244144894Sharti */ 2245144894Sharti ParsePushInput(fullname, NULL, NULL, 0); 2246144894Sharti} 2247144894Sharti 2248144894Sharti/** 2249144894Sharti * parse_message 2250144894Sharti * Parse a .warning or .error directive 2251144894Sharti * 2252144894Sharti * The input is the line minus the ".error"/".warning". We substitute 2253144894Sharti * variables, print the message and exit(1) (for .error) or just print 2254144894Sharti * a warning if the directive is malformed. 2255144894Sharti */ 2256144894Shartistatic void 2257144894Shartiparse_message(char *line, int iserror, int lineno __unused) 2258144894Sharti{ 2259144894Sharti 2260144894Sharti if (!isspace((u_char)*line)) { 2261144894Sharti Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s", 2262144894Sharti iserror ? "error" : "warning", line); 2263144894Sharti return; 2264144894Sharti } 2265144894Sharti 2266144894Sharti while (isspace((u_char)*line)) 2267144894Sharti line++; 2268144894Sharti 2269144894Sharti line = Buf_Peel(Var_Subst(NULL, line, VAR_GLOBAL, FALSE)); 2270144894Sharti Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); 2271144894Sharti free(line); 2272144894Sharti 2273144894Sharti if (iserror) { 2274144894Sharti /* Terminate immediately. */ 2275144894Sharti exit(1); 2276144894Sharti } 2277144894Sharti} 2278144894Sharti 2279144894Sharti/** 2280144894Sharti * parse_undef 2281144894Sharti * Parse an .undef directive. 2282144894Sharti */ 2283144894Shartistatic void 2284144894Shartiparse_undef(char *line, int code __unused, int lineno __unused) 2285144894Sharti{ 2286144894Sharti char *cp; 2287144894Sharti 2288144894Sharti while (isspace((u_char)*line)) 2289144894Sharti line++; 2290144894Sharti 2291144894Sharti for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) { 2292144894Sharti ; 2293144894Sharti } 2294144894Sharti *cp = '\0'; 2295144894Sharti 2296144894Sharti cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, FALSE)); 2297144894Sharti Var_Delete(cp, VAR_GLOBAL); 2298144894Sharti free(cp); 2299144894Sharti} 2300144894Sharti 2301144894Sharti/** 2302144894Sharti * parse_for 2303144894Sharti * Parse a .for directive. 2304144894Sharti */ 2305144894Shartistatic void 2306144894Shartiparse_for(char *line, int code __unused, int lineno) 2307144894Sharti{ 2308144894Sharti 2309144894Sharti if (!For_For(line)) { 2310144894Sharti /* syntax error */ 2311144894Sharti return; 2312144894Sharti } 2313144894Sharti line = NULL; 2314144894Sharti 2315144894Sharti /* 2316144894Sharti * Skip after the matching endfor. 2317144894Sharti */ 2318144894Sharti do { 2319144894Sharti free(line); 2320144894Sharti line = ParseSkipLine(0, 1); 2321144894Sharti if (line == NULL) { 2322144894Sharti Parse_Error(PARSE_FATAL, 2323144894Sharti "Unexpected end of file in for loop.\n"); 2324144894Sharti return; 2325144894Sharti } 2326144894Sharti } while (For_Eval(line)); 2327144894Sharti free(line); 2328144894Sharti 2329144894Sharti /* execute */ 2330144894Sharti For_Run(lineno); 2331144894Sharti} 2332144894Sharti 2333144894Sharti/** 2334144894Sharti * parse_endfor 2335144894Sharti * Parse endfor. This may only happen if there was no matching .for. 2336144894Sharti */ 2337144894Shartistatic void 2338144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused) 2339144894Sharti{ 2340144894Sharti 2341144894Sharti Parse_Error(PARSE_FATAL, "for-less endfor"); 2342144894Sharti} 2343144894Sharti 2344144894Sharti/** 2345144894Sharti * directive_hash 2346144894Sharti */ 2347144894Shartistatic int 2348144894Shartidirective_hash(const u_char *key, size_t len) 2349144894Sharti{ 2350144894Sharti unsigned f0, f1; 2351144894Sharti const u_char *kp = key; 2352144894Sharti 2353144894Sharti if (len < 2 || len > 9) 2354144894Sharti return (-1); 2355144894Sharti 2356144894Sharti for (f0 = f1 = 0; kp < key + len; ++kp) { 2357144894Sharti if (*kp < 97 || *kp > 119) 2358144894Sharti return (-1); 2359144894Sharti f0 += directive_T0[-97 + *kp]; 2360144894Sharti f1 += directive_T1[-97 + *kp]; 2361144894Sharti } 2362144894Sharti 2363144894Sharti f0 %= 38; 2364144894Sharti f1 %= 38; 2365144894Sharti 2366144894Sharti return (directive_g[f0] + directive_g[f1]) % 18; 2367144894Sharti} 2368144894Sharti 2369144894Sharti/** 2370144894Sharti * parse_directive 2371144894Sharti * Got a line starting with a '.'. Check if this is a directive 2372144894Sharti * and parse it. 2373144894Sharti * 2374144894Sharti * return: 2375144894Sharti * TRUE if line was a directive, FALSE otherwise. 2376144894Sharti */ 2377144894Shartistatic Boolean 2378144894Shartiparse_directive(char *line) 2379144894Sharti{ 2380144894Sharti char *start; 2381144894Sharti char *cp; 2382144894Sharti int dir; 2383144894Sharti 2384144894Sharti /* 2385144894Sharti * Get the keyword: 2386144894Sharti * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).* 2387144894Sharti * \1 is the keyword. 2388144894Sharti */ 2389144894Sharti for (start = line; isspace((u_char)*start); start++) { 2390144894Sharti ; 2391144894Sharti } 2392144894Sharti 2393144894Sharti if (!isalpha((u_char)*start)) { 2394144894Sharti return (FALSE); 2395144894Sharti } 2396144894Sharti 2397144894Sharti cp = start + 1; 2398144894Sharti while (isalnum((u_char)*cp) || *cp == '_') { 2399144894Sharti cp++; 2400144894Sharti } 2401144894Sharti 2402144894Sharti dir = directive_hash(start, cp - start); 2403144894Sharti if (dir < 0 || dir >= (int)NDIRECTS || 2404144894Sharti (size_t)(cp - start) != strlen(directives[dir].name) || 2405144894Sharti strncmp(start, directives[dir].name, cp - start) != 0) { 2406144894Sharti /* not actually matched */ 2407144894Sharti return (FALSE); 2408144894Sharti } 2409144894Sharti 2410144894Sharti if (!skipLine || directives[dir].skip_flag) 2411144894Sharti (*directives[dir].func)(cp, directives[dir].code, 2412144894Sharti CURFILE->lineno); 2413144894Sharti return (TRUE); 2414144894Sharti} 2415144894Sharti 24161590Srgrimes/*- 24171590Srgrimes *--------------------------------------------------------------------- 24181590Srgrimes * Parse_File -- 24191590Srgrimes * Parse a file into its component parts, incorporating it into the 24201590Srgrimes * current dependency graph. This is the main function and controls 24211590Srgrimes * almost every other function in this module 24221590Srgrimes * 24231590Srgrimes * Results: 24241590Srgrimes * None 24251590Srgrimes * 24261590Srgrimes * Side Effects: 24271590Srgrimes * Loads. Nodes are added to the list of all targets, nodes and links 24281590Srgrimes * are added to the dependency graph. etc. etc. etc. 24291590Srgrimes *--------------------------------------------------------------------- 24301590Srgrimes */ 24311590Srgrimesvoid 2432144341ShartiParse_File(const char *name, FILE *stream) 24331590Srgrimes{ 2434144026Sharti char *cp; /* pointer into the line */ 2435144026Sharti char *line; /* the line we're working on */ 24361590Srgrimes 2437144026Sharti inLine = FALSE; 2438144026Sharti fatals = 0; 24391590Srgrimes 2440144341Sharti ParsePushInput(estrdup(name), stream, NULL, 0); 2441131456Seik 2442144742Sharti while ((line = ParseReadLine()) != NULL) { 2443144894Sharti if (*line == '.' && parse_directive(line + 1)) { 2444144894Sharti /* directive consumed */ 2445144894Sharti goto nextLine; 2446144742Sharti } 2447144894Sharti if (skipLine || *line == '#') { 2448144894Sharti /* Skipping .if block or comment. */ 2449144742Sharti goto nextLine; 2450144742Sharti } 24518874Srgrimes 2452144742Sharti if (*line == '\t') { 2453144742Sharti /* 2454144742Sharti * If a line starts with a tab, it can only 2455144742Sharti * hope to be a creation command. 2456144742Sharti */ 2457144742Sharti for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 2458144742Sharti continue; 2459144742Sharti } 2460144742Sharti if (*cp) { 2461144742Sharti if (inLine) { 2462144742Sharti LstNode *ln; 2463144742Sharti GNode *gn; 2464143684Sharti 2465144742Sharti /* 2466144742Sharti * So long as it's not a blank 2467144742Sharti * line and we're actually in a 2468144742Sharti * dependency spec, add the 2469144742Sharti * command to the list of 2470144742Sharti * commands of all targets in 2471144742Sharti * the dependency spec. 2472144742Sharti */ 2473144742Sharti LST_FOREACH(ln, &targets) { 2474144742Sharti gn = Lst_Datum(ln); 2475144742Sharti 2476144026Sharti /* 2477144742Sharti * if target already 2478144742Sharti * supplied, ignore 2479144742Sharti * commands 2480144026Sharti */ 2481144742Sharti if (!(gn->type & OP_HAS_COMMANDS)) 2482144742Sharti Lst_AtEnd(&gn->commands, cp); 2483144742Sharti else 2484144742Sharti Parse_Error(PARSE_WARNING, "duplicate script " 2485144742Sharti "for target \"%s\" ignored", gn->name); 2486144026Sharti } 2487144742Sharti continue; 2488144742Sharti } else { 2489144742Sharti Parse_Error(PARSE_FATAL, 2490144742Sharti "Unassociated shell command \"%s\"", 2491144742Sharti cp); 2492144026Sharti } 2493144742Sharti } 24941590Srgrimes#ifdef SYSVINCLUDE 2495144742Sharti } else if (strncmp(line, "include", 7) == 0 && 2496144742Sharti isspace((unsigned char)line[7]) && 2497144742Sharti strchr(line, ':') == NULL) { 2498144742Sharti /* 2499144742Sharti * It's an S3/S5-style "include". 2500144742Sharti */ 2501144742Sharti ParseTraditionalInclude(line + 7); 2502144742Sharti goto nextLine; 25031590Srgrimes#endif 2504144742Sharti } else if (Parse_IsVar(line)) { 2505144742Sharti ParseFinishLine(); 2506144742Sharti Parse_DoVar(line, VAR_GLOBAL); 25078874Srgrimes 2508144742Sharti } else { 2509144742Sharti /* 2510144742Sharti * We now know it's a dependency line so it 2511144742Sharti * needs to have all variables expanded before 2512144742Sharti * being parsed. Tell the variable module to 2513144742Sharti * complain if some variable is undefined... 2514144742Sharti * To make life easier on novices, if the line 2515144742Sharti * is indented we first make sure the line has 2516144742Sharti * a dependency operator in it. If it doesn't 2517144742Sharti * have an operator and we're in a dependency 2518144742Sharti * line's script, we assume it's actually a 2519144742Sharti * shell command and add it to the current 2520144894Sharti * list of targets. XXX this comment seems wrong. 2521144742Sharti */ 2522144742Sharti cp = line; 2523144742Sharti if (isspace((unsigned char)line[0])) { 2524144742Sharti while (*cp != '\0' && 2525144742Sharti isspace((unsigned char)*cp)) { 2526144742Sharti cp++; 2527144026Sharti } 2528144742Sharti if (*cp == '\0') { 2529144742Sharti goto nextLine; 2530144742Sharti } 2531144742Sharti } 25321590Srgrimes 2533144742Sharti ParseFinishLine(); 2534142457Sharti 2535144894Sharti cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, TRUE)); 25368874Srgrimes 2537144742Sharti free(line); 2538144742Sharti line = cp; 2539144026Sharti 2540144742Sharti /* 2541144742Sharti * Need a non-circular list for the target nodes 2542144742Sharti */ 2543144742Sharti Lst_Destroy(&targets, NOFREE); 2544144742Sharti inLine = TRUE; 2545144026Sharti 2546144742Sharti ParseDoDependency(line); 2547144026Sharti } 2548144026Sharti 2549144742Sharti nextLine: 2550144742Sharti free(line); 2551144742Sharti } 25528874Srgrimes 2553144026Sharti ParseFinishLine(); 25541590Srgrimes 25551590Srgrimes /* 2556144026Sharti * Make sure conditionals are clean 25571590Srgrimes */ 2558144026Sharti Cond_End(); 25591590Srgrimes 2560144026Sharti if (fatals) 2561144026Sharti errx(1, "fatal errors encountered -- cannot continue"); 25621590Srgrimes} 25631590Srgrimes 25641590Srgrimes/*- 25651590Srgrimes *----------------------------------------------------------------------- 25661590Srgrimes * Parse_MainName -- 25671590Srgrimes * Return a Lst of the main target to create for main()'s sake. If 25681590Srgrimes * no such target exists, we Punt with an obnoxious error message. 25691590Srgrimes * 25701590Srgrimes * Results: 25711590Srgrimes * A Lst of the single node to create. 25721590Srgrimes * 25731590Srgrimes * Side Effects: 25741590Srgrimes * None. 25751590Srgrimes * 25761590Srgrimes *----------------------------------------------------------------------- 25771590Srgrimes */ 2578138916Shartivoid 2579138916ShartiParse_MainName(Lst *listmain) 25801590Srgrimes{ 25811590Srgrimes 2582144026Sharti if (mainNode == NULL) { 2583144026Sharti Punt("no target to make."); 2584144026Sharti /*NOTREACHED*/ 2585144026Sharti } else if (mainNode->type & OP_DOUBLEDEP) { 2586144026Sharti Lst_AtEnd(listmain, mainNode); 2587144026Sharti Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 2588144026Sharti } else 2589144026Sharti Lst_AtEnd(listmain, mainNode); 25901590Srgrimes} 2591