parse.c revision 146140
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 146140 2005-05-12 14:16:44Z harti $"); 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" 93141104Sharti#include "str.h" 94141104Sharti#include "suff.h" 95141104Sharti#include "targ.h" 96141104Sharti#include "util.h" 97141104Sharti#include "var.h" 981590Srgrimes 991590Srgrimes/* 100144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to 1011590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file, 1021590Srgrimes * or if it's DONE. 1031590Srgrimes */ 1041590Srgrimes#define CONTINUE 1 1051590Srgrimes#define DONE 0 106138916Sharti 107138916Sharti/* targets we're working on */ 108138916Shartistatic Lst targets = Lst_Initializer(targets); 109138916Sharti 110144026Sharti/* true if currently in a dependency line or its commands */ 111144026Shartistatic Boolean inLine; 1121590Srgrimes 113144026Shartistatic int fatals = 0; 1141590Srgrimes 115144026Sharti/* 116144026Sharti * The main target to create. This is the first target on the 117144026Sharti * first dependency line in the first makefile. 118144026Sharti */ 119144026Shartistatic GNode *mainNode; 120126824Sru 121144341Sharti/* 122144341Sharti * Definitions for handling #include specifications 123144341Sharti */ 124144341Shartistruct IFile { 125144341Sharti char *fname; /* name of previous file */ 126144341Sharti int lineno; /* saved line number */ 127144341Sharti FILE *F; /* the open stream */ 128144341Sharti char *str; /* the string when parsing a string */ 129144341Sharti char *ptr; /* the current pointer when parsing a string */ 130144341Sharti TAILQ_ENTRY(IFile) link;/* stack the files */ 131144341Sharti}; 132144026Sharti 133138916Sharti/* stack of IFiles generated by * #includes */ 134144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); 1351590Srgrimes 136144341Sharti/* access current file */ 137144341Sharti#define CURFILE (TAILQ_FIRST(&includes)) 138144341Sharti 139138916Sharti/* list of directories for "..." includes */ 140144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); 141138916Sharti 142138916Sharti/* list of directories for <...> includes */ 143144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); 144138916Sharti 145144026Sharti/* 1461590Srgrimes * specType contains the SPECial TYPE of the current target. It is 1471590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children 1481590Srgrimes * are linked as children of the parent but not vice versa. This variable is 1491590Srgrimes * set in ParseDoDependency 1501590Srgrimes */ 1511590Srgrimestypedef enum { 152144026Sharti Begin, /* .BEGIN */ 153144026Sharti Default, /* .DEFAULT */ 154144026Sharti End, /* .END */ 155145971Sharti ExportVar, /* .EXPORTVAR */ 156144026Sharti Ignore, /* .IGNORE */ 157144026Sharti Includes, /* .INCLUDES */ 158144026Sharti Interrupt, /* .INTERRUPT */ 159144026Sharti Libs, /* .LIBS */ 160144026Sharti MFlags, /* .MFLAGS or .MAKEFLAGS */ 161144026Sharti Main, /* .MAIN and we don't have anyth. user-spec. to make */ 162144026Sharti Not, /* Not special */ 163144026Sharti NotParallel, /* .NOTPARALELL */ 164144026Sharti Null, /* .NULL */ 165144026Sharti Order, /* .ORDER */ 166144026Sharti Parallel, /* .PARALLEL */ 167144026Sharti ExPath, /* .PATH */ 168144026Sharti Phony, /* .PHONY */ 169144026Sharti Posix, /* .POSIX */ 170144026Sharti Precious, /* .PRECIOUS */ 171144026Sharti ExShell, /* .SHELL */ 172144026Sharti Silent, /* .SILENT */ 173144026Sharti SingleShell, /* .SINGLESHELL */ 174144026Sharti Suffixes, /* .SUFFIXES */ 175144026Sharti Wait, /* .WAIT */ 176145679Sharti Warn, /* .WARN */ 177144026Sharti Attribute /* Generic attribute */ 1781590Srgrimes} ParseSpecial; 1791590Srgrimes 1801590Srgrimesstatic ParseSpecial specType; 18118730Sstevestatic int waiting; 1821590Srgrimes 1831590Srgrimes/* 18469527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 1851590Srgrimes * seen, then set to each successive source on the line. 1861590Srgrimes */ 187144026Shartistatic GNode *predecessor; 1881590Srgrimes 1891590Srgrimes/* 1901590Srgrimes * The parseKeywords table is searched using binary search when deciding 1911590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial 1921590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while 1931590Srgrimes * the 'op' field is the operator to apply to the list of targets if the 1941590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source) 1951590Srgrimes */ 196145616Shartistatic const struct keyword { 197144026Sharti const char *name; /* Name of keyword */ 198144026Sharti ParseSpecial spec; /* Type when used as a target */ 199144026Sharti int op; /* Operator when used as a source */ 2001590Srgrimes} parseKeywords[] = { 201145616Sharti /* KEYWORD-START-TAG */ 202144026Sharti { ".BEGIN", Begin, 0 }, 203144026Sharti { ".DEFAULT", Default, 0 }, 204144026Sharti { ".END", End, 0 }, 205144026Sharti { ".EXEC", Attribute, OP_EXEC }, 206145971Sharti { ".EXPORTVAR", ExportVar, 0 }, 207144026Sharti { ".IGNORE", Ignore, OP_IGNORE }, 208144026Sharti { ".INCLUDES", Includes, 0 }, 209144026Sharti { ".INTERRUPT", Interrupt, 0 }, 210144026Sharti { ".INVISIBLE", Attribute, OP_INVISIBLE }, 211144026Sharti { ".JOIN", Attribute, OP_JOIN }, 212144026Sharti { ".LIBS", Libs, 0 }, 213144026Sharti { ".MAIN", Main, 0 }, 214144026Sharti { ".MAKE", Attribute, OP_MAKE }, 215144026Sharti { ".MAKEFLAGS", MFlags, 0 }, 216144026Sharti { ".MFLAGS", MFlags, 0 }, 217144026Sharti { ".NOTMAIN", Attribute, OP_NOTMAIN }, 218144026Sharti { ".NOTPARALLEL", NotParallel, 0 }, 219144026Sharti { ".NO_PARALLEL", NotParallel, 0 }, 220144026Sharti { ".NULL", Null, 0 }, 221144026Sharti { ".OPTIONAL", Attribute, OP_OPTIONAL }, 222144026Sharti { ".ORDER", Order, 0 }, 223144026Sharti { ".PARALLEL", Parallel, 0 }, 224144026Sharti { ".PATH", ExPath, 0 }, 225144026Sharti { ".PHONY", Phony, OP_PHONY }, 226144026Sharti { ".POSIX", Posix, 0 }, 227144026Sharti { ".PRECIOUS", Precious, OP_PRECIOUS }, 228144026Sharti { ".RECURSIVE", Attribute, OP_MAKE }, 229144026Sharti { ".SHELL", ExShell, 0 }, 230144026Sharti { ".SILENT", Silent, OP_SILENT }, 231144026Sharti { ".SINGLESHELL", SingleShell, 0 }, 232144026Sharti { ".SUFFIXES", Suffixes, 0 }, 233144026Sharti { ".USE", Attribute, OP_USE }, 234144026Sharti { ".WAIT", Wait, 0 }, 235145679Sharti { ".WARN", Warn, 0 }, 236145616Sharti /* KEYWORD-END-TAG */ 2371590Srgrimes}; 238145616Sharti#define NKEYWORDS (sizeof(parseKeywords) / sizeof(parseKeywords[0])) 2391590Srgrimes 240144894Shartistatic void parse_include(char *, int, int); 241144894Shartistatic void parse_message(char *, int, int); 242144894Shartistatic void parse_undef(char *, int, int); 243144894Shartistatic void parse_for(char *, int, int); 244144894Shartistatic void parse_endfor(char *, int, int); 245144894Sharti 246144894Shartistatic const struct directive { 247144894Sharti const char *name; 248144894Sharti int code; 249144894Sharti Boolean skip_flag; /* execute even when skipped */ 250144894Sharti void (*func)(char *, int, int); 251144894Sharti} directives[] = { 252145612Sharti /* DIRECTIVES-START-TAG */ 253144894Sharti { "elif", COND_ELIF, TRUE, Cond_If }, 254144894Sharti { "elifdef", COND_ELIFDEF, TRUE, Cond_If }, 255144894Sharti { "elifmake", COND_ELIFMAKE, TRUE, Cond_If }, 256144894Sharti { "elifndef", COND_ELIFNDEF, TRUE, Cond_If }, 257144894Sharti { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If }, 258144894Sharti { "else", COND_ELSE, TRUE, Cond_Else }, 259144894Sharti { "endfor", 0, FALSE, parse_endfor }, 260144894Sharti { "endif", COND_ENDIF, TRUE, Cond_Endif }, 261144894Sharti { "error", 1, FALSE, parse_message }, 262144894Sharti { "for", 0, FALSE, parse_for }, 263144894Sharti { "if", COND_IF, TRUE, Cond_If }, 264144894Sharti { "ifdef", COND_IFDEF, TRUE, Cond_If }, 265144894Sharti { "ifmake", COND_IFMAKE, TRUE, Cond_If }, 266144894Sharti { "ifndef", COND_IFNDEF, TRUE, Cond_If }, 267144894Sharti { "ifnmake", COND_IFNMAKE, TRUE, Cond_If }, 268144894Sharti { "include", 0, FALSE, parse_include }, 269144894Sharti { "undef", 0, FALSE, parse_undef }, 270144894Sharti { "warning", 0, FALSE, parse_message }, 271145612Sharti /* DIRECTIVES-END-TAG */ 272144894Sharti}; 273144894Sharti#define NDIRECTS (sizeof(directives) / sizeof(directives[0])) 274144894Sharti 2751590Srgrimes/*- 276145616Sharti * ParseFindKeyword 2771590Srgrimes * Look in the table of keywords for one matching the given string. 2781590Srgrimes * 2791590Srgrimes * Results: 280145616Sharti * The pointer to keyword table entry or NULL. 2811590Srgrimes */ 282145616Shartistatic const struct keyword * 283145616ShartiParseFindKeyword(const char *str) 2841590Srgrimes{ 285145616Sharti int kw; 2868874Srgrimes 287145616Sharti kw = keyword_hash(str, strlen(str)); 288145616Sharti if (kw < 0 || kw >= (int)NKEYWORDS || 289145616Sharti strcmp(str, parseKeywords[kw].name) != 0) 290145616Sharti return (NULL); 291145616Sharti return (&parseKeywords[kw]); 2921590Srgrimes} 2931590Srgrimes 2941590Srgrimes/*- 2951590Srgrimes * Parse_Error -- 2961590Srgrimes * Error message abort function for parsing. Prints out the context 2971590Srgrimes * of the error (line number and file) as well as the message with 2981590Srgrimes * two optional arguments. 2991590Srgrimes * 3001590Srgrimes * Results: 3011590Srgrimes * None 3021590Srgrimes * 3031590Srgrimes * Side Effects: 3041590Srgrimes * "fatals" is incremented if the level is PARSE_FATAL. 3051590Srgrimes */ 3061590Srgrimes/* VARARGS */ 3071590Srgrimesvoid 30898136SjmallettParse_Error(int type, const char *fmt, ...) 3091590Srgrimes{ 3101590Srgrimes va_list ap; 31193056Simp 3121590Srgrimes va_start(ap, fmt); 313144745Sharti if (CURFILE != NULL) 314144745Sharti fprintf(stderr, "\"%s\", line %d: ", 315144745Sharti CURFILE->fname, CURFILE->lineno); 3161590Srgrimes if (type == PARSE_WARNING) 317138232Sharti fprintf(stderr, "warning: "); 318138232Sharti vfprintf(stderr, fmt, ap); 3191590Srgrimes va_end(ap); 320138232Sharti fprintf(stderr, "\n"); 321138232Sharti fflush(stderr); 3221590Srgrimes if (type == PARSE_FATAL) 3231590Srgrimes fatals += 1; 3241590Srgrimes} 3251590Srgrimes 326144341Sharti/** 327144341Sharti * ParsePushInput 328144341Sharti * 329144341Sharti * Push a new input source onto the input stack. If ptr is NULL 330144341Sharti * the fullname is used to fopen the file. If it is not NULL, 331144341Sharti * ptr is assumed to point to the string to be parsed. If opening the 332144341Sharti * file fails, the fullname is freed. 333144341Sharti */ 334144341Shartistatic void 335144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) 336144341Sharti{ 337144341Sharti struct IFile *nf; 338144341Sharti 339144341Sharti nf = emalloc(sizeof(*nf)); 340144341Sharti nf->fname = fullname; 341144341Sharti nf->lineno = lineno; 342144341Sharti 343144341Sharti if (ptr == NULL) { 344144341Sharti /* the input source is a file */ 345144341Sharti if ((nf->F = fp) == NULL) { 346144341Sharti nf->F = fopen(fullname, "r"); 347144341Sharti if (nf->F == NULL) { 348144341Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", 349144341Sharti fullname); 350144341Sharti free(fullname); 351144341Sharti free(nf); 352144341Sharti return; 353144341Sharti } 354144341Sharti } 355144341Sharti nf->str = nf->ptr = NULL; 356144341Sharti Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 357144341Sharti } else { 358144341Sharti nf->str = nf->ptr = ptr; 359144341Sharti nf->F = NULL; 360144341Sharti } 361144341Sharti TAILQ_INSERT_HEAD(&includes, nf, link); 362144341Sharti} 363144341Sharti 364144341Sharti/** 365144341Sharti * ParsePopInput 366144341Sharti * Called when EOF is reached in the current file. If we were reading 367144341Sharti * an include file, the includes stack is popped and things set up 368144341Sharti * to go back to reading the previous file at the previous location. 369144341Sharti * 370144341Sharti * Results: 371144341Sharti * CONTINUE if there's more to do. DONE if not. 372144341Sharti * 373144341Sharti * Side Effects: 374144341Sharti * The old curFile.F is closed. The includes list is shortened. 375144341Sharti * curFile.lineno, curFile.F, and curFile.fname are changed if 376144341Sharti * CONTINUE is returned. 377144341Sharti */ 378144341Shartistatic int 379144341ShartiParsePopInput(void) 380144341Sharti{ 381144341Sharti struct IFile *ifile; /* the state on the top of the includes stack */ 382144341Sharti 383144341Sharti assert(!TAILQ_EMPTY(&includes)); 384144341Sharti 385144341Sharti ifile = TAILQ_FIRST(&includes); 386144341Sharti TAILQ_REMOVE(&includes, ifile, link); 387144341Sharti 388144341Sharti free(ifile->fname); 389144341Sharti if (ifile->F != NULL) { 390144341Sharti fclose(ifile->F); 391144341Sharti Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 392144341Sharti } 393144341Sharti if (ifile->str != NULL) { 394144341Sharti free(ifile->str); 395144341Sharti } 396144341Sharti free(ifile); 397144341Sharti 398144341Sharti return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); 399144341Sharti} 400144341Sharti 401145679Sharti/** 402145679Sharti * parse_warn 403145679Sharti * Parse the .WARN pseudo-target. 404145679Sharti */ 405145679Shartistatic void 406145679Shartiparse_warn(char *line) 407145679Sharti{ 408145679Sharti char **argv; 409145679Sharti int argc; 410145679Sharti int i; 411145679Sharti 412145679Sharti argv = brk_string(line, &argc, TRUE); 413145679Sharti 414145679Sharti for (i = 1; i < argc; i++) 415145679Sharti Main_ParseWarn(argv[i], 0); 416145679Sharti} 417145679Sharti 4181590Srgrimes/*- 4191590Srgrimes *--------------------------------------------------------------------- 4201590Srgrimes * ParseLinkSrc -- 421143100Sharti * Link the parent nodes to their new child. Used by 4221590Srgrimes * ParseDoDependency. If the specType isn't 'Not', the parent 4231590Srgrimes * isn't linked as a parent of the child. 4241590Srgrimes * 4251590Srgrimes * Side Effects: 426143100Sharti * New elements are added to the parents lists of cgn and the 4271590Srgrimes * children list of cgn. the unmade field of pgn is updated 4281590Srgrimes * to reflect the additional child. 4291590Srgrimes *--------------------------------------------------------------------- 4301590Srgrimes */ 431143027Shartistatic void 432143027ShartiParseLinkSrc(Lst *parents, GNode *cgn) 4331590Srgrimes{ 434143027Sharti LstNode *ln; 435143027Sharti GNode *pgn; 436138232Sharti 437143027Sharti LST_FOREACH(ln, parents) { 438143027Sharti pgn = Lst_Datum(ln); 439143027Sharti if (Lst_Member(&pgn->children, cgn) == NULL) { 440143027Sharti Lst_AtEnd(&pgn->children, cgn); 441143027Sharti if (specType == Not) { 442143027Sharti Lst_AtEnd(&cgn->parents, pgn); 443143027Sharti } 444143027Sharti pgn->unmade += 1; 445143027Sharti } 4461590Srgrimes } 4471590Srgrimes} 4481590Srgrimes 4491590Srgrimes/*- 4501590Srgrimes *--------------------------------------------------------------------- 4511590Srgrimes * ParseDoOp -- 452143684Sharti * Apply the parsed operator to all target nodes. Used in 453143684Sharti * ParseDoDependency once all targets have been found and their 454143684Sharti * operator parsed. If the previous and new operators are incompatible, 455143684Sharti * a major error is taken. 4561590Srgrimes * 4571590Srgrimes * Side Effects: 4581590Srgrimes * The type field of the node is altered to reflect any new bits in 4591590Srgrimes * the op. 4601590Srgrimes *--------------------------------------------------------------------- 4611590Srgrimes */ 462143684Shartistatic void 463143684ShartiParseDoOp(int op) 4641590Srgrimes{ 465143684Sharti GNode *cohort; 466143684Sharti LstNode *ln; 467143684Sharti GNode *gn; 468138232Sharti 469143684Sharti LST_FOREACH(ln, &targets) { 470143684Sharti gn = Lst_Datum(ln); 4711590Srgrimes 472143684Sharti /* 473143684Sharti * If the dependency mask of the operator and the node don't 474143684Sharti * match and the node has actually had an operator applied to 475143684Sharti * it before, and the operator actually has some dependency 476143684Sharti * information in it, complain. 477143684Sharti */ 478143684Sharti if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && 479143684Sharti !OP_NOP(gn->type) && !OP_NOP(op)) { 480143684Sharti Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 481143684Sharti gn->name); 482143684Sharti return; 483143684Sharti } 4848874Srgrimes 485143684Sharti if (op == OP_DOUBLEDEP && 486143684Sharti (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 487143684Sharti /* 488143684Sharti * If the node was the object of a :: operator, we need 489143684Sharti * to create a new instance of it for the children and 490143684Sharti * commands on this dependency line. The new instance 491143684Sharti * is placed on the 'cohorts' list of the initial one 492143684Sharti * (note the initial one is not on its own cohorts list) 493143684Sharti * and the new instance is linked to all parents of the 494143684Sharti * initial instance. 495143684Sharti */ 496143684Sharti cohort = Targ_NewGN(gn->name); 4971590Srgrimes 498143684Sharti /* 499143684Sharti * Duplicate links to parents so graph traversal is 500143684Sharti * simple. Perhaps some type bits should be duplicated? 501143684Sharti * 502143684Sharti * Make the cohort invisible as well to avoid 503143684Sharti * duplicating it into other variables. True, parents 504143684Sharti * of this target won't tend to do anything with their 505143684Sharti * local variables, but better safe than sorry. 506143684Sharti */ 507143684Sharti ParseLinkSrc(&gn->parents, cohort); 508143684Sharti cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 509143684Sharti Lst_AtEnd(&gn->cohorts, cohort); 5101590Srgrimes 511143684Sharti /* 512143684Sharti * Replace the node in the targets list with the 513143684Sharti * new copy 514143684Sharti */ 515143684Sharti Lst_Replace(ln, cohort); 516143684Sharti gn = cohort; 517143684Sharti } 518143684Sharti /* 519143684Sharti * We don't want to nuke any previous flags (whatever they were) 520143684Sharti * so we just OR the new operator into the old 521143684Sharti */ 522143684Sharti gn->type |= op; 523143684Sharti } 5241590Srgrimes} 5251590Srgrimes 5261590Srgrimes/*- 5271590Srgrimes *--------------------------------------------------------------------- 5281590Srgrimes * ParseDoSrc -- 5291590Srgrimes * Given the name of a source, figure out if it is an attribute 5301590Srgrimes * and apply it to the targets if it is. Else decide if there is 5311590Srgrimes * some attribute which should be applied *to* the source because 5321590Srgrimes * of some special target and apply it if so. Otherwise, make the 5331590Srgrimes * source be a child of the targets in the list 'targets' 5341590Srgrimes * 5351590Srgrimes * Results: 5361590Srgrimes * None 5371590Srgrimes * 5381590Srgrimes * Side Effects: 5391590Srgrimes * Operator bits may be added to the list of targets or to the source. 5401590Srgrimes * The targets may have a new source added to their lists of children. 5411590Srgrimes *--------------------------------------------------------------------- 5421590Srgrimes */ 5431590Srgrimesstatic void 544138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc) 5451590Srgrimes{ 546144026Sharti GNode *gn = NULL; 547145616Sharti const struct keyword *kw; 5481590Srgrimes 549145616Sharti if (src[0] == '.' && isupper ((unsigned char)src[1])) { 550145616Sharti if ((kw = ParseFindKeyword(src)) != NULL) { 551145616Sharti if (kw->op != 0) { 552145616Sharti ParseDoOp(kw->op); 553144026Sharti return; 554144026Sharti } 555145616Sharti if (kw->spec == Wait) { 556144026Sharti waiting++; 557144026Sharti return; 558144026Sharti } 559144026Sharti } 5601590Srgrimes } 56118730Ssteve 562144026Sharti switch (specType) { 563144026Sharti case Main: 564144026Sharti /* 565144026Sharti * If we have noted the existence of a .MAIN, it means we need 566144026Sharti * to add the sources of said target to the list of things 567144026Sharti * to create. The string 'src' is likely to be free, so we 568144026Sharti * must make a new copy of it. Note that this will only be 569144026Sharti * invoked if the user didn't specify a target on the command 570144026Sharti * line. This is to allow #ifmake's to succeed, or something... 571144026Sharti */ 572144026Sharti Lst_AtEnd(&create, estrdup(src)); 573144026Sharti /* 574144026Sharti * Add the name to the .TARGETS variable as well, so the user 575144026Sharti * can employ that, if desired. 576144026Sharti */ 577144026Sharti Var_Append(".TARGETS", src, VAR_GLOBAL); 578144026Sharti return; 57918730Ssteve 580144026Sharti case Order: 581144026Sharti /* 582144026Sharti * Create proper predecessor/successor links between the 583144026Sharti * previous source and the current one. 584144026Sharti */ 585144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 586144026Sharti if (predecessor != NULL) { 587144026Sharti Lst_AtEnd(&predecessor->successors, gn); 588144026Sharti Lst_AtEnd(&gn->preds, predecessor); 589144026Sharti } 590144026Sharti /* 591144026Sharti * The current source now becomes the predecessor for the next 592144026Sharti * one. 593144026Sharti */ 594144026Sharti predecessor = gn; 595144026Sharti break; 59618730Ssteve 597144026Sharti default: 598144026Sharti /* 599144026Sharti * If the source is not an attribute, we need to find/create 600144026Sharti * a node for it. After that we can apply any operator to it 601144026Sharti * from a special target or link it to its parents, as 602144026Sharti * appropriate. 603144026Sharti * 604144026Sharti * In the case of a source that was the object of a :: operator, 605144026Sharti * the attribute is applied to all of its instances (as kept in 606144026Sharti * the 'cohorts' list of the node) or all the cohorts are linked 607144026Sharti * to all the targets. 608144026Sharti */ 609144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 6101590Srgrimes if (tOp) { 611144026Sharti gn->type |= tOp; 6121590Srgrimes } else { 613144026Sharti ParseLinkSrc(&targets, gn); 6141590Srgrimes } 615144026Sharti if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 616144026Sharti GNode *cohort; 617144026Sharti LstNode *ln; 618144026Sharti 619144026Sharti for (ln = Lst_First(&gn->cohorts); ln != NULL; 620144026Sharti ln = Lst_Succ(ln)) { 621144026Sharti cohort = Lst_Datum(ln); 622144026Sharti if (tOp) { 623144026Sharti cohort->type |= tOp; 624144026Sharti } else { 625144026Sharti ParseLinkSrc(&targets, cohort); 626144026Sharti } 627144026Sharti } 628144026Sharti } 629144026Sharti break; 6301590Srgrimes } 63118730Ssteve 632144026Sharti gn->order = waiting; 633144026Sharti Lst_AtEnd(allsrc, gn); 634144026Sharti if (waiting) { 635144026Sharti LstNode *ln; 636144026Sharti GNode *p; 6371590Srgrimes 638143684Sharti /* 639144026Sharti * Check if GNodes needs to be synchronized. 640144026Sharti * This has to be when two nodes are on different sides of a 641144026Sharti * .WAIT directive. 642143684Sharti */ 643144026Sharti LST_FOREACH(ln, allsrc) { 644144026Sharti p = Lst_Datum(ln); 645144026Sharti 646144026Sharti if (p->order >= gn->order) 647144026Sharti break; 648144026Sharti /* 649144026Sharti * XXX: This can cause loops, and loops can cause 650144026Sharti * unmade targets, but checking is tedious, and the 651144026Sharti * debugging output can show the problem 652144026Sharti */ 653144026Sharti Lst_AtEnd(&p->successors, gn); 654144026Sharti Lst_AtEnd(&gn->preds, p); 655144026Sharti } 656143684Sharti } 6571590Srgrimes} 6581590Srgrimes 659138232Sharti 6601590Srgrimes/*- 6611590Srgrimes *--------------------------------------------------------------------- 6621590Srgrimes * ParseDoDependency -- 6631590Srgrimes * Parse the dependency line in line. 6641590Srgrimes * 6651590Srgrimes * Results: 6661590Srgrimes * None 6671590Srgrimes * 6681590Srgrimes * Side Effects: 6691590Srgrimes * The nodes of the sources are linked as children to the nodes of the 6701590Srgrimes * targets. Some nodes may be created. 6711590Srgrimes * 6721590Srgrimes * We parse a dependency line by first extracting words from the line and 6731590Srgrimes * finding nodes in the list of all targets with that name. This is done 6741590Srgrimes * until a character is encountered which is an operator character. Currently 6751590Srgrimes * these are only ! and :. At this point the operator is parsed and the 6761590Srgrimes * pointer into the line advanced until the first source is encountered. 677144026Sharti * The parsed operator is applied to each node in the 'targets' list, 6781590Srgrimes * which is where the nodes found for the targets are kept, by means of 6791590Srgrimes * the ParseDoOp function. 6801590Srgrimes * The sources are read in much the same way as the targets were except 6811590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell 6821590Srgrimes * and all instances of the resulting words in the list of all targets 6831590Srgrimes * are found. Each of the resulting nodes is then linked to each of the 6841590Srgrimes * targets as one of its children. 6851590Srgrimes * Certain targets are handled specially. These are the ones detailed 6861590Srgrimes * by the specType variable. 6871590Srgrimes * The storing of transformation rules is also taken care of here. 6881590Srgrimes * A target is recognized as a transformation rule by calling 6891590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten 6901590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard 6911590Srgrimes * Targ_FindNode in the target module. 6921590Srgrimes *--------------------------------------------------------------------- 6931590Srgrimes */ 6941590Srgrimesstatic void 695141270ShartiParseDoDependency(char *line) 6961590Srgrimes{ 697144026Sharti char *cp; /* our current position */ 698144026Sharti GNode *gn; /* a general purpose temporary node */ 699144026Sharti int op; /* the operator on the line */ 700144026Sharti char savec; /* a place to save a character */ 701144026Sharti Lst paths; /* Search paths to alter when parsing .PATH targets */ 702144026Sharti int tOp; /* operator from special target */ 703144026Sharti LstNode *ln; 704145616Sharti const struct keyword *kw; 7051590Srgrimes 706144026Sharti tOp = 0; 7071590Srgrimes 708144026Sharti specType = Not; 709144026Sharti waiting = 0; 710144026Sharti Lst_Init(&paths); 7111590Srgrimes 712144026Sharti do { 713144026Sharti for (cp = line; 714144026Sharti *cp && !isspace((unsigned char)*cp) && *cp != '('; 715144026Sharti cp++) { 716144026Sharti if (*cp == '$') { 717144026Sharti /* 718144026Sharti * Must be a dynamic source (would have been 719144026Sharti * expanded otherwise), so call the Var module 720144026Sharti * to parse the puppy so we can safely advance 721144026Sharti * beyond it...There should be no errors in this 722144026Sharti * as they would have been discovered in the 723144026Sharti * initial Var_Subst and we wouldn't be here. 724144026Sharti */ 725144026Sharti size_t length = 0; 726144026Sharti Boolean freeIt; 727144026Sharti char *result; 7281590Srgrimes 729144026Sharti result = Var_Parse(cp, VAR_CMD, TRUE, 730144026Sharti &length, &freeIt); 7311590Srgrimes 732144026Sharti if (freeIt) { 733144026Sharti free(result); 734144026Sharti } 735144026Sharti cp += length - 1; 736102178Sru 737144026Sharti } else if (*cp == '!' || *cp == ':') { 738144026Sharti /* 739144026Sharti * We don't want to end a word on ':' or '!' if 740144026Sharti * there is a better match later on in the 741144026Sharti * string (greedy matching). 742144026Sharti * This allows the user to have targets like: 743144026Sharti * fie::fi:fo: fum 744144026Sharti * foo::bar: 745144026Sharti * where "fie::fi:fo" and "foo::bar" are the 746144026Sharti * targets. In real life this is used for perl5 747144026Sharti * library man pages where "::" separates an 748144026Sharti * object from its class. Ie: 749144026Sharti * "File::Spec::Unix". This behaviour is also 750144026Sharti * consistent with other versions of make. 751144026Sharti */ 752144026Sharti char *p = cp + 1; 753102178Sru 754144026Sharti if (*cp == ':' && *p == ':') 755144026Sharti p++; 756102178Sru 757144026Sharti /* Found the best match already. */ 758144026Sharti if (*p == '\0' || isspace(*p)) 759144026Sharti break; 760102178Sru 761144026Sharti p += strcspn(p, "!:"); 7628874Srgrimes 763144026Sharti /* No better match later on... */ 764144026Sharti if (*p == '\0') 765144026Sharti break; 766144026Sharti } 767144026Sharti continue; 7681590Srgrimes } 769144026Sharti if (*cp == '(') { 770144026Sharti /* 771144026Sharti * Archives must be handled specially to make sure the 772144026Sharti * OP_ARCHV flag is set in their 'type' field, for one 773144026Sharti * thing, and because things like "archive(file1.o 774144026Sharti * file2.o file3.o)" are permissible. Arch_ParseArchive 775144026Sharti * will set 'line' to be the first non-blank after the 776144026Sharti * archive-spec. It creates/finds nodes for the members 777144026Sharti * and places them on the given list, returning SUCCESS 778144026Sharti * if all went well and FAILURE if there was an error in 779144026Sharti * the specification. On error, line should remain 780144026Sharti * untouched. 781144026Sharti */ 782144026Sharti if (Arch_ParseArchive(&line, &targets, VAR_CMD) != 783144026Sharti SUCCESS) { 784144026Sharti Parse_Error(PARSE_FATAL, 785144026Sharti "Error in archive specification: \"%s\"", 786144026Sharti line); 787144026Sharti return; 788144026Sharti } else { 789144026Sharti cp = line; 790144026Sharti continue; 791144026Sharti } 792144026Sharti } 793144026Sharti savec = *cp; 7948874Srgrimes 795144026Sharti if (!*cp) { 796144026Sharti /* 797144026Sharti * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often 798144026Sharti * triggered by undetected conflicts from cvs/rcs 799144026Sharti * merges. 800144026Sharti */ 801144026Sharti if (strncmp(line, "<<<<<<", 6) == 0 || 802144026Sharti strncmp(line, "======", 6) == 0 || 803144026Sharti strncmp(line, ">>>>>>", 6) == 0) { 804144026Sharti Parse_Error(PARSE_FATAL, "Makefile appears to " 805144026Sharti "contain unresolved cvs/rcs/??? merge " 806144026Sharti "conflicts"); 807144026Sharti } else 808144026Sharti Parse_Error(PARSE_FATAL, "Need an operator"); 809144026Sharti return; 810144026Sharti } 811144026Sharti *cp = '\0'; 8121590Srgrimes /* 813144026Sharti * Have a word in line. See if it's a special target and set 814144026Sharti * specType to match it. 8151590Srgrimes */ 816144026Sharti if (*line == '.' && isupper((unsigned char)line[1])) { 817144026Sharti /* 818144026Sharti * See if the target is a special target that must have 819144026Sharti * it or its sources handled specially. 820144026Sharti */ 821145616Sharti if ((kw = ParseFindKeyword(line)) != NULL) { 822145616Sharti if (specType == ExPath && kw->spec != ExPath) { 823144026Sharti Parse_Error(PARSE_FATAL, 824144026Sharti "Mismatched special targets"); 825144026Sharti return; 826144026Sharti } 827144026Sharti 828145616Sharti specType = kw->spec; 829145616Sharti tOp = kw->op; 830144026Sharti 831144026Sharti /* 832144026Sharti * Certain special targets have special 833144026Sharti * semantics: 834144026Sharti * .PATH Have to set the dirSearchPath 835144026Sharti * variable too 836144026Sharti * .MAIN Its sources are only used if 837144026Sharti * nothing has been specified to 838144026Sharti * create. 839144026Sharti * .DEFAULT Need to create a node to hang 840144026Sharti * commands on, but we don't want 841144026Sharti * it in the graph, nor do we want 842144026Sharti * it to be the Main Target, so we 843144026Sharti * create it, set OP_NOTMAIN and 844144026Sharti * add it to the list, setting 845144026Sharti * DEFAULT to the new node for 846144026Sharti * later use. We claim the node is 847144026Sharti * A transformation rule to make 848144026Sharti * life easier later, when we'll 849144026Sharti * use Make_HandleUse to actually 850144026Sharti * apply the .DEFAULT commands. 851144026Sharti * .PHONY The list of targets 852144026Sharti * .BEGIN 853144026Sharti * .END 854144026Sharti * .INTERRUPT Are not to be considered the 855144026Sharti * main target. 856144026Sharti * .NOTPARALLEL Make only one target at a time. 857144026Sharti * .SINGLESHELL Create a shell for each 858144026Sharti * command. 859144026Sharti * .ORDER Must set initial predecessor 860144026Sharti * to NULL 861144026Sharti */ 862144026Sharti switch (specType) { 863144026Sharti case ExPath: 864144026Sharti Lst_AtEnd(&paths, &dirSearchPath); 865144026Sharti break; 866144026Sharti case Main: 867144026Sharti if (!Lst_IsEmpty(&create)) { 868144026Sharti specType = Not; 869144026Sharti } 870144026Sharti break; 871144026Sharti case Begin: 872144026Sharti case End: 873144026Sharti case Interrupt: 874144026Sharti gn = Targ_FindNode(line, TARG_CREATE); 875144026Sharti gn->type |= OP_NOTMAIN; 876144026Sharti Lst_AtEnd(&targets, gn); 877144026Sharti break; 878144026Sharti case Default: 879144026Sharti gn = Targ_NewGN(".DEFAULT"); 880144026Sharti gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 881144026Sharti Lst_AtEnd(&targets, gn); 882144026Sharti DEFAULT = gn; 883144026Sharti break; 884144026Sharti case NotParallel: 885146140Sharti jobLimit = 1; 886144026Sharti break; 887144026Sharti case SingleShell: 888144026Sharti compatMake = 1; 889144026Sharti break; 890144026Sharti case Order: 891144026Sharti predecessor = NULL; 892144026Sharti break; 893144026Sharti default: 894144026Sharti break; 895144026Sharti } 896144026Sharti 897144026Sharti } else if (strncmp(line, ".PATH", 5) == 0) { 898144026Sharti /* 899144026Sharti * .PATH<suffix> has to be handled specially. 900144026Sharti * Call on the suffix module to give us a path 901144026Sharti * to modify. 902144026Sharti */ 903144026Sharti struct Path *path; 904144026Sharti 905144026Sharti specType = ExPath; 906144026Sharti path = Suff_GetPath(&line[5]); 907144026Sharti if (path == NULL) { 908144026Sharti Parse_Error(PARSE_FATAL, "Suffix '%s' " 909144026Sharti "not defined (yet)", &line[5]); 910144026Sharti return; 911144026Sharti } else 912144026Sharti Lst_AtEnd(&paths, path); 9131590Srgrimes } 9141590Srgrimes } 915144026Sharti 9161590Srgrimes /* 917144026Sharti * Have word in line. Get or create its node and stick it at 918144026Sharti * the end of the targets list 9191590Srgrimes */ 920144029Sharti if (specType == Not && *line != '\0') { 9218874Srgrimes 922144026Sharti /* target names to be found and added to targets list */ 923144026Sharti Lst curTargs = Lst_Initializer(curTargs); 9248874Srgrimes 925144026Sharti if (Dir_HasWildcards(line)) { 926144026Sharti /* 927144026Sharti * Targets are to be sought only in the current 928144026Sharti * directory, so create an empty path for the 929144026Sharti * thing. Note we need to use Path_Clear in the 930144026Sharti * destruction of the path as the Dir module 931144026Sharti * could have added a directory to the path... 932144026Sharti */ 933144026Sharti struct Path emptyPath = 934144026Sharti TAILQ_HEAD_INITIALIZER(emptyPath); 935138916Sharti 936144026Sharti Path_Expand(line, &emptyPath, &curTargs); 937144026Sharti Path_Clear(&emptyPath); 9388874Srgrimes 939144026Sharti } else { 940144026Sharti /* 941144026Sharti * No wildcards, but we want to avoid code 942144026Sharti * duplication, so create a list with the word 943144026Sharti * on it. 944144026Sharti */ 945144026Sharti Lst_AtEnd(&curTargs, line); 946144026Sharti } 9478874Srgrimes 948144026Sharti while (!Lst_IsEmpty(&curTargs)) { 949144026Sharti char *targName = Lst_DeQueue(&curTargs); 950144026Sharti 951144026Sharti if (!Suff_IsTransform (targName)) { 952144026Sharti gn = Targ_FindNode(targName, 953144026Sharti TARG_CREATE); 954144026Sharti } else { 955144026Sharti gn = Suff_AddTransform(targName); 956144026Sharti } 957144026Sharti 958144026Sharti Lst_AtEnd(&targets, gn); 959144026Sharti } 960144026Sharti } else if (specType == ExPath && *line != '.' && *line != '\0'){ 961144026Sharti Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 962144026Sharti line); 963144026Sharti } 964144026Sharti 965144026Sharti *cp = savec; 9661590Srgrimes /* 967144026Sharti * If it is a special type and not .PATH, it's the only 968144026Sharti * target we allow on this line... 9691590Srgrimes */ 970144026Sharti if (specType != Not && specType != ExPath) { 971144026Sharti Boolean warnFlag = FALSE; 9728874Srgrimes 973144029Sharti while (*cp != '!' && *cp != ':' && *cp) { 974144026Sharti if (*cp != ' ' && *cp != '\t') { 975144026Sharti warnFlag = TRUE; 976144026Sharti } 977144026Sharti cp++; 978144026Sharti } 979144026Sharti if (warnFlag) { 980144026Sharti Parse_Error(PARSE_WARNING, 981144026Sharti "Extra target ignored"); 982144026Sharti } 9831590Srgrimes } else { 984144026Sharti while (*cp && isspace((unsigned char)*cp)) { 985144026Sharti cp++; 986144026Sharti } 9871590Srgrimes } 988144026Sharti line = cp; 989144029Sharti } while (*line != '!' && *line != ':' && *line); 9908874Srgrimes 991144026Sharti if (!Lst_IsEmpty(&targets)) { 992144026Sharti switch (specType) { 993144026Sharti default: 994144026Sharti Parse_Error(PARSE_WARNING, "Special and mundane " 995144026Sharti "targets don't mix. Mundane ones ignored"); 996144026Sharti break; 997144026Sharti case Default: 998144026Sharti case Begin: 999144026Sharti case End: 1000144026Sharti case Interrupt: 1001144026Sharti /* 1002144026Sharti * These four create nodes on which to hang commands, so 1003144026Sharti * targets shouldn't be empty... 1004144026Sharti */ 1005144026Sharti case Not: 1006144026Sharti /* 1007144026Sharti * Nothing special here -- targets can be empty if it 1008144026Sharti * wants. 1009144026Sharti */ 1010144026Sharti break; 1011144026Sharti } 10121590Srgrimes } 10138874Srgrimes 10141590Srgrimes /* 1015144026Sharti * Have now parsed all the target names. Must parse the operator next. 1016144026Sharti * The result is left in op. 10171590Srgrimes */ 1018144026Sharti if (*cp == '!') { 1019144026Sharti op = OP_FORCE; 1020144026Sharti } else if (*cp == ':') { 1021144026Sharti if (cp[1] == ':') { 1022144026Sharti op = OP_DOUBLEDEP; 1023144026Sharti cp++; 1024144026Sharti } else { 1025144026Sharti op = OP_DEPENDS; 10261590Srgrimes } 10271590Srgrimes } else { 1028144026Sharti Parse_Error(PARSE_FATAL, "Missing dependency operator"); 1029144026Sharti return; 1030144026Sharti } 1031144026Sharti 1032144026Sharti cp++; /* Advance beyond operator */ 1033144026Sharti 1034144026Sharti ParseDoOp(op); 1035144026Sharti 1036144026Sharti /* 1037144026Sharti * Get to the first source 1038144026Sharti */ 1039144026Sharti while (*cp && isspace((unsigned char)*cp)) { 10401590Srgrimes cp++; 10411590Srgrimes } 10421590Srgrimes line = cp; 10431590Srgrimes 1044144026Sharti /* 1045144026Sharti * Several special targets take different actions if present with no 1046144026Sharti * sources: 1047144026Sharti * a .SUFFIXES line with no sources clears out all old suffixes 1048144026Sharti * a .PRECIOUS line makes all targets precious 1049144026Sharti * a .IGNORE line ignores errors for all targets 1050144026Sharti * a .SILENT line creates silence when making all targets 1051144026Sharti * a .PATH removes all directories from the search path(s). 1052144026Sharti */ 1053144026Sharti if (!*line) { 1054144026Sharti switch (specType) { 1055144026Sharti case Suffixes: 1056144026Sharti Suff_ClearSuffixes(); 1057144026Sharti break; 1058144026Sharti case Precious: 1059144026Sharti allPrecious = TRUE; 1060144026Sharti break; 1061144026Sharti case Ignore: 1062144026Sharti ignoreErrors = TRUE; 1063144026Sharti break; 1064144026Sharti case Silent: 1065144026Sharti beSilent = TRUE; 1066144026Sharti break; 1067144026Sharti case ExPath: 1068144026Sharti LST_FOREACH(ln, &paths) 1069144026Sharti Path_Clear(Lst_Datum(ln)); 1070144026Sharti break; 1071144026Sharti case Posix: 1072144026Sharti Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 1073144026Sharti break; 1074144026Sharti default: 1075144026Sharti break; 1076144026Sharti } 1077144026Sharti 1078144026Sharti } else if (specType == MFlags) { 10791590Srgrimes /* 1080144026Sharti * Call on functions in main.c to deal with these arguments and 1081144026Sharti * set the initial character to a null-character so the loop to 1082144026Sharti * get sources won't get anything 10831590Srgrimes */ 1084144026Sharti Main_ParseArgLine(line, 0); 1085144026Sharti *line = '\0'; 10861590Srgrimes 1087145679Sharti } else if (specType == Warn) { 1088145679Sharti parse_warn(line); 1089145679Sharti *line = '\0'; 1090145679Sharti 1091144026Sharti } else if (specType == ExShell) { 1092144026Sharti if (Job_ParseShell(line) != SUCCESS) { 1093144026Sharti Parse_Error(PARSE_FATAL, 1094144026Sharti "improper shell specification"); 1095144026Sharti return; 1096144026Sharti } 1097144026Sharti *line = '\0'; 1098144026Sharti 1099144029Sharti } else if (specType == NotParallel || specType == SingleShell) { 1100144026Sharti *line = '\0'; 11011590Srgrimes } 11021590Srgrimes 1103144026Sharti /* 1104144026Sharti * NOW GO FOR THE SOURCES 1105144026Sharti */ 1106144029Sharti if (specType == Suffixes || specType == ExPath || 1107144029Sharti specType == Includes || specType == Libs || 1108144029Sharti specType == Null) { 1109144026Sharti while (*line) { 1110144026Sharti /* 1111144026Sharti * If the target was one that doesn't take files as its 1112144026Sharti * sources but takes something like suffixes, we take 1113144026Sharti * each space-separated word on the line as a something 1114144026Sharti * and deal with it accordingly. 1115144026Sharti * 1116144026Sharti * If the target was .SUFFIXES, we take each source as 1117144026Sharti * a suffix and add it to the list of suffixes 1118144026Sharti * maintained by the Suff module. 1119144026Sharti * 1120144026Sharti * If the target was a .PATH, we add the source as a 1121144026Sharti * directory to search on the search path. 1122144026Sharti * 1123144026Sharti * If it was .INCLUDES, the source is taken to be the 1124144026Sharti * suffix of files which will be #included and whose 1125144026Sharti * search path should be present in the .INCLUDES 1126144026Sharti * variable. 1127144026Sharti * 1128144026Sharti * If it was .LIBS, the source is taken to be the 1129144026Sharti * suffix of files which are considered libraries and 1130144026Sharti * whose search path should be present in the .LIBS 1131144026Sharti * variable. 1132144026Sharti * 1133144026Sharti * If it was .NULL, the source is the suffix to use 1134144026Sharti * when a file has no valid suffix. 1135144026Sharti */ 1136144026Sharti char savech; 1137144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1138144026Sharti cp++; 1139144026Sharti } 1140144026Sharti savech = *cp; 1141144026Sharti *cp = '\0'; 1142144026Sharti switch (specType) { 1143144026Sharti case Suffixes: 1144144026Sharti Suff_AddSuffix(line); 1145144026Sharti break; 1146144026Sharti case ExPath: 1147144026Sharti LST_FOREACH(ln, &paths) 1148144026Sharti Path_AddDir(Lst_Datum(ln), line); 1149144026Sharti break; 1150144026Sharti case Includes: 1151144026Sharti Suff_AddInclude(line); 1152144026Sharti break; 1153144026Sharti case Libs: 1154144026Sharti Suff_AddLib(line); 1155144026Sharti break; 1156144026Sharti case Null: 1157144026Sharti Suff_SetNull(line); 1158144026Sharti break; 1159144026Sharti default: 1160144026Sharti break; 1161144026Sharti } 1162144026Sharti *cp = savech; 1163144026Sharti if (savech != '\0') { 1164144026Sharti cp++; 1165144026Sharti } 1166144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1167144026Sharti cp++; 1168144026Sharti } 1169144026Sharti line = cp; 1170144026Sharti } 1171144026Sharti Lst_Destroy(&paths, NOFREE); 11721590Srgrimes 1173145971Sharti } else if (specType == ExportVar) { 1174145971Sharti Var_SetEnv(line, VAR_GLOBAL); 1175145971Sharti 1176144026Sharti } else { 1177144026Sharti /* list of sources in order */ 1178144026Sharti Lst curSrcs = Lst_Initializer(curSrc); 11791590Srgrimes 1180144026Sharti while (*line) { 1181144026Sharti /* 1182144026Sharti * The targets take real sources, so we must beware of 1183144026Sharti * archive specifications (i.e. things with left 1184144026Sharti * parentheses in them) and handle them accordingly. 1185144026Sharti */ 1186144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1187144026Sharti if (*cp == '(' && cp > line && cp[-1] != '$') { 1188144026Sharti /* 1189144026Sharti * Only stop for a left parenthesis if 1190144026Sharti * it isn't at the start of a word 1191144026Sharti * (that'll be for variable changes 1192144026Sharti * later) and isn't preceded by a dollar 1193144026Sharti * sign (a dynamic source). 1194144026Sharti */ 1195144026Sharti break; 1196144026Sharti } else { 1197144026Sharti cp++; 1198144026Sharti } 1199144026Sharti } 12001590Srgrimes 1201144026Sharti if (*cp == '(') { 1202144026Sharti GNode *gnp; 12038874Srgrimes 1204144026Sharti /* list of archive source names after exp. */ 1205144026Sharti Lst sources = Lst_Initializer(sources); 1206138916Sharti 1207144026Sharti if (Arch_ParseArchive(&line, &sources, 1208144026Sharti VAR_CMD) != SUCCESS) { 1209144026Sharti Parse_Error(PARSE_FATAL, "Error in " 1210144026Sharti "source archive spec \"%s\"", line); 1211144026Sharti return; 1212144026Sharti } 1213141270Sharti 1214144026Sharti while (!Lst_IsEmpty(&sources)) { 1215144026Sharti gnp = Lst_DeQueue(&sources); 1216144026Sharti ParseDoSrc(tOp, gnp->name, &curSrcs); 1217144026Sharti } 1218144026Sharti cp = line; 1219144026Sharti } else { 1220144026Sharti if (*cp) { 1221144026Sharti *cp = '\0'; 1222144026Sharti cp += 1; 1223144026Sharti } 12241590Srgrimes 1225144026Sharti ParseDoSrc(tOp, line, &curSrcs); 1226144026Sharti } 1227144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1228144026Sharti cp++; 1229144026Sharti } 1230144026Sharti line = cp; 12311590Srgrimes } 1232144026Sharti Lst_Destroy(&curSrcs, NOFREE); 1233144026Sharti } 12341590Srgrimes 1235144026Sharti if (mainNode == NULL) { 1236144026Sharti /* 1237144026Sharti * If we have yet to decide on a main target to make, in the 1238144026Sharti * absence of any user input, we want the first target on 1239144026Sharti * the first dependency line that is actually a real target 1240144026Sharti * (i.e. isn't a .USE or .EXEC rule) to be made. 1241144026Sharti */ 1242144026Sharti LST_FOREACH(ln, &targets) { 1243144026Sharti gn = Lst_Datum(ln); 1244144026Sharti if ((gn->type & (OP_NOTMAIN | OP_USE | 1245144026Sharti OP_EXEC | OP_TRANSFORM)) == 0) { 1246144026Sharti mainNode = gn; 1247144026Sharti Targ_SetMain(gn); 1248144026Sharti break; 1249144026Sharti } 12501590Srgrimes } 12511590Srgrimes } 12521590Srgrimes} 12531590Srgrimes 12541590Srgrimes/*- 12551590Srgrimes *--------------------------------------------------------------------- 12561590Srgrimes * Parse_IsVar -- 12571590Srgrimes * Return TRUE if the passed line is a variable assignment. A variable 12581590Srgrimes * assignment consists of a single word followed by optional whitespace 12591590Srgrimes * followed by either a += or an = operator. 12601590Srgrimes * This function is used both by the Parse_File function and main when 12611590Srgrimes * parsing the command-line arguments. 12621590Srgrimes * 12631590Srgrimes * Results: 12641590Srgrimes * TRUE if it is. FALSE if it ain't 12651590Srgrimes * 12661590Srgrimes * Side Effects: 12671590Srgrimes * none 12681590Srgrimes *--------------------------------------------------------------------- 12691590Srgrimes */ 12701590SrgrimesBoolean 1271138232ShartiParse_IsVar(char *line) 12721590Srgrimes{ 1273144026Sharti Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1274144026Sharti Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1275138232Sharti 1276144026Sharti int level = 0; 1277103503Sjmallett#define ISEQOPERATOR(c) \ 1278144029Sharti ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') 12791590Srgrimes 1280144026Sharti /* 1281144026Sharti * Skip to variable name 1282144026Sharti */ 1283144029Sharti for (; *line == ' ' || *line == '\t'; line++) 1284144026Sharti continue; 12851590Srgrimes 1286144026Sharti for (; *line != '=' || level != 0; line++) { 1287144026Sharti switch (*line) { 1288144026Sharti case '\0': 1289144026Sharti /* 1290144026Sharti * end-of-line -- can't be a variable assignment. 1291144026Sharti */ 1292144026Sharti return (FALSE); 129318730Ssteve 1294144026Sharti case ' ': 1295144026Sharti case '\t': 1296144026Sharti /* 1297144026Sharti * there can be as much white space as desired so long 1298144026Sharti * as there is only one word before the operator 1299144026Sharti */ 1300144026Sharti wasSpace = TRUE; 1301144026Sharti break; 130218730Ssteve 1303144026Sharti case '(': 1304144026Sharti case '{': 1305144026Sharti level++; 1306144026Sharti break; 130718730Ssteve 1308144026Sharti case '}': 1309144026Sharti case ')': 1310144026Sharti level--; 1311144026Sharti break; 131218730Ssteve 1313144026Sharti default: 1314144026Sharti if (wasSpace && haveName) { 1315144026Sharti if (ISEQOPERATOR(*line)) { 1316144026Sharti /* 1317144026Sharti * We must have a finished word 1318144026Sharti */ 1319144026Sharti if (level != 0) 1320144026Sharti return (FALSE); 132118730Ssteve 1322144026Sharti /* 1323144026Sharti * When an = operator [+?!:] is found, 1324144026Sharti * the next character must be an = or 1325144026Sharti * it ain't a valid assignment. 1326144026Sharti */ 1327144026Sharti if (line[1] == '=') 1328144026Sharti return (haveName); 132918730Ssteve#ifdef SUNSHCMD 1330144026Sharti /* 1331144026Sharti * This is a shell command 1332144026Sharti */ 1333144026Sharti if (strncmp(line, ":sh", 3) == 0) 1334144026Sharti return (haveName); 133518730Ssteve#endif 1336144026Sharti } 1337144026Sharti /* 1338144026Sharti * This is the start of another word, so not 1339144026Sharti * assignment. 1340144026Sharti */ 1341144026Sharti return (FALSE); 1342144026Sharti 1343144026Sharti } else { 1344144026Sharti haveName = TRUE; 1345144026Sharti wasSpace = FALSE; 1346144026Sharti } 1347144026Sharti break; 1348144026Sharti } 13491590Srgrimes } 13501590Srgrimes 1351144026Sharti return (haveName); 13521590Srgrimes} 13531590Srgrimes 13541590Srgrimes/*- 13551590Srgrimes *--------------------------------------------------------------------- 13561590Srgrimes * Parse_DoVar -- 13571590Srgrimes * Take the variable assignment in the passed line and do it in the 13581590Srgrimes * global context. 13591590Srgrimes * 13601590Srgrimes * Note: There is a lexical ambiguity with assignment modifier characters 13611590Srgrimes * in variable names. This routine interprets the character before the = 13621590Srgrimes * as a modifier. Therefore, an assignment like 13631590Srgrimes * C++=/usr/bin/CC 13641590Srgrimes * is interpreted as "C+ +=" instead of "C++ =". 13651590Srgrimes * 13661590Srgrimes * Results: 13671590Srgrimes * none 13681590Srgrimes * 13691590Srgrimes * Side Effects: 13701590Srgrimes * the variable structure of the given variable name is altered in the 13711590Srgrimes * global context. 13721590Srgrimes *--------------------------------------------------------------------- 13731590Srgrimes */ 13741590Srgrimesvoid 1375138232ShartiParse_DoVar(char *line, GNode *ctxt) 13761590Srgrimes{ 1377144026Sharti char *cp; /* pointer into line */ 1378144026Sharti enum { 1379144026Sharti VAR_SUBST, 1380144026Sharti VAR_APPEND, 1381144026Sharti VAR_SHELL, 1382144026Sharti VAR_NORMAL 1383144026Sharti } type; /* Type of assignment */ 1384144026Sharti char *opc; /* ptr to operator character to 1385144026Sharti * null-terminate the variable name */ 1386144026Sharti 1387144026Sharti /* 1388144026Sharti * Skip to variable name 1389144026Sharti */ 1390144029Sharti while (*line == ' ' || *line == '\t') { 1391144026Sharti line++; 1392144026Sharti } 13931590Srgrimes 1394144026Sharti /* 1395144026Sharti * Skip to operator character, nulling out whitespace as we go 1396144026Sharti */ 1397144026Sharti for (cp = line + 1; *cp != '='; cp++) { 1398144026Sharti if (isspace((unsigned char)*cp)) { 1399144026Sharti *cp = '\0'; 1400144026Sharti } 14011590Srgrimes } 1402144026Sharti opc = cp - 1; /* operator is the previous character */ 1403144026Sharti *cp++ = '\0'; /* nuke the = */ 14041590Srgrimes 1405144026Sharti /* 1406144026Sharti * Check operator type 1407144026Sharti */ 1408144026Sharti switch (*opc) { 1409144026Sharti case '+': 1410144026Sharti type = VAR_APPEND; 1411144026Sharti *opc = '\0'; 1412144026Sharti break; 14131590Srgrimes 1414144026Sharti case '?': 1415144026Sharti /* 1416144026Sharti * If the variable already has a value, we don't do anything. 1417144026Sharti */ 1418144026Sharti *opc = '\0'; 1419144026Sharti if (Var_Exists(line, ctxt)) { 1420144026Sharti return; 1421144026Sharti } else { 1422144026Sharti type = VAR_NORMAL; 1423144026Sharti } 1424144026Sharti break; 14251590Srgrimes 1426144026Sharti case ':': 1427144026Sharti type = VAR_SUBST; 1428144026Sharti *opc = '\0'; 1429144026Sharti break; 14301590Srgrimes 1431144026Sharti case '!': 1432144026Sharti type = VAR_SHELL; 1433144026Sharti *opc = '\0'; 1434144026Sharti break; 14351590Srgrimes 1436144026Sharti default: 143718730Ssteve#ifdef SUNSHCMD 1438144026Sharti while (*opc != ':') { 1439144026Sharti if (opc == line) 1440144026Sharti break; 1441144026Sharti else 1442144026Sharti --opc; 1443144026Sharti } 144418730Ssteve 1445144026Sharti if (strncmp(opc, ":sh", 3) == 0) { 1446144026Sharti type = VAR_SHELL; 1447144026Sharti *opc = '\0'; 1448144026Sharti break; 1449144026Sharti } 1450144026Sharti#endif 1451144026Sharti type = VAR_NORMAL; 145218730Ssteve break; 1453144026Sharti } 14541590Srgrimes 1455144026Sharti while (isspace((unsigned char)*cp)) { 1456144026Sharti cp++; 1457144026Sharti } 14581590Srgrimes 1459144026Sharti if (type == VAR_APPEND) { 1460144026Sharti Var_Append(line, cp, ctxt); 14611590Srgrimes 1462144026Sharti } else if (type == VAR_SUBST) { 1463144026Sharti /* 1464144026Sharti * Allow variables in the old value to be undefined, but leave 1465144026Sharti * their invocation alone -- this is done by forcing oldVars 1466144026Sharti * to be false. 1467144026Sharti * XXX: This can cause recursive variables, but that's not 1468144026Sharti * hard to do, and this allows someone to do something like 1469144026Sharti * 1470144026Sharti * CFLAGS = $(.INCLUDES) 1471144026Sharti * CFLAGS := -I.. $(CFLAGS) 1472144026Sharti * 1473144026Sharti * And not get an error. 1474144026Sharti */ 1475144026Sharti Boolean oldOldVars = oldVars; 147698509Sjmallett 1477144026Sharti oldVars = FALSE; 147898509Sjmallett 1479144026Sharti /* 1480144026Sharti * make sure that we set the variable the first time to nothing 1481144026Sharti * so that it gets substituted! 1482144026Sharti */ 1483144026Sharti if (!Var_Exists(line, ctxt)) 1484144026Sharti Var_Set(line, "", ctxt); 1485142457Sharti 1486146027Sharti cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE)); 14871590Srgrimes 1488144026Sharti oldVars = oldOldVars; 14891590Srgrimes 1490144026Sharti Var_Set(line, cp, ctxt); 1491144026Sharti free(cp); 14921590Srgrimes 1493144026Sharti } else if (type == VAR_SHELL) { 1494144026Sharti /* 1495144026Sharti * TRUE if the command needs to be freed, i.e. 1496144026Sharti * if any variable expansion was performed 1497144026Sharti */ 1498144026Sharti Boolean freeCmd = FALSE; 1499144026Sharti Buffer *buf; 1500144026Sharti const char *error; 15011590Srgrimes 1502144026Sharti if (strchr(cp, '$') != NULL) { 1503144026Sharti /* 1504144026Sharti * There's a dollar sign in the command, so perform 1505144026Sharti * variable expansion on the whole thing. The 1506144026Sharti * resulting string will need freeing when we're done, 1507144026Sharti * so set freeCmd to TRUE. 1508144026Sharti */ 1509146027Sharti cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE)); 1510144026Sharti freeCmd = TRUE; 1511144026Sharti } 15121590Srgrimes 1513144026Sharti buf = Cmd_Exec(cp, &error); 1514144026Sharti Var_Set(line, Buf_Data(buf), ctxt); 1515144026Sharti Buf_Destroy(buf, TRUE); 1516144026Sharti 1517144026Sharti if (error) 1518144026Sharti Parse_Error(PARSE_WARNING, error, cp); 1519144026Sharti 1520144026Sharti if (freeCmd) 1521144026Sharti free(cp); 1522144026Sharti 1523144026Sharti } else { 1524144026Sharti /* 1525144026Sharti * Normal assignment -- just do it. 1526144026Sharti */ 1527144026Sharti Var_Set(line, cp, ctxt); 1528144026Sharti } 15291590Srgrimes} 15301590Srgrimes 15311590Srgrimes/*- 15321590Srgrimes *----------------------------------------------------------------------- 15331590Srgrimes * ParseHasCommands -- 15341590Srgrimes * Callback procedure for Parse_File when destroying the list of 15351590Srgrimes * targets on the last dependency line. Marks a target as already 15361590Srgrimes * having commands if it does, to keep from having shell commands 15371590Srgrimes * on multiple dependency lines. 15381590Srgrimes * 15391590Srgrimes * Results: 15405814Sjkh * None 15411590Srgrimes * 15421590Srgrimes * Side Effects: 15431590Srgrimes * OP_HAS_COMMANDS may be set for the target. 15441590Srgrimes * 15451590Srgrimes *----------------------------------------------------------------------- 15461590Srgrimes */ 15475814Sjkhstatic void 1548104696SjmallettParseHasCommands(void *gnp) 15491590Srgrimes{ 1550144026Sharti GNode *gn = gnp; 1551138232Sharti 1552144026Sharti if (!Lst_IsEmpty(&gn->commands)) { 1553144026Sharti gn->type |= OP_HAS_COMMANDS; 1554144026Sharti } 15551590Srgrimes} 15561590Srgrimes 15571590Srgrimes/*- 15581590Srgrimes *----------------------------------------------------------------------- 15591590Srgrimes * Parse_AddIncludeDir -- 15601590Srgrimes * Add a directory to the path searched for included makefiles 15611590Srgrimes * bracketed by double-quotes. Used by functions in main.c 15621590Srgrimes * 15631590Srgrimes * Results: 15641590Srgrimes * None. 15651590Srgrimes * 15661590Srgrimes * Side Effects: 15671590Srgrimes * The directory is appended to the list. 15681590Srgrimes * 15691590Srgrimes *----------------------------------------------------------------------- 15701590Srgrimes */ 15711590Srgrimesvoid 1572138232ShartiParse_AddIncludeDir(char *dir) 15731590Srgrimes{ 1574138232Sharti 1575144026Sharti Path_AddDir(&parseIncPath, dir); 15761590Srgrimes} 15771590Srgrimes 15781590Srgrimes/*- 15791590Srgrimes *--------------------------------------------------------------------- 15801590Srgrimes * Parse_FromString -- 15811590Srgrimes * Start Parsing from the given string 15828874Srgrimes * 15831590Srgrimes * Results: 15841590Srgrimes * None 15851590Srgrimes * 15861590Srgrimes * Side Effects: 1587126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1588126824Sru * curFile.fname and curFile.F are altered for the new file 15891590Srgrimes *--------------------------------------------------------------------- 15901590Srgrimes */ 15911590Srgrimesvoid 1592126824SruParse_FromString(char *str, int lineno) 15931590Srgrimes{ 15941590Srgrimes 1595144026Sharti DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 15961590Srgrimes 1597144341Sharti ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); 15981590Srgrimes} 15991590Srgrimes 16001590Srgrimes#ifdef SYSVINCLUDE 16011590Srgrimes/*- 16021590Srgrimes *--------------------------------------------------------------------- 16031590Srgrimes * ParseTraditionalInclude -- 16041590Srgrimes * Push to another file. 16058874Srgrimes * 16061590Srgrimes * The input is the line minus the "include". The file name is 16071590Srgrimes * the string following the "include". 16081590Srgrimes * 16091590Srgrimes * Results: 16101590Srgrimes * None 16111590Srgrimes * 16121590Srgrimes * Side Effects: 1613126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1614126824Sru * curFile.fname and curFile.F are altered for the new file 16151590Srgrimes *--------------------------------------------------------------------- 16161590Srgrimes */ 16171590Srgrimesstatic void 1618141270ShartiParseTraditionalInclude(char *file) 16191590Srgrimes{ 1620144026Sharti char *fullname; /* full pathname of file */ 1621144026Sharti char *cp; /* current position in file spec */ 16221590Srgrimes 1623144026Sharti /* 1624144026Sharti * Skip over whitespace 1625144026Sharti */ 1626144029Sharti while (*file == ' ' || *file == '\t') { 1627144026Sharti file++; 1628144026Sharti } 16291590Srgrimes 1630144026Sharti if (*file == '\0') { 1631144026Sharti Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); 1632144026Sharti return; 1633144026Sharti } 16341590Srgrimes 1635144026Sharti /* 1636144026Sharti * Skip to end of line or next whitespace 1637144026Sharti */ 1638144026Sharti for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1639144026Sharti continue; 1640144026Sharti } 16411590Srgrimes 1642144026Sharti *cp = '\0'; 16431590Srgrimes 1644144026Sharti /* 1645144026Sharti * Substitute for any variables in the file name before trying to 1646144026Sharti * find the thing. 1647144026Sharti */ 1648146027Sharti file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 16491590Srgrimes 16501590Srgrimes /* 1651144026Sharti * Now we know the file's name, we attempt to find the durn thing. 1652144026Sharti * Search for it first on the -I search path, then on the .PATH 1653144026Sharti * search path, if not found in a -I directory. 16541590Srgrimes */ 1655144026Sharti fullname = Path_FindFile(file, &parseIncPath); 1656144026Sharti if (fullname == NULL) { 1657144026Sharti fullname = Path_FindFile(file, &dirSearchPath); 1658144026Sharti } 16591590Srgrimes 1660144026Sharti if (fullname == NULL) { 1661144026Sharti /* 1662144026Sharti * Still haven't found the makefile. Look for it on the system 1663144026Sharti * path as a last resort. 1664144026Sharti */ 1665144026Sharti fullname = Path_FindFile(file, &sysIncPath); 1666144026Sharti } 16671590Srgrimes 1668144026Sharti if (fullname == NULL) { 1669144026Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1670144026Sharti /* XXXHB free(file) */ 1671144026Sharti return; 1672144026Sharti } 1673142457Sharti 1674144026Sharti /* XXXHB free(file) */ 16751590Srgrimes 1676144026Sharti /* 1677144341Sharti * We set up the name of the file to be the absolute 1678144026Sharti * name of the include file so error messages refer to the right 1679144341Sharti * place. 16801590Srgrimes */ 1681144341Sharti ParsePushInput(fullname, NULL, NULL, 0); 16821590Srgrimes} 16831590Srgrimes#endif 16841590Srgrimes 16851590Srgrimes/*- 16861590Srgrimes *--------------------------------------------------------------------- 16871590Srgrimes * ParseReadc -- 16888874Srgrimes * Read a character from the current file 16891590Srgrimes * 16901590Srgrimes * Results: 16911590Srgrimes * The character that was read 16921590Srgrimes * 16931590Srgrimes * Side Effects: 16941590Srgrimes *--------------------------------------------------------------------- 16951590Srgrimes */ 16961590Srgrimesstatic int 1697104696SjmallettParseReadc(void) 16981590Srgrimes{ 1699138232Sharti 1700144341Sharti if (CURFILE->F != NULL) 1701144341Sharti return (fgetc(CURFILE->F)); 17028874Srgrimes 1703144341Sharti if (CURFILE->str != NULL && *CURFILE->ptr != '\0') 1704144341Sharti return (*CURFILE->ptr++); 1705144341Sharti 1706144026Sharti return (EOF); 17071590Srgrimes} 17081590Srgrimes 17091590Srgrimes 17101590Srgrimes/*- 17111590Srgrimes *--------------------------------------------------------------------- 17121590Srgrimes * ParseUnreadc -- 17138874Srgrimes * Put back a character to the current file 17141590Srgrimes * 17151590Srgrimes * Results: 17161590Srgrimes * None. 17171590Srgrimes * 17181590Srgrimes * Side Effects: 17191590Srgrimes *--------------------------------------------------------------------- 17201590Srgrimes */ 17211590Srgrimesstatic void 1722104696SjmallettParseUnreadc(int c) 17231590Srgrimes{ 1724138232Sharti 1725144341Sharti if (CURFILE->F != NULL) { 1726144341Sharti ungetc(c, CURFILE->F); 1727144026Sharti return; 1728144026Sharti } 1729144341Sharti if (CURFILE->str != NULL) { 1730144341Sharti *--(CURFILE->ptr) = c; 1731144026Sharti return; 1732144026Sharti } 17331590Srgrimes} 17341590Srgrimes 17351590Srgrimes/* ParseSkipLine(): 1736104696Sjmallett * Grab the next line unless it begins with a dot (`.') and we're told to 1737104696Sjmallett * ignore such lines. 17381590Srgrimes */ 17391590Srgrimesstatic char * 1740126824SruParseSkipLine(int skip, int keep_newline) 17411590Srgrimes{ 1742144026Sharti char *line; 1743144026Sharti int c, lastc; 1744144026Sharti Buffer *buf; 17451590Srgrimes 1746144026Sharti buf = Buf_Init(MAKE_BSIZE); 17471590Srgrimes 1748144026Sharti do { 1749144026Sharti Buf_Clear(buf); 1750144026Sharti lastc = '\0'; 17518874Srgrimes 1752144026Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') 1753144026Sharti && c != EOF) { 1754144026Sharti if (skip && c == '#' && lastc != '\\') { 1755144026Sharti /* 1756144026Sharti * let a comment be terminated even by an 1757144026Sharti * escaped \n. This is consistent to comment 1758144026Sharti * handling in ParseReadLine 1759144026Sharti */ 1760144026Sharti while ((c = ParseReadc()) != '\n' && c != EOF) 1761144026Sharti ; 1762144026Sharti break; 1763144026Sharti } 1764144026Sharti if (c == '\n') { 1765144026Sharti if (keep_newline) 1766144026Sharti Buf_AddByte(buf, (Byte)c); 1767144026Sharti else 1768144026Sharti Buf_ReplaceLastByte(buf, (Byte)' '); 1769144341Sharti CURFILE->lineno++; 17708874Srgrimes 1771144026Sharti while ((c = ParseReadc()) == ' ' || c == '\t') 1772144026Sharti continue; 17738874Srgrimes 1774144026Sharti if (c == EOF) 1775144026Sharti break; 1776144026Sharti } 177774272Swill 1778144026Sharti Buf_AddByte(buf, (Byte)c); 1779144026Sharti lastc = c; 1780144026Sharti } 178118456Ssteve 1782144026Sharti if (c == EOF) { 1783144026Sharti Parse_Error(PARSE_FATAL, 1784144026Sharti "Unclosed conditional/for loop"); 1785144026Sharti Buf_Destroy(buf, TRUE); 1786144026Sharti return (NULL); 1787144026Sharti } 178818456Ssteve 1789144341Sharti CURFILE->lineno++; 1790144026Sharti Buf_AddByte(buf, (Byte)'\0'); 1791144026Sharti line = Buf_Data(buf); 1792144026Sharti } while (skip == 1 && line[0] != '.'); 179318456Ssteve 1794144026Sharti Buf_Destroy(buf, FALSE); 1795144026Sharti return (line); 17961590Srgrimes} 17971590Srgrimes 17981590Srgrimes/*- 17991590Srgrimes *--------------------------------------------------------------------- 18001590Srgrimes * ParseReadLine -- 18011590Srgrimes * Read an entire line from the input file. Called only by Parse_File. 18021590Srgrimes * To facilitate escaped newlines and what have you, a character is 18031590Srgrimes * buffered in 'lastc', which is '\0' when no characters have been 18041590Srgrimes * read. When we break out of the loop, c holds the terminating 18051590Srgrimes * character and lastc holds a character that should be added to 18061590Srgrimes * the line (unless we don't read anything but a terminator). 18071590Srgrimes * 18081590Srgrimes * Results: 18091590Srgrimes * A line w/o its newline 18101590Srgrimes * 18111590Srgrimes * Side Effects: 18121590Srgrimes * Only those associated with reading a character 18131590Srgrimes *--------------------------------------------------------------------- 18141590Srgrimes */ 18151590Srgrimesstatic char * 1816138232ShartiParseReadLine(void) 18171590Srgrimes{ 1818144026Sharti Buffer *buf; /* Buffer for current line */ 1819144026Sharti int c; /* the current character */ 1820144026Sharti int lastc; /* The most-recent character */ 1821144026Sharti Boolean semiNL; /* treat semi-colons as newlines */ 1822144026Sharti Boolean ignDepOp; /* TRUE if should ignore dependency operators 18231590Srgrimes * for the purposes of setting semiNL */ 1824144026Sharti Boolean ignComment; /* TRUE if should ignore comments (in a 18251590Srgrimes * shell command */ 1826144026Sharti char *line; /* Result */ 1827144026Sharti char *ep; /* to strip trailing blanks */ 18281590Srgrimes 1829144742Sharti again: 1830144026Sharti semiNL = FALSE; 1831144026Sharti ignDepOp = FALSE; 1832144026Sharti ignComment = FALSE; 18331590Srgrimes 1834144742Sharti lastc = '\0'; 1835144742Sharti 1836144026Sharti /* 1837144742Sharti * Handle tab at the beginning of the line. A leading tab (shell 1838144742Sharti * command) forces us to ignore comments and dependency operators and 1839144742Sharti * treat semi-colons as semi-colons (by leaving semiNL FALSE). 1840144742Sharti * This also discards completely blank lines. 1841144026Sharti */ 1842144026Sharti for (;;) { 1843144026Sharti c = ParseReadc(); 1844144742Sharti if (c == EOF) { 1845144742Sharti if (ParsePopInput() == DONE) { 1846144742Sharti /* End of all inputs - return NULL */ 1847144742Sharti return (NULL); 1848144742Sharti } 1849144742Sharti continue; 1850144742Sharti } 18511590Srgrimes 1852144026Sharti if (c == '\t') { 1853144026Sharti ignComment = ignDepOp = TRUE; 1854144742Sharti lastc = c; 1855144026Sharti break; 1856144742Sharti } 1857144742Sharti if (c != '\n') { 1858144026Sharti ParseUnreadc(c); 1859144026Sharti break; 1860144026Sharti } 1861144742Sharti CURFILE->lineno++; 18621590Srgrimes } 18638874Srgrimes 1864144742Sharti buf = Buf_Init(MAKE_BSIZE); 18658874Srgrimes 1866144742Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { 1867144026Sharti test_char: 1868144742Sharti switch (c) { 1869144742Sharti case '\n': 1870144742Sharti /* 1871144742Sharti * Escaped newline: read characters until a 1872144742Sharti * non-space or an unescaped newline and 1873144742Sharti * replace them all by a single space. This is 1874144742Sharti * done by storing the space over the backslash 1875144742Sharti * and dropping through with the next nonspace. 1876144742Sharti * If it is a semi-colon and semiNL is TRUE, 1877144742Sharti * it will be recognized as a newline in the 1878144742Sharti * code below this... 1879144742Sharti */ 1880144742Sharti CURFILE->lineno++; 1881144742Sharti lastc = ' '; 1882144742Sharti while ((c = ParseReadc()) == ' ' || c == '\t') { 1883144742Sharti continue; 1884144742Sharti } 1885144742Sharti if (c == EOF || c == '\n') { 1886144742Sharti goto line_read; 1887144742Sharti } else { 1888144026Sharti /* 1889144742Sharti * Check for comments, semiNL's, etc. -- 1890144742Sharti * easier than ParseUnreadc(c); 1891144742Sharti * continue; 1892144026Sharti */ 1893144742Sharti goto test_char; 1894144742Sharti } 1895144742Sharti /*NOTREACHED*/ 1896144742Sharti break; 1897144026Sharti 1898144742Sharti case ';': 1899144742Sharti /* 1900144742Sharti * Semi-colon: Need to see if it should be 1901144742Sharti * interpreted as a newline 1902144742Sharti */ 1903144742Sharti if (semiNL) { 1904144026Sharti /* 1905144742Sharti * To make sure the command that may 1906144742Sharti * be following this semi-colon begins 1907144742Sharti * with a tab, we push one back into the 1908144742Sharti * input stream. This will overwrite the 1909144742Sharti * semi-colon in the buffer. If there is 1910144742Sharti * no command following, this does no 1911144742Sharti * harm, since the newline remains in 1912144742Sharti * the buffer and the 1913144742Sharti * whole line is ignored. 1914144026Sharti */ 1915144742Sharti ParseUnreadc('\t'); 1916144742Sharti goto line_read; 1917144742Sharti } 1918144742Sharti break; 1919144742Sharti case '=': 1920144742Sharti if (!semiNL) { 1921144742Sharti /* 1922144742Sharti * Haven't seen a dependency operator 1923144742Sharti * before this, so this must be a 1924144742Sharti * variable assignment -- don't pay 1925144742Sharti * attention to dependency operators 1926144742Sharti * after this. 1927144742Sharti */ 1928144742Sharti ignDepOp = TRUE; 1929144742Sharti } else if (lastc == ':' || lastc == '!') { 1930144742Sharti /* 1931144742Sharti * Well, we've seen a dependency 1932144742Sharti * operator already, but it was the 1933144742Sharti * previous character, so this is really 1934144742Sharti * just an expanded variable assignment. 1935144742Sharti * Revert semi-colons to being just 1936144742Sharti * semi-colons again and ignore any more 1937144742Sharti * dependency operators. 1938144742Sharti * 1939144742Sharti * XXX: Note that a line like 1940144742Sharti * "foo : a:=b" will blow up, but who'd 1941144742Sharti * write a line like that anyway? 1942144742Sharti */ 1943144742Sharti ignDepOp = TRUE; 1944144742Sharti semiNL = FALSE; 1945144742Sharti } 1946144742Sharti break; 1947144742Sharti case '#': 1948144742Sharti if (!ignComment) { 1949144742Sharti if (lastc != '\\') { 1950144026Sharti /* 1951144742Sharti * If the character is a hash 1952144742Sharti * mark and it isn't escaped 1953144742Sharti * (or we're being compatible), 1954144742Sharti * the thing is a comment. 1955144742Sharti * Skip to the end of the line. 1956144026Sharti */ 1957144742Sharti do { 1958144742Sharti c = ParseReadc(); 1959144742Sharti } while (c != '\n' && c != EOF); 1960144026Sharti goto line_read; 1961144742Sharti } else { 1962144026Sharti /* 1963144742Sharti * Don't add the backslash. 1964144742Sharti * Just let the # get copied 1965144742Sharti * over. 1966144026Sharti */ 1967144742Sharti lastc = c; 1968144742Sharti continue; 1969144026Sharti } 1970144742Sharti } 1971144742Sharti break; 1972144026Sharti 1973144742Sharti case ':': 1974144742Sharti case '!': 1975144742Sharti if (!ignDepOp) { 1976144742Sharti /* 1977144742Sharti * A semi-colon is recognized as a 1978144742Sharti * newline only on dependency lines. 1979144742Sharti * Dependency lines are lines with a 1980144742Sharti * colon or an exclamation point. 1981144742Sharti * Ergo... 1982144742Sharti */ 1983144742Sharti semiNL = TRUE; 1984144742Sharti } 1985144742Sharti break; 1986144026Sharti 1987144742Sharti default: 1988144742Sharti break; 1989144742Sharti } 1990144742Sharti /* 1991144742Sharti * Copy in the previous character (there may be none if this 1992144742Sharti * was the first character) and save this one in 1993144742Sharti * lastc. 1994144742Sharti */ 1995144742Sharti if (lastc != '\0') 1996144026Sharti Buf_AddByte(buf, (Byte)lastc); 1997144742Sharti lastc = c; 1998144742Sharti } 1999144026Sharti line_read: 2000144742Sharti CURFILE->lineno++; 2001144026Sharti 2002144742Sharti if (lastc != '\0') { 2003144742Sharti Buf_AddByte(buf, (Byte)lastc); 2004144742Sharti } 2005144742Sharti Buf_AddByte(buf, (Byte)'\0'); 2006144742Sharti line = Buf_Peel(buf); 20071590Srgrimes 2008144742Sharti /* 2009144742Sharti * Strip trailing blanks and tabs from the line. 2010144742Sharti * Do not strip a blank or tab that is preceded by 2011144742Sharti * a '\' 2012144742Sharti */ 2013144742Sharti ep = line; 2014144742Sharti while (*ep) 2015144742Sharti ++ep; 2016144742Sharti while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2017144742Sharti if (ep > line + 1 && ep[-2] == '\\') 2018144742Sharti break; 2019144742Sharti --ep; 2020144742Sharti } 2021144742Sharti *ep = 0; 2022144742Sharti 2023144742Sharti if (line[0] == '\0') { 2024144742Sharti /* empty line - just ignore */ 2025144742Sharti free(line); 2026144742Sharti goto again; 2027144742Sharti } 2028144742Sharti 2029144742Sharti return (line); 20301590Srgrimes} 20311590Srgrimes 20321590Srgrimes/*- 20331590Srgrimes *----------------------------------------------------------------------- 20341590Srgrimes * ParseFinishLine -- 20351590Srgrimes * Handle the end of a dependency group. 20361590Srgrimes * 20371590Srgrimes * Results: 20381590Srgrimes * Nothing. 20391590Srgrimes * 20401590Srgrimes * Side Effects: 20411590Srgrimes * inLine set FALSE. 'targets' list destroyed. 20421590Srgrimes * 20431590Srgrimes *----------------------------------------------------------------------- 20441590Srgrimes */ 20451590Srgrimesstatic void 2046104696SjmallettParseFinishLine(void) 20471590Srgrimes{ 2048143372Sharti const LstNode *ln; 2049138232Sharti 2050143372Sharti if (inLine) { 2051143372Sharti LST_FOREACH(ln, &targets) { 2052143372Sharti if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) 2053143372Sharti Suff_EndTransform(Lst_Datum(ln)); 2054143372Sharti } 2055143372Sharti Lst_Destroy(&targets, ParseHasCommands); 2056143372Sharti inLine = FALSE; 2057143372Sharti } 20581590Srgrimes} 20591590Srgrimes 2060144894Sharti/** 2061144894Sharti * parse_include 2062144894Sharti * Parse an .include directive and push the file onto the input stack. 2063144894Sharti * The input is the line minus the .include. A file spec is a string 2064144894Sharti * enclosed in <> or "". The former is looked for only in sysIncPath. 2065144894Sharti * The latter in . and the directories specified by -I command line 2066144894Sharti * options 2067144894Sharti */ 2068144894Shartistatic void 2069144894Shartiparse_include(char *file, int code __unused, int lineno __unused) 2070144894Sharti{ 2071144894Sharti char *fullname; /* full pathname of file */ 2072144894Sharti char endc; /* the character which ends the file spec */ 2073144894Sharti char *cp; /* current position in file spec */ 2074144894Sharti Boolean isSystem; /* TRUE if makefile is a system makefile */ 2075144894Sharti char *prefEnd, *Fname; 2076144894Sharti char *newName; 20778874Srgrimes 2078144894Sharti /* 2079144894Sharti * Skip to delimiter character so we know where to look 2080144894Sharti */ 2081144894Sharti while (*file == ' ' || *file == '\t') { 2082144894Sharti file++; 2083144894Sharti } 2084144894Sharti 2085144894Sharti if (*file != '"' && *file != '<') { 2086144894Sharti Parse_Error(PARSE_FATAL, 2087144894Sharti ".include filename must be delimited by '\"' or '<'"); 2088144894Sharti return; 2089144894Sharti } 2090144894Sharti 2091144894Sharti /* 2092144894Sharti * Set the search path on which to find the include file based on the 2093144894Sharti * characters which bracket its name. Angle-brackets imply it's 2094144894Sharti * a system Makefile while double-quotes imply it's a user makefile 2095144894Sharti */ 2096144894Sharti if (*file == '<') { 2097144894Sharti isSystem = TRUE; 2098144894Sharti endc = '>'; 2099144894Sharti } else { 2100144894Sharti isSystem = FALSE; 2101144894Sharti endc = '"'; 2102144894Sharti } 2103144894Sharti 2104144894Sharti /* 2105144894Sharti * Skip to matching delimiter 2106144894Sharti */ 2107144894Sharti for (cp = ++file; *cp != endc; cp++) { 2108144894Sharti if (*cp == '\0') { 2109144894Sharti Parse_Error(PARSE_FATAL, 2110144894Sharti "Unclosed .include filename. '%c' expected", endc); 2111144894Sharti return; 2112144894Sharti } 2113144894Sharti } 2114144894Sharti *cp = '\0'; 2115144894Sharti 2116144894Sharti /* 2117144894Sharti * Substitute for any variables in the file name before trying to 2118144894Sharti * find the thing. 2119144894Sharti */ 2120146027Sharti file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 2121144894Sharti 2122144894Sharti /* 2123144894Sharti * Now we know the file's name and its search path, we attempt to 2124144894Sharti * find the durn thing. A return of NULL indicates the file don't 2125144894Sharti * exist. 2126144894Sharti */ 2127144894Sharti if (!isSystem) { 2128144894Sharti /* 2129144894Sharti * Include files contained in double-quotes are first searched 2130144894Sharti * for relative to the including file's location. We don't want 2131144894Sharti * to cd there, of course, so we just tack on the old file's 2132144894Sharti * leading path components and call Dir_FindFile to see if 2133144894Sharti * we can locate the beast. 2134144894Sharti */ 2135144894Sharti 2136144894Sharti /* Make a temporary copy of this, to be safe. */ 2137144894Sharti Fname = estrdup(CURFILE->fname); 2138144894Sharti 2139144894Sharti prefEnd = strrchr(Fname, '/'); 2140144894Sharti if (prefEnd != NULL) { 2141144894Sharti *prefEnd = '\0'; 2142144894Sharti if (file[0] == '/') 2143144894Sharti newName = estrdup(file); 2144144894Sharti else 2145144894Sharti newName = str_concat(Fname, file, STR_ADDSLASH); 2146144894Sharti fullname = Path_FindFile(newName, &parseIncPath); 2147144894Sharti if (fullname == NULL) { 2148144894Sharti fullname = Path_FindFile(newName, 2149144894Sharti &dirSearchPath); 2150144894Sharti } 2151144894Sharti free(newName); 2152144894Sharti *prefEnd = '/'; 2153144894Sharti } else { 2154144894Sharti fullname = NULL; 2155144894Sharti } 2156144894Sharti free(Fname); 2157144894Sharti } else { 2158144894Sharti fullname = NULL; 2159144894Sharti } 2160144894Sharti 2161144894Sharti if (fullname == NULL) { 2162144894Sharti /* 2163144894Sharti * System makefile or makefile wasn't found in same directory as 2164144894Sharti * included makefile. Search for it first on the -I search path, 2165144894Sharti * then on the .PATH search path, if not found in a -I 2166144894Sharti * directory. 2167144894Sharti * XXX: Suffix specific? 2168144894Sharti */ 2169144894Sharti fullname = Path_FindFile(file, &parseIncPath); 2170144894Sharti if (fullname == NULL) { 2171144894Sharti fullname = Path_FindFile(file, &dirSearchPath); 2172144894Sharti } 2173144894Sharti } 2174144894Sharti 2175144894Sharti if (fullname == NULL) { 2176144894Sharti /* 2177144894Sharti * Still haven't found the makefile. Look for it on the system 2178144894Sharti * path as a last resort. 2179144894Sharti */ 2180144894Sharti fullname = Path_FindFile(file, &sysIncPath); 2181144894Sharti } 2182144894Sharti 2183144894Sharti if (fullname == NULL) { 2184144894Sharti *cp = endc; 2185144894Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 2186144894Sharti free(file); 2187144894Sharti return; 2188144894Sharti } 2189144894Sharti free(file); 2190144894Sharti 2191144894Sharti /* 2192144894Sharti * We set up the name of the file to be the absolute 2193144894Sharti * name of the include file so error messages refer to the right 2194144894Sharti * place. 2195144894Sharti */ 2196144894Sharti ParsePushInput(fullname, NULL, NULL, 0); 2197144894Sharti} 2198144894Sharti 2199144894Sharti/** 2200144894Sharti * parse_message 2201144894Sharti * Parse a .warning or .error directive 2202144894Sharti * 2203144894Sharti * The input is the line minus the ".error"/".warning". We substitute 2204144894Sharti * variables, print the message and exit(1) (for .error) or just print 2205144894Sharti * a warning if the directive is malformed. 2206144894Sharti */ 2207144894Shartistatic void 2208144894Shartiparse_message(char *line, int iserror, int lineno __unused) 2209144894Sharti{ 2210144894Sharti 2211144894Sharti if (!isspace((u_char)*line)) { 2212144894Sharti Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s", 2213144894Sharti iserror ? "error" : "warning", line); 2214144894Sharti return; 2215144894Sharti } 2216144894Sharti 2217144894Sharti while (isspace((u_char)*line)) 2218144894Sharti line++; 2219144894Sharti 2220146027Sharti line = Buf_Peel(Var_Subst(line, VAR_GLOBAL, FALSE)); 2221144894Sharti Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); 2222144894Sharti free(line); 2223144894Sharti 2224144894Sharti if (iserror) { 2225144894Sharti /* Terminate immediately. */ 2226144894Sharti exit(1); 2227144894Sharti } 2228144894Sharti} 2229144894Sharti 2230144894Sharti/** 2231144894Sharti * parse_undef 2232144894Sharti * Parse an .undef directive. 2233144894Sharti */ 2234144894Shartistatic void 2235144894Shartiparse_undef(char *line, int code __unused, int lineno __unused) 2236144894Sharti{ 2237144894Sharti char *cp; 2238144894Sharti 2239144894Sharti while (isspace((u_char)*line)) 2240144894Sharti line++; 2241144894Sharti 2242144894Sharti for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) { 2243144894Sharti ; 2244144894Sharti } 2245144894Sharti *cp = '\0'; 2246144894Sharti 2247146027Sharti cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); 2248144894Sharti Var_Delete(cp, VAR_GLOBAL); 2249144894Sharti free(cp); 2250144894Sharti} 2251144894Sharti 2252144894Sharti/** 2253144894Sharti * parse_for 2254144894Sharti * Parse a .for directive. 2255144894Sharti */ 2256144894Shartistatic void 2257144894Shartiparse_for(char *line, int code __unused, int lineno) 2258144894Sharti{ 2259144894Sharti 2260144894Sharti if (!For_For(line)) { 2261144894Sharti /* syntax error */ 2262144894Sharti return; 2263144894Sharti } 2264144894Sharti line = NULL; 2265144894Sharti 2266144894Sharti /* 2267144894Sharti * Skip after the matching endfor. 2268144894Sharti */ 2269144894Sharti do { 2270144894Sharti free(line); 2271144894Sharti line = ParseSkipLine(0, 1); 2272144894Sharti if (line == NULL) { 2273144894Sharti Parse_Error(PARSE_FATAL, 2274144894Sharti "Unexpected end of file in for loop.\n"); 2275144894Sharti return; 2276144894Sharti } 2277144894Sharti } while (For_Eval(line)); 2278144894Sharti free(line); 2279144894Sharti 2280144894Sharti /* execute */ 2281144894Sharti For_Run(lineno); 2282144894Sharti} 2283144894Sharti 2284144894Sharti/** 2285144894Sharti * parse_endfor 2286144894Sharti * Parse endfor. This may only happen if there was no matching .for. 2287144894Sharti */ 2288144894Shartistatic void 2289144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused) 2290144894Sharti{ 2291144894Sharti 2292144894Sharti Parse_Error(PARSE_FATAL, "for-less endfor"); 2293144894Sharti} 2294144894Sharti 2295144894Sharti/** 2296144894Sharti * parse_directive 2297144894Sharti * Got a line starting with a '.'. Check if this is a directive 2298144894Sharti * and parse it. 2299144894Sharti * 2300144894Sharti * return: 2301144894Sharti * TRUE if line was a directive, FALSE otherwise. 2302144894Sharti */ 2303144894Shartistatic Boolean 2304144894Shartiparse_directive(char *line) 2305144894Sharti{ 2306144894Sharti char *start; 2307144894Sharti char *cp; 2308144894Sharti int dir; 2309144894Sharti 2310144894Sharti /* 2311144894Sharti * Get the keyword: 2312144894Sharti * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).* 2313144894Sharti * \1 is the keyword. 2314144894Sharti */ 2315144894Sharti for (start = line; isspace((u_char)*start); start++) { 2316144894Sharti ; 2317144894Sharti } 2318144894Sharti 2319144894Sharti if (!isalpha((u_char)*start)) { 2320144894Sharti return (FALSE); 2321144894Sharti } 2322144894Sharti 2323144894Sharti cp = start + 1; 2324144894Sharti while (isalnum((u_char)*cp) || *cp == '_') { 2325144894Sharti cp++; 2326144894Sharti } 2327144894Sharti 2328144894Sharti dir = directive_hash(start, cp - start); 2329144894Sharti if (dir < 0 || dir >= (int)NDIRECTS || 2330144894Sharti (size_t)(cp - start) != strlen(directives[dir].name) || 2331144894Sharti strncmp(start, directives[dir].name, cp - start) != 0) { 2332144894Sharti /* not actually matched */ 2333144894Sharti return (FALSE); 2334144894Sharti } 2335144894Sharti 2336144894Sharti if (!skipLine || directives[dir].skip_flag) 2337144894Sharti (*directives[dir].func)(cp, directives[dir].code, 2338144894Sharti CURFILE->lineno); 2339144894Sharti return (TRUE); 2340144894Sharti} 2341144894Sharti 23421590Srgrimes/*- 23431590Srgrimes *--------------------------------------------------------------------- 23441590Srgrimes * Parse_File -- 23451590Srgrimes * Parse a file into its component parts, incorporating it into the 23461590Srgrimes * current dependency graph. This is the main function and controls 23471590Srgrimes * almost every other function in this module 23481590Srgrimes * 23491590Srgrimes * Results: 23501590Srgrimes * None 23511590Srgrimes * 23521590Srgrimes * Side Effects: 23531590Srgrimes * Loads. Nodes are added to the list of all targets, nodes and links 23541590Srgrimes * are added to the dependency graph. etc. etc. etc. 23551590Srgrimes *--------------------------------------------------------------------- 23561590Srgrimes */ 23571590Srgrimesvoid 2358144341ShartiParse_File(const char *name, FILE *stream) 23591590Srgrimes{ 2360144026Sharti char *cp; /* pointer into the line */ 2361144026Sharti char *line; /* the line we're working on */ 23621590Srgrimes 2363144026Sharti inLine = FALSE; 2364144026Sharti fatals = 0; 23651590Srgrimes 2366144341Sharti ParsePushInput(estrdup(name), stream, NULL, 0); 2367131456Seik 2368144742Sharti while ((line = ParseReadLine()) != NULL) { 2369144894Sharti if (*line == '.' && parse_directive(line + 1)) { 2370144894Sharti /* directive consumed */ 2371144894Sharti goto nextLine; 2372144742Sharti } 2373144894Sharti if (skipLine || *line == '#') { 2374144894Sharti /* Skipping .if block or comment. */ 2375144742Sharti goto nextLine; 2376144742Sharti } 23778874Srgrimes 2378144742Sharti if (*line == '\t') { 2379144742Sharti /* 2380144742Sharti * If a line starts with a tab, it can only 2381144742Sharti * hope to be a creation command. 2382144742Sharti */ 2383144742Sharti for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 2384144742Sharti continue; 2385144742Sharti } 2386144742Sharti if (*cp) { 2387144742Sharti if (inLine) { 2388144742Sharti LstNode *ln; 2389144742Sharti GNode *gn; 2390143684Sharti 2391144742Sharti /* 2392144742Sharti * So long as it's not a blank 2393144742Sharti * line and we're actually in a 2394144742Sharti * dependency spec, add the 2395144742Sharti * command to the list of 2396144742Sharti * commands of all targets in 2397144742Sharti * the dependency spec. 2398144742Sharti */ 2399144742Sharti LST_FOREACH(ln, &targets) { 2400144742Sharti gn = Lst_Datum(ln); 2401144742Sharti 2402144026Sharti /* 2403144742Sharti * if target already 2404144742Sharti * supplied, ignore 2405144742Sharti * commands 2406144026Sharti */ 2407144742Sharti if (!(gn->type & OP_HAS_COMMANDS)) 2408144742Sharti Lst_AtEnd(&gn->commands, cp); 2409144742Sharti else 2410144742Sharti Parse_Error(PARSE_WARNING, "duplicate script " 2411144742Sharti "for target \"%s\" ignored", gn->name); 2412144026Sharti } 2413144742Sharti continue; 2414144742Sharti } else { 2415144742Sharti Parse_Error(PARSE_FATAL, 2416144742Sharti "Unassociated shell command \"%s\"", 2417144742Sharti cp); 2418144026Sharti } 2419144742Sharti } 24201590Srgrimes#ifdef SYSVINCLUDE 2421144742Sharti } else if (strncmp(line, "include", 7) == 0 && 2422144742Sharti isspace((unsigned char)line[7]) && 2423144742Sharti strchr(line, ':') == NULL) { 2424144742Sharti /* 2425144742Sharti * It's an S3/S5-style "include". 2426144742Sharti */ 2427144742Sharti ParseTraditionalInclude(line + 7); 2428144742Sharti goto nextLine; 24291590Srgrimes#endif 2430144742Sharti } else if (Parse_IsVar(line)) { 2431144742Sharti ParseFinishLine(); 2432144742Sharti Parse_DoVar(line, VAR_GLOBAL); 24338874Srgrimes 2434144742Sharti } else { 2435144742Sharti /* 2436144742Sharti * We now know it's a dependency line so it 2437144742Sharti * needs to have all variables expanded before 2438144742Sharti * being parsed. Tell the variable module to 2439144742Sharti * complain if some variable is undefined... 2440144742Sharti * To make life easier on novices, if the line 2441144742Sharti * is indented we first make sure the line has 2442144742Sharti * a dependency operator in it. If it doesn't 2443144742Sharti * have an operator and we're in a dependency 2444144742Sharti * line's script, we assume it's actually a 2445144742Sharti * shell command and add it to the current 2446144894Sharti * list of targets. XXX this comment seems wrong. 2447144742Sharti */ 2448144742Sharti cp = line; 2449144742Sharti if (isspace((unsigned char)line[0])) { 2450144742Sharti while (*cp != '\0' && 2451144742Sharti isspace((unsigned char)*cp)) { 2452144742Sharti cp++; 2453144026Sharti } 2454144742Sharti if (*cp == '\0') { 2455144742Sharti goto nextLine; 2456144742Sharti } 2457144742Sharti } 24581590Srgrimes 2459144742Sharti ParseFinishLine(); 2460142457Sharti 2461146027Sharti cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE)); 24628874Srgrimes 2463144742Sharti free(line); 2464144742Sharti line = cp; 2465144026Sharti 2466144742Sharti /* 2467144742Sharti * Need a non-circular list for the target nodes 2468144742Sharti */ 2469144742Sharti Lst_Destroy(&targets, NOFREE); 2470144742Sharti inLine = TRUE; 2471144026Sharti 2472144742Sharti ParseDoDependency(line); 2473144026Sharti } 2474144026Sharti 2475144742Sharti nextLine: 2476144742Sharti free(line); 2477144742Sharti } 24788874Srgrimes 2479144026Sharti ParseFinishLine(); 24801590Srgrimes 24811590Srgrimes /* 2482144026Sharti * Make sure conditionals are clean 24831590Srgrimes */ 2484144026Sharti Cond_End(); 24851590Srgrimes 2486144026Sharti if (fatals) 2487144026Sharti errx(1, "fatal errors encountered -- cannot continue"); 24881590Srgrimes} 24891590Srgrimes 24901590Srgrimes/*- 24911590Srgrimes *----------------------------------------------------------------------- 24921590Srgrimes * Parse_MainName -- 24931590Srgrimes * Return a Lst of the main target to create for main()'s sake. If 24941590Srgrimes * no such target exists, we Punt with an obnoxious error message. 24951590Srgrimes * 24961590Srgrimes * Results: 24971590Srgrimes * A Lst of the single node to create. 24981590Srgrimes * 24991590Srgrimes * Side Effects: 25001590Srgrimes * None. 25011590Srgrimes * 25021590Srgrimes *----------------------------------------------------------------------- 25031590Srgrimes */ 2504138916Shartivoid 2505138916ShartiParse_MainName(Lst *listmain) 25061590Srgrimes{ 25071590Srgrimes 2508144026Sharti if (mainNode == NULL) { 2509144026Sharti Punt("no target to make."); 2510144026Sharti /*NOTREACHED*/ 2511144026Sharti } else if (mainNode->type & OP_DOUBLEDEP) { 2512144026Sharti Lst_AtEnd(listmain, mainNode); 2513144026Sharti Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 2514144026Sharti } else 2515144026Sharti Lst_AtEnd(listmain, mainNode); 25161590Srgrimes} 2517