parse.c revision 150595
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 150595 2005-09-26 20:31:00Z phk $"); 431590Srgrimes 441590Srgrimes/*- 451590Srgrimes * parse.c -- 461590Srgrimes * Functions to parse a makefile. 471590Srgrimes * 481590Srgrimes * Most important structures are kept in Lsts. Directories for 491590Srgrimes * the #include "..." function are kept in the 'parseIncPath' Lst, while 501590Srgrimes * those for the #include <...> are kept in the 'sysIncPath' Lst. The 511590Srgrimes * targets currently being defined are kept in the 'targets' Lst. 521590Srgrimes * 531590Srgrimes * Interface: 541590Srgrimes * 55144026Sharti * Parse_File Function used to parse a makefile. It must 56144026Sharti * be given the name of the file, which should 57144026Sharti * already have been opened, and a function 58144026Sharti * to call to read a character from the file. 591590Srgrimes * 60144026Sharti * Parse_IsVar Returns TRUE if the given line is a 61144026Sharti * variable assignment. Used by MainParseArgs 62144026Sharti * to determine if an argument is a target 63144026Sharti * or a variable assignment. Used internally 64144026Sharti * for pretty much the same thing... 651590Srgrimes * 66144026Sharti * Parse_Error Function called when an error occurs in 67144026Sharti * parsing. Used by the variable and 68144026Sharti * conditional modules. 69144026Sharti * 70144026Sharti * Parse_MainName Returns a Lst of the main target to create. 711590Srgrimes */ 721590Srgrimes 73144341Sharti#include <assert.h> 74141104Sharti#include <ctype.h> 751590Srgrimes#include <stdarg.h> 76141104Sharti#include <string.h> 77141104Sharti#include <stdlib.h> 7827644Scharnier#include <err.h> 79141104Sharti 80141104Sharti#include "arch.h" 81141104Sharti#include "buf.h" 82141104Sharti#include "cond.h" 83141104Sharti#include "config.h" 841590Srgrimes#include "dir.h" 85141104Sharti#include "for.h" 86141104Sharti#include "globals.h" 87141104Sharti#include "GNode.h" 88145683Sharti#include "hash_tables.h" 891590Srgrimes#include "job.h" 90141104Sharti#include "make.h" 91141104Sharti#include "parse.h" 921590Srgrimes#include "pathnames.h" 93146572Sharti#include "shell.h" 94141104Sharti#include "str.h" 95141104Sharti#include "suff.h" 96141104Sharti#include "targ.h" 97141104Sharti#include "util.h" 98141104Sharti#include "var.h" 991590Srgrimes 1001590Srgrimes/* 101144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to 1021590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file, 1031590Srgrimes * or if it's DONE. 1041590Srgrimes */ 1051590Srgrimes#define CONTINUE 1 1061590Srgrimes#define DONE 0 107138916Sharti 108138916Sharti/* targets we're working on */ 109138916Shartistatic Lst targets = Lst_Initializer(targets); 110138916Sharti 111144026Sharti/* true if currently in a dependency line or its commands */ 112144026Shartistatic Boolean inLine; 1131590Srgrimes 114144026Shartistatic int fatals = 0; 1151590Srgrimes 116144026Sharti/* 117144026Sharti * The main target to create. This is the first target on the 118144026Sharti * first dependency line in the first makefile. 119144026Sharti */ 120144026Shartistatic GNode *mainNode; 121126824Sru 122144341Sharti/* 123144341Sharti * Definitions for handling #include specifications 124144341Sharti */ 125144341Shartistruct IFile { 126144341Sharti char *fname; /* name of previous file */ 127144341Sharti int lineno; /* saved line number */ 128144341Sharti FILE *F; /* the open stream */ 129144341Sharti char *str; /* the string when parsing a string */ 130144341Sharti char *ptr; /* the current pointer when parsing a string */ 131144341Sharti TAILQ_ENTRY(IFile) link;/* stack the files */ 132144341Sharti}; 133144026Sharti 134138916Sharti/* stack of IFiles generated by * #includes */ 135144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); 1361590Srgrimes 137144341Sharti/* access current file */ 138144341Sharti#define CURFILE (TAILQ_FIRST(&includes)) 139144341Sharti 140138916Sharti/* list of directories for "..." includes */ 141144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); 142138916Sharti 143138916Sharti/* list of directories for <...> includes */ 144144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); 145138916Sharti 146144026Sharti/* 1471590Srgrimes * specType contains the SPECial TYPE of the current target. It is 1481590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children 1491590Srgrimes * are linked as children of the parent but not vice versa. This variable is 1501590Srgrimes * set in ParseDoDependency 1511590Srgrimes */ 1521590Srgrimestypedef enum { 153144026Sharti Begin, /* .BEGIN */ 154144026Sharti Default, /* .DEFAULT */ 155144026Sharti End, /* .END */ 156145971Sharti ExportVar, /* .EXPORTVAR */ 157144026Sharti Ignore, /* .IGNORE */ 158144026Sharti Includes, /* .INCLUDES */ 159144026Sharti Interrupt, /* .INTERRUPT */ 160144026Sharti Libs, /* .LIBS */ 161144026Sharti MFlags, /* .MFLAGS or .MAKEFLAGS */ 162144026Sharti Main, /* .MAIN and we don't have anyth. user-spec. to make */ 163144026Sharti Not, /* Not special */ 164144026Sharti NotParallel, /* .NOTPARALELL */ 165144026Sharti Null, /* .NULL */ 166144026Sharti Order, /* .ORDER */ 167144026Sharti Parallel, /* .PARALLEL */ 168144026Sharti ExPath, /* .PATH */ 169144026Sharti Phony, /* .PHONY */ 170144026Sharti Posix, /* .POSIX */ 171144026Sharti Precious, /* .PRECIOUS */ 172144026Sharti ExShell, /* .SHELL */ 173144026Sharti Silent, /* .SILENT */ 174144026Sharti SingleShell, /* .SINGLESHELL */ 175144026Sharti Suffixes, /* .SUFFIXES */ 176144026Sharti Wait, /* .WAIT */ 177145679Sharti Warn, /* .WARN */ 178144026Sharti Attribute /* Generic attribute */ 1791590Srgrimes} ParseSpecial; 1801590Srgrimes 1811590Srgrimesstatic ParseSpecial specType; 18218730Sstevestatic int waiting; 1831590Srgrimes 1841590Srgrimes/* 18569527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 1861590Srgrimes * seen, then set to each successive source on the line. 1871590Srgrimes */ 188144026Shartistatic GNode *predecessor; 1891590Srgrimes 1901590Srgrimes/* 1911590Srgrimes * The parseKeywords table is searched using binary search when deciding 1921590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial 1931590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while 1941590Srgrimes * the 'op' field is the operator to apply to the list of targets if the 1951590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source) 1961590Srgrimes */ 197145616Shartistatic const struct keyword { 198144026Sharti const char *name; /* Name of keyword */ 199144026Sharti ParseSpecial spec; /* Type when used as a target */ 200144026Sharti int op; /* Operator when used as a source */ 2011590Srgrimes} parseKeywords[] = { 202145616Sharti /* KEYWORD-START-TAG */ 203144026Sharti { ".BEGIN", Begin, 0 }, 204144026Sharti { ".DEFAULT", Default, 0 }, 205144026Sharti { ".END", End, 0 }, 206144026Sharti { ".EXEC", Attribute, OP_EXEC }, 207145971Sharti { ".EXPORTVAR", ExportVar, 0 }, 208144026Sharti { ".IGNORE", Ignore, OP_IGNORE }, 209144026Sharti { ".INCLUDES", Includes, 0 }, 210144026Sharti { ".INTERRUPT", Interrupt, 0 }, 211144026Sharti { ".INVISIBLE", Attribute, OP_INVISIBLE }, 212144026Sharti { ".JOIN", Attribute, OP_JOIN }, 213144026Sharti { ".LIBS", Libs, 0 }, 214144026Sharti { ".MAIN", Main, 0 }, 215144026Sharti { ".MAKE", Attribute, OP_MAKE }, 216144026Sharti { ".MAKEFLAGS", MFlags, 0 }, 217144026Sharti { ".MFLAGS", MFlags, 0 }, 218144026Sharti { ".NOTMAIN", Attribute, OP_NOTMAIN }, 219144026Sharti { ".NOTPARALLEL", NotParallel, 0 }, 220144026Sharti { ".NO_PARALLEL", NotParallel, 0 }, 221144026Sharti { ".NULL", Null, 0 }, 222144026Sharti { ".OPTIONAL", Attribute, OP_OPTIONAL }, 223144026Sharti { ".ORDER", Order, 0 }, 224144026Sharti { ".PARALLEL", Parallel, 0 }, 225144026Sharti { ".PATH", ExPath, 0 }, 226144026Sharti { ".PHONY", Phony, OP_PHONY }, 227144026Sharti { ".POSIX", Posix, 0 }, 228144026Sharti { ".PRECIOUS", Precious, OP_PRECIOUS }, 229144026Sharti { ".RECURSIVE", Attribute, OP_MAKE }, 230144026Sharti { ".SHELL", ExShell, 0 }, 231144026Sharti { ".SILENT", Silent, OP_SILENT }, 232144026Sharti { ".SINGLESHELL", SingleShell, 0 }, 233144026Sharti { ".SUFFIXES", Suffixes, 0 }, 234144026Sharti { ".USE", Attribute, OP_USE }, 235144026Sharti { ".WAIT", Wait, 0 }, 236145679Sharti { ".WARN", Warn, 0 }, 237145616Sharti /* KEYWORD-END-TAG */ 2381590Srgrimes}; 239145616Sharti#define NKEYWORDS (sizeof(parseKeywords) / sizeof(parseKeywords[0])) 2401590Srgrimes 241144894Shartistatic void parse_include(char *, int, int); 242150595Sphkstatic void parse_sinclude(char *, int, int); 243144894Shartistatic void parse_message(char *, int, int); 244144894Shartistatic void parse_undef(char *, int, int); 245144894Shartistatic void parse_for(char *, int, int); 246144894Shartistatic void parse_endfor(char *, int, int); 247144894Sharti 248144894Shartistatic const struct directive { 249144894Sharti const char *name; 250144894Sharti int code; 251144894Sharti Boolean skip_flag; /* execute even when skipped */ 252144894Sharti void (*func)(char *, int, int); 253144894Sharti} directives[] = { 254145612Sharti /* DIRECTIVES-START-TAG */ 255144894Sharti { "elif", COND_ELIF, TRUE, Cond_If }, 256144894Sharti { "elifdef", COND_ELIFDEF, TRUE, Cond_If }, 257144894Sharti { "elifmake", COND_ELIFMAKE, TRUE, Cond_If }, 258144894Sharti { "elifndef", COND_ELIFNDEF, TRUE, Cond_If }, 259144894Sharti { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If }, 260144894Sharti { "else", COND_ELSE, TRUE, Cond_Else }, 261144894Sharti { "endfor", 0, FALSE, parse_endfor }, 262144894Sharti { "endif", COND_ENDIF, TRUE, Cond_Endif }, 263144894Sharti { "error", 1, FALSE, parse_message }, 264144894Sharti { "for", 0, FALSE, parse_for }, 265144894Sharti { "if", COND_IF, TRUE, Cond_If }, 266144894Sharti { "ifdef", COND_IFDEF, TRUE, Cond_If }, 267144894Sharti { "ifmake", COND_IFMAKE, TRUE, Cond_If }, 268144894Sharti { "ifndef", COND_IFNDEF, TRUE, Cond_If }, 269144894Sharti { "ifnmake", COND_IFNMAKE, TRUE, Cond_If }, 270144894Sharti { "include", 0, FALSE, parse_include }, 271150595Sphk { "sinclude", 0, FALSE, parse_sinclude }, 272144894Sharti { "undef", 0, FALSE, parse_undef }, 273144894Sharti { "warning", 0, FALSE, parse_message }, 274145612Sharti /* DIRECTIVES-END-TAG */ 275144894Sharti}; 276144894Sharti#define NDIRECTS (sizeof(directives) / sizeof(directives[0])) 277144894Sharti 2781590Srgrimes/*- 279145616Sharti * ParseFindKeyword 2801590Srgrimes * Look in the table of keywords for one matching the given string. 2811590Srgrimes * 2821590Srgrimes * Results: 283145616Sharti * The pointer to keyword table entry or NULL. 2841590Srgrimes */ 285145616Shartistatic const struct keyword * 286145616ShartiParseFindKeyword(const char *str) 2871590Srgrimes{ 288145616Sharti int kw; 2898874Srgrimes 290145616Sharti kw = keyword_hash(str, strlen(str)); 291145616Sharti if (kw < 0 || kw >= (int)NKEYWORDS || 292145616Sharti strcmp(str, parseKeywords[kw].name) != 0) 293145616Sharti return (NULL); 294145616Sharti return (&parseKeywords[kw]); 2951590Srgrimes} 2961590Srgrimes 2971590Srgrimes/*- 2981590Srgrimes * Parse_Error -- 2991590Srgrimes * Error message abort function for parsing. Prints out the context 3001590Srgrimes * of the error (line number and file) as well as the message with 3011590Srgrimes * two optional arguments. 3021590Srgrimes * 3031590Srgrimes * Results: 3041590Srgrimes * None 3051590Srgrimes * 3061590Srgrimes * Side Effects: 3071590Srgrimes * "fatals" is incremented if the level is PARSE_FATAL. 3081590Srgrimes */ 3091590Srgrimes/* VARARGS */ 3101590Srgrimesvoid 31198136SjmallettParse_Error(int type, const char *fmt, ...) 3121590Srgrimes{ 3131590Srgrimes va_list ap; 31493056Simp 3151590Srgrimes va_start(ap, fmt); 316144745Sharti if (CURFILE != NULL) 317144745Sharti fprintf(stderr, "\"%s\", line %d: ", 318144745Sharti CURFILE->fname, CURFILE->lineno); 3191590Srgrimes if (type == PARSE_WARNING) 320138232Sharti fprintf(stderr, "warning: "); 321138232Sharti vfprintf(stderr, fmt, ap); 3221590Srgrimes va_end(ap); 323138232Sharti fprintf(stderr, "\n"); 324138232Sharti fflush(stderr); 3251590Srgrimes if (type == PARSE_FATAL) 3261590Srgrimes fatals += 1; 3271590Srgrimes} 3281590Srgrimes 329144341Sharti/** 330144341Sharti * ParsePushInput 331144341Sharti * 332144341Sharti * Push a new input source onto the input stack. If ptr is NULL 333144341Sharti * the fullname is used to fopen the file. If it is not NULL, 334144341Sharti * ptr is assumed to point to the string to be parsed. If opening the 335144341Sharti * file fails, the fullname is freed. 336144341Sharti */ 337144341Shartistatic void 338144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) 339144341Sharti{ 340144341Sharti struct IFile *nf; 341144341Sharti 342144341Sharti nf = emalloc(sizeof(*nf)); 343144341Sharti nf->fname = fullname; 344144341Sharti nf->lineno = lineno; 345144341Sharti 346144341Sharti if (ptr == NULL) { 347144341Sharti /* the input source is a file */ 348144341Sharti if ((nf->F = fp) == NULL) { 349144341Sharti nf->F = fopen(fullname, "r"); 350144341Sharti if (nf->F == NULL) { 351144341Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", 352144341Sharti fullname); 353144341Sharti free(fullname); 354144341Sharti free(nf); 355144341Sharti return; 356144341Sharti } 357144341Sharti } 358144341Sharti nf->str = nf->ptr = NULL; 359144341Sharti Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 360144341Sharti } else { 361144341Sharti nf->str = nf->ptr = ptr; 362144341Sharti nf->F = NULL; 363144341Sharti } 364144341Sharti TAILQ_INSERT_HEAD(&includes, nf, link); 365144341Sharti} 366144341Sharti 367144341Sharti/** 368144341Sharti * ParsePopInput 369144341Sharti * Called when EOF is reached in the current file. If we were reading 370144341Sharti * an include file, the includes stack is popped and things set up 371144341Sharti * to go back to reading the previous file at the previous location. 372144341Sharti * 373144341Sharti * Results: 374144341Sharti * CONTINUE if there's more to do. DONE if not. 375144341Sharti * 376144341Sharti * Side Effects: 377144341Sharti * The old curFile.F is closed. The includes list is shortened. 378144341Sharti * curFile.lineno, curFile.F, and curFile.fname are changed if 379144341Sharti * CONTINUE is returned. 380144341Sharti */ 381144341Shartistatic int 382144341ShartiParsePopInput(void) 383144341Sharti{ 384144341Sharti struct IFile *ifile; /* the state on the top of the includes stack */ 385144341Sharti 386144341Sharti assert(!TAILQ_EMPTY(&includes)); 387144341Sharti 388144341Sharti ifile = TAILQ_FIRST(&includes); 389144341Sharti TAILQ_REMOVE(&includes, ifile, link); 390144341Sharti 391144341Sharti free(ifile->fname); 392144341Sharti if (ifile->F != NULL) { 393144341Sharti fclose(ifile->F); 394144341Sharti Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 395144341Sharti } 396144341Sharti if (ifile->str != NULL) { 397144341Sharti free(ifile->str); 398144341Sharti } 399144341Sharti free(ifile); 400144341Sharti 401144341Sharti return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); 402144341Sharti} 403144341Sharti 404145679Sharti/** 405145679Sharti * parse_warn 406145679Sharti * Parse the .WARN pseudo-target. 407145679Sharti */ 408145679Shartistatic void 409145679Shartiparse_warn(char *line) 410145679Sharti{ 411146345Sharti ArgArray aa; 412146345Sharti int i; 413145679Sharti 414146345Sharti brk_string(&aa, line, TRUE); 415145679Sharti 416146345Sharti for (i = 1; i < aa.argc; i++) 417146345Sharti Main_ParseWarn(aa.argv[i], 0); 418145679Sharti} 419145679Sharti 4201590Srgrimes/*- 4211590Srgrimes *--------------------------------------------------------------------- 4221590Srgrimes * ParseLinkSrc -- 423143100Sharti * Link the parent nodes to their new child. Used by 4241590Srgrimes * ParseDoDependency. If the specType isn't 'Not', the parent 4251590Srgrimes * isn't linked as a parent of the child. 4261590Srgrimes * 4271590Srgrimes * Side Effects: 428143100Sharti * New elements are added to the parents lists of cgn and the 4291590Srgrimes * children list of cgn. the unmade field of pgn is updated 4301590Srgrimes * to reflect the additional child. 4311590Srgrimes *--------------------------------------------------------------------- 4321590Srgrimes */ 433143027Shartistatic void 434143027ShartiParseLinkSrc(Lst *parents, GNode *cgn) 4351590Srgrimes{ 436143027Sharti LstNode *ln; 437143027Sharti GNode *pgn; 438138232Sharti 439143027Sharti LST_FOREACH(ln, parents) { 440143027Sharti pgn = Lst_Datum(ln); 441143027Sharti if (Lst_Member(&pgn->children, cgn) == NULL) { 442143027Sharti Lst_AtEnd(&pgn->children, cgn); 443143027Sharti if (specType == Not) { 444143027Sharti Lst_AtEnd(&cgn->parents, pgn); 445143027Sharti } 446143027Sharti pgn->unmade += 1; 447143027Sharti } 4481590Srgrimes } 4491590Srgrimes} 4501590Srgrimes 4511590Srgrimes/*- 4521590Srgrimes *--------------------------------------------------------------------- 4531590Srgrimes * ParseDoOp -- 454143684Sharti * Apply the parsed operator to all target nodes. Used in 455143684Sharti * ParseDoDependency once all targets have been found and their 456143684Sharti * operator parsed. If the previous and new operators are incompatible, 457143684Sharti * a major error is taken. 4581590Srgrimes * 4591590Srgrimes * Side Effects: 4601590Srgrimes * The type field of the node is altered to reflect any new bits in 4611590Srgrimes * the op. 4621590Srgrimes *--------------------------------------------------------------------- 4631590Srgrimes */ 464143684Shartistatic void 465143684ShartiParseDoOp(int op) 4661590Srgrimes{ 467143684Sharti GNode *cohort; 468143684Sharti LstNode *ln; 469143684Sharti GNode *gn; 470138232Sharti 471143684Sharti LST_FOREACH(ln, &targets) { 472143684Sharti gn = Lst_Datum(ln); 4731590Srgrimes 474143684Sharti /* 475143684Sharti * If the dependency mask of the operator and the node don't 476143684Sharti * match and the node has actually had an operator applied to 477143684Sharti * it before, and the operator actually has some dependency 478143684Sharti * information in it, complain. 479143684Sharti */ 480143684Sharti if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && 481143684Sharti !OP_NOP(gn->type) && !OP_NOP(op)) { 482143684Sharti Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 483143684Sharti gn->name); 484143684Sharti return; 485143684Sharti } 4868874Srgrimes 487143684Sharti if (op == OP_DOUBLEDEP && 488143684Sharti (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 489143684Sharti /* 490143684Sharti * If the node was the object of a :: operator, we need 491143684Sharti * to create a new instance of it for the children and 492143684Sharti * commands on this dependency line. The new instance 493143684Sharti * is placed on the 'cohorts' list of the initial one 494143684Sharti * (note the initial one is not on its own cohorts list) 495143684Sharti * and the new instance is linked to all parents of the 496143684Sharti * initial instance. 497143684Sharti */ 498143684Sharti cohort = Targ_NewGN(gn->name); 4991590Srgrimes 500143684Sharti /* 501143684Sharti * Duplicate links to parents so graph traversal is 502143684Sharti * simple. Perhaps some type bits should be duplicated? 503143684Sharti * 504143684Sharti * Make the cohort invisible as well to avoid 505143684Sharti * duplicating it into other variables. True, parents 506143684Sharti * of this target won't tend to do anything with their 507143684Sharti * local variables, but better safe than sorry. 508143684Sharti */ 509143684Sharti ParseLinkSrc(&gn->parents, cohort); 510143684Sharti cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 511143684Sharti Lst_AtEnd(&gn->cohorts, cohort); 5121590Srgrimes 513143684Sharti /* 514143684Sharti * Replace the node in the targets list with the 515143684Sharti * new copy 516143684Sharti */ 517143684Sharti Lst_Replace(ln, cohort); 518143684Sharti gn = cohort; 519143684Sharti } 520143684Sharti /* 521143684Sharti * We don't want to nuke any previous flags (whatever they were) 522143684Sharti * so we just OR the new operator into the old 523143684Sharti */ 524143684Sharti gn->type |= op; 525143684Sharti } 5261590Srgrimes} 5271590Srgrimes 5281590Srgrimes/*- 5291590Srgrimes *--------------------------------------------------------------------- 5301590Srgrimes * ParseDoSrc -- 5311590Srgrimes * Given the name of a source, figure out if it is an attribute 5321590Srgrimes * and apply it to the targets if it is. Else decide if there is 5331590Srgrimes * some attribute which should be applied *to* the source because 5341590Srgrimes * of some special target and apply it if so. Otherwise, make the 5351590Srgrimes * source be a child of the targets in the list 'targets' 5361590Srgrimes * 5371590Srgrimes * Results: 5381590Srgrimes * None 5391590Srgrimes * 5401590Srgrimes * Side Effects: 5411590Srgrimes * Operator bits may be added to the list of targets or to the source. 5421590Srgrimes * The targets may have a new source added to their lists of children. 5431590Srgrimes *--------------------------------------------------------------------- 5441590Srgrimes */ 5451590Srgrimesstatic void 546138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc) 5471590Srgrimes{ 548144026Sharti GNode *gn = NULL; 549145616Sharti const struct keyword *kw; 5501590Srgrimes 551145616Sharti if (src[0] == '.' && isupper ((unsigned char)src[1])) { 552145616Sharti if ((kw = ParseFindKeyword(src)) != NULL) { 553145616Sharti if (kw->op != 0) { 554145616Sharti ParseDoOp(kw->op); 555144026Sharti return; 556144026Sharti } 557145616Sharti if (kw->spec == Wait) { 558144026Sharti waiting++; 559144026Sharti return; 560144026Sharti } 561144026Sharti } 5621590Srgrimes } 56318730Ssteve 564144026Sharti switch (specType) { 565144026Sharti case Main: 566144026Sharti /* 567144026Sharti * If we have noted the existence of a .MAIN, it means we need 568144026Sharti * to add the sources of said target to the list of things 569144026Sharti * to create. The string 'src' is likely to be free, so we 570144026Sharti * must make a new copy of it. Note that this will only be 571144026Sharti * invoked if the user didn't specify a target on the command 572144026Sharti * line. This is to allow #ifmake's to succeed, or something... 573144026Sharti */ 574144026Sharti Lst_AtEnd(&create, estrdup(src)); 575144026Sharti /* 576144026Sharti * Add the name to the .TARGETS variable as well, so the user 577144026Sharti * can employ that, if desired. 578144026Sharti */ 579144026Sharti Var_Append(".TARGETS", src, VAR_GLOBAL); 580144026Sharti return; 58118730Ssteve 582144026Sharti case Order: 583144026Sharti /* 584144026Sharti * Create proper predecessor/successor links between the 585144026Sharti * previous source and the current one. 586144026Sharti */ 587144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 588144026Sharti if (predecessor != NULL) { 589144026Sharti Lst_AtEnd(&predecessor->successors, gn); 590144026Sharti Lst_AtEnd(&gn->preds, predecessor); 591144026Sharti } 592144026Sharti /* 593144026Sharti * The current source now becomes the predecessor for the next 594144026Sharti * one. 595144026Sharti */ 596144026Sharti predecessor = gn; 597144026Sharti break; 59818730Ssteve 599144026Sharti default: 600144026Sharti /* 601144026Sharti * If the source is not an attribute, we need to find/create 602144026Sharti * a node for it. After that we can apply any operator to it 603144026Sharti * from a special target or link it to its parents, as 604144026Sharti * appropriate. 605144026Sharti * 606144026Sharti * In the case of a source that was the object of a :: operator, 607144026Sharti * the attribute is applied to all of its instances (as kept in 608144026Sharti * the 'cohorts' list of the node) or all the cohorts are linked 609144026Sharti * to all the targets. 610144026Sharti */ 611144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 6121590Srgrimes if (tOp) { 613144026Sharti gn->type |= tOp; 6141590Srgrimes } else { 615144026Sharti ParseLinkSrc(&targets, gn); 6161590Srgrimes } 617144026Sharti if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 618144026Sharti GNode *cohort; 619144026Sharti LstNode *ln; 620144026Sharti 621144026Sharti for (ln = Lst_First(&gn->cohorts); ln != NULL; 622144026Sharti ln = Lst_Succ(ln)) { 623144026Sharti cohort = Lst_Datum(ln); 624144026Sharti if (tOp) { 625144026Sharti cohort->type |= tOp; 626144026Sharti } else { 627144026Sharti ParseLinkSrc(&targets, cohort); 628144026Sharti } 629144026Sharti } 630144026Sharti } 631144026Sharti break; 6321590Srgrimes } 63318730Ssteve 634144026Sharti gn->order = waiting; 635144026Sharti Lst_AtEnd(allsrc, gn); 636144026Sharti if (waiting) { 637144026Sharti LstNode *ln; 638144026Sharti GNode *p; 6391590Srgrimes 640143684Sharti /* 641144026Sharti * Check if GNodes needs to be synchronized. 642144026Sharti * This has to be when two nodes are on different sides of a 643144026Sharti * .WAIT directive. 644143684Sharti */ 645144026Sharti LST_FOREACH(ln, allsrc) { 646144026Sharti p = Lst_Datum(ln); 647144026Sharti 648144026Sharti if (p->order >= gn->order) 649144026Sharti break; 650144026Sharti /* 651144026Sharti * XXX: This can cause loops, and loops can cause 652144026Sharti * unmade targets, but checking is tedious, and the 653144026Sharti * debugging output can show the problem 654144026Sharti */ 655144026Sharti Lst_AtEnd(&p->successors, gn); 656144026Sharti Lst_AtEnd(&gn->preds, p); 657144026Sharti } 658143684Sharti } 6591590Srgrimes} 6601590Srgrimes 661138232Sharti 6621590Srgrimes/*- 6631590Srgrimes *--------------------------------------------------------------------- 6641590Srgrimes * ParseDoDependency -- 6651590Srgrimes * Parse the dependency line in line. 6661590Srgrimes * 6671590Srgrimes * Results: 6681590Srgrimes * None 6691590Srgrimes * 6701590Srgrimes * Side Effects: 6711590Srgrimes * The nodes of the sources are linked as children to the nodes of the 6721590Srgrimes * targets. Some nodes may be created. 6731590Srgrimes * 6741590Srgrimes * We parse a dependency line by first extracting words from the line and 6751590Srgrimes * finding nodes in the list of all targets with that name. This is done 6761590Srgrimes * until a character is encountered which is an operator character. Currently 6771590Srgrimes * these are only ! and :. At this point the operator is parsed and the 6781590Srgrimes * pointer into the line advanced until the first source is encountered. 679144026Sharti * The parsed operator is applied to each node in the 'targets' list, 6801590Srgrimes * which is where the nodes found for the targets are kept, by means of 6811590Srgrimes * the ParseDoOp function. 6821590Srgrimes * The sources are read in much the same way as the targets were except 6831590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell 6841590Srgrimes * and all instances of the resulting words in the list of all targets 6851590Srgrimes * are found. Each of the resulting nodes is then linked to each of the 6861590Srgrimes * targets as one of its children. 6871590Srgrimes * Certain targets are handled specially. These are the ones detailed 6881590Srgrimes * by the specType variable. 6891590Srgrimes * The storing of transformation rules is also taken care of here. 6901590Srgrimes * A target is recognized as a transformation rule by calling 6911590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten 6921590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard 6931590Srgrimes * Targ_FindNode in the target module. 6941590Srgrimes *--------------------------------------------------------------------- 6951590Srgrimes */ 6961590Srgrimesstatic void 697141270ShartiParseDoDependency(char *line) 6981590Srgrimes{ 699144026Sharti char *cp; /* our current position */ 700144026Sharti GNode *gn; /* a general purpose temporary node */ 701144026Sharti int op; /* the operator on the line */ 702144026Sharti char savec; /* a place to save a character */ 703144026Sharti Lst paths; /* Search paths to alter when parsing .PATH targets */ 704144026Sharti int tOp; /* operator from special target */ 705144026Sharti LstNode *ln; 706145616Sharti const struct keyword *kw; 7071590Srgrimes 708144026Sharti tOp = 0; 7091590Srgrimes 710144026Sharti specType = Not; 711144026Sharti waiting = 0; 712144026Sharti Lst_Init(&paths); 7131590Srgrimes 714144026Sharti do { 715144026Sharti for (cp = line; 716144026Sharti *cp && !isspace((unsigned char)*cp) && *cp != '('; 717144026Sharti cp++) { 718144026Sharti if (*cp == '$') { 719144026Sharti /* 720144026Sharti * Must be a dynamic source (would have been 721144026Sharti * expanded otherwise), so call the Var module 722144026Sharti * to parse the puppy so we can safely advance 723144026Sharti * beyond it...There should be no errors in this 724144026Sharti * as they would have been discovered in the 725144026Sharti * initial Var_Subst and we wouldn't be here. 726144026Sharti */ 727144026Sharti size_t length = 0; 728144026Sharti Boolean freeIt; 729144026Sharti char *result; 7301590Srgrimes 731144026Sharti result = Var_Parse(cp, VAR_CMD, TRUE, 732144026Sharti &length, &freeIt); 7331590Srgrimes 734144026Sharti if (freeIt) { 735144026Sharti free(result); 736144026Sharti } 737144026Sharti cp += length - 1; 738102178Sru 739144026Sharti } else if (*cp == '!' || *cp == ':') { 740144026Sharti /* 741144026Sharti * We don't want to end a word on ':' or '!' if 742144026Sharti * there is a better match later on in the 743144026Sharti * string (greedy matching). 744144026Sharti * This allows the user to have targets like: 745144026Sharti * fie::fi:fo: fum 746144026Sharti * foo::bar: 747144026Sharti * where "fie::fi:fo" and "foo::bar" are the 748144026Sharti * targets. In real life this is used for perl5 749144026Sharti * library man pages where "::" separates an 750144026Sharti * object from its class. Ie: 751144026Sharti * "File::Spec::Unix". This behaviour is also 752144026Sharti * consistent with other versions of make. 753144026Sharti */ 754144026Sharti char *p = cp + 1; 755102178Sru 756144026Sharti if (*cp == ':' && *p == ':') 757144026Sharti p++; 758102178Sru 759144026Sharti /* Found the best match already. */ 760144026Sharti if (*p == '\0' || isspace(*p)) 761144026Sharti break; 762102178Sru 763144026Sharti p += strcspn(p, "!:"); 7648874Srgrimes 765144026Sharti /* No better match later on... */ 766144026Sharti if (*p == '\0') 767144026Sharti break; 768144026Sharti } 769144026Sharti continue; 7701590Srgrimes } 771144026Sharti if (*cp == '(') { 772144026Sharti /* 773144026Sharti * Archives must be handled specially to make sure the 774144026Sharti * OP_ARCHV flag is set in their 'type' field, for one 775144026Sharti * thing, and because things like "archive(file1.o 776144026Sharti * file2.o file3.o)" are permissible. Arch_ParseArchive 777144026Sharti * will set 'line' to be the first non-blank after the 778144026Sharti * archive-spec. It creates/finds nodes for the members 779146338Sharti * and places them on the given list, returning TRUE 780146338Sharti * if all went well and FALSE if there was an error in 781144026Sharti * the specification. On error, line should remain 782144026Sharti * untouched. 783144026Sharti */ 784146338Sharti if (!Arch_ParseArchive(&line, &targets, VAR_CMD)) { 785144026Sharti Parse_Error(PARSE_FATAL, 786144026Sharti "Error in archive specification: \"%s\"", 787144026Sharti line); 788144026Sharti return; 789144026Sharti } else { 790144026Sharti cp = line; 791144026Sharti continue; 792144026Sharti } 793144026Sharti } 794144026Sharti savec = *cp; 7958874Srgrimes 796144026Sharti if (!*cp) { 797144026Sharti /* 798144026Sharti * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often 799144026Sharti * triggered by undetected conflicts from cvs/rcs 800144026Sharti * merges. 801144026Sharti */ 802144026Sharti if (strncmp(line, "<<<<<<", 6) == 0 || 803144026Sharti strncmp(line, "======", 6) == 0 || 804144026Sharti strncmp(line, ">>>>>>", 6) == 0) { 805144026Sharti Parse_Error(PARSE_FATAL, "Makefile appears to " 806144026Sharti "contain unresolved cvs/rcs/??? merge " 807144026Sharti "conflicts"); 808144026Sharti } else 809144026Sharti Parse_Error(PARSE_FATAL, "Need an operator"); 810144026Sharti return; 811144026Sharti } 812144026Sharti *cp = '\0'; 8131590Srgrimes /* 814144026Sharti * Have a word in line. See if it's a special target and set 815144026Sharti * specType to match it. 8161590Srgrimes */ 817144026Sharti if (*line == '.' && isupper((unsigned char)line[1])) { 818144026Sharti /* 819144026Sharti * See if the target is a special target that must have 820144026Sharti * it or its sources handled specially. 821144026Sharti */ 822145616Sharti if ((kw = ParseFindKeyword(line)) != NULL) { 823145616Sharti if (specType == ExPath && kw->spec != ExPath) { 824144026Sharti Parse_Error(PARSE_FATAL, 825144026Sharti "Mismatched special targets"); 826144026Sharti return; 827144026Sharti } 828144026Sharti 829145616Sharti specType = kw->spec; 830145616Sharti tOp = kw->op; 831144026Sharti 832144026Sharti /* 833144026Sharti * Certain special targets have special 834144026Sharti * semantics: 835144026Sharti * .PATH Have to set the dirSearchPath 836144026Sharti * variable too 837144026Sharti * .MAIN Its sources are only used if 838144026Sharti * nothing has been specified to 839144026Sharti * create. 840144026Sharti * .DEFAULT Need to create a node to hang 841144026Sharti * commands on, but we don't want 842144026Sharti * it in the graph, nor do we want 843144026Sharti * it to be the Main Target, so we 844144026Sharti * create it, set OP_NOTMAIN and 845144026Sharti * add it to the list, setting 846144026Sharti * DEFAULT to the new node for 847144026Sharti * later use. We claim the node is 848144026Sharti * A transformation rule to make 849144026Sharti * life easier later, when we'll 850144026Sharti * use Make_HandleUse to actually 851144026Sharti * apply the .DEFAULT commands. 852144026Sharti * .PHONY The list of targets 853144026Sharti * .BEGIN 854144026Sharti * .END 855144026Sharti * .INTERRUPT Are not to be considered the 856144026Sharti * main target. 857144026Sharti * .NOTPARALLEL Make only one target at a time. 858144026Sharti * .SINGLESHELL Create a shell for each 859144026Sharti * command. 860144026Sharti * .ORDER Must set initial predecessor 861144026Sharti * to NULL 862144026Sharti */ 863144026Sharti switch (specType) { 864144026Sharti case ExPath: 865144026Sharti Lst_AtEnd(&paths, &dirSearchPath); 866144026Sharti break; 867144026Sharti case Main: 868144026Sharti if (!Lst_IsEmpty(&create)) { 869144026Sharti specType = Not; 870144026Sharti } 871144026Sharti break; 872144026Sharti case Begin: 873144026Sharti case End: 874144026Sharti case Interrupt: 875144026Sharti gn = Targ_FindNode(line, TARG_CREATE); 876144026Sharti gn->type |= OP_NOTMAIN; 877144026Sharti Lst_AtEnd(&targets, gn); 878144026Sharti break; 879144026Sharti case Default: 880144026Sharti gn = Targ_NewGN(".DEFAULT"); 881144026Sharti gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 882144026Sharti Lst_AtEnd(&targets, gn); 883144026Sharti DEFAULT = gn; 884144026Sharti break; 885144026Sharti case NotParallel: 886146140Sharti jobLimit = 1; 887144026Sharti break; 888144026Sharti case SingleShell: 889144026Sharti compatMake = 1; 890144026Sharti break; 891144026Sharti case Order: 892144026Sharti predecessor = NULL; 893144026Sharti break; 894144026Sharti default: 895144026Sharti break; 896144026Sharti } 897144026Sharti 898144026Sharti } else if (strncmp(line, ".PATH", 5) == 0) { 899144026Sharti /* 900144026Sharti * .PATH<suffix> has to be handled specially. 901144026Sharti * Call on the suffix module to give us a path 902144026Sharti * to modify. 903144026Sharti */ 904144026Sharti struct Path *path; 905144026Sharti 906144026Sharti specType = ExPath; 907144026Sharti path = Suff_GetPath(&line[5]); 908144026Sharti if (path == NULL) { 909144026Sharti Parse_Error(PARSE_FATAL, "Suffix '%s' " 910144026Sharti "not defined (yet)", &line[5]); 911144026Sharti return; 912144026Sharti } else 913144026Sharti Lst_AtEnd(&paths, path); 9141590Srgrimes } 9151590Srgrimes } 916144026Sharti 9171590Srgrimes /* 918144026Sharti * Have word in line. Get or create its node and stick it at 919144026Sharti * the end of the targets list 9201590Srgrimes */ 921144029Sharti if (specType == Not && *line != '\0') { 9228874Srgrimes 923144026Sharti /* target names to be found and added to targets list */ 924144026Sharti Lst curTargs = Lst_Initializer(curTargs); 9258874Srgrimes 926144026Sharti if (Dir_HasWildcards(line)) { 927144026Sharti /* 928144026Sharti * Targets are to be sought only in the current 929144026Sharti * directory, so create an empty path for the 930144026Sharti * thing. Note we need to use Path_Clear in the 931144026Sharti * destruction of the path as the Dir module 932144026Sharti * could have added a directory to the path... 933144026Sharti */ 934144026Sharti struct Path emptyPath = 935144026Sharti TAILQ_HEAD_INITIALIZER(emptyPath); 936138916Sharti 937144026Sharti Path_Expand(line, &emptyPath, &curTargs); 938144026Sharti Path_Clear(&emptyPath); 9398874Srgrimes 940144026Sharti } else { 941144026Sharti /* 942144026Sharti * No wildcards, but we want to avoid code 943144026Sharti * duplication, so create a list with the word 944144026Sharti * on it. 945144026Sharti */ 946144026Sharti Lst_AtEnd(&curTargs, line); 947144026Sharti } 9488874Srgrimes 949144026Sharti while (!Lst_IsEmpty(&curTargs)) { 950144026Sharti char *targName = Lst_DeQueue(&curTargs); 951144026Sharti 952144026Sharti if (!Suff_IsTransform (targName)) { 953144026Sharti gn = Targ_FindNode(targName, 954144026Sharti TARG_CREATE); 955144026Sharti } else { 956144026Sharti gn = Suff_AddTransform(targName); 957144026Sharti } 958144026Sharti 959144026Sharti Lst_AtEnd(&targets, gn); 960144026Sharti } 961144026Sharti } else if (specType == ExPath && *line != '.' && *line != '\0'){ 962144026Sharti Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 963144026Sharti line); 964144026Sharti } 965144026Sharti 966144026Sharti *cp = savec; 9671590Srgrimes /* 968144026Sharti * If it is a special type and not .PATH, it's the only 969144026Sharti * target we allow on this line... 9701590Srgrimes */ 971144026Sharti if (specType != Not && specType != ExPath) { 972144026Sharti Boolean warnFlag = FALSE; 9738874Srgrimes 974144029Sharti while (*cp != '!' && *cp != ':' && *cp) { 975144026Sharti if (*cp != ' ' && *cp != '\t') { 976144026Sharti warnFlag = TRUE; 977144026Sharti } 978144026Sharti cp++; 979144026Sharti } 980144026Sharti if (warnFlag) { 981144026Sharti Parse_Error(PARSE_WARNING, 982144026Sharti "Extra target ignored"); 983144026Sharti } 9841590Srgrimes } else { 985144026Sharti while (*cp && isspace((unsigned char)*cp)) { 986144026Sharti cp++; 987144026Sharti } 9881590Srgrimes } 989144026Sharti line = cp; 990144029Sharti } while (*line != '!' && *line != ':' && *line); 9918874Srgrimes 992144026Sharti if (!Lst_IsEmpty(&targets)) { 993144026Sharti switch (specType) { 994144026Sharti default: 995144026Sharti Parse_Error(PARSE_WARNING, "Special and mundane " 996144026Sharti "targets don't mix. Mundane ones ignored"); 997144026Sharti break; 998144026Sharti case Default: 999144026Sharti case Begin: 1000144026Sharti case End: 1001144026Sharti case Interrupt: 1002144026Sharti /* 1003144026Sharti * These four create nodes on which to hang commands, so 1004144026Sharti * targets shouldn't be empty... 1005144026Sharti */ 1006144026Sharti case Not: 1007144026Sharti /* 1008144026Sharti * Nothing special here -- targets can be empty if it 1009144026Sharti * wants. 1010144026Sharti */ 1011144026Sharti break; 1012144026Sharti } 10131590Srgrimes } 10148874Srgrimes 10151590Srgrimes /* 1016144026Sharti * Have now parsed all the target names. Must parse the operator next. 1017144026Sharti * The result is left in op. 10181590Srgrimes */ 1019144026Sharti if (*cp == '!') { 1020144026Sharti op = OP_FORCE; 1021144026Sharti } else if (*cp == ':') { 1022144026Sharti if (cp[1] == ':') { 1023144026Sharti op = OP_DOUBLEDEP; 1024144026Sharti cp++; 1025144026Sharti } else { 1026144026Sharti op = OP_DEPENDS; 10271590Srgrimes } 10281590Srgrimes } else { 1029144026Sharti Parse_Error(PARSE_FATAL, "Missing dependency operator"); 1030144026Sharti return; 1031144026Sharti } 1032144026Sharti 1033144026Sharti cp++; /* Advance beyond operator */ 1034144026Sharti 1035144026Sharti ParseDoOp(op); 1036144026Sharti 1037144026Sharti /* 1038144026Sharti * Get to the first source 1039144026Sharti */ 1040144026Sharti while (*cp && isspace((unsigned char)*cp)) { 10411590Srgrimes cp++; 10421590Srgrimes } 10431590Srgrimes line = cp; 10441590Srgrimes 1045144026Sharti /* 1046144026Sharti * Several special targets take different actions if present with no 1047144026Sharti * sources: 1048144026Sharti * a .SUFFIXES line with no sources clears out all old suffixes 1049144026Sharti * a .PRECIOUS line makes all targets precious 1050144026Sharti * a .IGNORE line ignores errors for all targets 1051144026Sharti * a .SILENT line creates silence when making all targets 1052144026Sharti * a .PATH removes all directories from the search path(s). 1053144026Sharti */ 1054144026Sharti if (!*line) { 1055144026Sharti switch (specType) { 1056144026Sharti case Suffixes: 1057144026Sharti Suff_ClearSuffixes(); 1058144026Sharti break; 1059144026Sharti case Precious: 1060144026Sharti allPrecious = TRUE; 1061144026Sharti break; 1062144026Sharti case Ignore: 1063144026Sharti ignoreErrors = TRUE; 1064144026Sharti break; 1065144026Sharti case Silent: 1066144026Sharti beSilent = TRUE; 1067144026Sharti break; 1068144026Sharti case ExPath: 1069144026Sharti LST_FOREACH(ln, &paths) 1070144026Sharti Path_Clear(Lst_Datum(ln)); 1071144026Sharti break; 1072144026Sharti case Posix: 1073144026Sharti Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 1074144026Sharti break; 1075144026Sharti default: 1076144026Sharti break; 1077144026Sharti } 1078144026Sharti 1079144026Sharti } else if (specType == MFlags) { 10801590Srgrimes /* 1081144026Sharti * Call on functions in main.c to deal with these arguments and 1082144026Sharti * set the initial character to a null-character so the loop to 1083144026Sharti * get sources won't get anything 10841590Srgrimes */ 1085144026Sharti Main_ParseArgLine(line, 0); 1086144026Sharti *line = '\0'; 10871590Srgrimes 1088145679Sharti } else if (specType == Warn) { 1089145679Sharti parse_warn(line); 1090145679Sharti *line = '\0'; 1091145679Sharti 1092144026Sharti } else if (specType == ExShell) { 1093146572Sharti if (!Shell_Parse(line)) { 1094144026Sharti Parse_Error(PARSE_FATAL, 1095144026Sharti "improper shell specification"); 1096144026Sharti return; 1097144026Sharti } 1098144026Sharti *line = '\0'; 1099144026Sharti 1100144029Sharti } else if (specType == NotParallel || specType == SingleShell) { 1101144026Sharti *line = '\0'; 11021590Srgrimes } 11031590Srgrimes 1104144026Sharti /* 1105144026Sharti * NOW GO FOR THE SOURCES 1106144026Sharti */ 1107144029Sharti if (specType == Suffixes || specType == ExPath || 1108144029Sharti specType == Includes || specType == Libs || 1109144029Sharti specType == Null) { 1110144026Sharti while (*line) { 1111144026Sharti /* 1112144026Sharti * If the target was one that doesn't take files as its 1113144026Sharti * sources but takes something like suffixes, we take 1114144026Sharti * each space-separated word on the line as a something 1115144026Sharti * and deal with it accordingly. 1116144026Sharti * 1117144026Sharti * If the target was .SUFFIXES, we take each source as 1118144026Sharti * a suffix and add it to the list of suffixes 1119144026Sharti * maintained by the Suff module. 1120144026Sharti * 1121144026Sharti * If the target was a .PATH, we add the source as a 1122144026Sharti * directory to search on the search path. 1123144026Sharti * 1124144026Sharti * If it was .INCLUDES, the source is taken to be the 1125144026Sharti * suffix of files which will be #included and whose 1126144026Sharti * search path should be present in the .INCLUDES 1127144026Sharti * variable. 1128144026Sharti * 1129144026Sharti * If it was .LIBS, the source is taken to be the 1130144026Sharti * suffix of files which are considered libraries and 1131144026Sharti * whose search path should be present in the .LIBS 1132144026Sharti * variable. 1133144026Sharti * 1134144026Sharti * If it was .NULL, the source is the suffix to use 1135144026Sharti * when a file has no valid suffix. 1136144026Sharti */ 1137144026Sharti char savech; 1138144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1139144026Sharti cp++; 1140144026Sharti } 1141144026Sharti savech = *cp; 1142144026Sharti *cp = '\0'; 1143144026Sharti switch (specType) { 1144144026Sharti case Suffixes: 1145144026Sharti Suff_AddSuffix(line); 1146144026Sharti break; 1147144026Sharti case ExPath: 1148144026Sharti LST_FOREACH(ln, &paths) 1149144026Sharti Path_AddDir(Lst_Datum(ln), line); 1150144026Sharti break; 1151144026Sharti case Includes: 1152144026Sharti Suff_AddInclude(line); 1153144026Sharti break; 1154144026Sharti case Libs: 1155144026Sharti Suff_AddLib(line); 1156144026Sharti break; 1157144026Sharti case Null: 1158144026Sharti Suff_SetNull(line); 1159144026Sharti break; 1160144026Sharti default: 1161144026Sharti break; 1162144026Sharti } 1163144026Sharti *cp = savech; 1164144026Sharti if (savech != '\0') { 1165144026Sharti cp++; 1166144026Sharti } 1167144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1168144026Sharti cp++; 1169144026Sharti } 1170144026Sharti line = cp; 1171144026Sharti } 1172144026Sharti Lst_Destroy(&paths, NOFREE); 11731590Srgrimes 1174145971Sharti } else if (specType == ExportVar) { 1175145971Sharti Var_SetEnv(line, VAR_GLOBAL); 1176145971Sharti 1177144026Sharti } else { 1178144026Sharti /* list of sources in order */ 1179144026Sharti Lst curSrcs = Lst_Initializer(curSrc); 11801590Srgrimes 1181144026Sharti while (*line) { 1182144026Sharti /* 1183144026Sharti * The targets take real sources, so we must beware of 1184144026Sharti * archive specifications (i.e. things with left 1185144026Sharti * parentheses in them) and handle them accordingly. 1186144026Sharti */ 1187144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1188144026Sharti if (*cp == '(' && cp > line && cp[-1] != '$') { 1189144026Sharti /* 1190144026Sharti * Only stop for a left parenthesis if 1191144026Sharti * it isn't at the start of a word 1192144026Sharti * (that'll be for variable changes 1193144026Sharti * later) and isn't preceded by a dollar 1194144026Sharti * sign (a dynamic source). 1195144026Sharti */ 1196144026Sharti break; 1197144026Sharti } else { 1198144026Sharti cp++; 1199144026Sharti } 1200144026Sharti } 12011590Srgrimes 1202144026Sharti if (*cp == '(') { 1203144026Sharti GNode *gnp; 12048874Srgrimes 1205144026Sharti /* list of archive source names after exp. */ 1206144026Sharti Lst sources = Lst_Initializer(sources); 1207138916Sharti 1208146338Sharti if (!Arch_ParseArchive(&line, &sources, 1209146338Sharti VAR_CMD)) { 1210144026Sharti Parse_Error(PARSE_FATAL, "Error in " 1211144026Sharti "source archive spec \"%s\"", line); 1212144026Sharti return; 1213144026Sharti } 1214141270Sharti 1215144026Sharti while (!Lst_IsEmpty(&sources)) { 1216144026Sharti gnp = Lst_DeQueue(&sources); 1217144026Sharti ParseDoSrc(tOp, gnp->name, &curSrcs); 1218144026Sharti } 1219144026Sharti cp = line; 1220144026Sharti } else { 1221144026Sharti if (*cp) { 1222144026Sharti *cp = '\0'; 1223144026Sharti cp += 1; 1224144026Sharti } 12251590Srgrimes 1226144026Sharti ParseDoSrc(tOp, line, &curSrcs); 1227144026Sharti } 1228144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1229144026Sharti cp++; 1230144026Sharti } 1231144026Sharti line = cp; 12321590Srgrimes } 1233144026Sharti Lst_Destroy(&curSrcs, NOFREE); 1234144026Sharti } 12351590Srgrimes 1236144026Sharti if (mainNode == NULL) { 1237144026Sharti /* 1238144026Sharti * If we have yet to decide on a main target to make, in the 1239144026Sharti * absence of any user input, we want the first target on 1240144026Sharti * the first dependency line that is actually a real target 1241144026Sharti * (i.e. isn't a .USE or .EXEC rule) to be made. 1242144026Sharti */ 1243144026Sharti LST_FOREACH(ln, &targets) { 1244144026Sharti gn = Lst_Datum(ln); 1245144026Sharti if ((gn->type & (OP_NOTMAIN | OP_USE | 1246144026Sharti OP_EXEC | OP_TRANSFORM)) == 0) { 1247144026Sharti mainNode = gn; 1248144026Sharti Targ_SetMain(gn); 1249144026Sharti break; 1250144026Sharti } 12511590Srgrimes } 12521590Srgrimes } 12531590Srgrimes} 12541590Srgrimes 12551590Srgrimes/*- 12561590Srgrimes *--------------------------------------------------------------------- 12571590Srgrimes * Parse_IsVar -- 12581590Srgrimes * Return TRUE if the passed line is a variable assignment. A variable 12591590Srgrimes * assignment consists of a single word followed by optional whitespace 12601590Srgrimes * followed by either a += or an = operator. 12611590Srgrimes * This function is used both by the Parse_File function and main when 12621590Srgrimes * parsing the command-line arguments. 12631590Srgrimes * 12641590Srgrimes * Results: 12651590Srgrimes * TRUE if it is. FALSE if it ain't 12661590Srgrimes * 12671590Srgrimes * Side Effects: 12681590Srgrimes * none 12691590Srgrimes *--------------------------------------------------------------------- 12701590Srgrimes */ 12711590SrgrimesBoolean 1272138232ShartiParse_IsVar(char *line) 12731590Srgrimes{ 1274144026Sharti Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1275144026Sharti Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1276138232Sharti 1277144026Sharti int level = 0; 1278103503Sjmallett#define ISEQOPERATOR(c) \ 1279144029Sharti ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') 12801590Srgrimes 1281144026Sharti /* 1282144026Sharti * Skip to variable name 1283144026Sharti */ 1284144029Sharti for (; *line == ' ' || *line == '\t'; line++) 1285144026Sharti continue; 12861590Srgrimes 1287144026Sharti for (; *line != '=' || level != 0; line++) { 1288144026Sharti switch (*line) { 1289144026Sharti case '\0': 1290144026Sharti /* 1291144026Sharti * end-of-line -- can't be a variable assignment. 1292144026Sharti */ 1293144026Sharti return (FALSE); 129418730Ssteve 1295144026Sharti case ' ': 1296144026Sharti case '\t': 1297144026Sharti /* 1298144026Sharti * there can be as much white space as desired so long 1299144026Sharti * as there is only one word before the operator 1300144026Sharti */ 1301144026Sharti wasSpace = TRUE; 1302144026Sharti break; 130318730Ssteve 1304144026Sharti case '(': 1305144026Sharti case '{': 1306144026Sharti level++; 1307144026Sharti break; 130818730Ssteve 1309144026Sharti case '}': 1310144026Sharti case ')': 1311144026Sharti level--; 1312144026Sharti break; 131318730Ssteve 1314144026Sharti default: 1315144026Sharti if (wasSpace && haveName) { 1316144026Sharti if (ISEQOPERATOR(*line)) { 1317144026Sharti /* 1318144026Sharti * We must have a finished word 1319144026Sharti */ 1320144026Sharti if (level != 0) 1321144026Sharti return (FALSE); 132218730Ssteve 1323144026Sharti /* 1324144026Sharti * When an = operator [+?!:] is found, 1325144026Sharti * the next character must be an = or 1326144026Sharti * it ain't a valid assignment. 1327144026Sharti */ 1328144026Sharti if (line[1] == '=') 1329144026Sharti return (haveName); 133018730Ssteve#ifdef SUNSHCMD 1331144026Sharti /* 1332144026Sharti * This is a shell command 1333144026Sharti */ 1334144026Sharti if (strncmp(line, ":sh", 3) == 0) 1335144026Sharti return (haveName); 133618730Ssteve#endif 1337144026Sharti } 1338144026Sharti /* 1339144026Sharti * This is the start of another word, so not 1340144026Sharti * assignment. 1341144026Sharti */ 1342144026Sharti return (FALSE); 1343144026Sharti 1344144026Sharti } else { 1345144026Sharti haveName = TRUE; 1346144026Sharti wasSpace = FALSE; 1347144026Sharti } 1348144026Sharti break; 1349144026Sharti } 13501590Srgrimes } 13511590Srgrimes 1352144026Sharti return (haveName); 13531590Srgrimes} 13541590Srgrimes 13551590Srgrimes/*- 13561590Srgrimes *--------------------------------------------------------------------- 13571590Srgrimes * Parse_DoVar -- 13581590Srgrimes * Take the variable assignment in the passed line and do it in the 13591590Srgrimes * global context. 13601590Srgrimes * 13611590Srgrimes * Note: There is a lexical ambiguity with assignment modifier characters 13621590Srgrimes * in variable names. This routine interprets the character before the = 13631590Srgrimes * as a modifier. Therefore, an assignment like 13641590Srgrimes * C++=/usr/bin/CC 13651590Srgrimes * is interpreted as "C+ +=" instead of "C++ =". 13661590Srgrimes * 13671590Srgrimes * Results: 13681590Srgrimes * none 13691590Srgrimes * 13701590Srgrimes * Side Effects: 13711590Srgrimes * the variable structure of the given variable name is altered in the 13721590Srgrimes * global context. 13731590Srgrimes *--------------------------------------------------------------------- 13741590Srgrimes */ 13751590Srgrimesvoid 1376138232ShartiParse_DoVar(char *line, GNode *ctxt) 13771590Srgrimes{ 1378144026Sharti char *cp; /* pointer into line */ 1379144026Sharti enum { 1380144026Sharti VAR_SUBST, 1381144026Sharti VAR_APPEND, 1382144026Sharti VAR_SHELL, 1383144026Sharti VAR_NORMAL 1384144026Sharti } type; /* Type of assignment */ 1385144026Sharti char *opc; /* ptr to operator character to 1386144026Sharti * null-terminate the variable name */ 1387144026Sharti 1388144026Sharti /* 1389144026Sharti * Skip to variable name 1390144026Sharti */ 1391144029Sharti while (*line == ' ' || *line == '\t') { 1392144026Sharti line++; 1393144026Sharti } 13941590Srgrimes 1395144026Sharti /* 1396144026Sharti * Skip to operator character, nulling out whitespace as we go 1397144026Sharti */ 1398144026Sharti for (cp = line + 1; *cp != '='; cp++) { 1399144026Sharti if (isspace((unsigned char)*cp)) { 1400144026Sharti *cp = '\0'; 1401144026Sharti } 14021590Srgrimes } 1403144026Sharti opc = cp - 1; /* operator is the previous character */ 1404144026Sharti *cp++ = '\0'; /* nuke the = */ 14051590Srgrimes 1406144026Sharti /* 1407144026Sharti * Check operator type 1408144026Sharti */ 1409144026Sharti switch (*opc) { 1410144026Sharti case '+': 1411144026Sharti type = VAR_APPEND; 1412144026Sharti *opc = '\0'; 1413144026Sharti break; 14141590Srgrimes 1415144026Sharti case '?': 1416144026Sharti /* 1417144026Sharti * If the variable already has a value, we don't do anything. 1418144026Sharti */ 1419144026Sharti *opc = '\0'; 1420144026Sharti if (Var_Exists(line, ctxt)) { 1421144026Sharti return; 1422144026Sharti } else { 1423144026Sharti type = VAR_NORMAL; 1424144026Sharti } 1425144026Sharti break; 14261590Srgrimes 1427144026Sharti case ':': 1428144026Sharti type = VAR_SUBST; 1429144026Sharti *opc = '\0'; 1430144026Sharti break; 14311590Srgrimes 1432144026Sharti case '!': 1433144026Sharti type = VAR_SHELL; 1434144026Sharti *opc = '\0'; 1435144026Sharti break; 14361590Srgrimes 1437144026Sharti default: 143818730Ssteve#ifdef SUNSHCMD 1439144026Sharti while (*opc != ':') { 1440144026Sharti if (opc == line) 1441144026Sharti break; 1442144026Sharti else 1443144026Sharti --opc; 1444144026Sharti } 144518730Ssteve 1446144026Sharti if (strncmp(opc, ":sh", 3) == 0) { 1447144026Sharti type = VAR_SHELL; 1448144026Sharti *opc = '\0'; 1449144026Sharti break; 1450144026Sharti } 1451144026Sharti#endif 1452144026Sharti type = VAR_NORMAL; 145318730Ssteve break; 1454144026Sharti } 14551590Srgrimes 1456144026Sharti while (isspace((unsigned char)*cp)) { 1457144026Sharti cp++; 1458144026Sharti } 14591590Srgrimes 1460144026Sharti if (type == VAR_APPEND) { 1461144026Sharti Var_Append(line, cp, ctxt); 14621590Srgrimes 1463144026Sharti } else if (type == VAR_SUBST) { 1464144026Sharti /* 1465144026Sharti * Allow variables in the old value to be undefined, but leave 1466144026Sharti * their invocation alone -- this is done by forcing oldVars 1467144026Sharti * to be false. 1468144026Sharti * XXX: This can cause recursive variables, but that's not 1469144026Sharti * hard to do, and this allows someone to do something like 1470144026Sharti * 1471144026Sharti * CFLAGS = $(.INCLUDES) 1472144026Sharti * CFLAGS := -I.. $(CFLAGS) 1473144026Sharti * 1474144026Sharti * And not get an error. 1475144026Sharti */ 1476144026Sharti Boolean oldOldVars = oldVars; 147798509Sjmallett 1478144026Sharti oldVars = FALSE; 147998509Sjmallett 1480144026Sharti /* 1481144026Sharti * make sure that we set the variable the first time to nothing 1482144026Sharti * so that it gets substituted! 1483144026Sharti */ 1484144026Sharti if (!Var_Exists(line, ctxt)) 1485144026Sharti Var_Set(line, "", ctxt); 1486142457Sharti 1487146027Sharti cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE)); 14881590Srgrimes 1489144026Sharti oldVars = oldOldVars; 14901590Srgrimes 1491144026Sharti Var_Set(line, cp, ctxt); 1492144026Sharti free(cp); 14931590Srgrimes 1494144026Sharti } else if (type == VAR_SHELL) { 1495144026Sharti /* 1496144026Sharti * TRUE if the command needs to be freed, i.e. 1497144026Sharti * if any variable expansion was performed 1498144026Sharti */ 1499144026Sharti Boolean freeCmd = FALSE; 1500144026Sharti Buffer *buf; 1501144026Sharti const char *error; 15021590Srgrimes 1503144026Sharti if (strchr(cp, '$') != NULL) { 1504144026Sharti /* 1505144026Sharti * There's a dollar sign in the command, so perform 1506144026Sharti * variable expansion on the whole thing. The 1507144026Sharti * resulting string will need freeing when we're done, 1508144026Sharti * so set freeCmd to TRUE. 1509144026Sharti */ 1510146027Sharti cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE)); 1511144026Sharti freeCmd = TRUE; 1512144026Sharti } 15131590Srgrimes 1514144026Sharti buf = Cmd_Exec(cp, &error); 1515144026Sharti Var_Set(line, Buf_Data(buf), ctxt); 1516144026Sharti Buf_Destroy(buf, TRUE); 1517144026Sharti 1518144026Sharti if (error) 1519144026Sharti Parse_Error(PARSE_WARNING, error, cp); 1520144026Sharti 1521144026Sharti if (freeCmd) 1522144026Sharti free(cp); 1523144026Sharti 1524144026Sharti } else { 1525144026Sharti /* 1526144026Sharti * Normal assignment -- just do it. 1527144026Sharti */ 1528144026Sharti Var_Set(line, cp, ctxt); 1529144026Sharti } 15301590Srgrimes} 15311590Srgrimes 15321590Srgrimes/*- 15331590Srgrimes *----------------------------------------------------------------------- 15341590Srgrimes * ParseHasCommands -- 15351590Srgrimes * Callback procedure for Parse_File when destroying the list of 15361590Srgrimes * targets on the last dependency line. Marks a target as already 15371590Srgrimes * having commands if it does, to keep from having shell commands 15381590Srgrimes * on multiple dependency lines. 15391590Srgrimes * 15401590Srgrimes * Results: 15415814Sjkh * None 15421590Srgrimes * 15431590Srgrimes * Side Effects: 15441590Srgrimes * OP_HAS_COMMANDS may be set for the target. 15451590Srgrimes * 15461590Srgrimes *----------------------------------------------------------------------- 15471590Srgrimes */ 15485814Sjkhstatic void 1549104696SjmallettParseHasCommands(void *gnp) 15501590Srgrimes{ 1551144026Sharti GNode *gn = gnp; 1552138232Sharti 1553144026Sharti if (!Lst_IsEmpty(&gn->commands)) { 1554144026Sharti gn->type |= OP_HAS_COMMANDS; 1555144026Sharti } 15561590Srgrimes} 15571590Srgrimes 15581590Srgrimes/*- 15591590Srgrimes *----------------------------------------------------------------------- 15601590Srgrimes * Parse_AddIncludeDir -- 15611590Srgrimes * Add a directory to the path searched for included makefiles 15621590Srgrimes * bracketed by double-quotes. Used by functions in main.c 15631590Srgrimes * 15641590Srgrimes * Results: 15651590Srgrimes * None. 15661590Srgrimes * 15671590Srgrimes * Side Effects: 15681590Srgrimes * The directory is appended to the list. 15691590Srgrimes * 15701590Srgrimes *----------------------------------------------------------------------- 15711590Srgrimes */ 15721590Srgrimesvoid 1573138232ShartiParse_AddIncludeDir(char *dir) 15741590Srgrimes{ 1575138232Sharti 1576144026Sharti Path_AddDir(&parseIncPath, dir); 15771590Srgrimes} 15781590Srgrimes 15791590Srgrimes/*- 15801590Srgrimes *--------------------------------------------------------------------- 15811590Srgrimes * Parse_FromString -- 15821590Srgrimes * Start Parsing from the given string 15838874Srgrimes * 15841590Srgrimes * Results: 15851590Srgrimes * None 15861590Srgrimes * 15871590Srgrimes * Side Effects: 1588126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1589126824Sru * curFile.fname and curFile.F are altered for the new file 15901590Srgrimes *--------------------------------------------------------------------- 15911590Srgrimes */ 15921590Srgrimesvoid 1593126824SruParse_FromString(char *str, int lineno) 15941590Srgrimes{ 15951590Srgrimes 1596144026Sharti DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 15971590Srgrimes 1598144341Sharti ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); 15991590Srgrimes} 16001590Srgrimes 16011590Srgrimes#ifdef SYSVINCLUDE 16021590Srgrimes/*- 16031590Srgrimes *--------------------------------------------------------------------- 16041590Srgrimes * ParseTraditionalInclude -- 16051590Srgrimes * Push to another file. 16068874Srgrimes * 16071590Srgrimes * The input is the line minus the "include". The file name is 16081590Srgrimes * the string following the "include". 16091590Srgrimes * 16101590Srgrimes * Results: 16111590Srgrimes * None 16121590Srgrimes * 16131590Srgrimes * Side Effects: 1614126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1615126824Sru * curFile.fname and curFile.F are altered for the new file 16161590Srgrimes *--------------------------------------------------------------------- 16171590Srgrimes */ 16181590Srgrimesstatic void 1619141270ShartiParseTraditionalInclude(char *file) 16201590Srgrimes{ 1621144026Sharti char *fullname; /* full pathname of file */ 1622144026Sharti char *cp; /* current position in file spec */ 16231590Srgrimes 1624144026Sharti /* 1625144026Sharti * Skip over whitespace 1626144026Sharti */ 1627144029Sharti while (*file == ' ' || *file == '\t') { 1628144026Sharti file++; 1629144026Sharti } 16301590Srgrimes 1631144026Sharti if (*file == '\0') { 1632144026Sharti Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); 1633144026Sharti return; 1634144026Sharti } 16351590Srgrimes 1636144026Sharti /* 1637144026Sharti * Skip to end of line or next whitespace 1638144026Sharti */ 1639144026Sharti for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1640144026Sharti continue; 1641144026Sharti } 16421590Srgrimes 1643144026Sharti *cp = '\0'; 16441590Srgrimes 1645144026Sharti /* 1646144026Sharti * Substitute for any variables in the file name before trying to 1647144026Sharti * find the thing. 1648144026Sharti */ 1649146027Sharti file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 16501590Srgrimes 16511590Srgrimes /* 1652144026Sharti * Now we know the file's name, we attempt to find the durn thing. 1653144026Sharti * Search for it first on the -I search path, then on the .PATH 1654144026Sharti * search path, if not found in a -I directory. 16551590Srgrimes */ 1656144026Sharti fullname = Path_FindFile(file, &parseIncPath); 1657144026Sharti if (fullname == NULL) { 1658144026Sharti fullname = Path_FindFile(file, &dirSearchPath); 1659144026Sharti } 16601590Srgrimes 1661144026Sharti if (fullname == NULL) { 1662144026Sharti /* 1663144026Sharti * Still haven't found the makefile. Look for it on the system 1664144026Sharti * path as a last resort. 1665144026Sharti */ 1666144026Sharti fullname = Path_FindFile(file, &sysIncPath); 1667144026Sharti } 16681590Srgrimes 1669144026Sharti if (fullname == NULL) { 1670144026Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1671144026Sharti /* XXXHB free(file) */ 1672144026Sharti return; 1673144026Sharti } 1674142457Sharti 1675144026Sharti /* XXXHB free(file) */ 16761590Srgrimes 1677144026Sharti /* 1678144341Sharti * We set up the name of the file to be the absolute 1679144026Sharti * name of the include file so error messages refer to the right 1680144341Sharti * place. 16811590Srgrimes */ 1682144341Sharti ParsePushInput(fullname, NULL, NULL, 0); 16831590Srgrimes} 16841590Srgrimes#endif 16851590Srgrimes 16861590Srgrimes/*- 16871590Srgrimes *--------------------------------------------------------------------- 16881590Srgrimes * ParseReadc -- 16898874Srgrimes * Read a character from the current file 16901590Srgrimes * 16911590Srgrimes * Results: 16921590Srgrimes * The character that was read 16931590Srgrimes * 16941590Srgrimes * Side Effects: 16951590Srgrimes *--------------------------------------------------------------------- 16961590Srgrimes */ 16971590Srgrimesstatic int 1698104696SjmallettParseReadc(void) 16991590Srgrimes{ 1700138232Sharti 1701144341Sharti if (CURFILE->F != NULL) 1702144341Sharti return (fgetc(CURFILE->F)); 17038874Srgrimes 1704144341Sharti if (CURFILE->str != NULL && *CURFILE->ptr != '\0') 1705144341Sharti return (*CURFILE->ptr++); 1706144341Sharti 1707144026Sharti return (EOF); 17081590Srgrimes} 17091590Srgrimes 17101590Srgrimes 17111590Srgrimes/*- 17121590Srgrimes *--------------------------------------------------------------------- 17131590Srgrimes * ParseUnreadc -- 17148874Srgrimes * Put back a character to the current file 17151590Srgrimes * 17161590Srgrimes * Results: 17171590Srgrimes * None. 17181590Srgrimes * 17191590Srgrimes * Side Effects: 17201590Srgrimes *--------------------------------------------------------------------- 17211590Srgrimes */ 17221590Srgrimesstatic void 1723104696SjmallettParseUnreadc(int c) 17241590Srgrimes{ 1725138232Sharti 1726144341Sharti if (CURFILE->F != NULL) { 1727144341Sharti ungetc(c, CURFILE->F); 1728144026Sharti return; 1729144026Sharti } 1730144341Sharti if (CURFILE->str != NULL) { 1731144341Sharti *--(CURFILE->ptr) = c; 1732144026Sharti return; 1733144026Sharti } 17341590Srgrimes} 17351590Srgrimes 17361590Srgrimes/* ParseSkipLine(): 1737104696Sjmallett * Grab the next line unless it begins with a dot (`.') and we're told to 1738104696Sjmallett * ignore such lines. 17391590Srgrimes */ 17401590Srgrimesstatic char * 1741126824SruParseSkipLine(int skip, int keep_newline) 17421590Srgrimes{ 1743144026Sharti char *line; 1744144026Sharti int c, lastc; 1745144026Sharti Buffer *buf; 17461590Srgrimes 1747144026Sharti buf = Buf_Init(MAKE_BSIZE); 17481590Srgrimes 1749144026Sharti do { 1750144026Sharti Buf_Clear(buf); 1751144026Sharti lastc = '\0'; 17528874Srgrimes 1753144026Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') 1754144026Sharti && c != EOF) { 1755144026Sharti if (skip && c == '#' && lastc != '\\') { 1756144026Sharti /* 1757144026Sharti * let a comment be terminated even by an 1758144026Sharti * escaped \n. This is consistent to comment 1759144026Sharti * handling in ParseReadLine 1760144026Sharti */ 1761144026Sharti while ((c = ParseReadc()) != '\n' && c != EOF) 1762144026Sharti ; 1763144026Sharti break; 1764144026Sharti } 1765144026Sharti if (c == '\n') { 1766144026Sharti if (keep_newline) 1767144026Sharti Buf_AddByte(buf, (Byte)c); 1768144026Sharti else 1769144026Sharti Buf_ReplaceLastByte(buf, (Byte)' '); 1770144341Sharti CURFILE->lineno++; 17718874Srgrimes 1772144026Sharti while ((c = ParseReadc()) == ' ' || c == '\t') 1773144026Sharti continue; 17748874Srgrimes 1775144026Sharti if (c == EOF) 1776144026Sharti break; 1777144026Sharti } 177874272Swill 1779144026Sharti Buf_AddByte(buf, (Byte)c); 1780144026Sharti lastc = c; 1781144026Sharti } 178218456Ssteve 1783144026Sharti if (c == EOF) { 1784144026Sharti Parse_Error(PARSE_FATAL, 1785144026Sharti "Unclosed conditional/for loop"); 1786144026Sharti Buf_Destroy(buf, TRUE); 1787144026Sharti return (NULL); 1788144026Sharti } 178918456Ssteve 1790144341Sharti CURFILE->lineno++; 1791144026Sharti Buf_AddByte(buf, (Byte)'\0'); 1792144026Sharti line = Buf_Data(buf); 1793144026Sharti } while (skip == 1 && line[0] != '.'); 179418456Ssteve 1795144026Sharti Buf_Destroy(buf, FALSE); 1796144026Sharti return (line); 17971590Srgrimes} 17981590Srgrimes 17991590Srgrimes/*- 18001590Srgrimes *--------------------------------------------------------------------- 18011590Srgrimes * ParseReadLine -- 18021590Srgrimes * Read an entire line from the input file. Called only by Parse_File. 18031590Srgrimes * To facilitate escaped newlines and what have you, a character is 18041590Srgrimes * buffered in 'lastc', which is '\0' when no characters have been 18051590Srgrimes * read. When we break out of the loop, c holds the terminating 18061590Srgrimes * character and lastc holds a character that should be added to 18071590Srgrimes * the line (unless we don't read anything but a terminator). 18081590Srgrimes * 18091590Srgrimes * Results: 18101590Srgrimes * A line w/o its newline 18111590Srgrimes * 18121590Srgrimes * Side Effects: 18131590Srgrimes * Only those associated with reading a character 18141590Srgrimes *--------------------------------------------------------------------- 18151590Srgrimes */ 18161590Srgrimesstatic char * 1817138232ShartiParseReadLine(void) 18181590Srgrimes{ 1819144026Sharti Buffer *buf; /* Buffer for current line */ 1820144026Sharti int c; /* the current character */ 1821144026Sharti int lastc; /* The most-recent character */ 1822144026Sharti Boolean semiNL; /* treat semi-colons as newlines */ 1823144026Sharti Boolean ignDepOp; /* TRUE if should ignore dependency operators 18241590Srgrimes * for the purposes of setting semiNL */ 1825144026Sharti Boolean ignComment; /* TRUE if should ignore comments (in a 18261590Srgrimes * shell command */ 1827144026Sharti char *line; /* Result */ 1828144026Sharti char *ep; /* to strip trailing blanks */ 18291590Srgrimes 1830144742Sharti again: 1831144026Sharti semiNL = FALSE; 1832144026Sharti ignDepOp = FALSE; 1833144026Sharti ignComment = FALSE; 18341590Srgrimes 1835144742Sharti lastc = '\0'; 1836144742Sharti 1837144026Sharti /* 1838144742Sharti * Handle tab at the beginning of the line. A leading tab (shell 1839144742Sharti * command) forces us to ignore comments and dependency operators and 1840144742Sharti * treat semi-colons as semi-colons (by leaving semiNL FALSE). 1841144742Sharti * This also discards completely blank lines. 1842144026Sharti */ 1843144026Sharti for (;;) { 1844144026Sharti c = ParseReadc(); 1845144742Sharti if (c == EOF) { 1846144742Sharti if (ParsePopInput() == DONE) { 1847144742Sharti /* End of all inputs - return NULL */ 1848144742Sharti return (NULL); 1849144742Sharti } 1850144742Sharti continue; 1851144742Sharti } 18521590Srgrimes 1853144026Sharti if (c == '\t') { 1854144026Sharti ignComment = ignDepOp = TRUE; 1855144742Sharti lastc = c; 1856144026Sharti break; 1857144742Sharti } 1858144742Sharti if (c != '\n') { 1859144026Sharti ParseUnreadc(c); 1860144026Sharti break; 1861144026Sharti } 1862144742Sharti CURFILE->lineno++; 18631590Srgrimes } 18648874Srgrimes 1865144742Sharti buf = Buf_Init(MAKE_BSIZE); 18668874Srgrimes 1867144742Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { 1868144026Sharti test_char: 1869144742Sharti switch (c) { 1870144742Sharti case '\n': 1871144742Sharti /* 1872144742Sharti * Escaped newline: read characters until a 1873144742Sharti * non-space or an unescaped newline and 1874144742Sharti * replace them all by a single space. This is 1875144742Sharti * done by storing the space over the backslash 1876144742Sharti * and dropping through with the next nonspace. 1877144742Sharti * If it is a semi-colon and semiNL is TRUE, 1878144742Sharti * it will be recognized as a newline in the 1879144742Sharti * code below this... 1880144742Sharti */ 1881144742Sharti CURFILE->lineno++; 1882144742Sharti lastc = ' '; 1883144742Sharti while ((c = ParseReadc()) == ' ' || c == '\t') { 1884144742Sharti continue; 1885144742Sharti } 1886144742Sharti if (c == EOF || c == '\n') { 1887144742Sharti goto line_read; 1888144742Sharti } else { 1889144026Sharti /* 1890144742Sharti * Check for comments, semiNL's, etc. -- 1891144742Sharti * easier than ParseUnreadc(c); 1892144742Sharti * continue; 1893144026Sharti */ 1894144742Sharti goto test_char; 1895144742Sharti } 1896144742Sharti /*NOTREACHED*/ 1897144742Sharti break; 1898144026Sharti 1899144742Sharti case ';': 1900144742Sharti /* 1901144742Sharti * Semi-colon: Need to see if it should be 1902144742Sharti * interpreted as a newline 1903144742Sharti */ 1904144742Sharti if (semiNL) { 1905144026Sharti /* 1906144742Sharti * To make sure the command that may 1907144742Sharti * be following this semi-colon begins 1908144742Sharti * with a tab, we push one back into the 1909144742Sharti * input stream. This will overwrite the 1910144742Sharti * semi-colon in the buffer. If there is 1911144742Sharti * no command following, this does no 1912144742Sharti * harm, since the newline remains in 1913144742Sharti * the buffer and the 1914144742Sharti * whole line is ignored. 1915144026Sharti */ 1916144742Sharti ParseUnreadc('\t'); 1917144742Sharti goto line_read; 1918144742Sharti } 1919144742Sharti break; 1920144742Sharti case '=': 1921144742Sharti if (!semiNL) { 1922144742Sharti /* 1923144742Sharti * Haven't seen a dependency operator 1924144742Sharti * before this, so this must be a 1925144742Sharti * variable assignment -- don't pay 1926144742Sharti * attention to dependency operators 1927144742Sharti * after this. 1928144742Sharti */ 1929144742Sharti ignDepOp = TRUE; 1930144742Sharti } else if (lastc == ':' || lastc == '!') { 1931144742Sharti /* 1932144742Sharti * Well, we've seen a dependency 1933144742Sharti * operator already, but it was the 1934144742Sharti * previous character, so this is really 1935144742Sharti * just an expanded variable assignment. 1936144742Sharti * Revert semi-colons to being just 1937144742Sharti * semi-colons again and ignore any more 1938144742Sharti * dependency operators. 1939144742Sharti * 1940144742Sharti * XXX: Note that a line like 1941144742Sharti * "foo : a:=b" will blow up, but who'd 1942144742Sharti * write a line like that anyway? 1943144742Sharti */ 1944144742Sharti ignDepOp = TRUE; 1945144742Sharti semiNL = FALSE; 1946144742Sharti } 1947144742Sharti break; 1948144742Sharti case '#': 1949144742Sharti if (!ignComment) { 1950144742Sharti if (lastc != '\\') { 1951144026Sharti /* 1952144742Sharti * If the character is a hash 1953144742Sharti * mark and it isn't escaped 1954144742Sharti * (or we're being compatible), 1955144742Sharti * the thing is a comment. 1956144742Sharti * Skip to the end of the line. 1957144026Sharti */ 1958144742Sharti do { 1959144742Sharti c = ParseReadc(); 1960144742Sharti } while (c != '\n' && c != EOF); 1961144026Sharti goto line_read; 1962144742Sharti } else { 1963144026Sharti /* 1964144742Sharti * Don't add the backslash. 1965144742Sharti * Just let the # get copied 1966144742Sharti * over. 1967144026Sharti */ 1968144742Sharti lastc = c; 1969144742Sharti continue; 1970144026Sharti } 1971144742Sharti } 1972144742Sharti break; 1973144026Sharti 1974144742Sharti case ':': 1975144742Sharti case '!': 1976144742Sharti if (!ignDepOp) { 1977144742Sharti /* 1978144742Sharti * A semi-colon is recognized as a 1979144742Sharti * newline only on dependency lines. 1980144742Sharti * Dependency lines are lines with a 1981144742Sharti * colon or an exclamation point. 1982144742Sharti * Ergo... 1983144742Sharti */ 1984144742Sharti semiNL = TRUE; 1985144742Sharti } 1986144742Sharti break; 1987144026Sharti 1988144742Sharti default: 1989144742Sharti break; 1990144742Sharti } 1991144742Sharti /* 1992144742Sharti * Copy in the previous character (there may be none if this 1993144742Sharti * was the first character) and save this one in 1994144742Sharti * lastc. 1995144742Sharti */ 1996144742Sharti if (lastc != '\0') 1997144026Sharti Buf_AddByte(buf, (Byte)lastc); 1998144742Sharti lastc = c; 1999144742Sharti } 2000144026Sharti line_read: 2001144742Sharti CURFILE->lineno++; 2002144026Sharti 2003144742Sharti if (lastc != '\0') { 2004144742Sharti Buf_AddByte(buf, (Byte)lastc); 2005144742Sharti } 2006144742Sharti Buf_AddByte(buf, (Byte)'\0'); 2007144742Sharti line = Buf_Peel(buf); 20081590Srgrimes 2009144742Sharti /* 2010144742Sharti * Strip trailing blanks and tabs from the line. 2011144742Sharti * Do not strip a blank or tab that is preceded by 2012144742Sharti * a '\' 2013144742Sharti */ 2014144742Sharti ep = line; 2015144742Sharti while (*ep) 2016144742Sharti ++ep; 2017144742Sharti while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2018144742Sharti if (ep > line + 1 && ep[-2] == '\\') 2019144742Sharti break; 2020144742Sharti --ep; 2021144742Sharti } 2022144742Sharti *ep = 0; 2023144742Sharti 2024144742Sharti if (line[0] == '\0') { 2025144742Sharti /* empty line - just ignore */ 2026144742Sharti free(line); 2027144742Sharti goto again; 2028144742Sharti } 2029144742Sharti 2030144742Sharti return (line); 20311590Srgrimes} 20321590Srgrimes 20331590Srgrimes/*- 20341590Srgrimes *----------------------------------------------------------------------- 20351590Srgrimes * ParseFinishLine -- 20361590Srgrimes * Handle the end of a dependency group. 20371590Srgrimes * 20381590Srgrimes * Results: 20391590Srgrimes * Nothing. 20401590Srgrimes * 20411590Srgrimes * Side Effects: 20421590Srgrimes * inLine set FALSE. 'targets' list destroyed. 20431590Srgrimes * 20441590Srgrimes *----------------------------------------------------------------------- 20451590Srgrimes */ 20461590Srgrimesstatic void 2047104696SjmallettParseFinishLine(void) 20481590Srgrimes{ 2049143372Sharti const LstNode *ln; 2050138232Sharti 2051143372Sharti if (inLine) { 2052143372Sharti LST_FOREACH(ln, &targets) { 2053143372Sharti if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) 2054143372Sharti Suff_EndTransform(Lst_Datum(ln)); 2055143372Sharti } 2056143372Sharti Lst_Destroy(&targets, ParseHasCommands); 2057143372Sharti inLine = FALSE; 2058143372Sharti } 20591590Srgrimes} 20601590Srgrimes 2061144894Sharti/** 2062144894Sharti * parse_include 2063144894Sharti * Parse an .include directive and push the file onto the input stack. 2064144894Sharti * The input is the line minus the .include. A file spec is a string 2065144894Sharti * enclosed in <> or "". The former is looked for only in sysIncPath. 2066144894Sharti * The latter in . and the directories specified by -I command line 2067144894Sharti * options 2068144894Sharti */ 2069144894Shartistatic void 2070150595Sphkxparse_include(char *file, int sinclude) 2071144894Sharti{ 2072144894Sharti char *fullname; /* full pathname of file */ 2073144894Sharti char endc; /* the character which ends the file spec */ 2074144894Sharti char *cp; /* current position in file spec */ 2075144894Sharti Boolean isSystem; /* TRUE if makefile is a system makefile */ 2076144894Sharti char *prefEnd, *Fname; 2077144894Sharti char *newName; 20788874Srgrimes 2079144894Sharti /* 2080144894Sharti * Skip to delimiter character so we know where to look 2081144894Sharti */ 2082144894Sharti while (*file == ' ' || *file == '\t') { 2083144894Sharti file++; 2084144894Sharti } 2085144894Sharti 2086144894Sharti if (*file != '"' && *file != '<') { 2087144894Sharti Parse_Error(PARSE_FATAL, 2088144894Sharti ".include filename must be delimited by '\"' or '<'"); 2089144894Sharti return; 2090144894Sharti } 2091144894Sharti 2092144894Sharti /* 2093144894Sharti * Set the search path on which to find the include file based on the 2094144894Sharti * characters which bracket its name. Angle-brackets imply it's 2095144894Sharti * a system Makefile while double-quotes imply it's a user makefile 2096144894Sharti */ 2097144894Sharti if (*file == '<') { 2098144894Sharti isSystem = TRUE; 2099144894Sharti endc = '>'; 2100144894Sharti } else { 2101144894Sharti isSystem = FALSE; 2102144894Sharti endc = '"'; 2103144894Sharti } 2104144894Sharti 2105144894Sharti /* 2106144894Sharti * Skip to matching delimiter 2107144894Sharti */ 2108144894Sharti for (cp = ++file; *cp != endc; cp++) { 2109144894Sharti if (*cp == '\0') { 2110144894Sharti Parse_Error(PARSE_FATAL, 2111144894Sharti "Unclosed .include filename. '%c' expected", endc); 2112144894Sharti return; 2113144894Sharti } 2114144894Sharti } 2115144894Sharti *cp = '\0'; 2116144894Sharti 2117144894Sharti /* 2118144894Sharti * Substitute for any variables in the file name before trying to 2119144894Sharti * find the thing. 2120144894Sharti */ 2121146027Sharti file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 2122144894Sharti 2123144894Sharti /* 2124144894Sharti * Now we know the file's name and its search path, we attempt to 2125144894Sharti * find the durn thing. A return of NULL indicates the file don't 2126144894Sharti * exist. 2127144894Sharti */ 2128144894Sharti if (!isSystem) { 2129144894Sharti /* 2130144894Sharti * Include files contained in double-quotes are first searched 2131144894Sharti * for relative to the including file's location. We don't want 2132144894Sharti * to cd there, of course, so we just tack on the old file's 2133144894Sharti * leading path components and call Dir_FindFile to see if 2134144894Sharti * we can locate the beast. 2135144894Sharti */ 2136144894Sharti 2137144894Sharti /* Make a temporary copy of this, to be safe. */ 2138144894Sharti Fname = estrdup(CURFILE->fname); 2139144894Sharti 2140144894Sharti prefEnd = strrchr(Fname, '/'); 2141144894Sharti if (prefEnd != NULL) { 2142144894Sharti *prefEnd = '\0'; 2143144894Sharti if (file[0] == '/') 2144144894Sharti newName = estrdup(file); 2145144894Sharti else 2146144894Sharti newName = str_concat(Fname, file, STR_ADDSLASH); 2147144894Sharti fullname = Path_FindFile(newName, &parseIncPath); 2148144894Sharti if (fullname == NULL) { 2149144894Sharti fullname = Path_FindFile(newName, 2150144894Sharti &dirSearchPath); 2151144894Sharti } 2152144894Sharti free(newName); 2153144894Sharti *prefEnd = '/'; 2154144894Sharti } else { 2155144894Sharti fullname = NULL; 2156144894Sharti } 2157144894Sharti free(Fname); 2158144894Sharti } else { 2159144894Sharti fullname = NULL; 2160144894Sharti } 2161144894Sharti 2162144894Sharti if (fullname == NULL) { 2163144894Sharti /* 2164144894Sharti * System makefile or makefile wasn't found in same directory as 2165144894Sharti * included makefile. Search for it first on the -I search path, 2166144894Sharti * then on the .PATH search path, if not found in a -I 2167144894Sharti * directory. 2168144894Sharti * XXX: Suffix specific? 2169144894Sharti */ 2170144894Sharti fullname = Path_FindFile(file, &parseIncPath); 2171144894Sharti if (fullname == NULL) { 2172144894Sharti fullname = Path_FindFile(file, &dirSearchPath); 2173144894Sharti } 2174144894Sharti } 2175144894Sharti 2176144894Sharti if (fullname == NULL) { 2177144894Sharti /* 2178144894Sharti * Still haven't found the makefile. Look for it on the system 2179144894Sharti * path as a last resort. 2180144894Sharti */ 2181144894Sharti fullname = Path_FindFile(file, &sysIncPath); 2182144894Sharti } 2183144894Sharti 2184144894Sharti if (fullname == NULL) { 2185144894Sharti *cp = endc; 2186150595Sphk if (!sinclude) 2187150595Sphk Parse_Error(PARSE_FATAL, "Could not find %s", file); 2188144894Sharti free(file); 2189144894Sharti return; 2190144894Sharti } 2191144894Sharti free(file); 2192144894Sharti 2193144894Sharti /* 2194144894Sharti * We set up the name of the file to be the absolute 2195144894Sharti * name of the include file so error messages refer to the right 2196144894Sharti * place. 2197144894Sharti */ 2198144894Sharti ParsePushInput(fullname, NULL, NULL, 0); 2199144894Sharti} 2200144894Sharti 2201150595Sphkstatic void 2202150595Sphkparse_include(char *file, int code __unused, int lineno __unused) 2203150595Sphk{ 2204150595Sphk xparse_include(file, 0); 2205150595Sphk} 2206150595Sphk 2207150595Sphkstatic void 2208150595Sphkparse_sinclude(char *file, int code __unused, int lineno __unused) 2209150595Sphk{ 2210150595Sphk xparse_include(file, 1); 2211150595Sphk} 2212150595Sphk 2213144894Sharti/** 2214144894Sharti * parse_message 2215144894Sharti * Parse a .warning or .error directive 2216144894Sharti * 2217144894Sharti * The input is the line minus the ".error"/".warning". We substitute 2218144894Sharti * variables, print the message and exit(1) (for .error) or just print 2219144894Sharti * a warning if the directive is malformed. 2220144894Sharti */ 2221144894Shartistatic void 2222144894Shartiparse_message(char *line, int iserror, int lineno __unused) 2223144894Sharti{ 2224144894Sharti 2225144894Sharti if (!isspace((u_char)*line)) { 2226144894Sharti Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s", 2227144894Sharti iserror ? "error" : "warning", line); 2228144894Sharti return; 2229144894Sharti } 2230144894Sharti 2231144894Sharti while (isspace((u_char)*line)) 2232144894Sharti line++; 2233144894Sharti 2234146027Sharti line = Buf_Peel(Var_Subst(line, VAR_GLOBAL, FALSE)); 2235144894Sharti Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); 2236144894Sharti free(line); 2237144894Sharti 2238144894Sharti if (iserror) { 2239144894Sharti /* Terminate immediately. */ 2240144894Sharti exit(1); 2241144894Sharti } 2242144894Sharti} 2243144894Sharti 2244144894Sharti/** 2245144894Sharti * parse_undef 2246144894Sharti * Parse an .undef directive. 2247144894Sharti */ 2248144894Shartistatic void 2249144894Shartiparse_undef(char *line, int code __unused, int lineno __unused) 2250144894Sharti{ 2251144894Sharti char *cp; 2252144894Sharti 2253144894Sharti while (isspace((u_char)*line)) 2254144894Sharti line++; 2255144894Sharti 2256144894Sharti for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) { 2257144894Sharti ; 2258144894Sharti } 2259144894Sharti *cp = '\0'; 2260144894Sharti 2261146027Sharti cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); 2262144894Sharti Var_Delete(cp, VAR_GLOBAL); 2263144894Sharti free(cp); 2264144894Sharti} 2265144894Sharti 2266144894Sharti/** 2267144894Sharti * parse_for 2268144894Sharti * Parse a .for directive. 2269144894Sharti */ 2270144894Shartistatic void 2271144894Shartiparse_for(char *line, int code __unused, int lineno) 2272144894Sharti{ 2273144894Sharti 2274144894Sharti if (!For_For(line)) { 2275144894Sharti /* syntax error */ 2276144894Sharti return; 2277144894Sharti } 2278144894Sharti line = NULL; 2279144894Sharti 2280144894Sharti /* 2281144894Sharti * Skip after the matching endfor. 2282144894Sharti */ 2283144894Sharti do { 2284144894Sharti free(line); 2285144894Sharti line = ParseSkipLine(0, 1); 2286144894Sharti if (line == NULL) { 2287144894Sharti Parse_Error(PARSE_FATAL, 2288144894Sharti "Unexpected end of file in for loop.\n"); 2289144894Sharti return; 2290144894Sharti } 2291144894Sharti } while (For_Eval(line)); 2292144894Sharti free(line); 2293144894Sharti 2294144894Sharti /* execute */ 2295144894Sharti For_Run(lineno); 2296144894Sharti} 2297144894Sharti 2298144894Sharti/** 2299144894Sharti * parse_endfor 2300144894Sharti * Parse endfor. This may only happen if there was no matching .for. 2301144894Sharti */ 2302144894Shartistatic void 2303144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused) 2304144894Sharti{ 2305144894Sharti 2306144894Sharti Parse_Error(PARSE_FATAL, "for-less endfor"); 2307144894Sharti} 2308144894Sharti 2309144894Sharti/** 2310144894Sharti * parse_directive 2311144894Sharti * Got a line starting with a '.'. Check if this is a directive 2312144894Sharti * and parse it. 2313144894Sharti * 2314144894Sharti * return: 2315144894Sharti * TRUE if line was a directive, FALSE otherwise. 2316144894Sharti */ 2317144894Shartistatic Boolean 2318144894Shartiparse_directive(char *line) 2319144894Sharti{ 2320144894Sharti char *start; 2321144894Sharti char *cp; 2322144894Sharti int dir; 2323144894Sharti 2324144894Sharti /* 2325144894Sharti * Get the keyword: 2326144894Sharti * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).* 2327144894Sharti * \1 is the keyword. 2328144894Sharti */ 2329144894Sharti for (start = line; isspace((u_char)*start); start++) { 2330144894Sharti ; 2331144894Sharti } 2332144894Sharti 2333144894Sharti if (!isalpha((u_char)*start)) { 2334144894Sharti return (FALSE); 2335144894Sharti } 2336144894Sharti 2337144894Sharti cp = start + 1; 2338144894Sharti while (isalnum((u_char)*cp) || *cp == '_') { 2339144894Sharti cp++; 2340144894Sharti } 2341144894Sharti 2342144894Sharti dir = directive_hash(start, cp - start); 2343144894Sharti if (dir < 0 || dir >= (int)NDIRECTS || 2344144894Sharti (size_t)(cp - start) != strlen(directives[dir].name) || 2345144894Sharti strncmp(start, directives[dir].name, cp - start) != 0) { 2346144894Sharti /* not actually matched */ 2347144894Sharti return (FALSE); 2348144894Sharti } 2349144894Sharti 2350144894Sharti if (!skipLine || directives[dir].skip_flag) 2351144894Sharti (*directives[dir].func)(cp, directives[dir].code, 2352144894Sharti CURFILE->lineno); 2353144894Sharti return (TRUE); 2354144894Sharti} 2355144894Sharti 23561590Srgrimes/*- 23571590Srgrimes *--------------------------------------------------------------------- 23581590Srgrimes * Parse_File -- 23591590Srgrimes * Parse a file into its component parts, incorporating it into the 23601590Srgrimes * current dependency graph. This is the main function and controls 23611590Srgrimes * almost every other function in this module 23621590Srgrimes * 23631590Srgrimes * Results: 23641590Srgrimes * None 23651590Srgrimes * 23661590Srgrimes * Side Effects: 23671590Srgrimes * Loads. Nodes are added to the list of all targets, nodes and links 23681590Srgrimes * are added to the dependency graph. etc. etc. etc. 23691590Srgrimes *--------------------------------------------------------------------- 23701590Srgrimes */ 23711590Srgrimesvoid 2372144341ShartiParse_File(const char *name, FILE *stream) 23731590Srgrimes{ 2374144026Sharti char *cp; /* pointer into the line */ 2375144026Sharti char *line; /* the line we're working on */ 23761590Srgrimes 2377144026Sharti inLine = FALSE; 2378144026Sharti fatals = 0; 23791590Srgrimes 2380144341Sharti ParsePushInput(estrdup(name), stream, NULL, 0); 2381131456Seik 2382144742Sharti while ((line = ParseReadLine()) != NULL) { 2383144894Sharti if (*line == '.' && parse_directive(line + 1)) { 2384144894Sharti /* directive consumed */ 2385144894Sharti goto nextLine; 2386144742Sharti } 2387144894Sharti if (skipLine || *line == '#') { 2388144894Sharti /* Skipping .if block or comment. */ 2389144742Sharti goto nextLine; 2390144742Sharti } 23918874Srgrimes 2392144742Sharti if (*line == '\t') { 2393144742Sharti /* 2394144742Sharti * If a line starts with a tab, it can only 2395144742Sharti * hope to be a creation command. 2396144742Sharti */ 2397144742Sharti for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 2398144742Sharti continue; 2399144742Sharti } 2400144742Sharti if (*cp) { 2401144742Sharti if (inLine) { 2402144742Sharti LstNode *ln; 2403144742Sharti GNode *gn; 2404143684Sharti 2405144742Sharti /* 2406144742Sharti * So long as it's not a blank 2407144742Sharti * line and we're actually in a 2408144742Sharti * dependency spec, add the 2409144742Sharti * command to the list of 2410144742Sharti * commands of all targets in 2411144742Sharti * the dependency spec. 2412144742Sharti */ 2413144742Sharti LST_FOREACH(ln, &targets) { 2414144742Sharti gn = Lst_Datum(ln); 2415144742Sharti 2416144026Sharti /* 2417144742Sharti * if target already 2418144742Sharti * supplied, ignore 2419144742Sharti * commands 2420144026Sharti */ 2421144742Sharti if (!(gn->type & OP_HAS_COMMANDS)) 2422144742Sharti Lst_AtEnd(&gn->commands, cp); 2423144742Sharti else 2424144742Sharti Parse_Error(PARSE_WARNING, "duplicate script " 2425144742Sharti "for target \"%s\" ignored", gn->name); 2426144026Sharti } 2427144742Sharti continue; 2428144742Sharti } else { 2429144742Sharti Parse_Error(PARSE_FATAL, 2430144742Sharti "Unassociated shell command \"%s\"", 2431144742Sharti cp); 2432144026Sharti } 2433144742Sharti } 24341590Srgrimes#ifdef SYSVINCLUDE 2435144742Sharti } else if (strncmp(line, "include", 7) == 0 && 2436144742Sharti isspace((unsigned char)line[7]) && 2437144742Sharti strchr(line, ':') == NULL) { 2438144742Sharti /* 2439144742Sharti * It's an S3/S5-style "include". 2440144742Sharti */ 2441144742Sharti ParseTraditionalInclude(line + 7); 2442144742Sharti goto nextLine; 24431590Srgrimes#endif 2444144742Sharti } else if (Parse_IsVar(line)) { 2445144742Sharti ParseFinishLine(); 2446144742Sharti Parse_DoVar(line, VAR_GLOBAL); 24478874Srgrimes 2448144742Sharti } else { 2449144742Sharti /* 2450144742Sharti * We now know it's a dependency line so it 2451144742Sharti * needs to have all variables expanded before 2452144742Sharti * being parsed. Tell the variable module to 2453144742Sharti * complain if some variable is undefined... 2454144742Sharti * To make life easier on novices, if the line 2455144742Sharti * is indented we first make sure the line has 2456144742Sharti * a dependency operator in it. If it doesn't 2457144742Sharti * have an operator and we're in a dependency 2458144742Sharti * line's script, we assume it's actually a 2459144742Sharti * shell command and add it to the current 2460144894Sharti * list of targets. XXX this comment seems wrong. 2461144742Sharti */ 2462144742Sharti cp = line; 2463144742Sharti if (isspace((unsigned char)line[0])) { 2464144742Sharti while (*cp != '\0' && 2465144742Sharti isspace((unsigned char)*cp)) { 2466144742Sharti cp++; 2467144026Sharti } 2468144742Sharti if (*cp == '\0') { 2469144742Sharti goto nextLine; 2470144742Sharti } 2471144742Sharti } 24721590Srgrimes 2473144742Sharti ParseFinishLine(); 2474142457Sharti 2475146027Sharti cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE)); 24768874Srgrimes 2477144742Sharti free(line); 2478144742Sharti line = cp; 2479144026Sharti 2480144742Sharti /* 2481144742Sharti * Need a non-circular list for the target nodes 2482144742Sharti */ 2483144742Sharti Lst_Destroy(&targets, NOFREE); 2484144742Sharti inLine = TRUE; 2485144026Sharti 2486144742Sharti ParseDoDependency(line); 2487144026Sharti } 2488144026Sharti 2489144742Sharti nextLine: 2490144742Sharti free(line); 2491144742Sharti } 24928874Srgrimes 2493144026Sharti ParseFinishLine(); 24941590Srgrimes 24951590Srgrimes /* 2496144026Sharti * Make sure conditionals are clean 24971590Srgrimes */ 2498144026Sharti Cond_End(); 24991590Srgrimes 2500144026Sharti if (fatals) 2501144026Sharti errx(1, "fatal errors encountered -- cannot continue"); 25021590Srgrimes} 25031590Srgrimes 25041590Srgrimes/*- 25051590Srgrimes *----------------------------------------------------------------------- 25061590Srgrimes * Parse_MainName -- 25071590Srgrimes * Return a Lst of the main target to create for main()'s sake. If 25081590Srgrimes * no such target exists, we Punt with an obnoxious error message. 25091590Srgrimes * 25101590Srgrimes * Results: 25111590Srgrimes * A Lst of the single node to create. 25121590Srgrimes * 25131590Srgrimes * Side Effects: 25141590Srgrimes * None. 25151590Srgrimes * 25161590Srgrimes *----------------------------------------------------------------------- 25171590Srgrimes */ 2518138916Shartivoid 2519138916ShartiParse_MainName(Lst *listmain) 25201590Srgrimes{ 25211590Srgrimes 2522144026Sharti if (mainNode == NULL) { 2523144026Sharti Punt("no target to make."); 2524144026Sharti /*NOTREACHED*/ 2525144026Sharti } else if (mainNode->type & OP_DOUBLEDEP) { 2526144026Sharti Lst_AtEnd(listmain, mainNode); 2527144026Sharti Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 2528144026Sharti } else 2529144026Sharti Lst_AtEnd(listmain, mainNode); 25301590Srgrimes} 2531