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$"); 431590Srgrimes 441590Srgrimes/*- 451590Srgrimes * parse.c -- 461590Srgrimes * Functions to parse a makefile. 471590Srgrimes * 481590Srgrimes * Most important structures are kept in Lsts. Directories for 491590Srgrimes * the #include "..." function are kept in the 'parseIncPath' Lst, while 501590Srgrimes * those for the #include <...> are kept in the 'sysIncPath' Lst. The 511590Srgrimes * targets currently being defined are kept in the 'targets' Lst. 521590Srgrimes * 531590Srgrimes * Interface: 541590Srgrimes * 55144026Sharti * Parse_File Function used to parse a makefile. It must 56144026Sharti * be given the name of the file, which should 57144026Sharti * already have been opened, and a function 58144026Sharti * to call to read a character from the file. 591590Srgrimes * 60144026Sharti * Parse_IsVar Returns TRUE if the given line is a 61144026Sharti * variable assignment. Used by MainParseArgs 62144026Sharti * to determine if an argument is a target 63144026Sharti * or a variable assignment. Used internally 64144026Sharti * for pretty much the same thing... 651590Srgrimes * 66144026Sharti * Parse_Error Function called when an error occurs in 67144026Sharti * parsing. Used by the variable and 68144026Sharti * conditional modules. 69144026Sharti * 70144026Sharti * Parse_MainName Returns a Lst of the main target to create. 711590Srgrimes */ 721590Srgrimes 73144341Sharti#include <assert.h> 74141104Sharti#include <ctype.h> 751590Srgrimes#include <stdarg.h> 76141104Sharti#include <string.h> 77141104Sharti#include <stdlib.h> 7827644Scharnier#include <err.h> 79141104Sharti 80141104Sharti#include "arch.h" 81141104Sharti#include "buf.h" 82141104Sharti#include "cond.h" 83141104Sharti#include "config.h" 841590Srgrimes#include "dir.h" 85141104Sharti#include "for.h" 86141104Sharti#include "globals.h" 87141104Sharti#include "GNode.h" 88145683Sharti#include "hash_tables.h" 891590Srgrimes#include "job.h" 90141104Sharti#include "make.h" 91141104Sharti#include "parse.h" 921590Srgrimes#include "pathnames.h" 93146572Sharti#include "shell.h" 94141104Sharti#include "str.h" 95141104Sharti#include "suff.h" 96141104Sharti#include "targ.h" 97141104Sharti#include "util.h" 98141104Sharti#include "var.h" 991590Srgrimes 1001590Srgrimes/* 101144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to 1021590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file, 1031590Srgrimes * or if it's DONE. 1041590Srgrimes */ 1051590Srgrimes#define CONTINUE 1 1061590Srgrimes#define DONE 0 107138916Sharti 108138916Sharti/* targets we're working on */ 109138916Shartistatic Lst targets = Lst_Initializer(targets); 110138916Sharti 111144026Sharti/* true if currently in a dependency line or its commands */ 112144026Shartistatic Boolean inLine; 1131590Srgrimes 114144026Shartistatic int fatals = 0; 1151590Srgrimes 116144026Sharti/* 117144026Sharti * The main target to create. This is the first target on the 118144026Sharti * first dependency line in the first makefile. 119144026Sharti */ 120144026Shartistatic GNode *mainNode; 121126824Sru 122144341Sharti/* 123144341Sharti * Definitions for handling #include specifications 124144341Sharti */ 125144341Shartistruct IFile { 126144341Sharti char *fname; /* name of previous file */ 127144341Sharti int lineno; /* saved line number */ 128144341Sharti FILE *F; /* the open stream */ 129144341Sharti char *str; /* the string when parsing a string */ 130144341Sharti char *ptr; /* the current pointer when parsing a string */ 131144341Sharti TAILQ_ENTRY(IFile) link;/* stack the files */ 132144341Sharti}; 133144026Sharti 134138916Sharti/* stack of IFiles generated by * #includes */ 135144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); 1361590Srgrimes 137144341Sharti/* access current file */ 138144341Sharti#define CURFILE (TAILQ_FIRST(&includes)) 139144341Sharti 140138916Sharti/* list of directories for "..." includes */ 141144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); 142138916Sharti 143138916Sharti/* list of directories for <...> includes */ 144144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); 145138916Sharti 146144026Sharti/* 1471590Srgrimes * specType contains the SPECial TYPE of the current target. It is 1481590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children 1491590Srgrimes * are linked as children of the parent but not vice versa. This variable is 1501590Srgrimes * set in ParseDoDependency 1511590Srgrimes */ 1521590Srgrimestypedef enum { 153144026Sharti Begin, /* .BEGIN */ 154144026Sharti Default, /* .DEFAULT */ 155144026Sharti End, /* .END */ 156145971Sharti ExportVar, /* .EXPORTVAR */ 157144026Sharti Ignore, /* .IGNORE */ 158144026Sharti Includes, /* .INCLUDES */ 159144026Sharti Interrupt, /* .INTERRUPT */ 160144026Sharti Libs, /* .LIBS */ 161144026Sharti MFlags, /* .MFLAGS or .MAKEFLAGS */ 162144026Sharti Main, /* .MAIN and we don't have anyth. user-spec. to make */ 163144026Sharti Not, /* Not special */ 164144026Sharti NotParallel, /* .NOTPARALELL */ 165144026Sharti Null, /* .NULL */ 166144026Sharti Order, /* .ORDER */ 167144026Sharti Parallel, /* .PARALLEL */ 168144026Sharti ExPath, /* .PATH */ 169144026Sharti Phony, /* .PHONY */ 170144026Sharti Posix, /* .POSIX */ 171177101Sobrien MakefileDeps, /* .MAKEFILEDEPS */ 172144026Sharti Precious, /* .PRECIOUS */ 173144026Sharti ExShell, /* .SHELL */ 174144026Sharti Silent, /* .SILENT */ 175144026Sharti SingleShell, /* .SINGLESHELL */ 176144026Sharti Suffixes, /* .SUFFIXES */ 177144026Sharti Wait, /* .WAIT */ 178145679Sharti Warn, /* .WARN */ 179144026Sharti Attribute /* Generic attribute */ 1801590Srgrimes} ParseSpecial; 1811590Srgrimes 1821590Srgrimesstatic ParseSpecial specType; 18318730Sstevestatic int waiting; 1841590Srgrimes 1851590Srgrimes/* 18669527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 1871590Srgrimes * seen, then set to each successive source on the line. 1881590Srgrimes */ 189144026Shartistatic GNode *predecessor; 1901590Srgrimes 1911590Srgrimes/* 1921590Srgrimes * The parseKeywords table is searched using binary search when deciding 1931590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial 1941590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while 1951590Srgrimes * the 'op' field is the operator to apply to the list of targets if the 1961590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source) 1971590Srgrimes */ 198145616Shartistatic const struct keyword { 199144026Sharti const char *name; /* Name of keyword */ 200144026Sharti ParseSpecial spec; /* Type when used as a target */ 201144026Sharti int op; /* Operator when used as a source */ 2021590Srgrimes} parseKeywords[] = { 203145616Sharti /* KEYWORD-START-TAG */ 204144026Sharti { ".BEGIN", Begin, 0 }, 205144026Sharti { ".DEFAULT", Default, 0 }, 206144026Sharti { ".END", End, 0 }, 207144026Sharti { ".EXEC", Attribute, OP_EXEC }, 208145971Sharti { ".EXPORTVAR", ExportVar, 0 }, 209144026Sharti { ".IGNORE", Ignore, OP_IGNORE }, 210144026Sharti { ".INCLUDES", Includes, 0 }, 211144026Sharti { ".INTERRUPT", Interrupt, 0 }, 212144026Sharti { ".INVISIBLE", Attribute, OP_INVISIBLE }, 213144026Sharti { ".JOIN", Attribute, OP_JOIN }, 214144026Sharti { ".LIBS", Libs, 0 }, 215144026Sharti { ".MAIN", Main, 0 }, 216144026Sharti { ".MAKE", Attribute, OP_MAKE }, 217177101Sobrien { ".MAKEFILEDEPS", MakefileDeps, 0 }, 218144026Sharti { ".MAKEFLAGS", MFlags, 0 }, 219144026Sharti { ".MFLAGS", MFlags, 0 }, 220144026Sharti { ".NOTMAIN", Attribute, OP_NOTMAIN }, 221144026Sharti { ".NOTPARALLEL", NotParallel, 0 }, 222144026Sharti { ".NO_PARALLEL", NotParallel, 0 }, 223144026Sharti { ".NULL", Null, 0 }, 224144026Sharti { ".OPTIONAL", Attribute, OP_OPTIONAL }, 225144026Sharti { ".ORDER", Order, 0 }, 226144026Sharti { ".PARALLEL", Parallel, 0 }, 227144026Sharti { ".PATH", ExPath, 0 }, 228144026Sharti { ".PHONY", Phony, OP_PHONY }, 229144026Sharti { ".POSIX", Posix, 0 }, 230144026Sharti { ".PRECIOUS", Precious, OP_PRECIOUS }, 231144026Sharti { ".RECURSIVE", Attribute, OP_MAKE }, 232144026Sharti { ".SHELL", ExShell, 0 }, 233144026Sharti { ".SILENT", Silent, OP_SILENT }, 234144026Sharti { ".SINGLESHELL", SingleShell, 0 }, 235144026Sharti { ".SUFFIXES", Suffixes, 0 }, 236144026Sharti { ".USE", Attribute, OP_USE }, 237144026Sharti { ".WAIT", Wait, 0 }, 238145679Sharti { ".WARN", Warn, 0 }, 239145616Sharti /* KEYWORD-END-TAG */ 2401590Srgrimes}; 241145616Sharti#define NKEYWORDS (sizeof(parseKeywords) / sizeof(parseKeywords[0])) 2421590Srgrimes 243144894Shartistatic void parse_include(char *, int, int); 244150595Sphkstatic void parse_sinclude(char *, int, int); 245144894Shartistatic void parse_message(char *, int, int); 246144894Shartistatic void parse_undef(char *, int, int); 247144894Shartistatic void parse_for(char *, int, int); 248144894Shartistatic void parse_endfor(char *, int, int); 249144894Sharti 250144894Shartistatic const struct directive { 251144894Sharti const char *name; 252144894Sharti int code; 253144894Sharti Boolean skip_flag; /* execute even when skipped */ 254144894Sharti void (*func)(char *, int, int); 255144894Sharti} directives[] = { 256145612Sharti /* DIRECTIVES-START-TAG */ 257144894Sharti { "elif", COND_ELIF, TRUE, Cond_If }, 258144894Sharti { "elifdef", COND_ELIFDEF, TRUE, Cond_If }, 259144894Sharti { "elifmake", COND_ELIFMAKE, TRUE, Cond_If }, 260144894Sharti { "elifndef", COND_ELIFNDEF, TRUE, Cond_If }, 261144894Sharti { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If }, 262144894Sharti { "else", COND_ELSE, TRUE, Cond_Else }, 263144894Sharti { "endfor", 0, FALSE, parse_endfor }, 264144894Sharti { "endif", COND_ENDIF, TRUE, Cond_Endif }, 265144894Sharti { "error", 1, FALSE, parse_message }, 266144894Sharti { "for", 0, FALSE, parse_for }, 267144894Sharti { "if", COND_IF, TRUE, Cond_If }, 268144894Sharti { "ifdef", COND_IFDEF, TRUE, Cond_If }, 269144894Sharti { "ifmake", COND_IFMAKE, TRUE, Cond_If }, 270144894Sharti { "ifndef", COND_IFNDEF, TRUE, Cond_If }, 271144894Sharti { "ifnmake", COND_IFNMAKE, TRUE, Cond_If }, 272144894Sharti { "include", 0, FALSE, parse_include }, 273150595Sphk { "sinclude", 0, FALSE, parse_sinclude }, 274144894Sharti { "undef", 0, FALSE, parse_undef }, 275144894Sharti { "warning", 0, FALSE, parse_message }, 276145612Sharti /* DIRECTIVES-END-TAG */ 277144894Sharti}; 278144894Sharti#define NDIRECTS (sizeof(directives) / sizeof(directives[0])) 279144894Sharti 2801590Srgrimes/*- 281145616Sharti * ParseFindKeyword 2821590Srgrimes * Look in the table of keywords for one matching the given string. 2831590Srgrimes * 2841590Srgrimes * Results: 285145616Sharti * The pointer to keyword table entry or NULL. 2861590Srgrimes */ 287145616Shartistatic const struct keyword * 288145616ShartiParseFindKeyword(const char *str) 2891590Srgrimes{ 290145616Sharti int kw; 2918874Srgrimes 292145616Sharti kw = keyword_hash(str, strlen(str)); 293145616Sharti if (kw < 0 || kw >= (int)NKEYWORDS || 294145616Sharti strcmp(str, parseKeywords[kw].name) != 0) 295145616Sharti return (NULL); 296145616Sharti return (&parseKeywords[kw]); 2971590Srgrimes} 2981590Srgrimes 2991590Srgrimes/*- 3001590Srgrimes * Parse_Error -- 3011590Srgrimes * Error message abort function for parsing. Prints out the context 3021590Srgrimes * of the error (line number and file) as well as the message with 3031590Srgrimes * two optional arguments. 3041590Srgrimes * 3051590Srgrimes * Results: 3061590Srgrimes * None 3071590Srgrimes * 3081590Srgrimes * Side Effects: 3091590Srgrimes * "fatals" is incremented if the level is PARSE_FATAL. 3101590Srgrimes */ 3111590Srgrimes/* VARARGS */ 3121590Srgrimesvoid 31398136SjmallettParse_Error(int type, const char *fmt, ...) 3141590Srgrimes{ 3151590Srgrimes va_list ap; 31693056Simp 3171590Srgrimes va_start(ap, fmt); 318144745Sharti if (CURFILE != NULL) 319144745Sharti fprintf(stderr, "\"%s\", line %d: ", 320144745Sharti CURFILE->fname, CURFILE->lineno); 3211590Srgrimes if (type == PARSE_WARNING) 322138232Sharti fprintf(stderr, "warning: "); 323138232Sharti vfprintf(stderr, fmt, ap); 3241590Srgrimes va_end(ap); 325138232Sharti fprintf(stderr, "\n"); 326138232Sharti fflush(stderr); 3271590Srgrimes if (type == PARSE_FATAL) 3281590Srgrimes fatals += 1; 3291590Srgrimes} 3301590Srgrimes 331144341Sharti/** 332144341Sharti * ParsePushInput 333144341Sharti * 334144341Sharti * Push a new input source onto the input stack. If ptr is NULL 335144341Sharti * the fullname is used to fopen the file. If it is not NULL, 336144341Sharti * ptr is assumed to point to the string to be parsed. If opening the 337144341Sharti * file fails, the fullname is freed. 338144341Sharti */ 339144341Shartistatic void 340144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) 341144341Sharti{ 342144341Sharti struct IFile *nf; 343144341Sharti 344144341Sharti nf = emalloc(sizeof(*nf)); 345144341Sharti nf->fname = fullname; 346144341Sharti nf->lineno = lineno; 347144341Sharti 348144341Sharti if (ptr == NULL) { 349144341Sharti /* the input source is a file */ 350144341Sharti if ((nf->F = fp) == NULL) { 351144341Sharti nf->F = fopen(fullname, "r"); 352144341Sharti if (nf->F == NULL) { 353144341Sharti Parse_Error(PARSE_FATAL, "Cannot open %s", 354144341Sharti fullname); 355144341Sharti free(fullname); 356144341Sharti free(nf); 357144341Sharti return; 358144341Sharti } 359144341Sharti } 360144341Sharti nf->str = nf->ptr = NULL; 361144341Sharti Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 362144341Sharti } else { 363144341Sharti nf->str = nf->ptr = ptr; 364144341Sharti nf->F = NULL; 365144341Sharti } 366144341Sharti TAILQ_INSERT_HEAD(&includes, nf, link); 367144341Sharti} 368144341Sharti 369144341Sharti/** 370144341Sharti * ParsePopInput 371144341Sharti * Called when EOF is reached in the current file. If we were reading 372144341Sharti * an include file, the includes stack is popped and things set up 373144341Sharti * to go back to reading the previous file at the previous location. 374144341Sharti * 375144341Sharti * Results: 376144341Sharti * CONTINUE if there's more to do. DONE if not. 377144341Sharti * 378144341Sharti * Side Effects: 379144341Sharti * The old curFile.F is closed. The includes list is shortened. 380144341Sharti * curFile.lineno, curFile.F, and curFile.fname are changed if 381144341Sharti * CONTINUE is returned. 382144341Sharti */ 383144341Shartistatic int 384144341ShartiParsePopInput(void) 385144341Sharti{ 386144341Sharti struct IFile *ifile; /* the state on the top of the includes stack */ 387144341Sharti 388144341Sharti assert(!TAILQ_EMPTY(&includes)); 389144341Sharti 390144341Sharti ifile = TAILQ_FIRST(&includes); 391144341Sharti TAILQ_REMOVE(&includes, ifile, link); 392144341Sharti 393144341Sharti free(ifile->fname); 394144341Sharti if (ifile->F != NULL) { 395144341Sharti fclose(ifile->F); 396144341Sharti Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 397144341Sharti } 398144341Sharti if (ifile->str != NULL) { 399144341Sharti free(ifile->str); 400144341Sharti } 401144341Sharti free(ifile); 402144341Sharti 403144341Sharti return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); 404144341Sharti} 405144341Sharti 406145679Sharti/** 407145679Sharti * parse_warn 408145679Sharti * Parse the .WARN pseudo-target. 409145679Sharti */ 410145679Shartistatic void 411145679Shartiparse_warn(char *line) 412145679Sharti{ 413146345Sharti ArgArray aa; 414146345Sharti int i; 415145679Sharti 416146345Sharti brk_string(&aa, line, TRUE); 417145679Sharti 418146345Sharti for (i = 1; i < aa.argc; i++) 419146345Sharti Main_ParseWarn(aa.argv[i], 0); 420145679Sharti} 421145679Sharti 4221590Srgrimes/*- 4231590Srgrimes *--------------------------------------------------------------------- 4241590Srgrimes * ParseLinkSrc -- 425143100Sharti * Link the parent nodes to their new child. Used by 4261590Srgrimes * ParseDoDependency. If the specType isn't 'Not', the parent 4271590Srgrimes * isn't linked as a parent of the child. 4281590Srgrimes * 4291590Srgrimes * Side Effects: 430143100Sharti * New elements are added to the parents lists of cgn and the 4311590Srgrimes * children list of cgn. the unmade field of pgn is updated 4321590Srgrimes * to reflect the additional child. 4331590Srgrimes *--------------------------------------------------------------------- 4341590Srgrimes */ 435143027Shartistatic void 436143027ShartiParseLinkSrc(Lst *parents, GNode *cgn) 4371590Srgrimes{ 438143027Sharti LstNode *ln; 439143027Sharti GNode *pgn; 440138232Sharti 441143027Sharti LST_FOREACH(ln, parents) { 442143027Sharti pgn = Lst_Datum(ln); 443143027Sharti if (Lst_Member(&pgn->children, cgn) == NULL) { 444143027Sharti Lst_AtEnd(&pgn->children, cgn); 445143027Sharti if (specType == Not) { 446143027Sharti Lst_AtEnd(&cgn->parents, pgn); 447143027Sharti } 448143027Sharti pgn->unmade += 1; 449143027Sharti } 4501590Srgrimes } 4511590Srgrimes} 4521590Srgrimes 4531590Srgrimes/*- 4541590Srgrimes *--------------------------------------------------------------------- 4551590Srgrimes * ParseDoOp -- 456143684Sharti * Apply the parsed operator to all target nodes. Used in 457143684Sharti * ParseDoDependency once all targets have been found and their 458143684Sharti * operator parsed. If the previous and new operators are incompatible, 459143684Sharti * a major error is taken. 4601590Srgrimes * 4611590Srgrimes * Side Effects: 4621590Srgrimes * The type field of the node is altered to reflect any new bits in 4631590Srgrimes * the op. 4641590Srgrimes *--------------------------------------------------------------------- 4651590Srgrimes */ 466143684Shartistatic void 467143684ShartiParseDoOp(int op) 4681590Srgrimes{ 469143684Sharti GNode *cohort; 470143684Sharti LstNode *ln; 471143684Sharti GNode *gn; 472138232Sharti 473143684Sharti LST_FOREACH(ln, &targets) { 474143684Sharti gn = Lst_Datum(ln); 4751590Srgrimes 476143684Sharti /* 477143684Sharti * If the dependency mask of the operator and the node don't 478143684Sharti * match and the node has actually had an operator applied to 479143684Sharti * it before, and the operator actually has some dependency 480143684Sharti * information in it, complain. 481143684Sharti */ 482143684Sharti if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && 483143684Sharti !OP_NOP(gn->type) && !OP_NOP(op)) { 484143684Sharti Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 485143684Sharti gn->name); 486143684Sharti return; 487143684Sharti } 4888874Srgrimes 489143684Sharti if (op == OP_DOUBLEDEP && 490143684Sharti (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 491143684Sharti /* 492143684Sharti * If the node was the object of a :: operator, we need 493143684Sharti * to create a new instance of it for the children and 494143684Sharti * commands on this dependency line. The new instance 495143684Sharti * is placed on the 'cohorts' list of the initial one 496143684Sharti * (note the initial one is not on its own cohorts list) 497143684Sharti * and the new instance is linked to all parents of the 498143684Sharti * initial instance. 499143684Sharti */ 500143684Sharti cohort = Targ_NewGN(gn->name); 5011590Srgrimes 502143684Sharti /* 503143684Sharti * Duplicate links to parents so graph traversal is 504143684Sharti * simple. Perhaps some type bits should be duplicated? 505143684Sharti * 506143684Sharti * Make the cohort invisible as well to avoid 507143684Sharti * duplicating it into other variables. True, parents 508143684Sharti * of this target won't tend to do anything with their 509143684Sharti * local variables, but better safe than sorry. 510143684Sharti */ 511143684Sharti ParseLinkSrc(&gn->parents, cohort); 512143684Sharti cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 513143684Sharti Lst_AtEnd(&gn->cohorts, cohort); 5141590Srgrimes 515143684Sharti /* 516143684Sharti * Replace the node in the targets list with the 517143684Sharti * new copy 518143684Sharti */ 519143684Sharti Lst_Replace(ln, cohort); 520143684Sharti gn = cohort; 521143684Sharti } 522143684Sharti /* 523143684Sharti * We don't want to nuke any previous flags (whatever they were) 524143684Sharti * so we just OR the new operator into the old 525143684Sharti */ 526143684Sharti gn->type |= op; 527143684Sharti } 5281590Srgrimes} 5291590Srgrimes 5301590Srgrimes/*- 5311590Srgrimes *--------------------------------------------------------------------- 5321590Srgrimes * ParseDoSrc -- 5331590Srgrimes * Given the name of a source, figure out if it is an attribute 5341590Srgrimes * and apply it to the targets if it is. Else decide if there is 5351590Srgrimes * some attribute which should be applied *to* the source because 5361590Srgrimes * of some special target and apply it if so. Otherwise, make the 5371590Srgrimes * source be a child of the targets in the list 'targets' 5381590Srgrimes * 5391590Srgrimes * Results: 5401590Srgrimes * None 5411590Srgrimes * 5421590Srgrimes * Side Effects: 5431590Srgrimes * Operator bits may be added to the list of targets or to the source. 5441590Srgrimes * The targets may have a new source added to their lists of children. 5451590Srgrimes *--------------------------------------------------------------------- 5461590Srgrimes */ 5471590Srgrimesstatic void 548138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc) 5491590Srgrimes{ 550144026Sharti GNode *gn = NULL; 551145616Sharti const struct keyword *kw; 5521590Srgrimes 553145616Sharti if (src[0] == '.' && isupper ((unsigned char)src[1])) { 554145616Sharti if ((kw = ParseFindKeyword(src)) != NULL) { 555145616Sharti if (kw->op != 0) { 556145616Sharti ParseDoOp(kw->op); 557144026Sharti return; 558144026Sharti } 559145616Sharti if (kw->spec == Wait) { 560144026Sharti waiting++; 561144026Sharti return; 562144026Sharti } 563144026Sharti } 5641590Srgrimes } 56518730Ssteve 566144026Sharti switch (specType) { 567144026Sharti case Main: 568144026Sharti /* 569144026Sharti * If we have noted the existence of a .MAIN, it means we need 570144026Sharti * to add the sources of said target to the list of things 571144026Sharti * to create. The string 'src' is likely to be free, so we 572144026Sharti * must make a new copy of it. Note that this will only be 573144026Sharti * invoked if the user didn't specify a target on the command 574144026Sharti * line. This is to allow #ifmake's to succeed, or something... 575144026Sharti */ 576144026Sharti Lst_AtEnd(&create, estrdup(src)); 577144026Sharti /* 578144026Sharti * Add the name to the .TARGETS variable as well, so the user 579144026Sharti * can employ that, if desired. 580144026Sharti */ 581144026Sharti Var_Append(".TARGETS", src, VAR_GLOBAL); 582144026Sharti return; 58318730Ssteve 584144026Sharti case Order: 585144026Sharti /* 586144026Sharti * Create proper predecessor/successor links between the 587144026Sharti * previous source and the current one. 588144026Sharti */ 589144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 590144026Sharti if (predecessor != NULL) { 591144026Sharti Lst_AtEnd(&predecessor->successors, gn); 592144026Sharti Lst_AtEnd(&gn->preds, predecessor); 593144026Sharti } 594144026Sharti /* 595144026Sharti * The current source now becomes the predecessor for the next 596144026Sharti * one. 597144026Sharti */ 598144026Sharti predecessor = gn; 599144026Sharti break; 60018730Ssteve 601144026Sharti default: 602144026Sharti /* 603144026Sharti * If the source is not an attribute, we need to find/create 604144026Sharti * a node for it. After that we can apply any operator to it 605144026Sharti * from a special target or link it to its parents, as 606144026Sharti * appropriate. 607144026Sharti * 608144026Sharti * In the case of a source that was the object of a :: operator, 609144026Sharti * the attribute is applied to all of its instances (as kept in 610144026Sharti * the 'cohorts' list of the node) or all the cohorts are linked 611144026Sharti * to all the targets. 612144026Sharti */ 613144026Sharti gn = Targ_FindNode(src, TARG_CREATE); 6141590Srgrimes if (tOp) { 615144026Sharti gn->type |= tOp; 6161590Srgrimes } else { 617144026Sharti ParseLinkSrc(&targets, gn); 6181590Srgrimes } 619144026Sharti if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 620144026Sharti GNode *cohort; 621144026Sharti LstNode *ln; 622144026Sharti 623144026Sharti for (ln = Lst_First(&gn->cohorts); ln != NULL; 624144026Sharti ln = Lst_Succ(ln)) { 625144026Sharti cohort = Lst_Datum(ln); 626144026Sharti if (tOp) { 627144026Sharti cohort->type |= tOp; 628144026Sharti } else { 629144026Sharti ParseLinkSrc(&targets, cohort); 630144026Sharti } 631144026Sharti } 632144026Sharti } 633144026Sharti break; 6341590Srgrimes } 63518730Ssteve 636144026Sharti gn->order = waiting; 637144026Sharti Lst_AtEnd(allsrc, gn); 638144026Sharti if (waiting) { 639144026Sharti LstNode *ln; 640144026Sharti GNode *p; 6411590Srgrimes 642143684Sharti /* 643144026Sharti * Check if GNodes needs to be synchronized. 644144026Sharti * This has to be when two nodes are on different sides of a 645144026Sharti * .WAIT directive. 646143684Sharti */ 647144026Sharti LST_FOREACH(ln, allsrc) { 648144026Sharti p = Lst_Datum(ln); 649144026Sharti 650144026Sharti if (p->order >= gn->order) 651144026Sharti break; 652144026Sharti /* 653144026Sharti * XXX: This can cause loops, and loops can cause 654144026Sharti * unmade targets, but checking is tedious, and the 655144026Sharti * debugging output can show the problem 656144026Sharti */ 657144026Sharti Lst_AtEnd(&p->successors, gn); 658144026Sharti Lst_AtEnd(&gn->preds, p); 659144026Sharti } 660143684Sharti } 6611590Srgrimes} 6621590Srgrimes 663138232Sharti 6641590Srgrimes/*- 6651590Srgrimes *--------------------------------------------------------------------- 6661590Srgrimes * ParseDoDependency -- 6671590Srgrimes * Parse the dependency line in line. 6681590Srgrimes * 6691590Srgrimes * Results: 6701590Srgrimes * None 6711590Srgrimes * 6721590Srgrimes * Side Effects: 6731590Srgrimes * The nodes of the sources are linked as children to the nodes of the 6741590Srgrimes * targets. Some nodes may be created. 6751590Srgrimes * 6761590Srgrimes * We parse a dependency line by first extracting words from the line and 6771590Srgrimes * finding nodes in the list of all targets with that name. This is done 6781590Srgrimes * until a character is encountered which is an operator character. Currently 6791590Srgrimes * these are only ! and :. At this point the operator is parsed and the 6801590Srgrimes * pointer into the line advanced until the first source is encountered. 681144026Sharti * The parsed operator is applied to each node in the 'targets' list, 6821590Srgrimes * which is where the nodes found for the targets are kept, by means of 6831590Srgrimes * the ParseDoOp function. 6841590Srgrimes * The sources are read in much the same way as the targets were except 6851590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell 6861590Srgrimes * and all instances of the resulting words in the list of all targets 6871590Srgrimes * are found. Each of the resulting nodes is then linked to each of the 6881590Srgrimes * targets as one of its children. 6891590Srgrimes * Certain targets are handled specially. These are the ones detailed 6901590Srgrimes * by the specType variable. 6911590Srgrimes * The storing of transformation rules is also taken care of here. 6921590Srgrimes * A target is recognized as a transformation rule by calling 6931590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten 6941590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard 6951590Srgrimes * Targ_FindNode in the target module. 6961590Srgrimes *--------------------------------------------------------------------- 6971590Srgrimes */ 6981590Srgrimesstatic void 699141270ShartiParseDoDependency(char *line) 7001590Srgrimes{ 701144026Sharti char *cp; /* our current position */ 702201456Sobrien char *lstart = line; /* original input line */ 703144026Sharti GNode *gn; /* a general purpose temporary node */ 704144026Sharti int op; /* the operator on the line */ 705144026Sharti char savec; /* a place to save a character */ 706144026Sharti Lst paths; /* Search paths to alter when parsing .PATH targets */ 707144026Sharti int tOp; /* operator from special target */ 708144026Sharti LstNode *ln; 709145616Sharti const struct keyword *kw; 7101590Srgrimes 711144026Sharti tOp = 0; 7121590Srgrimes 713144026Sharti specType = Not; 714144026Sharti waiting = 0; 715144026Sharti Lst_Init(&paths); 7161590Srgrimes 717144026Sharti do { 718144026Sharti for (cp = line; 719144026Sharti *cp && !isspace((unsigned char)*cp) && *cp != '('; 720144026Sharti cp++) { 721144026Sharti if (*cp == '$') { 722144026Sharti /* 723144026Sharti * Must be a dynamic source (would have been 724144026Sharti * expanded otherwise), so call the Var module 725144026Sharti * to parse the puppy so we can safely advance 726144026Sharti * beyond it...There should be no errors in this 727144026Sharti * as they would have been discovered in the 728144026Sharti * initial Var_Subst and we wouldn't be here. 729144026Sharti */ 730144026Sharti size_t length = 0; 731144026Sharti Boolean freeIt; 732144026Sharti char *result; 7331590Srgrimes 734144026Sharti result = Var_Parse(cp, VAR_CMD, TRUE, 735144026Sharti &length, &freeIt); 7361590Srgrimes 737144026Sharti if (freeIt) { 738144026Sharti free(result); 739144026Sharti } 740144026Sharti cp += length - 1; 741102178Sru 742144026Sharti } else if (*cp == '!' || *cp == ':') { 743144026Sharti /* 744144026Sharti * We don't want to end a word on ':' or '!' if 745144026Sharti * there is a better match later on in the 746144026Sharti * string (greedy matching). 747144026Sharti * This allows the user to have targets like: 748144026Sharti * fie::fi:fo: fum 749144026Sharti * foo::bar: 750144026Sharti * where "fie::fi:fo" and "foo::bar" are the 751144026Sharti * targets. In real life this is used for perl5 752144026Sharti * library man pages where "::" separates an 753144026Sharti * object from its class. Ie: 754144026Sharti * "File::Spec::Unix". This behaviour is also 755144026Sharti * consistent with other versions of make. 756144026Sharti */ 757144026Sharti char *p = cp + 1; 758102178Sru 759144026Sharti if (*cp == ':' && *p == ':') 760144026Sharti p++; 761102178Sru 762144026Sharti /* Found the best match already. */ 763144026Sharti if (*p == '\0' || isspace(*p)) 764144026Sharti break; 765102178Sru 766144026Sharti p += strcspn(p, "!:"); 7678874Srgrimes 768144026Sharti /* No better match later on... */ 769144026Sharti if (*p == '\0') 770144026Sharti break; 771144026Sharti } 772144026Sharti continue; 7731590Srgrimes } 774144026Sharti if (*cp == '(') { 775144026Sharti /* 776144026Sharti * Archives must be handled specially to make sure the 777144026Sharti * OP_ARCHV flag is set in their 'type' field, for one 778144026Sharti * thing, and because things like "archive(file1.o 779144026Sharti * file2.o file3.o)" are permissible. Arch_ParseArchive 780144026Sharti * will set 'line' to be the first non-blank after the 781144026Sharti * archive-spec. It creates/finds nodes for the members 782146338Sharti * and places them on the given list, returning TRUE 783146338Sharti * if all went well and FALSE if there was an error in 784144026Sharti * the specification. On error, line should remain 785144026Sharti * untouched. 786144026Sharti */ 787146338Sharti if (!Arch_ParseArchive(&line, &targets, VAR_CMD)) { 788144026Sharti Parse_Error(PARSE_FATAL, 789144026Sharti "Error in archive specification: \"%s\"", 790144026Sharti line); 791144026Sharti return; 792144026Sharti } else { 793144026Sharti cp = line; 794144026Sharti continue; 795144026Sharti } 796144026Sharti } 797144026Sharti savec = *cp; 7988874Srgrimes 799144026Sharti if (!*cp) { 800144026Sharti /* 801144026Sharti * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often 802144026Sharti * triggered by undetected conflicts from cvs/rcs 803144026Sharti * merges. 804144026Sharti */ 805144026Sharti if (strncmp(line, "<<<<<<", 6) == 0 || 806201455Sobrien strncmp(line, "||||||", 6) == 0 || 807144026Sharti strncmp(line, "======", 6) == 0 || 808144026Sharti strncmp(line, ">>>>>>", 6) == 0) { 809144026Sharti Parse_Error(PARSE_FATAL, "Makefile appears to " 810144026Sharti "contain unresolved cvs/rcs/??? merge " 811144026Sharti "conflicts"); 812144026Sharti } else 813201456Sobrien Parse_Error(PARSE_FATAL, lstart[0] == '.' ? 814201456Sobrien "Unknown directive" : "Need an operator"); 815144026Sharti return; 816144026Sharti } 817144026Sharti *cp = '\0'; 8181590Srgrimes /* 819144026Sharti * Have a word in line. See if it's a special target and set 820144026Sharti * specType to match it. 8211590Srgrimes */ 822144026Sharti if (*line == '.' && isupper((unsigned char)line[1])) { 823144026Sharti /* 824144026Sharti * See if the target is a special target that must have 825144026Sharti * it or its sources handled specially. 826144026Sharti */ 827145616Sharti if ((kw = ParseFindKeyword(line)) != NULL) { 828145616Sharti if (specType == ExPath && kw->spec != ExPath) { 829144026Sharti Parse_Error(PARSE_FATAL, 830144026Sharti "Mismatched special targets"); 831144026Sharti return; 832144026Sharti } 833144026Sharti 834145616Sharti specType = kw->spec; 835145616Sharti tOp = kw->op; 836144026Sharti 837144026Sharti /* 838144026Sharti * Certain special targets have special 839144026Sharti * semantics: 840144026Sharti * .PATH Have to set the dirSearchPath 841144026Sharti * variable too 842144026Sharti * .MAIN Its sources are only used if 843144026Sharti * nothing has been specified to 844144026Sharti * create. 845144026Sharti * .DEFAULT Need to create a node to hang 846144026Sharti * commands on, but we don't want 847144026Sharti * it in the graph, nor do we want 848144026Sharti * it to be the Main Target, so we 849144026Sharti * create it, set OP_NOTMAIN and 850144026Sharti * add it to the list, setting 851144026Sharti * DEFAULT to the new node for 852144026Sharti * later use. We claim the node is 853144026Sharti * A transformation rule to make 854144026Sharti * life easier later, when we'll 855144026Sharti * use Make_HandleUse to actually 856144026Sharti * apply the .DEFAULT commands. 857144026Sharti * .PHONY The list of targets 858144026Sharti * .BEGIN 859144026Sharti * .END 860144026Sharti * .INTERRUPT Are not to be considered the 861144026Sharti * main target. 862144026Sharti * .NOTPARALLEL Make only one target at a time. 863144026Sharti * .SINGLESHELL Create a shell for each 864144026Sharti * command. 865144026Sharti * .ORDER Must set initial predecessor 866144026Sharti * to NULL 867144026Sharti */ 868144026Sharti switch (specType) { 869144026Sharti case ExPath: 870144026Sharti Lst_AtEnd(&paths, &dirSearchPath); 871144026Sharti break; 872144026Sharti case Main: 873144026Sharti if (!Lst_IsEmpty(&create)) { 874144026Sharti specType = Not; 875144026Sharti } 876144026Sharti break; 877144026Sharti case Begin: 878144026Sharti case End: 879144026Sharti case Interrupt: 880144026Sharti gn = Targ_FindNode(line, TARG_CREATE); 881144026Sharti gn->type |= OP_NOTMAIN; 882144026Sharti Lst_AtEnd(&targets, gn); 883144026Sharti break; 884144026Sharti case Default: 885144026Sharti gn = Targ_NewGN(".DEFAULT"); 886144026Sharti gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 887144026Sharti Lst_AtEnd(&targets, gn); 888144026Sharti DEFAULT = gn; 889144026Sharti break; 890144026Sharti case NotParallel: 891146140Sharti jobLimit = 1; 892144026Sharti break; 893144026Sharti case SingleShell: 894144026Sharti compatMake = 1; 895144026Sharti break; 896144026Sharti case Order: 897144026Sharti predecessor = NULL; 898144026Sharti break; 899144026Sharti default: 900144026Sharti break; 901144026Sharti } 902144026Sharti 903144026Sharti } else if (strncmp(line, ".PATH", 5) == 0) { 904144026Sharti /* 905144026Sharti * .PATH<suffix> has to be handled specially. 906144026Sharti * Call on the suffix module to give us a path 907144026Sharti * to modify. 908144026Sharti */ 909144026Sharti struct Path *path; 910144026Sharti 911144026Sharti specType = ExPath; 912144026Sharti path = Suff_GetPath(&line[5]); 913144026Sharti if (path == NULL) { 914144026Sharti Parse_Error(PARSE_FATAL, "Suffix '%s' " 915144026Sharti "not defined (yet)", &line[5]); 916144026Sharti return; 917144026Sharti } else 918144026Sharti Lst_AtEnd(&paths, path); 9191590Srgrimes } 9201590Srgrimes } 921144026Sharti 9221590Srgrimes /* 923144026Sharti * Have word in line. Get or create its node and stick it at 924144026Sharti * the end of the targets list 9251590Srgrimes */ 926144029Sharti if (specType == Not && *line != '\0') { 9278874Srgrimes 928144026Sharti /* target names to be found and added to targets list */ 929144026Sharti Lst curTargs = Lst_Initializer(curTargs); 9308874Srgrimes 931144026Sharti if (Dir_HasWildcards(line)) { 932144026Sharti /* 933144026Sharti * Targets are to be sought only in the current 934144026Sharti * directory, so create an empty path for the 935144026Sharti * thing. Note we need to use Path_Clear in the 936144026Sharti * destruction of the path as the Dir module 937144026Sharti * could have added a directory to the path... 938144026Sharti */ 939144026Sharti struct Path emptyPath = 940144026Sharti TAILQ_HEAD_INITIALIZER(emptyPath); 941138916Sharti 942144026Sharti Path_Expand(line, &emptyPath, &curTargs); 943144026Sharti Path_Clear(&emptyPath); 9448874Srgrimes 945144026Sharti } else { 946144026Sharti /* 947144026Sharti * No wildcards, but we want to avoid code 948144026Sharti * duplication, so create a list with the word 949144026Sharti * on it. 950144026Sharti */ 951144026Sharti Lst_AtEnd(&curTargs, line); 952144026Sharti } 9538874Srgrimes 954144026Sharti while (!Lst_IsEmpty(&curTargs)) { 955144026Sharti char *targName = Lst_DeQueue(&curTargs); 956144026Sharti 957144026Sharti if (!Suff_IsTransform (targName)) { 958144026Sharti gn = Targ_FindNode(targName, 959144026Sharti TARG_CREATE); 960144026Sharti } else { 961144026Sharti gn = Suff_AddTransform(targName); 962144026Sharti } 963144026Sharti 964144026Sharti Lst_AtEnd(&targets, gn); 965144026Sharti } 966144026Sharti } else if (specType == ExPath && *line != '.' && *line != '\0'){ 967144026Sharti Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 968144026Sharti line); 969144026Sharti } 970144026Sharti 971144026Sharti *cp = savec; 9721590Srgrimes /* 973144026Sharti * If it is a special type and not .PATH, it's the only 974144026Sharti * target we allow on this line... 9751590Srgrimes */ 976144026Sharti if (specType != Not && specType != ExPath) { 977144026Sharti Boolean warnFlag = FALSE; 9788874Srgrimes 979144029Sharti while (*cp != '!' && *cp != ':' && *cp) { 980144026Sharti if (*cp != ' ' && *cp != '\t') { 981144026Sharti warnFlag = TRUE; 982144026Sharti } 983144026Sharti cp++; 984144026Sharti } 985144026Sharti if (warnFlag) { 986144026Sharti Parse_Error(PARSE_WARNING, 987144026Sharti "Extra target ignored"); 988144026Sharti } 9891590Srgrimes } else { 990144026Sharti while (*cp && isspace((unsigned char)*cp)) { 991144026Sharti cp++; 992144026Sharti } 9931590Srgrimes } 994144026Sharti line = cp; 995144029Sharti } while (*line != '!' && *line != ':' && *line); 9968874Srgrimes 997144026Sharti if (!Lst_IsEmpty(&targets)) { 998144026Sharti switch (specType) { 999144026Sharti default: 1000144026Sharti Parse_Error(PARSE_WARNING, "Special and mundane " 1001144026Sharti "targets don't mix. Mundane ones ignored"); 1002144026Sharti break; 1003144026Sharti case Default: 1004144026Sharti case Begin: 1005144026Sharti case End: 1006144026Sharti case Interrupt: 1007144026Sharti /* 1008144026Sharti * These four create nodes on which to hang commands, so 1009144026Sharti * targets shouldn't be empty... 1010144026Sharti */ 1011144026Sharti case Not: 1012144026Sharti /* 1013144026Sharti * Nothing special here -- targets can be empty if it 1014144026Sharti * wants. 1015144026Sharti */ 1016144026Sharti break; 1017144026Sharti } 10181590Srgrimes } 10198874Srgrimes 10201590Srgrimes /* 1021144026Sharti * Have now parsed all the target names. Must parse the operator next. 1022144026Sharti * The result is left in op. 10231590Srgrimes */ 1024144026Sharti if (*cp == '!') { 1025144026Sharti op = OP_FORCE; 1026144026Sharti } else if (*cp == ':') { 1027144026Sharti if (cp[1] == ':') { 1028144026Sharti op = OP_DOUBLEDEP; 1029144026Sharti cp++; 1030144026Sharti } else { 1031144026Sharti op = OP_DEPENDS; 10321590Srgrimes } 10331590Srgrimes } else { 1034201456Sobrien Parse_Error(PARSE_FATAL, lstart[0] == '.' ? 1035201456Sobrien "Unknown directive" : "Missing dependency operator"); 1036144026Sharti return; 1037144026Sharti } 1038144026Sharti 1039144026Sharti cp++; /* Advance beyond operator */ 1040144026Sharti 1041144026Sharti ParseDoOp(op); 1042144026Sharti 1043144026Sharti /* 1044144026Sharti * Get to the first source 1045144026Sharti */ 1046144026Sharti while (*cp && isspace((unsigned char)*cp)) { 10471590Srgrimes cp++; 10481590Srgrimes } 10491590Srgrimes line = cp; 10501590Srgrimes 1051144026Sharti /* 1052144026Sharti * Several special targets take different actions if present with no 1053144026Sharti * sources: 1054144026Sharti * a .SUFFIXES line with no sources clears out all old suffixes 1055144026Sharti * a .PRECIOUS line makes all targets precious 1056144026Sharti * a .IGNORE line ignores errors for all targets 1057144026Sharti * a .SILENT line creates silence when making all targets 1058144026Sharti * a .PATH removes all directories from the search path(s). 1059144026Sharti */ 1060144026Sharti if (!*line) { 1061144026Sharti switch (specType) { 1062144026Sharti case Suffixes: 1063144026Sharti Suff_ClearSuffixes(); 1064144026Sharti break; 1065144026Sharti case Precious: 1066144026Sharti allPrecious = TRUE; 1067144026Sharti break; 1068144026Sharti case Ignore: 1069144026Sharti ignoreErrors = TRUE; 1070144026Sharti break; 1071144026Sharti case Silent: 1072144026Sharti beSilent = TRUE; 1073144026Sharti break; 1074144026Sharti case ExPath: 1075144026Sharti LST_FOREACH(ln, &paths) 1076144026Sharti Path_Clear(Lst_Datum(ln)); 1077144026Sharti break; 1078177101Sobrien case MakefileDeps: 1079177101Sobrien mfAutoDeps = TRUE; 1080177101Sobrien break; 1081144026Sharti case Posix: 1082167330Sfjoe is_posix = TRUE; 1083186558Sobrien Var_SetGlobal("%POSIX", "1003.2"); 1084144026Sharti break; 1085144026Sharti default: 1086144026Sharti break; 1087144026Sharti } 1088144026Sharti 1089144026Sharti } else if (specType == MFlags) { 10901590Srgrimes /* 1091144026Sharti * Call on functions in main.c to deal with these arguments and 1092144026Sharti * set the initial character to a null-character so the loop to 1093144026Sharti * get sources won't get anything 10941590Srgrimes */ 1095144026Sharti Main_ParseArgLine(line, 0); 1096144026Sharti *line = '\0'; 10971590Srgrimes 1098145679Sharti } else if (specType == Warn) { 1099145679Sharti parse_warn(line); 1100145679Sharti *line = '\0'; 1101145679Sharti 1102144026Sharti } else if (specType == ExShell) { 1103146572Sharti if (!Shell_Parse(line)) { 1104144026Sharti Parse_Error(PARSE_FATAL, 1105144026Sharti "improper shell specification"); 1106144026Sharti return; 1107144026Sharti } 1108144026Sharti *line = '\0'; 1109144026Sharti 1110144029Sharti } else if (specType == NotParallel || specType == SingleShell) { 1111144026Sharti *line = '\0'; 11121590Srgrimes } 11131590Srgrimes 1114144026Sharti /* 1115144026Sharti * NOW GO FOR THE SOURCES 1116144026Sharti */ 1117144029Sharti if (specType == Suffixes || specType == ExPath || 1118144029Sharti specType == Includes || specType == Libs || 1119144029Sharti specType == Null) { 1120144026Sharti while (*line) { 1121144026Sharti /* 1122144026Sharti * If the target was one that doesn't take files as its 1123144026Sharti * sources but takes something like suffixes, we take 1124144026Sharti * each space-separated word on the line as a something 1125144026Sharti * and deal with it accordingly. 1126144026Sharti * 1127144026Sharti * If the target was .SUFFIXES, we take each source as 1128144026Sharti * a suffix and add it to the list of suffixes 1129144026Sharti * maintained by the Suff module. 1130144026Sharti * 1131144026Sharti * If the target was a .PATH, we add the source as a 1132144026Sharti * directory to search on the search path. 1133144026Sharti * 1134144026Sharti * If it was .INCLUDES, the source is taken to be the 1135144026Sharti * suffix of files which will be #included and whose 1136144026Sharti * search path should be present in the .INCLUDES 1137144026Sharti * variable. 1138144026Sharti * 1139144026Sharti * If it was .LIBS, the source is taken to be the 1140144026Sharti * suffix of files which are considered libraries and 1141144026Sharti * whose search path should be present in the .LIBS 1142144026Sharti * variable. 1143144026Sharti * 1144144026Sharti * If it was .NULL, the source is the suffix to use 1145144026Sharti * when a file has no valid suffix. 1146144026Sharti */ 1147144026Sharti char savech; 1148144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1149144026Sharti cp++; 1150144026Sharti } 1151144026Sharti savech = *cp; 1152144026Sharti *cp = '\0'; 1153144026Sharti switch (specType) { 1154144026Sharti case Suffixes: 1155144026Sharti Suff_AddSuffix(line); 1156144026Sharti break; 1157144026Sharti case ExPath: 1158144026Sharti LST_FOREACH(ln, &paths) 1159144026Sharti Path_AddDir(Lst_Datum(ln), line); 1160144026Sharti break; 1161144026Sharti case Includes: 1162144026Sharti Suff_AddInclude(line); 1163144026Sharti break; 1164144026Sharti case Libs: 1165144026Sharti Suff_AddLib(line); 1166144026Sharti break; 1167144026Sharti case Null: 1168144026Sharti Suff_SetNull(line); 1169144026Sharti break; 1170144026Sharti default: 1171144026Sharti break; 1172144026Sharti } 1173144026Sharti *cp = savech; 1174144026Sharti if (savech != '\0') { 1175144026Sharti cp++; 1176144026Sharti } 1177144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1178144026Sharti cp++; 1179144026Sharti } 1180144026Sharti line = cp; 1181144026Sharti } 1182144026Sharti Lst_Destroy(&paths, NOFREE); 11831590Srgrimes 1184145971Sharti } else if (specType == ExportVar) { 1185145971Sharti Var_SetEnv(line, VAR_GLOBAL); 1186145971Sharti 1187144026Sharti } else { 1188144026Sharti /* list of sources in order */ 1189144026Sharti Lst curSrcs = Lst_Initializer(curSrc); 11901590Srgrimes 1191144026Sharti while (*line) { 1192144026Sharti /* 1193144026Sharti * The targets take real sources, so we must beware of 1194144026Sharti * archive specifications (i.e. things with left 1195144026Sharti * parentheses in them) and handle them accordingly. 1196144026Sharti */ 1197144026Sharti while (*cp && !isspace((unsigned char)*cp)) { 1198144026Sharti if (*cp == '(' && cp > line && cp[-1] != '$') { 1199144026Sharti /* 1200144026Sharti * Only stop for a left parenthesis if 1201144026Sharti * it isn't at the start of a word 1202144026Sharti * (that'll be for variable changes 1203144026Sharti * later) and isn't preceded by a dollar 1204144026Sharti * sign (a dynamic source). 1205144026Sharti */ 1206144026Sharti break; 1207144026Sharti } else { 1208144026Sharti cp++; 1209144026Sharti } 1210144026Sharti } 12111590Srgrimes 1212144026Sharti if (*cp == '(') { 1213144026Sharti GNode *gnp; 12148874Srgrimes 1215144026Sharti /* list of archive source names after exp. */ 1216144026Sharti Lst sources = Lst_Initializer(sources); 1217138916Sharti 1218146338Sharti if (!Arch_ParseArchive(&line, &sources, 1219146338Sharti VAR_CMD)) { 1220144026Sharti Parse_Error(PARSE_FATAL, "Error in " 1221144026Sharti "source archive spec \"%s\"", line); 1222144026Sharti return; 1223144026Sharti } 1224141270Sharti 1225144026Sharti while (!Lst_IsEmpty(&sources)) { 1226144026Sharti gnp = Lst_DeQueue(&sources); 1227144026Sharti ParseDoSrc(tOp, gnp->name, &curSrcs); 1228144026Sharti } 1229144026Sharti cp = line; 1230144026Sharti } else { 1231144026Sharti if (*cp) { 1232144026Sharti *cp = '\0'; 1233144026Sharti cp += 1; 1234144026Sharti } 12351590Srgrimes 1236144026Sharti ParseDoSrc(tOp, line, &curSrcs); 1237144026Sharti } 1238144026Sharti while (*cp && isspace((unsigned char)*cp)) { 1239144026Sharti cp++; 1240144026Sharti } 1241144026Sharti line = cp; 12421590Srgrimes } 1243144026Sharti Lst_Destroy(&curSrcs, NOFREE); 1244144026Sharti } 12451590Srgrimes 1246144026Sharti if (mainNode == NULL) { 1247144026Sharti /* 1248144026Sharti * If we have yet to decide on a main target to make, in the 1249144026Sharti * absence of any user input, we want the first target on 1250144026Sharti * the first dependency line that is actually a real target 1251144026Sharti * (i.e. isn't a .USE or .EXEC rule) to be made. 1252144026Sharti */ 1253144026Sharti LST_FOREACH(ln, &targets) { 1254144026Sharti gn = Lst_Datum(ln); 1255144026Sharti if ((gn->type & (OP_NOTMAIN | OP_USE | 1256144026Sharti OP_EXEC | OP_TRANSFORM)) == 0) { 1257144026Sharti mainNode = gn; 1258144026Sharti Targ_SetMain(gn); 1259144026Sharti break; 1260144026Sharti } 12611590Srgrimes } 12621590Srgrimes } 12631590Srgrimes} 12641590Srgrimes 12651590Srgrimes/*- 12661590Srgrimes *--------------------------------------------------------------------- 12671590Srgrimes * Parse_IsVar -- 12681590Srgrimes * Return TRUE if the passed line is a variable assignment. A variable 12691590Srgrimes * assignment consists of a single word followed by optional whitespace 12701590Srgrimes * followed by either a += or an = operator. 12711590Srgrimes * This function is used both by the Parse_File function and main when 12721590Srgrimes * parsing the command-line arguments. 12731590Srgrimes * 12741590Srgrimes * Results: 12751590Srgrimes * TRUE if it is. FALSE if it ain't 12761590Srgrimes * 12771590Srgrimes * Side Effects: 12781590Srgrimes * none 12791590Srgrimes *--------------------------------------------------------------------- 12801590Srgrimes */ 12811590SrgrimesBoolean 1282138232ShartiParse_IsVar(char *line) 12831590Srgrimes{ 1284144026Sharti Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1285144026Sharti Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1286138232Sharti 1287144026Sharti int level = 0; 1288103503Sjmallett#define ISEQOPERATOR(c) \ 1289144029Sharti ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') 12901590Srgrimes 1291144026Sharti /* 1292144026Sharti * Skip to variable name 1293144026Sharti */ 1294144029Sharti for (; *line == ' ' || *line == '\t'; line++) 1295144026Sharti continue; 12961590Srgrimes 1297144026Sharti for (; *line != '=' || level != 0; line++) { 1298144026Sharti switch (*line) { 1299144026Sharti case '\0': 1300144026Sharti /* 1301144026Sharti * end-of-line -- can't be a variable assignment. 1302144026Sharti */ 1303144026Sharti return (FALSE); 130418730Ssteve 1305144026Sharti case ' ': 1306144026Sharti case '\t': 1307144026Sharti /* 1308144026Sharti * there can be as much white space as desired so long 1309144026Sharti * as there is only one word before the operator 1310144026Sharti */ 1311144026Sharti wasSpace = TRUE; 1312144026Sharti break; 131318730Ssteve 1314144026Sharti case '(': 1315144026Sharti case '{': 1316144026Sharti level++; 1317144026Sharti break; 131818730Ssteve 1319144026Sharti case '}': 1320144026Sharti case ')': 1321144026Sharti level--; 1322144026Sharti break; 132318730Ssteve 1324144026Sharti default: 1325144026Sharti if (wasSpace && haveName) { 1326144026Sharti if (ISEQOPERATOR(*line)) { 1327144026Sharti /* 1328144026Sharti * We must have a finished word 1329144026Sharti */ 1330144026Sharti if (level != 0) 1331144026Sharti return (FALSE); 133218730Ssteve 1333144026Sharti /* 1334144026Sharti * When an = operator [+?!:] is found, 1335144026Sharti * the next character must be an = or 1336144026Sharti * it ain't a valid assignment. 1337144026Sharti */ 1338144026Sharti if (line[1] == '=') 1339144026Sharti return (haveName); 134018730Ssteve#ifdef SUNSHCMD 1341144026Sharti /* 1342144026Sharti * This is a shell command 1343144026Sharti */ 1344144026Sharti if (strncmp(line, ":sh", 3) == 0) 1345144026Sharti return (haveName); 134618730Ssteve#endif 1347144026Sharti } 1348144026Sharti /* 1349144026Sharti * This is the start of another word, so not 1350144026Sharti * assignment. 1351144026Sharti */ 1352144026Sharti return (FALSE); 1353144026Sharti 1354144026Sharti } else { 1355144026Sharti haveName = TRUE; 1356144026Sharti wasSpace = FALSE; 1357144026Sharti } 1358144026Sharti break; 1359144026Sharti } 13601590Srgrimes } 13611590Srgrimes 1362144026Sharti return (haveName); 13631590Srgrimes} 13641590Srgrimes 13651590Srgrimes/*- 13661590Srgrimes *--------------------------------------------------------------------- 13671590Srgrimes * Parse_DoVar -- 13681590Srgrimes * Take the variable assignment in the passed line and do it in the 13691590Srgrimes * global context. 13701590Srgrimes * 13711590Srgrimes * Note: There is a lexical ambiguity with assignment modifier characters 13721590Srgrimes * in variable names. This routine interprets the character before the = 13731590Srgrimes * as a modifier. Therefore, an assignment like 13741590Srgrimes * C++=/usr/bin/CC 13751590Srgrimes * is interpreted as "C+ +=" instead of "C++ =". 13761590Srgrimes * 13771590Srgrimes * Results: 13781590Srgrimes * none 13791590Srgrimes * 13801590Srgrimes * Side Effects: 13811590Srgrimes * the variable structure of the given variable name is altered in the 13821590Srgrimes * global context. 13831590Srgrimes *--------------------------------------------------------------------- 13841590Srgrimes */ 13851590Srgrimesvoid 1386138232ShartiParse_DoVar(char *line, GNode *ctxt) 13871590Srgrimes{ 1388144026Sharti char *cp; /* pointer into line */ 1389144026Sharti enum { 1390144026Sharti VAR_SUBST, 1391144026Sharti VAR_APPEND, 1392144026Sharti VAR_SHELL, 1393144026Sharti VAR_NORMAL 1394144026Sharti } type; /* Type of assignment */ 1395144026Sharti char *opc; /* ptr to operator character to 1396144026Sharti * null-terminate the variable name */ 1397144026Sharti 1398144026Sharti /* 1399144026Sharti * Skip to variable name 1400144026Sharti */ 1401144029Sharti while (*line == ' ' || *line == '\t') { 1402144026Sharti line++; 1403144026Sharti } 14041590Srgrimes 1405144026Sharti /* 1406144026Sharti * Skip to operator character, nulling out whitespace as we go 1407144026Sharti */ 1408144026Sharti for (cp = line + 1; *cp != '='; cp++) { 1409144026Sharti if (isspace((unsigned char)*cp)) { 1410144026Sharti *cp = '\0'; 1411144026Sharti } 14121590Srgrimes } 1413144026Sharti opc = cp - 1; /* operator is the previous character */ 1414144026Sharti *cp++ = '\0'; /* nuke the = */ 14151590Srgrimes 1416144026Sharti /* 1417144026Sharti * Check operator type 1418144026Sharti */ 1419144026Sharti switch (*opc) { 1420144026Sharti case '+': 1421144026Sharti type = VAR_APPEND; 1422144026Sharti *opc = '\0'; 1423144026Sharti break; 14241590Srgrimes 1425144026Sharti case '?': 1426144026Sharti /* 1427144026Sharti * If the variable already has a value, we don't do anything. 1428144026Sharti */ 1429144026Sharti *opc = '\0'; 1430144026Sharti if (Var_Exists(line, ctxt)) { 1431144026Sharti return; 1432144026Sharti } else { 1433144026Sharti type = VAR_NORMAL; 1434144026Sharti } 1435144026Sharti break; 14361590Srgrimes 1437144026Sharti case ':': 1438144026Sharti type = VAR_SUBST; 1439144026Sharti *opc = '\0'; 1440144026Sharti break; 14411590Srgrimes 1442144026Sharti case '!': 1443144026Sharti type = VAR_SHELL; 1444144026Sharti *opc = '\0'; 1445144026Sharti break; 14461590Srgrimes 1447144026Sharti default: 144818730Ssteve#ifdef SUNSHCMD 1449144026Sharti while (*opc != ':') { 1450144026Sharti if (opc == line) 1451144026Sharti break; 1452144026Sharti else 1453144026Sharti --opc; 1454144026Sharti } 145518730Ssteve 1456144026Sharti if (strncmp(opc, ":sh", 3) == 0) { 1457144026Sharti type = VAR_SHELL; 1458144026Sharti *opc = '\0'; 1459144026Sharti break; 1460144026Sharti } 1461144026Sharti#endif 1462144026Sharti type = VAR_NORMAL; 146318730Ssteve break; 1464144026Sharti } 14651590Srgrimes 1466144026Sharti while (isspace((unsigned char)*cp)) { 1467144026Sharti cp++; 1468144026Sharti } 14691590Srgrimes 1470144026Sharti if (type == VAR_APPEND) { 1471144026Sharti Var_Append(line, cp, ctxt); 14721590Srgrimes 1473144026Sharti } else if (type == VAR_SUBST) { 1474144026Sharti /* 1475144026Sharti * Allow variables in the old value to be undefined, but leave 1476144026Sharti * their invocation alone -- this is done by forcing oldVars 1477144026Sharti * to be false. 1478144026Sharti * XXX: This can cause recursive variables, but that's not 1479144026Sharti * hard to do, and this allows someone to do something like 1480144026Sharti * 1481144026Sharti * CFLAGS = $(.INCLUDES) 1482144026Sharti * CFLAGS := -I.. $(CFLAGS) 1483144026Sharti * 1484144026Sharti * And not get an error. 1485144026Sharti */ 1486144026Sharti Boolean oldOldVars = oldVars; 148798509Sjmallett 1488144026Sharti oldVars = FALSE; 148998509Sjmallett 1490144026Sharti /* 1491144026Sharti * make sure that we set the variable the first time to nothing 1492144026Sharti * so that it gets substituted! 1493144026Sharti */ 1494144026Sharti if (!Var_Exists(line, ctxt)) 1495144026Sharti Var_Set(line, "", ctxt); 1496142457Sharti 1497146027Sharti cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE)); 14981590Srgrimes 1499144026Sharti oldVars = oldOldVars; 15001590Srgrimes 1501144026Sharti Var_Set(line, cp, ctxt); 1502144026Sharti free(cp); 15031590Srgrimes 1504144026Sharti } else if (type == VAR_SHELL) { 1505144026Sharti /* 1506144026Sharti * TRUE if the command needs to be freed, i.e. 1507144026Sharti * if any variable expansion was performed 1508144026Sharti */ 1509144026Sharti Boolean freeCmd = FALSE; 1510144026Sharti Buffer *buf; 1511144026Sharti const char *error; 15121590Srgrimes 1513144026Sharti if (strchr(cp, '$') != NULL) { 1514144026Sharti /* 1515144026Sharti * There's a dollar sign in the command, so perform 1516144026Sharti * variable expansion on the whole thing. The 1517144026Sharti * resulting string will need freeing when we're done, 1518144026Sharti * so set freeCmd to TRUE. 1519144026Sharti */ 1520146027Sharti cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE)); 1521144026Sharti freeCmd = TRUE; 1522144026Sharti } 15231590Srgrimes 1524144026Sharti buf = Cmd_Exec(cp, &error); 1525144026Sharti Var_Set(line, Buf_Data(buf), ctxt); 1526144026Sharti Buf_Destroy(buf, TRUE); 1527144026Sharti 1528144026Sharti if (error) 1529144026Sharti Parse_Error(PARSE_WARNING, error, cp); 1530144026Sharti 1531144026Sharti if (freeCmd) 1532144026Sharti free(cp); 1533144026Sharti 1534144026Sharti } else { 1535144026Sharti /* 1536144026Sharti * Normal assignment -- just do it. 1537144026Sharti */ 1538144026Sharti Var_Set(line, cp, ctxt); 1539144026Sharti } 1540186559Sobrien if (strcmp(line, MAKE_JOB_PREFIX) == 0) 1541186559Sobrien Job_SetPrefix(); 15421590Srgrimes} 15431590Srgrimes 15441590Srgrimes/*- 15451590Srgrimes *----------------------------------------------------------------------- 15461590Srgrimes * ParseHasCommands -- 15471590Srgrimes * Callback procedure for Parse_File when destroying the list of 15481590Srgrimes * targets on the last dependency line. Marks a target as already 15491590Srgrimes * having commands if it does, to keep from having shell commands 15501590Srgrimes * on multiple dependency lines. 15511590Srgrimes * 15521590Srgrimes * Results: 15535814Sjkh * None 15541590Srgrimes * 15551590Srgrimes * Side Effects: 15561590Srgrimes * OP_HAS_COMMANDS may be set for the target. 15571590Srgrimes * 15581590Srgrimes *----------------------------------------------------------------------- 15591590Srgrimes */ 15605814Sjkhstatic void 1561104696SjmallettParseHasCommands(void *gnp) 15621590Srgrimes{ 1563144026Sharti GNode *gn = gnp; 1564138232Sharti 1565144026Sharti if (!Lst_IsEmpty(&gn->commands)) { 1566144026Sharti gn->type |= OP_HAS_COMMANDS; 1567144026Sharti } 15681590Srgrimes} 15691590Srgrimes 15701590Srgrimes/*- 15711590Srgrimes *----------------------------------------------------------------------- 15721590Srgrimes * Parse_AddIncludeDir -- 15731590Srgrimes * Add a directory to the path searched for included makefiles 15741590Srgrimes * bracketed by double-quotes. Used by functions in main.c 15751590Srgrimes * 15761590Srgrimes * Results: 15771590Srgrimes * None. 15781590Srgrimes * 15791590Srgrimes * Side Effects: 15801590Srgrimes * The directory is appended to the list. 15811590Srgrimes * 15821590Srgrimes *----------------------------------------------------------------------- 15831590Srgrimes */ 15841590Srgrimesvoid 1585138232ShartiParse_AddIncludeDir(char *dir) 15861590Srgrimes{ 1587138232Sharti 1588144026Sharti Path_AddDir(&parseIncPath, dir); 15891590Srgrimes} 15901590Srgrimes 15911590Srgrimes/*- 15921590Srgrimes *--------------------------------------------------------------------- 15931590Srgrimes * Parse_FromString -- 15941590Srgrimes * Start Parsing from the given string 15958874Srgrimes * 15961590Srgrimes * Results: 15971590Srgrimes * None 15981590Srgrimes * 15991590Srgrimes * Side Effects: 1600126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1601126824Sru * curFile.fname and curFile.F are altered for the new file 16021590Srgrimes *--------------------------------------------------------------------- 16031590Srgrimes */ 16041590Srgrimesvoid 1605126824SruParse_FromString(char *str, int lineno) 16061590Srgrimes{ 16071590Srgrimes 1608144026Sharti DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 16091590Srgrimes 1610144341Sharti ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); 16111590Srgrimes} 16121590Srgrimes 16131590Srgrimes#ifdef SYSVINCLUDE 16141590Srgrimes/*- 16151590Srgrimes *--------------------------------------------------------------------- 16161590Srgrimes * ParseTraditionalInclude -- 16171590Srgrimes * Push to another file. 16188874Srgrimes * 16191590Srgrimes * The input is the line minus the "include". The file name is 16201590Srgrimes * the string following the "include". 16211590Srgrimes * 16221590Srgrimes * Results: 16231590Srgrimes * None 16241590Srgrimes * 16251590Srgrimes * Side Effects: 1626126824Sru * A structure is added to the includes Lst and readProc, curFile.lineno, 1627126824Sru * curFile.fname and curFile.F are altered for the new file 16281590Srgrimes *--------------------------------------------------------------------- 16291590Srgrimes */ 16301590Srgrimesstatic void 1631141270ShartiParseTraditionalInclude(char *file) 16321590Srgrimes{ 1633144026Sharti char *fullname; /* full pathname of file */ 1634144026Sharti char *cp; /* current position in file spec */ 16351590Srgrimes 1636144026Sharti /* 1637144026Sharti * Skip over whitespace 1638144026Sharti */ 1639144029Sharti while (*file == ' ' || *file == '\t') { 1640144026Sharti file++; 1641144026Sharti } 16421590Srgrimes 1643144026Sharti if (*file == '\0') { 1644144026Sharti Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); 1645144026Sharti return; 1646144026Sharti } 16471590Srgrimes 1648144026Sharti /* 1649144026Sharti * Skip to end of line or next whitespace 1650144026Sharti */ 1651144026Sharti for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1652144026Sharti continue; 1653144026Sharti } 16541590Srgrimes 1655144026Sharti *cp = '\0'; 16561590Srgrimes 1657144026Sharti /* 1658144026Sharti * Substitute for any variables in the file name before trying to 1659144026Sharti * find the thing. 1660144026Sharti */ 1661146027Sharti file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 16621590Srgrimes 16631590Srgrimes /* 1664144026Sharti * Now we know the file's name, we attempt to find the durn thing. 1665144026Sharti * Search for it first on the -I search path, then on the .PATH 1666144026Sharti * search path, if not found in a -I directory. 16671590Srgrimes */ 1668144026Sharti fullname = Path_FindFile(file, &parseIncPath); 1669144026Sharti if (fullname == NULL) { 1670144026Sharti fullname = Path_FindFile(file, &dirSearchPath); 1671144026Sharti } 16721590Srgrimes 1673144026Sharti if (fullname == NULL) { 1674144026Sharti /* 1675144026Sharti * Still haven't found the makefile. Look for it on the system 1676144026Sharti * path as a last resort. 1677144026Sharti */ 1678144026Sharti fullname = Path_FindFile(file, &sysIncPath); 1679144026Sharti } 16801590Srgrimes 1681144026Sharti if (fullname == NULL) { 1682144026Sharti Parse_Error(PARSE_FATAL, "Could not find %s", file); 1683144026Sharti /* XXXHB free(file) */ 1684144026Sharti return; 1685144026Sharti } 1686142457Sharti 1687144026Sharti /* XXXHB free(file) */ 16881590Srgrimes 1689144026Sharti /* 1690144341Sharti * We set up the name of the file to be the absolute 1691144026Sharti * name of the include file so error messages refer to the right 1692144341Sharti * place. 16931590Srgrimes */ 1694144341Sharti ParsePushInput(fullname, NULL, NULL, 0); 16951590Srgrimes} 16961590Srgrimes#endif 16971590Srgrimes 16981590Srgrimes/*- 16991590Srgrimes *--------------------------------------------------------------------- 17001590Srgrimes * ParseReadc -- 17018874Srgrimes * Read a character from the current file 17021590Srgrimes * 17031590Srgrimes * Results: 17041590Srgrimes * The character that was read 17051590Srgrimes * 17061590Srgrimes * Side Effects: 17071590Srgrimes *--------------------------------------------------------------------- 17081590Srgrimes */ 17091590Srgrimesstatic int 1710104696SjmallettParseReadc(void) 17111590Srgrimes{ 1712138232Sharti 1713144341Sharti if (CURFILE->F != NULL) 1714144341Sharti return (fgetc(CURFILE->F)); 17158874Srgrimes 1716144341Sharti if (CURFILE->str != NULL && *CURFILE->ptr != '\0') 1717144341Sharti return (*CURFILE->ptr++); 1718144341Sharti 1719144026Sharti return (EOF); 17201590Srgrimes} 17211590Srgrimes 17221590Srgrimes 17231590Srgrimes/*- 17241590Srgrimes *--------------------------------------------------------------------- 17251590Srgrimes * ParseUnreadc -- 17268874Srgrimes * Put back a character to the current file 17271590Srgrimes * 17281590Srgrimes * Results: 17291590Srgrimes * None. 17301590Srgrimes * 17311590Srgrimes * Side Effects: 17321590Srgrimes *--------------------------------------------------------------------- 17331590Srgrimes */ 17341590Srgrimesstatic void 1735104696SjmallettParseUnreadc(int c) 17361590Srgrimes{ 1737138232Sharti 1738144341Sharti if (CURFILE->F != NULL) { 1739144341Sharti ungetc(c, CURFILE->F); 1740144026Sharti return; 1741144026Sharti } 1742144341Sharti if (CURFILE->str != NULL) { 1743144341Sharti *--(CURFILE->ptr) = c; 1744144026Sharti return; 1745144026Sharti } 17461590Srgrimes} 17471590Srgrimes 17481590Srgrimes/* ParseSkipLine(): 1749104696Sjmallett * Grab the next line unless it begins with a dot (`.') and we're told to 1750104696Sjmallett * ignore such lines. 17511590Srgrimes */ 17521590Srgrimesstatic char * 1753126824SruParseSkipLine(int skip, int keep_newline) 17541590Srgrimes{ 1755144026Sharti char *line; 1756144026Sharti int c, lastc; 1757144026Sharti Buffer *buf; 17581590Srgrimes 1759144026Sharti buf = Buf_Init(MAKE_BSIZE); 17601590Srgrimes 1761144026Sharti do { 1762144026Sharti Buf_Clear(buf); 1763144026Sharti lastc = '\0'; 17648874Srgrimes 1765144026Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') 1766144026Sharti && c != EOF) { 1767144026Sharti if (skip && c == '#' && lastc != '\\') { 1768144026Sharti /* 1769144026Sharti * let a comment be terminated even by an 1770144026Sharti * escaped \n. This is consistent to comment 1771144026Sharti * handling in ParseReadLine 1772144026Sharti */ 1773144026Sharti while ((c = ParseReadc()) != '\n' && c != EOF) 1774144026Sharti ; 1775144026Sharti break; 1776144026Sharti } 1777144026Sharti if (c == '\n') { 1778144026Sharti if (keep_newline) 1779144026Sharti Buf_AddByte(buf, (Byte)c); 1780144026Sharti else 1781144026Sharti Buf_ReplaceLastByte(buf, (Byte)' '); 1782144341Sharti CURFILE->lineno++; 17838874Srgrimes 1784144026Sharti while ((c = ParseReadc()) == ' ' || c == '\t') 1785144026Sharti continue; 17868874Srgrimes 1787144026Sharti if (c == EOF) 1788144026Sharti break; 1789144026Sharti } 179074272Swill 1791144026Sharti Buf_AddByte(buf, (Byte)c); 1792144026Sharti lastc = c; 1793144026Sharti } 179418456Ssteve 1795144026Sharti if (c == EOF) { 1796144026Sharti Parse_Error(PARSE_FATAL, 1797144026Sharti "Unclosed conditional/for loop"); 1798144026Sharti Buf_Destroy(buf, TRUE); 1799144026Sharti return (NULL); 1800144026Sharti } 180118456Ssteve 1802144341Sharti CURFILE->lineno++; 1803144026Sharti Buf_AddByte(buf, (Byte)'\0'); 1804144026Sharti line = Buf_Data(buf); 1805144026Sharti } while (skip == 1 && line[0] != '.'); 180618456Ssteve 1807144026Sharti Buf_Destroy(buf, FALSE); 1808144026Sharti return (line); 18091590Srgrimes} 18101590Srgrimes 18111590Srgrimes/*- 18121590Srgrimes *--------------------------------------------------------------------- 18131590Srgrimes * ParseReadLine -- 18141590Srgrimes * Read an entire line from the input file. Called only by Parse_File. 18151590Srgrimes * To facilitate escaped newlines and what have you, a character is 18161590Srgrimes * buffered in 'lastc', which is '\0' when no characters have been 18171590Srgrimes * read. When we break out of the loop, c holds the terminating 18181590Srgrimes * character and lastc holds a character that should be added to 18191590Srgrimes * the line (unless we don't read anything but a terminator). 18201590Srgrimes * 18211590Srgrimes * Results: 18221590Srgrimes * A line w/o its newline 18231590Srgrimes * 18241590Srgrimes * Side Effects: 18251590Srgrimes * Only those associated with reading a character 18261590Srgrimes *--------------------------------------------------------------------- 18271590Srgrimes */ 18281590Srgrimesstatic char * 1829138232ShartiParseReadLine(void) 18301590Srgrimes{ 1831144026Sharti Buffer *buf; /* Buffer for current line */ 1832144026Sharti int c; /* the current character */ 1833144026Sharti int lastc; /* The most-recent character */ 1834144026Sharti Boolean semiNL; /* treat semi-colons as newlines */ 1835144026Sharti Boolean ignDepOp; /* TRUE if should ignore dependency operators 18361590Srgrimes * for the purposes of setting semiNL */ 1837144026Sharti Boolean ignComment; /* TRUE if should ignore comments (in a 18381590Srgrimes * shell command */ 1839144026Sharti char *line; /* Result */ 1840144026Sharti char *ep; /* to strip trailing blanks */ 18411590Srgrimes 1842144742Sharti again: 1843144026Sharti semiNL = FALSE; 1844144026Sharti ignDepOp = FALSE; 1845144026Sharti ignComment = FALSE; 18461590Srgrimes 1847144742Sharti lastc = '\0'; 1848144742Sharti 1849144026Sharti /* 1850144742Sharti * Handle tab at the beginning of the line. A leading tab (shell 1851144742Sharti * command) forces us to ignore comments and dependency operators and 1852144742Sharti * treat semi-colons as semi-colons (by leaving semiNL FALSE). 1853144742Sharti * This also discards completely blank lines. 1854144026Sharti */ 1855144026Sharti for (;;) { 1856144026Sharti c = ParseReadc(); 1857144742Sharti if (c == EOF) { 1858144742Sharti if (ParsePopInput() == DONE) { 1859144742Sharti /* End of all inputs - return NULL */ 1860144742Sharti return (NULL); 1861144742Sharti } 1862144742Sharti continue; 1863144742Sharti } 18641590Srgrimes 1865144026Sharti if (c == '\t') { 1866144026Sharti ignComment = ignDepOp = TRUE; 1867144742Sharti lastc = c; 1868144026Sharti break; 1869144742Sharti } 1870144742Sharti if (c != '\n') { 1871144026Sharti ParseUnreadc(c); 1872144026Sharti break; 1873144026Sharti } 1874144742Sharti CURFILE->lineno++; 18751590Srgrimes } 18768874Srgrimes 1877144742Sharti buf = Buf_Init(MAKE_BSIZE); 18788874Srgrimes 1879144742Sharti while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { 1880144026Sharti test_char: 1881144742Sharti switch (c) { 1882144742Sharti case '\n': 1883144742Sharti /* 1884144742Sharti * Escaped newline: read characters until a 1885144742Sharti * non-space or an unescaped newline and 1886144742Sharti * replace them all by a single space. This is 1887144742Sharti * done by storing the space over the backslash 1888144742Sharti * and dropping through with the next nonspace. 1889144742Sharti * If it is a semi-colon and semiNL is TRUE, 1890144742Sharti * it will be recognized as a newline in the 1891144742Sharti * code below this... 1892144742Sharti */ 1893144742Sharti CURFILE->lineno++; 1894144742Sharti lastc = ' '; 1895144742Sharti while ((c = ParseReadc()) == ' ' || c == '\t') { 1896144742Sharti continue; 1897144742Sharti } 1898144742Sharti if (c == EOF || c == '\n') { 1899144742Sharti goto line_read; 1900144742Sharti } else { 1901144026Sharti /* 1902144742Sharti * Check for comments, semiNL's, etc. -- 1903144742Sharti * easier than ParseUnreadc(c); 1904144742Sharti * continue; 1905144026Sharti */ 1906144742Sharti goto test_char; 1907144742Sharti } 1908144742Sharti /*NOTREACHED*/ 1909144742Sharti break; 1910144026Sharti 1911144742Sharti case ';': 1912144742Sharti /* 1913144742Sharti * Semi-colon: Need to see if it should be 1914144742Sharti * interpreted as a newline 1915144742Sharti */ 1916144742Sharti if (semiNL) { 1917144026Sharti /* 1918144742Sharti * To make sure the command that may 1919144742Sharti * be following this semi-colon begins 1920144742Sharti * with a tab, we push one back into the 1921144742Sharti * input stream. This will overwrite the 1922144742Sharti * semi-colon in the buffer. If there is 1923144742Sharti * no command following, this does no 1924144742Sharti * harm, since the newline remains in 1925144742Sharti * the buffer and the 1926144742Sharti * whole line is ignored. 1927144026Sharti */ 1928144742Sharti ParseUnreadc('\t'); 1929144742Sharti goto line_read; 1930144742Sharti } 1931144742Sharti break; 1932144742Sharti case '=': 1933144742Sharti if (!semiNL) { 1934144742Sharti /* 1935144742Sharti * Haven't seen a dependency operator 1936144742Sharti * before this, so this must be a 1937144742Sharti * variable assignment -- don't pay 1938144742Sharti * attention to dependency operators 1939144742Sharti * after this. 1940144742Sharti */ 1941144742Sharti ignDepOp = TRUE; 1942144742Sharti } else if (lastc == ':' || lastc == '!') { 1943144742Sharti /* 1944144742Sharti * Well, we've seen a dependency 1945144742Sharti * operator already, but it was the 1946144742Sharti * previous character, so this is really 1947144742Sharti * just an expanded variable assignment. 1948144742Sharti * Revert semi-colons to being just 1949144742Sharti * semi-colons again and ignore any more 1950144742Sharti * dependency operators. 1951144742Sharti * 1952144742Sharti * XXX: Note that a line like 1953144742Sharti * "foo : a:=b" will blow up, but who'd 1954144742Sharti * write a line like that anyway? 1955144742Sharti */ 1956144742Sharti ignDepOp = TRUE; 1957144742Sharti semiNL = FALSE; 1958144742Sharti } 1959144742Sharti break; 1960144742Sharti case '#': 1961144742Sharti if (!ignComment) { 1962144742Sharti if (lastc != '\\') { 1963144026Sharti /* 1964144742Sharti * If the character is a hash 1965144742Sharti * mark and it isn't escaped 1966144742Sharti * (or we're being compatible), 1967144742Sharti * the thing is a comment. 1968144742Sharti * Skip to the end of the line. 1969144026Sharti */ 1970144742Sharti do { 1971144742Sharti c = ParseReadc(); 1972144742Sharti } while (c != '\n' && c != EOF); 1973144026Sharti goto line_read; 1974144742Sharti } else { 1975144026Sharti /* 1976144742Sharti * Don't add the backslash. 1977144742Sharti * Just let the # get copied 1978144742Sharti * over. 1979144026Sharti */ 1980144742Sharti lastc = c; 1981144742Sharti continue; 1982144026Sharti } 1983144742Sharti } 1984144742Sharti break; 1985144026Sharti 1986144742Sharti case ':': 1987144742Sharti case '!': 1988144742Sharti if (!ignDepOp) { 1989144742Sharti /* 1990144742Sharti * A semi-colon is recognized as a 1991144742Sharti * newline only on dependency lines. 1992144742Sharti * Dependency lines are lines with a 1993144742Sharti * colon or an exclamation point. 1994144742Sharti * Ergo... 1995144742Sharti */ 1996144742Sharti semiNL = TRUE; 1997144742Sharti } 1998144742Sharti break; 1999144026Sharti 2000144742Sharti default: 2001144742Sharti break; 2002144742Sharti } 2003144742Sharti /* 2004144742Sharti * Copy in the previous character (there may be none if this 2005144742Sharti * was the first character) and save this one in 2006144742Sharti * lastc. 2007144742Sharti */ 2008144742Sharti if (lastc != '\0') 2009144026Sharti Buf_AddByte(buf, (Byte)lastc); 2010144742Sharti lastc = c; 2011144742Sharti } 2012144026Sharti line_read: 2013144742Sharti CURFILE->lineno++; 2014144026Sharti 2015144742Sharti if (lastc != '\0') { 2016144742Sharti Buf_AddByte(buf, (Byte)lastc); 2017144742Sharti } 2018144742Sharti Buf_AddByte(buf, (Byte)'\0'); 2019144742Sharti line = Buf_Peel(buf); 20201590Srgrimes 2021144742Sharti /* 2022144742Sharti * Strip trailing blanks and tabs from the line. 2023144742Sharti * Do not strip a blank or tab that is preceded by 2024144742Sharti * a '\' 2025144742Sharti */ 2026144742Sharti ep = line; 2027144742Sharti while (*ep) 2028144742Sharti ++ep; 2029144742Sharti while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2030144742Sharti if (ep > line + 1 && ep[-2] == '\\') 2031144742Sharti break; 2032144742Sharti --ep; 2033144742Sharti } 2034144742Sharti *ep = 0; 2035144742Sharti 2036144742Sharti if (line[0] == '\0') { 2037144742Sharti /* empty line - just ignore */ 2038144742Sharti free(line); 2039144742Sharti goto again; 2040144742Sharti } 2041144742Sharti 2042144742Sharti return (line); 20431590Srgrimes} 20441590Srgrimes 20451590Srgrimes/*- 20461590Srgrimes *----------------------------------------------------------------------- 20471590Srgrimes * ParseFinishLine -- 20481590Srgrimes * Handle the end of a dependency group. 20491590Srgrimes * 20501590Srgrimes * Results: 20511590Srgrimes * Nothing. 20521590Srgrimes * 20531590Srgrimes * Side Effects: 20541590Srgrimes * inLine set FALSE. 'targets' list destroyed. 20551590Srgrimes * 20561590Srgrimes *----------------------------------------------------------------------- 20571590Srgrimes */ 20581590Srgrimesstatic void 2059104696SjmallettParseFinishLine(void) 20601590Srgrimes{ 2061143372Sharti const LstNode *ln; 2062138232Sharti 2063143372Sharti if (inLine) { 2064143372Sharti LST_FOREACH(ln, &targets) { 2065143372Sharti if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) 2066143372Sharti Suff_EndTransform(Lst_Datum(ln)); 2067143372Sharti } 2068143372Sharti Lst_Destroy(&targets, ParseHasCommands); 2069143372Sharti inLine = FALSE; 2070143372Sharti } 20711590Srgrimes} 20721590Srgrimes 2073144894Sharti/** 2074167330Sfjoe * xparse_include 2075144894Sharti * Parse an .include directive and push the file onto the input stack. 2076144894Sharti * The input is the line minus the .include. A file spec is a string 2077144894Sharti * enclosed in <> or "". The former is looked for only in sysIncPath. 2078144894Sharti * The latter in . and the directories specified by -I command line 2079144894Sharti * options 2080144894Sharti */ 2081144894Shartistatic void 2082150595Sphkxparse_include(char *file, int sinclude) 2083144894Sharti{ 2084144894Sharti char *fullname; /* full pathname of file */ 2085144894Sharti char endc; /* the character which ends the file spec */ 2086144894Sharti char *cp; /* current position in file spec */ 2087144894Sharti Boolean isSystem; /* TRUE if makefile is a system makefile */ 2088144894Sharti char *prefEnd, *Fname; 2089144894Sharti char *newName; 20908874Srgrimes 2091144894Sharti /* 2092144894Sharti * Skip to delimiter character so we know where to look 2093144894Sharti */ 2094144894Sharti while (*file == ' ' || *file == '\t') { 2095144894Sharti file++; 2096144894Sharti } 2097144894Sharti 2098144894Sharti if (*file != '"' && *file != '<') { 2099144894Sharti Parse_Error(PARSE_FATAL, 2100144894Sharti ".include filename must be delimited by '\"' or '<'"); 2101144894Sharti return; 2102144894Sharti } 2103144894Sharti 2104144894Sharti /* 2105144894Sharti * Set the search path on which to find the include file based on the 2106144894Sharti * characters which bracket its name. Angle-brackets imply it's 2107144894Sharti * a system Makefile while double-quotes imply it's a user makefile 2108144894Sharti */ 2109144894Sharti if (*file == '<') { 2110144894Sharti isSystem = TRUE; 2111144894Sharti endc = '>'; 2112144894Sharti } else { 2113144894Sharti isSystem = FALSE; 2114144894Sharti endc = '"'; 2115144894Sharti } 2116144894Sharti 2117144894Sharti /* 2118144894Sharti * Skip to matching delimiter 2119144894Sharti */ 2120144894Sharti for (cp = ++file; *cp != endc; cp++) { 2121144894Sharti if (*cp == '\0') { 2122144894Sharti Parse_Error(PARSE_FATAL, 2123144894Sharti "Unclosed .include filename. '%c' expected", endc); 2124144894Sharti return; 2125144894Sharti } 2126144894Sharti } 2127144894Sharti *cp = '\0'; 2128144894Sharti 2129144894Sharti /* 2130144894Sharti * Substitute for any variables in the file name before trying to 2131144894Sharti * find the thing. 2132144894Sharti */ 2133146027Sharti file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 2134144894Sharti 2135144894Sharti /* 2136144894Sharti * Now we know the file's name and its search path, we attempt to 2137144894Sharti * find the durn thing. A return of NULL indicates the file don't 2138144894Sharti * exist. 2139144894Sharti */ 2140144894Sharti if (!isSystem) { 2141144894Sharti /* 2142144894Sharti * Include files contained in double-quotes are first searched 2143144894Sharti * for relative to the including file's location. We don't want 2144144894Sharti * to cd there, of course, so we just tack on the old file's 2145151419Sru * leading path components and call Path_FindFile to see if 2146144894Sharti * we can locate the beast. 2147144894Sharti */ 2148144894Sharti 2149144894Sharti /* Make a temporary copy of this, to be safe. */ 2150144894Sharti Fname = estrdup(CURFILE->fname); 2151144894Sharti 2152144894Sharti prefEnd = strrchr(Fname, '/'); 2153144894Sharti if (prefEnd != NULL) { 2154144894Sharti *prefEnd = '\0'; 2155144894Sharti if (file[0] == '/') 2156144894Sharti newName = estrdup(file); 2157144894Sharti else 2158144894Sharti newName = str_concat(Fname, file, STR_ADDSLASH); 2159144894Sharti fullname = Path_FindFile(newName, &parseIncPath); 2160144894Sharti if (fullname == NULL) { 2161144894Sharti fullname = Path_FindFile(newName, 2162144894Sharti &dirSearchPath); 2163144894Sharti } 2164144894Sharti free(newName); 2165144894Sharti *prefEnd = '/'; 2166144894Sharti } else { 2167144894Sharti fullname = NULL; 2168144894Sharti } 2169144894Sharti free(Fname); 2170151419Sru if (fullname == NULL) { 2171151419Sru /* 2172151419Sru * Makefile wasn't found in same directory as included 2173151419Sru * makefile. Search for it first on the -I search path, 2174151419Sru * then on the .PATH search path, if not found in a -I 2175151419Sru * directory. 2176151419Sru * XXX: Suffix specific? 2177151419Sru */ 2178151419Sru fullname = Path_FindFile(file, &parseIncPath); 2179151419Sru if (fullname == NULL) { 2180151419Sru fullname = Path_FindFile(file, &dirSearchPath); 2181151419Sru } 2182151419Sru } 2183144894Sharti } else { 2184144894Sharti fullname = NULL; 2185144894Sharti } 2186144894Sharti 2187144894Sharti if (fullname == NULL) { 2188144894Sharti /* 2189151419Sru * System makefile or still haven't found the makefile. 2190151419Sru * Look for it on the system path. 2191144894Sharti */ 2192144894Sharti fullname = Path_FindFile(file, &sysIncPath); 2193144894Sharti } 2194144894Sharti 2195144894Sharti if (fullname == NULL) { 2196144894Sharti *cp = endc; 2197150595Sphk if (!sinclude) 2198150595Sphk Parse_Error(PARSE_FATAL, "Could not find %s", file); 2199167330Sfjoe else 2200167330Sfjoe Main_AddSourceMakefile(file); 2201144894Sharti free(file); 2202144894Sharti return; 2203144894Sharti } 2204167330Sfjoe Main_AddSourceMakefile(fullname); 2205144894Sharti free(file); 2206144894Sharti 2207144894Sharti /* 2208144894Sharti * We set up the name of the file to be the absolute 2209144894Sharti * name of the include file so error messages refer to the right 2210144894Sharti * place. 2211144894Sharti */ 2212144894Sharti ParsePushInput(fullname, NULL, NULL, 0); 2213160574Sobrien DEBUGF(DIR, (".include %s\n", fullname)); 2214144894Sharti} 2215144894Sharti 2216150595Sphkstatic void 2217150595Sphkparse_include(char *file, int code __unused, int lineno __unused) 2218150595Sphk{ 2219150595Sphk xparse_include(file, 0); 2220150595Sphk} 2221150595Sphk 2222150595Sphkstatic void 2223150595Sphkparse_sinclude(char *file, int code __unused, int lineno __unused) 2224150595Sphk{ 2225150595Sphk xparse_include(file, 1); 2226150595Sphk} 2227150595Sphk 2228144894Sharti/** 2229144894Sharti * parse_message 2230144894Sharti * Parse a .warning or .error directive 2231144894Sharti * 2232144894Sharti * The input is the line minus the ".error"/".warning". We substitute 2233144894Sharti * variables, print the message and exit(1) (for .error) or just print 2234144894Sharti * a warning if the directive is malformed. 2235144894Sharti */ 2236144894Shartistatic void 2237144894Shartiparse_message(char *line, int iserror, int lineno __unused) 2238144894Sharti{ 2239144894Sharti 2240144894Sharti if (!isspace((u_char)*line)) { 2241144894Sharti Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s", 2242144894Sharti iserror ? "error" : "warning", line); 2243144894Sharti return; 2244144894Sharti } 2245144894Sharti 2246144894Sharti while (isspace((u_char)*line)) 2247144894Sharti line++; 2248144894Sharti 2249168671Sru line = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); 2250144894Sharti Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); 2251144894Sharti free(line); 2252144894Sharti 2253144894Sharti if (iserror) { 2254144894Sharti /* Terminate immediately. */ 2255144894Sharti exit(1); 2256144894Sharti } 2257144894Sharti} 2258144894Sharti 2259144894Sharti/** 2260144894Sharti * parse_undef 2261144894Sharti * Parse an .undef directive. 2262144894Sharti */ 2263144894Shartistatic void 2264144894Shartiparse_undef(char *line, int code __unused, int lineno __unused) 2265144894Sharti{ 2266144894Sharti char *cp; 2267144894Sharti 2268144894Sharti while (isspace((u_char)*line)) 2269144894Sharti line++; 2270144894Sharti 2271144894Sharti for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) { 2272144894Sharti ; 2273144894Sharti } 2274144894Sharti *cp = '\0'; 2275144894Sharti 2276146027Sharti cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); 2277144894Sharti Var_Delete(cp, VAR_GLOBAL); 2278144894Sharti free(cp); 2279144894Sharti} 2280144894Sharti 2281144894Sharti/** 2282144894Sharti * parse_for 2283144894Sharti * Parse a .for directive. 2284144894Sharti */ 2285144894Shartistatic void 2286144894Shartiparse_for(char *line, int code __unused, int lineno) 2287144894Sharti{ 2288144894Sharti 2289144894Sharti if (!For_For(line)) { 2290144894Sharti /* syntax error */ 2291144894Sharti return; 2292144894Sharti } 2293144894Sharti line = NULL; 2294144894Sharti 2295144894Sharti /* 2296144894Sharti * Skip after the matching endfor. 2297144894Sharti */ 2298144894Sharti do { 2299144894Sharti free(line); 2300144894Sharti line = ParseSkipLine(0, 1); 2301144894Sharti if (line == NULL) { 2302144894Sharti Parse_Error(PARSE_FATAL, 2303144894Sharti "Unexpected end of file in for loop.\n"); 2304144894Sharti return; 2305144894Sharti } 2306144894Sharti } while (For_Eval(line)); 2307144894Sharti free(line); 2308144894Sharti 2309144894Sharti /* execute */ 2310144894Sharti For_Run(lineno); 2311144894Sharti} 2312144894Sharti 2313144894Sharti/** 2314144894Sharti * parse_endfor 2315144894Sharti * Parse endfor. This may only happen if there was no matching .for. 2316144894Sharti */ 2317144894Shartistatic void 2318144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused) 2319144894Sharti{ 2320144894Sharti 2321144894Sharti Parse_Error(PARSE_FATAL, "for-less endfor"); 2322144894Sharti} 2323144894Sharti 2324144894Sharti/** 2325144894Sharti * parse_directive 2326144894Sharti * Got a line starting with a '.'. Check if this is a directive 2327144894Sharti * and parse it. 2328144894Sharti * 2329144894Sharti * return: 2330144894Sharti * TRUE if line was a directive, FALSE otherwise. 2331144894Sharti */ 2332144894Shartistatic Boolean 2333144894Shartiparse_directive(char *line) 2334144894Sharti{ 2335144894Sharti char *start; 2336144894Sharti char *cp; 2337144894Sharti int dir; 2338144894Sharti 2339144894Sharti /* 2340144894Sharti * Get the keyword: 2341144894Sharti * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).* 2342144894Sharti * \1 is the keyword. 2343144894Sharti */ 2344144894Sharti for (start = line; isspace((u_char)*start); start++) { 2345144894Sharti ; 2346144894Sharti } 2347144894Sharti 2348144894Sharti if (!isalpha((u_char)*start)) { 2349144894Sharti return (FALSE); 2350144894Sharti } 2351144894Sharti 2352144894Sharti cp = start + 1; 2353144894Sharti while (isalnum((u_char)*cp) || *cp == '_') { 2354144894Sharti cp++; 2355144894Sharti } 2356144894Sharti 2357144894Sharti dir = directive_hash(start, cp - start); 2358144894Sharti if (dir < 0 || dir >= (int)NDIRECTS || 2359144894Sharti (size_t)(cp - start) != strlen(directives[dir].name) || 2360144894Sharti strncmp(start, directives[dir].name, cp - start) != 0) { 2361144894Sharti /* not actually matched */ 2362144894Sharti return (FALSE); 2363144894Sharti } 2364144894Sharti 2365144894Sharti if (!skipLine || directives[dir].skip_flag) 2366144894Sharti (*directives[dir].func)(cp, directives[dir].code, 2367144894Sharti CURFILE->lineno); 2368144894Sharti return (TRUE); 2369144894Sharti} 2370144894Sharti 23711590Srgrimes/*- 23721590Srgrimes *--------------------------------------------------------------------- 23731590Srgrimes * Parse_File -- 23741590Srgrimes * Parse a file into its component parts, incorporating it into the 23751590Srgrimes * current dependency graph. This is the main function and controls 23761590Srgrimes * almost every other function in this module 23771590Srgrimes * 23781590Srgrimes * Results: 23791590Srgrimes * None 23801590Srgrimes * 23811590Srgrimes * Side Effects: 23821590Srgrimes * Loads. Nodes are added to the list of all targets, nodes and links 23831590Srgrimes * are added to the dependency graph. etc. etc. etc. 23841590Srgrimes *--------------------------------------------------------------------- 23851590Srgrimes */ 23861590Srgrimesvoid 2387144341ShartiParse_File(const char *name, FILE *stream) 23881590Srgrimes{ 2389144026Sharti char *cp; /* pointer into the line */ 2390144026Sharti char *line; /* the line we're working on */ 23911590Srgrimes 2392144026Sharti inLine = FALSE; 2393144026Sharti fatals = 0; 23941590Srgrimes 2395144341Sharti ParsePushInput(estrdup(name), stream, NULL, 0); 2396131456Seik 2397144742Sharti while ((line = ParseReadLine()) != NULL) { 2398144894Sharti if (*line == '.' && parse_directive(line + 1)) { 2399144894Sharti /* directive consumed */ 2400144894Sharti goto nextLine; 2401144742Sharti } 2402144894Sharti if (skipLine || *line == '#') { 2403144894Sharti /* Skipping .if block or comment. */ 2404144742Sharti goto nextLine; 2405144742Sharti } 24068874Srgrimes 2407144742Sharti if (*line == '\t') { 2408144742Sharti /* 2409144742Sharti * If a line starts with a tab, it can only 2410144742Sharti * hope to be a creation command. 2411144742Sharti */ 2412144742Sharti for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 2413144742Sharti continue; 2414144742Sharti } 2415144742Sharti if (*cp) { 2416144742Sharti if (inLine) { 2417144742Sharti LstNode *ln; 2418144742Sharti GNode *gn; 2419143684Sharti 2420144742Sharti /* 2421144742Sharti * So long as it's not a blank 2422144742Sharti * line and we're actually in a 2423144742Sharti * dependency spec, add the 2424144742Sharti * command to the list of 2425144742Sharti * commands of all targets in 2426144742Sharti * the dependency spec. 2427144742Sharti */ 2428144742Sharti LST_FOREACH(ln, &targets) { 2429144742Sharti gn = Lst_Datum(ln); 2430144742Sharti 2431144026Sharti /* 2432144742Sharti * if target already 2433144742Sharti * supplied, ignore 2434144742Sharti * commands 2435144026Sharti */ 2436144742Sharti if (!(gn->type & OP_HAS_COMMANDS)) 2437144742Sharti Lst_AtEnd(&gn->commands, cp); 2438144742Sharti else 2439144742Sharti Parse_Error(PARSE_WARNING, "duplicate script " 2440144742Sharti "for target \"%s\" ignored", gn->name); 2441144026Sharti } 2442144742Sharti continue; 2443144742Sharti } else { 2444144742Sharti Parse_Error(PARSE_FATAL, 2445144742Sharti "Unassociated shell command \"%s\"", 2446144742Sharti cp); 2447144026Sharti } 2448144742Sharti } 24491590Srgrimes#ifdef SYSVINCLUDE 2450144742Sharti } else if (strncmp(line, "include", 7) == 0 && 2451144742Sharti isspace((unsigned char)line[7]) && 2452144742Sharti strchr(line, ':') == NULL) { 2453144742Sharti /* 2454144742Sharti * It's an S3/S5-style "include". 2455144742Sharti */ 2456144742Sharti ParseTraditionalInclude(line + 7); 2457144742Sharti goto nextLine; 24581590Srgrimes#endif 2459144742Sharti } else if (Parse_IsVar(line)) { 2460144742Sharti ParseFinishLine(); 2461144742Sharti Parse_DoVar(line, VAR_GLOBAL); 24628874Srgrimes 2463144742Sharti } else { 2464144742Sharti /* 2465144742Sharti * We now know it's a dependency line so it 2466144742Sharti * needs to have all variables expanded before 2467144742Sharti * being parsed. Tell the variable module to 2468144742Sharti * complain if some variable is undefined... 2469144742Sharti * To make life easier on novices, if the line 2470144742Sharti * is indented we first make sure the line has 2471144742Sharti * a dependency operator in it. If it doesn't 2472144742Sharti * have an operator and we're in a dependency 2473144742Sharti * line's script, we assume it's actually a 2474144742Sharti * shell command and add it to the current 2475144894Sharti * list of targets. XXX this comment seems wrong. 2476144742Sharti */ 2477144742Sharti cp = line; 2478144742Sharti if (isspace((unsigned char)line[0])) { 2479144742Sharti while (*cp != '\0' && 2480144742Sharti isspace((unsigned char)*cp)) { 2481144742Sharti cp++; 2482144026Sharti } 2483144742Sharti if (*cp == '\0') { 2484144742Sharti goto nextLine; 2485144742Sharti } 2486144742Sharti } 24871590Srgrimes 2488144742Sharti ParseFinishLine(); 2489142457Sharti 2490146027Sharti cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE)); 24918874Srgrimes 2492144742Sharti free(line); 2493144742Sharti line = cp; 2494144026Sharti 2495144742Sharti /* 2496144742Sharti * Need a non-circular list for the target nodes 2497144742Sharti */ 2498144742Sharti Lst_Destroy(&targets, NOFREE); 2499144742Sharti inLine = TRUE; 2500144026Sharti 2501144742Sharti ParseDoDependency(line); 2502144026Sharti } 2503144026Sharti 2504144742Sharti nextLine: 2505144742Sharti free(line); 2506144742Sharti } 25078874Srgrimes 2508144026Sharti ParseFinishLine(); 25091590Srgrimes 25101590Srgrimes /* 2511144026Sharti * Make sure conditionals are clean 25121590Srgrimes */ 2513144026Sharti Cond_End(); 25141590Srgrimes 2515144026Sharti if (fatals) 2516144026Sharti errx(1, "fatal errors encountered -- cannot continue"); 25171590Srgrimes} 25181590Srgrimes 25191590Srgrimes/*- 25201590Srgrimes *----------------------------------------------------------------------- 25211590Srgrimes * Parse_MainName -- 25221590Srgrimes * Return a Lst of the main target to create for main()'s sake. If 25231590Srgrimes * no such target exists, we Punt with an obnoxious error message. 25241590Srgrimes * 25251590Srgrimes * Results: 25261590Srgrimes * A Lst of the single node to create. 25271590Srgrimes * 25281590Srgrimes * Side Effects: 25291590Srgrimes * None. 25301590Srgrimes * 25311590Srgrimes *----------------------------------------------------------------------- 25321590Srgrimes */ 2533138916Shartivoid 2534138916ShartiParse_MainName(Lst *listmain) 25351590Srgrimes{ 25361590Srgrimes 2537144026Sharti if (mainNode == NULL) { 2538144026Sharti Punt("no target to make."); 2539144026Sharti /*NOTREACHED*/ 2540144026Sharti } else if (mainNode->type & OP_DOUBLEDEP) { 2541144026Sharti Lst_AtEnd(listmain, mainNode); 2542144026Sharti Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 2543144026Sharti } else 2544144026Sharti Lst_AtEnd(listmain, mainNode); 25451590Srgrimes} 2546