1/*- 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1989 by Berkeley Softworks 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)parse.c 8.3 (Berkeley) 3/19/94 39 */ 40 41#include <sys/cdefs.h> 42__FBSDID("$FreeBSD$"); 43 44/*- 45 * parse.c -- 46 * Functions to parse a makefile. 47 * 48 * Most important structures are kept in Lsts. Directories for 49 * the #include "..." function are kept in the 'parseIncPath' Lst, while 50 * those for the #include <...> are kept in the 'sysIncPath' Lst. The 51 * targets currently being defined are kept in the 'targets' Lst. 52 * 53 * Interface: 54 * 55 * Parse_File Function used to parse a makefile. It must 56 * be given the name of the file, which should 57 * already have been opened, and a function 58 * to call to read a character from the file. 59 * 60 * Parse_IsVar Returns TRUE if the given line is a 61 * variable assignment. Used by MainParseArgs 62 * to determine if an argument is a target 63 * or a variable assignment. Used internally 64 * for pretty much the same thing... 65 * 66 * Parse_Error Function called when an error occurs in 67 * parsing. Used by the variable and 68 * conditional modules. 69 * 70 * Parse_MainName Returns a Lst of the main target to create. 71 */ 72 73#include <assert.h> 74#include <ctype.h> 75#include <stdarg.h> 76#include <string.h> 77#include <stdlib.h> 78#include <err.h> 79 80#include "arch.h" 81#include "buf.h" 82#include "cond.h" 83#include "config.h" 84#include "dir.h" 85#include "for.h" 86#include "globals.h" 87#include "GNode.h" 88#include "hash_tables.h" 89#include "job.h" 90#include "make.h" 91#include "parse.h" 92#include "pathnames.h" 93#include "shell.h" 94#include "str.h" 95#include "suff.h" 96#include "targ.h" 97#include "util.h" 98#include "var.h" 99 100/* 101 * These values are returned by ParsePopInput to tell Parse_File whether to 102 * CONTINUE parsing, i.e. it had only reached the end of an include file, 103 * or if it's DONE. 104 */ 105#define CONTINUE 1 106#define DONE 0 107 108/* targets we're working on */ 109static Lst targets = Lst_Initializer(targets); 110 111/* true if currently in a dependency line or its commands */ 112static Boolean inLine; 113 114static int fatals = 0; 115 116/* 117 * The main target to create. This is the first target on the 118 * first dependency line in the first makefile. 119 */ 120static GNode *mainNode; 121 122/* 123 * Definitions for handling #include specifications 124 */ 125struct IFile { 126 char *fname; /* name of previous file */ 127 int lineno; /* saved line number */ 128 FILE *F; /* the open stream */ 129 char *str; /* the string when parsing a string */ 130 char *ptr; /* the current pointer when parsing a string */ 131 TAILQ_ENTRY(IFile) link;/* stack the files */ 132}; 133 134/* stack of IFiles generated by * #includes */ 135static TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); 136 137/* access current file */ 138#define CURFILE (TAILQ_FIRST(&includes)) 139 140/* list of directories for "..." includes */ 141struct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); 142 143/* list of directories for <...> includes */ 144struct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); 145 146/* 147 * specType contains the SPECial TYPE of the current target. It is 148 * Not if the target is unspecial. If it *is* special, however, the children 149 * are linked as children of the parent but not vice versa. This variable is 150 * set in ParseDoDependency 151 */ 152typedef enum { 153 Begin, /* .BEGIN */ 154 Default, /* .DEFAULT */ 155 End, /* .END */ 156 ExportVar, /* .EXPORTVAR */ 157 Ignore, /* .IGNORE */ 158 Includes, /* .INCLUDES */ 159 Interrupt, /* .INTERRUPT */ 160 Libs, /* .LIBS */ 161 MFlags, /* .MFLAGS or .MAKEFLAGS */ 162 Main, /* .MAIN and we don't have anyth. user-spec. to make */ 163 Not, /* Not special */ 164 NotParallel, /* .NOTPARALELL */ 165 Null, /* .NULL */ 166 Order, /* .ORDER */ 167 Parallel, /* .PARALLEL */ 168 ExPath, /* .PATH */ 169 Phony, /* .PHONY */ 170 Posix, /* .POSIX */ 171 MakefileDeps, /* .MAKEFILEDEPS */ 172 Precious, /* .PRECIOUS */ 173 ExShell, /* .SHELL */ 174 Silent, /* .SILENT */ 175 SingleShell, /* .SINGLESHELL */ 176 Suffixes, /* .SUFFIXES */ 177 Wait, /* .WAIT */ 178 Warn, /* .WARN */ 179 Attribute /* Generic attribute */ 180} ParseSpecial; 181 182static ParseSpecial specType; 183static int waiting; 184 185/* 186 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 187 * seen, then set to each successive source on the line. 188 */ 189static GNode *predecessor; 190 191/* 192 * The parseKeywords table is searched using binary search when deciding 193 * if a target or source is special. The 'spec' field is the ParseSpecial 194 * type of the keyword ("Not" if the keyword isn't special as a target) while 195 * the 'op' field is the operator to apply to the list of targets if the 196 * keyword is used as a source ("0" if the keyword isn't special as a source) 197 */ 198static const struct keyword { 199 const char *name; /* Name of keyword */ 200 ParseSpecial spec; /* Type when used as a target */ 201 int op; /* Operator when used as a source */ 202} parseKeywords[] = { 203 /* KEYWORD-START-TAG */ 204 { ".BEGIN", Begin, 0 }, 205 { ".DEFAULT", Default, 0 }, 206 { ".END", End, 0 }, 207 { ".EXEC", Attribute, OP_EXEC }, 208 { ".EXPORTVAR", ExportVar, 0 }, 209 { ".IGNORE", Ignore, OP_IGNORE }, 210 { ".INCLUDES", Includes, 0 }, 211 { ".INTERRUPT", Interrupt, 0 }, 212 { ".INVISIBLE", Attribute, OP_INVISIBLE }, 213 { ".JOIN", Attribute, OP_JOIN }, 214 { ".LIBS", Libs, 0 }, 215 { ".MAIN", Main, 0 }, 216 { ".MAKE", Attribute, OP_MAKE }, 217 { ".MAKEFILEDEPS", MakefileDeps, 0 }, 218 { ".MAKEFLAGS", MFlags, 0 }, 219 { ".MFLAGS", MFlags, 0 }, 220 { ".NOTMAIN", Attribute, OP_NOTMAIN }, 221 { ".NOTPARALLEL", NotParallel, 0 }, 222 { ".NO_PARALLEL", NotParallel, 0 }, 223 { ".NULL", Null, 0 }, 224 { ".OPTIONAL", Attribute, OP_OPTIONAL }, 225 { ".ORDER", Order, 0 }, 226 { ".PARALLEL", Parallel, 0 }, 227 { ".PATH", ExPath, 0 }, 228 { ".PHONY", Phony, OP_PHONY }, 229 { ".POSIX", Posix, 0 }, 230 { ".PRECIOUS", Precious, OP_PRECIOUS }, 231 { ".RECURSIVE", Attribute, OP_MAKE }, 232 { ".SHELL", ExShell, 0 }, 233 { ".SILENT", Silent, OP_SILENT }, 234 { ".SINGLESHELL", SingleShell, 0 }, 235 { ".SUFFIXES", Suffixes, 0 }, 236 { ".USE", Attribute, OP_USE }, 237 { ".WAIT", Wait, 0 }, 238 { ".WARN", Warn, 0 }, 239 /* KEYWORD-END-TAG */ 240}; 241#define NKEYWORDS (sizeof(parseKeywords) / sizeof(parseKeywords[0])) 242 243static void parse_include(char *, int, int); 244static void parse_sinclude(char *, int, int); 245static void parse_message(char *, int, int); 246static void parse_undef(char *, int, int); 247static void parse_for(char *, int, int); 248static void parse_endfor(char *, int, int); 249 250static const struct directive { 251 const char *name; 252 int code; 253 Boolean skip_flag; /* execute even when skipped */ 254 void (*func)(char *, int, int); 255} directives[] = { 256 /* DIRECTIVES-START-TAG */ 257 { "elif", COND_ELIF, TRUE, Cond_If }, 258 { "elifdef", COND_ELIFDEF, TRUE, Cond_If }, 259 { "elifmake", COND_ELIFMAKE, TRUE, Cond_If }, 260 { "elifndef", COND_ELIFNDEF, TRUE, Cond_If }, 261 { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If }, 262 { "else", COND_ELSE, TRUE, Cond_Else }, 263 { "endfor", 0, FALSE, parse_endfor }, 264 { "endif", COND_ENDIF, TRUE, Cond_Endif }, 265 { "error", 1, FALSE, parse_message }, 266 { "for", 0, FALSE, parse_for }, 267 { "if", COND_IF, TRUE, Cond_If }, 268 { "ifdef", COND_IFDEF, TRUE, Cond_If }, 269 { "ifmake", COND_IFMAKE, TRUE, Cond_If }, 270 { "ifndef", COND_IFNDEF, TRUE, Cond_If }, 271 { "ifnmake", COND_IFNMAKE, TRUE, Cond_If }, 272 { "include", 0, FALSE, parse_include }, 273 { "sinclude", 0, FALSE, parse_sinclude }, 274 { "undef", 0, FALSE, parse_undef }, 275 { "warning", 0, FALSE, parse_message }, 276 /* DIRECTIVES-END-TAG */ 277}; 278#define NDIRECTS (sizeof(directives) / sizeof(directives[0])) 279 280/*- 281 * ParseFindKeyword 282 * Look in the table of keywords for one matching the given string. 283 * 284 * Results: 285 * The pointer to keyword table entry or NULL. 286 */ 287static const struct keyword * 288ParseFindKeyword(const char *str) 289{ 290 int kw; 291 292 kw = keyword_hash(str, strlen(str)); 293 if (kw < 0 || kw >= (int)NKEYWORDS || 294 strcmp(str, parseKeywords[kw].name) != 0) 295 return (NULL); 296 return (&parseKeywords[kw]); 297} 298 299/*- 300 * Parse_Error -- 301 * Error message abort function for parsing. Prints out the context 302 * of the error (line number and file) as well as the message with 303 * two optional arguments. 304 * 305 * Results: 306 * None 307 * 308 * Side Effects: 309 * "fatals" is incremented if the level is PARSE_FATAL. 310 */ 311/* VARARGS */ 312void 313Parse_Error(int type, const char *fmt, ...) 314{ 315 va_list ap; 316 317 va_start(ap, fmt); 318 if (CURFILE != NULL) 319 fprintf(stderr, "\"%s\", line %d: ", 320 CURFILE->fname, CURFILE->lineno); 321 if (type == PARSE_WARNING) 322 fprintf(stderr, "warning: "); 323 vfprintf(stderr, fmt, ap); 324 va_end(ap); 325 fprintf(stderr, "\n"); 326 fflush(stderr); 327 if (type == PARSE_FATAL) 328 fatals += 1; 329} 330 331/** 332 * ParsePushInput 333 * 334 * Push a new input source onto the input stack. If ptr is NULL 335 * the fullname is used to fopen the file. If it is not NULL, 336 * ptr is assumed to point to the string to be parsed. If opening the 337 * file fails, the fullname is freed. 338 */ 339static void 340ParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) 341{ 342 struct IFile *nf; 343 344 nf = emalloc(sizeof(*nf)); 345 nf->fname = fullname; 346 nf->lineno = lineno; 347 348 if (ptr == NULL) { 349 /* the input source is a file */ 350 if ((nf->F = fp) == NULL) { 351 nf->F = fopen(fullname, "r"); 352 if (nf->F == NULL) { 353 Parse_Error(PARSE_FATAL, "Cannot open %s", 354 fullname); 355 free(fullname); 356 free(nf); 357 return; 358 } 359 } 360 nf->str = nf->ptr = NULL; 361 Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 362 } else { 363 nf->str = nf->ptr = ptr; 364 nf->F = NULL; 365 } 366 TAILQ_INSERT_HEAD(&includes, nf, link); 367} 368 369/** 370 * ParsePopInput 371 * Called when EOF is reached in the current file. If we were reading 372 * an include file, the includes stack is popped and things set up 373 * to go back to reading the previous file at the previous location. 374 * 375 * Results: 376 * CONTINUE if there's more to do. DONE if not. 377 * 378 * Side Effects: 379 * The old curFile.F is closed. The includes list is shortened. 380 * curFile.lineno, curFile.F, and curFile.fname are changed if 381 * CONTINUE is returned. 382 */ 383static int 384ParsePopInput(void) 385{ 386 struct IFile *ifile; /* the state on the top of the includes stack */ 387 388 assert(!TAILQ_EMPTY(&includes)); 389 390 ifile = TAILQ_FIRST(&includes); 391 TAILQ_REMOVE(&includes, ifile, link); 392 393 free(ifile->fname); 394 if (ifile->F != NULL) { 395 fclose(ifile->F); 396 Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 397 } 398 if (ifile->str != NULL) { 399 free(ifile->str); 400 } 401 free(ifile); 402 403 return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); 404} 405 406/** 407 * parse_warn 408 * Parse the .WARN pseudo-target. 409 */ 410static void 411parse_warn(char *line) 412{ 413 ArgArray aa; 414 int i; 415 416 brk_string(&aa, line, TRUE); 417 418 for (i = 1; i < aa.argc; i++) 419 Main_ParseWarn(aa.argv[i], 0); 420} 421 422/*- 423 *--------------------------------------------------------------------- 424 * ParseLinkSrc -- 425 * Link the parent nodes to their new child. Used by 426 * ParseDoDependency. If the specType isn't 'Not', the parent 427 * isn't linked as a parent of the child. 428 * 429 * Side Effects: 430 * New elements are added to the parents lists of cgn and the 431 * children list of cgn. the unmade field of pgn is updated 432 * to reflect the additional child. 433 *--------------------------------------------------------------------- 434 */ 435static void 436ParseLinkSrc(Lst *parents, GNode *cgn) 437{ 438 LstNode *ln; 439 GNode *pgn; 440 441 LST_FOREACH(ln, parents) { 442 pgn = Lst_Datum(ln); 443 if (Lst_Member(&pgn->children, cgn) == NULL) { 444 Lst_AtEnd(&pgn->children, cgn); 445 if (specType == Not) { 446 Lst_AtEnd(&cgn->parents, pgn); 447 } 448 pgn->unmade += 1; 449 } 450 } 451} 452 453/*- 454 *--------------------------------------------------------------------- 455 * ParseDoOp -- 456 * Apply the parsed operator to all target nodes. Used in 457 * ParseDoDependency once all targets have been found and their 458 * operator parsed. If the previous and new operators are incompatible, 459 * a major error is taken. 460 * 461 * Side Effects: 462 * The type field of the node is altered to reflect any new bits in 463 * the op. 464 *--------------------------------------------------------------------- 465 */ 466static void 467ParseDoOp(int op) 468{ 469 GNode *cohort; 470 LstNode *ln; 471 GNode *gn; 472 473 LST_FOREACH(ln, &targets) { 474 gn = Lst_Datum(ln); 475 476 /* 477 * If the dependency mask of the operator and the node don't 478 * match and the node has actually had an operator applied to 479 * it before, and the operator actually has some dependency 480 * information in it, complain. 481 */ 482 if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && 483 !OP_NOP(gn->type) && !OP_NOP(op)) { 484 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 485 gn->name); 486 return; 487 } 488 489 if (op == OP_DOUBLEDEP && 490 (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 491 /* 492 * If the node was the object of a :: operator, we need 493 * to create a new instance of it for the children and 494 * commands on this dependency line. The new instance 495 * is placed on the 'cohorts' list of the initial one 496 * (note the initial one is not on its own cohorts list) 497 * and the new instance is linked to all parents of the 498 * initial instance. 499 */ 500 cohort = Targ_NewGN(gn->name); 501 502 /* 503 * Duplicate links to parents so graph traversal is 504 * simple. Perhaps some type bits should be duplicated? 505 * 506 * Make the cohort invisible as well to avoid 507 * duplicating it into other variables. True, parents 508 * of this target won't tend to do anything with their 509 * local variables, but better safe than sorry. 510 */ 511 ParseLinkSrc(&gn->parents, cohort); 512 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 513 Lst_AtEnd(&gn->cohorts, cohort); 514 515 /* 516 * Replace the node in the targets list with the 517 * new copy 518 */ 519 Lst_Replace(ln, cohort); 520 gn = cohort; 521 } 522 /* 523 * We don't want to nuke any previous flags (whatever they were) 524 * so we just OR the new operator into the old 525 */ 526 gn->type |= op; 527 } 528} 529 530/*- 531 *--------------------------------------------------------------------- 532 * ParseDoSrc -- 533 * Given the name of a source, figure out if it is an attribute 534 * and apply it to the targets if it is. Else decide if there is 535 * some attribute which should be applied *to* the source because 536 * of some special target and apply it if so. Otherwise, make the 537 * source be a child of the targets in the list 'targets' 538 * 539 * Results: 540 * None 541 * 542 * Side Effects: 543 * Operator bits may be added to the list of targets or to the source. 544 * The targets may have a new source added to their lists of children. 545 *--------------------------------------------------------------------- 546 */ 547static void 548ParseDoSrc(int tOp, char *src, Lst *allsrc) 549{ 550 GNode *gn = NULL; 551 const struct keyword *kw; 552 553 if (src[0] == '.' && isupper ((unsigned char)src[1])) { 554 if ((kw = ParseFindKeyword(src)) != NULL) { 555 if (kw->op != 0) { 556 ParseDoOp(kw->op); 557 return; 558 } 559 if (kw->spec == Wait) { 560 waiting++; 561 return; 562 } 563 } 564 } 565 566 switch (specType) { 567 case Main: 568 /* 569 * If we have noted the existence of a .MAIN, it means we need 570 * to add the sources of said target to the list of things 571 * to create. The string 'src' is likely to be free, so we 572 * must make a new copy of it. Note that this will only be 573 * invoked if the user didn't specify a target on the command 574 * line. This is to allow #ifmake's to succeed, or something... 575 */ 576 Lst_AtEnd(&create, estrdup(src)); 577 /* 578 * Add the name to the .TARGETS variable as well, so the user 579 * can employ that, if desired. 580 */ 581 Var_Append(".TARGETS", src, VAR_GLOBAL); 582 return; 583 584 case Order: 585 /* 586 * Create proper predecessor/successor links between the 587 * previous source and the current one. 588 */ 589 gn = Targ_FindNode(src, TARG_CREATE); 590 if (predecessor != NULL) { 591 Lst_AtEnd(&predecessor->successors, gn); 592 Lst_AtEnd(&gn->preds, predecessor); 593 } 594 /* 595 * The current source now becomes the predecessor for the next 596 * one. 597 */ 598 predecessor = gn; 599 break; 600 601 default: 602 /* 603 * If the source is not an attribute, we need to find/create 604 * a node for it. After that we can apply any operator to it 605 * from a special target or link it to its parents, as 606 * appropriate. 607 * 608 * In the case of a source that was the object of a :: operator, 609 * the attribute is applied to all of its instances (as kept in 610 * the 'cohorts' list of the node) or all the cohorts are linked 611 * to all the targets. 612 */ 613 gn = Targ_FindNode(src, TARG_CREATE); 614 if (tOp) { 615 gn->type |= tOp; 616 } else { 617 ParseLinkSrc(&targets, gn); 618 } 619 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 620 GNode *cohort; 621 LstNode *ln; 622 623 for (ln = Lst_First(&gn->cohorts); ln != NULL; 624 ln = Lst_Succ(ln)) { 625 cohort = Lst_Datum(ln); 626 if (tOp) { 627 cohort->type |= tOp; 628 } else { 629 ParseLinkSrc(&targets, cohort); 630 } 631 } 632 } 633 break; 634 } 635 636 gn->order = waiting; 637 Lst_AtEnd(allsrc, gn); 638 if (waiting) { 639 LstNode *ln; 640 GNode *p; 641 642 /* 643 * Check if GNodes needs to be synchronized. 644 * This has to be when two nodes are on different sides of a 645 * .WAIT directive. 646 */ 647 LST_FOREACH(ln, allsrc) { 648 p = Lst_Datum(ln); 649 650 if (p->order >= gn->order) 651 break; 652 /* 653 * XXX: This can cause loops, and loops can cause 654 * unmade targets, but checking is tedious, and the 655 * debugging output can show the problem 656 */ 657 Lst_AtEnd(&p->successors, gn); 658 Lst_AtEnd(&gn->preds, p); 659 } 660 } 661} 662 663 664/*- 665 *--------------------------------------------------------------------- 666 * ParseDoDependency -- 667 * Parse the dependency line in line. 668 * 669 * Results: 670 * None 671 * 672 * Side Effects: 673 * The nodes of the sources are linked as children to the nodes of the 674 * targets. Some nodes may be created. 675 * 676 * We parse a dependency line by first extracting words from the line and 677 * finding nodes in the list of all targets with that name. This is done 678 * until a character is encountered which is an operator character. Currently 679 * these are only ! and :. At this point the operator is parsed and the 680 * pointer into the line advanced until the first source is encountered. 681 * The parsed operator is applied to each node in the 'targets' list, 682 * which is where the nodes found for the targets are kept, by means of 683 * the ParseDoOp function. 684 * The sources are read in much the same way as the targets were except 685 * that now they are expanded using the wildcarding scheme of the C-Shell 686 * and all instances of the resulting words in the list of all targets 687 * are found. Each of the resulting nodes is then linked to each of the 688 * targets as one of its children. 689 * Certain targets are handled specially. These are the ones detailed 690 * by the specType variable. 691 * The storing of transformation rules is also taken care of here. 692 * A target is recognized as a transformation rule by calling 693 * Suff_IsTransform. If it is a transformation rule, its node is gotten 694 * from the suffix module via Suff_AddTransform rather than the standard 695 * Targ_FindNode in the target module. 696 *--------------------------------------------------------------------- 697 */ 698static void 699ParseDoDependency(char *line) 700{ 701 char *cp; /* our current position */ 702 char *lstart = line; /* original input line */ 703 GNode *gn; /* a general purpose temporary node */ 704 int op; /* the operator on the line */ 705 char savec; /* a place to save a character */ 706 Lst paths; /* Search paths to alter when parsing .PATH targets */ 707 int tOp; /* operator from special target */ 708 LstNode *ln; 709 const struct keyword *kw; 710 711 tOp = 0; 712 713 specType = Not; 714 waiting = 0; 715 Lst_Init(&paths); 716 717 do { 718 for (cp = line; 719 *cp && !isspace((unsigned char)*cp) && *cp != '('; 720 cp++) { 721 if (*cp == '$') { 722 /* 723 * Must be a dynamic source (would have been 724 * expanded otherwise), so call the Var module 725 * to parse the puppy so we can safely advance 726 * beyond it...There should be no errors in this 727 * as they would have been discovered in the 728 * initial Var_Subst and we wouldn't be here. 729 */ 730 size_t length = 0; 731 Boolean freeIt; 732 char *result; 733 734 result = Var_Parse(cp, VAR_CMD, TRUE, 735 &length, &freeIt); 736 737 if (freeIt) { 738 free(result); 739 } 740 cp += length - 1; 741 742 } else if (*cp == '!' || *cp == ':') { 743 /* 744 * We don't want to end a word on ':' or '!' if 745 * there is a better match later on in the 746 * string (greedy matching). 747 * This allows the user to have targets like: 748 * fie::fi:fo: fum 749 * foo::bar: 750 * where "fie::fi:fo" and "foo::bar" are the 751 * targets. In real life this is used for perl5 752 * library man pages where "::" separates an 753 * object from its class. Ie: 754 * "File::Spec::Unix". This behaviour is also 755 * consistent with other versions of make. 756 */ 757 char *p = cp + 1; 758 759 if (*cp == ':' && *p == ':') 760 p++; 761 762 /* Found the best match already. */ 763 if (*p == '\0' || isspace(*p)) 764 break; 765 766 p += strcspn(p, "!:"); 767 768 /* No better match later on... */ 769 if (*p == '\0') 770 break; 771 } 772 continue; 773 } 774 if (*cp == '(') { 775 /* 776 * Archives must be handled specially to make sure the 777 * OP_ARCHV flag is set in their 'type' field, for one 778 * thing, and because things like "archive(file1.o 779 * file2.o file3.o)" are permissible. Arch_ParseArchive 780 * will set 'line' to be the first non-blank after the 781 * archive-spec. It creates/finds nodes for the members 782 * and places them on the given list, returning TRUE 783 * if all went well and FALSE if there was an error in 784 * the specification. On error, line should remain 785 * untouched. 786 */ 787 if (!Arch_ParseArchive(&line, &targets, VAR_CMD)) { 788 Parse_Error(PARSE_FATAL, 789 "Error in archive specification: \"%s\"", 790 line); 791 return; 792 } else { 793 cp = line; 794 continue; 795 } 796 } 797 savec = *cp; 798 799 if (!*cp) { 800 /* 801 * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often 802 * triggered by undetected conflicts from cvs/rcs 803 * merges. 804 */ 805 if (strncmp(line, "<<<<<<", 6) == 0 || 806 strncmp(line, "||||||", 6) == 0 || 807 strncmp(line, "======", 6) == 0 || 808 strncmp(line, ">>>>>>", 6) == 0) { 809 Parse_Error(PARSE_FATAL, "Makefile appears to " 810 "contain unresolved cvs/rcs/??? merge " 811 "conflicts"); 812 } else 813 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? 814 "Unknown directive" : "Need an operator"); 815 return; 816 } 817 *cp = '\0'; 818 /* 819 * Have a word in line. See if it's a special target and set 820 * specType to match it. 821 */ 822 if (*line == '.' && isupper((unsigned char)line[1])) { 823 /* 824 * See if the target is a special target that must have 825 * it or its sources handled specially. 826 */ 827 if ((kw = ParseFindKeyword(line)) != NULL) { 828 if (specType == ExPath && kw->spec != ExPath) { 829 Parse_Error(PARSE_FATAL, 830 "Mismatched special targets"); 831 return; 832 } 833 834 specType = kw->spec; 835 tOp = kw->op; 836 837 /* 838 * Certain special targets have special 839 * semantics: 840 * .PATH Have to set the dirSearchPath 841 * variable too 842 * .MAIN Its sources are only used if 843 * nothing has been specified to 844 * create. 845 * .DEFAULT Need to create a node to hang 846 * commands on, but we don't want 847 * it in the graph, nor do we want 848 * it to be the Main Target, so we 849 * create it, set OP_NOTMAIN and 850 * add it to the list, setting 851 * DEFAULT to the new node for 852 * later use. We claim the node is 853 * A transformation rule to make 854 * life easier later, when we'll 855 * use Make_HandleUse to actually 856 * apply the .DEFAULT commands. 857 * .PHONY The list of targets 858 * .BEGIN 859 * .END 860 * .INTERRUPT Are not to be considered the 861 * main target. 862 * .NOTPARALLEL Make only one target at a time. 863 * .SINGLESHELL Create a shell for each 864 * command. 865 * .ORDER Must set initial predecessor 866 * to NULL 867 */ 868 switch (specType) { 869 case ExPath: 870 Lst_AtEnd(&paths, &dirSearchPath); 871 break; 872 case Main: 873 if (!Lst_IsEmpty(&create)) { 874 specType = Not; 875 } 876 break; 877 case Begin: 878 case End: 879 case Interrupt: 880 gn = Targ_FindNode(line, TARG_CREATE); 881 gn->type |= OP_NOTMAIN; 882 Lst_AtEnd(&targets, gn); 883 break; 884 case Default: 885 gn = Targ_NewGN(".DEFAULT"); 886 gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 887 Lst_AtEnd(&targets, gn); 888 DEFAULT = gn; 889 break; 890 case NotParallel: 891 jobLimit = 1; 892 break; 893 case SingleShell: 894 compatMake = 1; 895 break; 896 case Order: 897 predecessor = NULL; 898 break; 899 default: 900 break; 901 } 902 903 } else if (strncmp(line, ".PATH", 5) == 0) { 904 /* 905 * .PATH<suffix> has to be handled specially. 906 * Call on the suffix module to give us a path 907 * to modify. 908 */ 909 struct Path *path; 910 911 specType = ExPath; 912 path = Suff_GetPath(&line[5]); 913 if (path == NULL) { 914 Parse_Error(PARSE_FATAL, "Suffix '%s' " 915 "not defined (yet)", &line[5]); 916 return; 917 } else 918 Lst_AtEnd(&paths, path); 919 } 920 } 921 922 /* 923 * Have word in line. Get or create its node and stick it at 924 * the end of the targets list 925 */ 926 if (specType == Not && *line != '\0') { 927 928 /* target names to be found and added to targets list */ 929 Lst curTargs = Lst_Initializer(curTargs); 930 931 if (Dir_HasWildcards(line)) { 932 /* 933 * Targets are to be sought only in the current 934 * directory, so create an empty path for the 935 * thing. Note we need to use Path_Clear in the 936 * destruction of the path as the Dir module 937 * could have added a directory to the path... 938 */ 939 struct Path emptyPath = 940 TAILQ_HEAD_INITIALIZER(emptyPath); 941 942 Path_Expand(line, &emptyPath, &curTargs); 943 Path_Clear(&emptyPath); 944 945 } else { 946 /* 947 * No wildcards, but we want to avoid code 948 * duplication, so create a list with the word 949 * on it. 950 */ 951 Lst_AtEnd(&curTargs, line); 952 } 953 954 while (!Lst_IsEmpty(&curTargs)) { 955 char *targName = Lst_DeQueue(&curTargs); 956 957 if (!Suff_IsTransform (targName)) { 958 gn = Targ_FindNode(targName, 959 TARG_CREATE); 960 } else { 961 gn = Suff_AddTransform(targName); 962 } 963 964 Lst_AtEnd(&targets, gn); 965 } 966 } else if (specType == ExPath && *line != '.' && *line != '\0'){ 967 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 968 line); 969 } 970 971 *cp = savec; 972 /* 973 * If it is a special type and not .PATH, it's the only 974 * target we allow on this line... 975 */ 976 if (specType != Not && specType != ExPath) { 977 Boolean warnFlag = FALSE; 978 979 while (*cp != '!' && *cp != ':' && *cp) { 980 if (*cp != ' ' && *cp != '\t') { 981 warnFlag = TRUE; 982 } 983 cp++; 984 } 985 if (warnFlag) { 986 Parse_Error(PARSE_WARNING, 987 "Extra target ignored"); 988 } 989 } else { 990 while (*cp && isspace((unsigned char)*cp)) { 991 cp++; 992 } 993 } 994 line = cp; 995 } while (*line != '!' && *line != ':' && *line); 996 997 if (!Lst_IsEmpty(&targets)) { 998 switch (specType) { 999 default: 1000 Parse_Error(PARSE_WARNING, "Special and mundane " 1001 "targets don't mix. Mundane ones ignored"); 1002 break; 1003 case Default: 1004 case Begin: 1005 case End: 1006 case Interrupt: 1007 /* 1008 * These four create nodes on which to hang commands, so 1009 * targets shouldn't be empty... 1010 */ 1011 case Not: 1012 /* 1013 * Nothing special here -- targets can be empty if it 1014 * wants. 1015 */ 1016 break; 1017 } 1018 } 1019 1020 /* 1021 * Have now parsed all the target names. Must parse the operator next. 1022 * The result is left in op. 1023 */ 1024 if (*cp == '!') { 1025 op = OP_FORCE; 1026 } else if (*cp == ':') { 1027 if (cp[1] == ':') { 1028 op = OP_DOUBLEDEP; 1029 cp++; 1030 } else { 1031 op = OP_DEPENDS; 1032 } 1033 } else { 1034 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? 1035 "Unknown directive" : "Missing dependency operator"); 1036 return; 1037 } 1038 1039 cp++; /* Advance beyond operator */ 1040 1041 ParseDoOp(op); 1042 1043 /* 1044 * Get to the first source 1045 */ 1046 while (*cp && isspace((unsigned char)*cp)) { 1047 cp++; 1048 } 1049 line = cp; 1050 1051 /* 1052 * Several special targets take different actions if present with no 1053 * sources: 1054 * a .SUFFIXES line with no sources clears out all old suffixes 1055 * a .PRECIOUS line makes all targets precious 1056 * a .IGNORE line ignores errors for all targets 1057 * a .SILENT line creates silence when making all targets 1058 * a .PATH removes all directories from the search path(s). 1059 */ 1060 if (!*line) { 1061 switch (specType) { 1062 case Suffixes: 1063 Suff_ClearSuffixes(); 1064 break; 1065 case Precious: 1066 allPrecious = TRUE; 1067 break; 1068 case Ignore: 1069 ignoreErrors = TRUE; 1070 break; 1071 case Silent: 1072 beSilent = TRUE; 1073 break; 1074 case ExPath: 1075 LST_FOREACH(ln, &paths) 1076 Path_Clear(Lst_Datum(ln)); 1077 break; 1078 case MakefileDeps: 1079 mfAutoDeps = TRUE; 1080 break; 1081 case Posix: 1082 is_posix = TRUE; 1083 Var_SetGlobal("%POSIX", "1003.2"); 1084 break; 1085 default: 1086 break; 1087 } 1088 1089 } else if (specType == MFlags) { 1090 /* 1091 * Call on functions in main.c to deal with these arguments and 1092 * set the initial character to a null-character so the loop to 1093 * get sources won't get anything 1094 */ 1095 Main_ParseArgLine(line, 0); 1096 *line = '\0'; 1097 1098 } else if (specType == Warn) { 1099 parse_warn(line); 1100 *line = '\0'; 1101 1102 } else if (specType == ExShell) { 1103 if (!Shell_Parse(line)) { 1104 Parse_Error(PARSE_FATAL, 1105 "improper shell specification"); 1106 return; 1107 } 1108 *line = '\0'; 1109 1110 } else if (specType == NotParallel || specType == SingleShell) { 1111 *line = '\0'; 1112 } 1113 1114 /* 1115 * NOW GO FOR THE SOURCES 1116 */ 1117 if (specType == Suffixes || specType == ExPath || 1118 specType == Includes || specType == Libs || 1119 specType == Null) { 1120 while (*line) { 1121 /* 1122 * If the target was one that doesn't take files as its 1123 * sources but takes something like suffixes, we take 1124 * each space-separated word on the line as a something 1125 * and deal with it accordingly. 1126 * 1127 * If the target was .SUFFIXES, we take each source as 1128 * a suffix and add it to the list of suffixes 1129 * maintained by the Suff module. 1130 * 1131 * If the target was a .PATH, we add the source as a 1132 * directory to search on the search path. 1133 * 1134 * If it was .INCLUDES, the source is taken to be the 1135 * suffix of files which will be #included and whose 1136 * search path should be present in the .INCLUDES 1137 * variable. 1138 * 1139 * If it was .LIBS, the source is taken to be the 1140 * suffix of files which are considered libraries and 1141 * whose search path should be present in the .LIBS 1142 * variable. 1143 * 1144 * If it was .NULL, the source is the suffix to use 1145 * when a file has no valid suffix. 1146 */ 1147 char savech; 1148 while (*cp && !isspace((unsigned char)*cp)) { 1149 cp++; 1150 } 1151 savech = *cp; 1152 *cp = '\0'; 1153 switch (specType) { 1154 case Suffixes: 1155 Suff_AddSuffix(line); 1156 break; 1157 case ExPath: 1158 LST_FOREACH(ln, &paths) 1159 Path_AddDir(Lst_Datum(ln), line); 1160 break; 1161 case Includes: 1162 Suff_AddInclude(line); 1163 break; 1164 case Libs: 1165 Suff_AddLib(line); 1166 break; 1167 case Null: 1168 Suff_SetNull(line); 1169 break; 1170 default: 1171 break; 1172 } 1173 *cp = savech; 1174 if (savech != '\0') { 1175 cp++; 1176 } 1177 while (*cp && isspace((unsigned char)*cp)) { 1178 cp++; 1179 } 1180 line = cp; 1181 } 1182 Lst_Destroy(&paths, NOFREE); 1183 1184 } else if (specType == ExportVar) { 1185 Var_SetEnv(line, VAR_GLOBAL); 1186 1187 } else { 1188 /* list of sources in order */ 1189 Lst curSrcs = Lst_Initializer(curSrc); 1190 1191 while (*line) { 1192 /* 1193 * The targets take real sources, so we must beware of 1194 * archive specifications (i.e. things with left 1195 * parentheses in them) and handle them accordingly. 1196 */ 1197 while (*cp && !isspace((unsigned char)*cp)) { 1198 if (*cp == '(' && cp > line && cp[-1] != '$') { 1199 /* 1200 * Only stop for a left parenthesis if 1201 * it isn't at the start of a word 1202 * (that'll be for variable changes 1203 * later) and isn't preceded by a dollar 1204 * sign (a dynamic source). 1205 */ 1206 break; 1207 } else { 1208 cp++; 1209 } 1210 } 1211 1212 if (*cp == '(') { 1213 GNode *gnp; 1214 1215 /* list of archive source names after exp. */ 1216 Lst sources = Lst_Initializer(sources); 1217 1218 if (!Arch_ParseArchive(&line, &sources, 1219 VAR_CMD)) { 1220 Parse_Error(PARSE_FATAL, "Error in " 1221 "source archive spec \"%s\"", line); 1222 return; 1223 } 1224 1225 while (!Lst_IsEmpty(&sources)) { 1226 gnp = Lst_DeQueue(&sources); 1227 ParseDoSrc(tOp, gnp->name, &curSrcs); 1228 } 1229 cp = line; 1230 } else { 1231 if (*cp) { 1232 *cp = '\0'; 1233 cp += 1; 1234 } 1235 1236 ParseDoSrc(tOp, line, &curSrcs); 1237 } 1238 while (*cp && isspace((unsigned char)*cp)) { 1239 cp++; 1240 } 1241 line = cp; 1242 } 1243 Lst_Destroy(&curSrcs, NOFREE); 1244 } 1245 1246 if (mainNode == NULL) { 1247 /* 1248 * If we have yet to decide on a main target to make, in the 1249 * absence of any user input, we want the first target on 1250 * the first dependency line that is actually a real target 1251 * (i.e. isn't a .USE or .EXEC rule) to be made. 1252 */ 1253 LST_FOREACH(ln, &targets) { 1254 gn = Lst_Datum(ln); 1255 if ((gn->type & (OP_NOTMAIN | OP_USE | 1256 OP_EXEC | OP_TRANSFORM)) == 0) { 1257 mainNode = gn; 1258 Targ_SetMain(gn); 1259 break; 1260 } 1261 } 1262 } 1263} 1264 1265/*- 1266 *--------------------------------------------------------------------- 1267 * Parse_IsVar -- 1268 * Return TRUE if the passed line is a variable assignment. A variable 1269 * assignment consists of a single word followed by optional whitespace 1270 * followed by either a += or an = operator. 1271 * This function is used both by the Parse_File function and main when 1272 * parsing the command-line arguments. 1273 * 1274 * Results: 1275 * TRUE if it is. FALSE if it ain't 1276 * 1277 * Side Effects: 1278 * none 1279 *--------------------------------------------------------------------- 1280 */ 1281Boolean 1282Parse_IsVar(char *line) 1283{ 1284 Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1285 Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1286 1287 int level = 0; 1288#define ISEQOPERATOR(c) \ 1289 ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') 1290 1291 /* 1292 * Skip to variable name 1293 */ 1294 for (; *line == ' ' || *line == '\t'; line++) 1295 continue; 1296 1297 for (; *line != '=' || level != 0; line++) { 1298 switch (*line) { 1299 case '\0': 1300 /* 1301 * end-of-line -- can't be a variable assignment. 1302 */ 1303 return (FALSE); 1304 1305 case ' ': 1306 case '\t': 1307 /* 1308 * there can be as much white space as desired so long 1309 * as there is only one word before the operator 1310 */ 1311 wasSpace = TRUE; 1312 break; 1313 1314 case '(': 1315 case '{': 1316 level++; 1317 break; 1318 1319 case '}': 1320 case ')': 1321 level--; 1322 break; 1323 1324 default: 1325 if (wasSpace && haveName) { 1326 if (ISEQOPERATOR(*line)) { 1327 /* 1328 * We must have a finished word 1329 */ 1330 if (level != 0) 1331 return (FALSE); 1332 1333 /* 1334 * When an = operator [+?!:] is found, 1335 * the next character must be an = or 1336 * it ain't a valid assignment. 1337 */ 1338 if (line[1] == '=') 1339 return (haveName); 1340#ifdef SUNSHCMD 1341 /* 1342 * This is a shell command 1343 */ 1344 if (strncmp(line, ":sh", 3) == 0) 1345 return (haveName); 1346#endif 1347 } 1348 /* 1349 * This is the start of another word, so not 1350 * assignment. 1351 */ 1352 return (FALSE); 1353 1354 } else { 1355 haveName = TRUE; 1356 wasSpace = FALSE; 1357 } 1358 break; 1359 } 1360 } 1361 1362 return (haveName); 1363} 1364 1365/*- 1366 *--------------------------------------------------------------------- 1367 * Parse_DoVar -- 1368 * Take the variable assignment in the passed line and do it in the 1369 * global context. 1370 * 1371 * Note: There is a lexical ambiguity with assignment modifier characters 1372 * in variable names. This routine interprets the character before the = 1373 * as a modifier. Therefore, an assignment like 1374 * C++=/usr/bin/CC 1375 * is interpreted as "C+ +=" instead of "C++ =". 1376 * 1377 * Results: 1378 * none 1379 * 1380 * Side Effects: 1381 * the variable structure of the given variable name is altered in the 1382 * global context. 1383 *--------------------------------------------------------------------- 1384 */ 1385void 1386Parse_DoVar(char *line, GNode *ctxt) 1387{ 1388 char *cp; /* pointer into line */ 1389 enum { 1390 VAR_SUBST, 1391 VAR_APPEND, 1392 VAR_SHELL, 1393 VAR_NORMAL 1394 } type; /* Type of assignment */ 1395 char *opc; /* ptr to operator character to 1396 * null-terminate the variable name */ 1397 1398 /* 1399 * Skip to variable name 1400 */ 1401 while (*line == ' ' || *line == '\t') { 1402 line++; 1403 } 1404 1405 /* 1406 * Skip to operator character, nulling out whitespace as we go 1407 */ 1408 for (cp = line + 1; *cp != '='; cp++) { 1409 if (isspace((unsigned char)*cp)) { 1410 *cp = '\0'; 1411 } 1412 } 1413 opc = cp - 1; /* operator is the previous character */ 1414 *cp++ = '\0'; /* nuke the = */ 1415 1416 /* 1417 * Check operator type 1418 */ 1419 switch (*opc) { 1420 case '+': 1421 type = VAR_APPEND; 1422 *opc = '\0'; 1423 break; 1424 1425 case '?': 1426 /* 1427 * If the variable already has a value, we don't do anything. 1428 */ 1429 *opc = '\0'; 1430 if (Var_Exists(line, ctxt)) { 1431 return; 1432 } else { 1433 type = VAR_NORMAL; 1434 } 1435 break; 1436 1437 case ':': 1438 type = VAR_SUBST; 1439 *opc = '\0'; 1440 break; 1441 1442 case '!': 1443 type = VAR_SHELL; 1444 *opc = '\0'; 1445 break; 1446 1447 default: 1448#ifdef SUNSHCMD 1449 while (*opc != ':') { 1450 if (opc == line) 1451 break; 1452 else 1453 --opc; 1454 } 1455 1456 if (strncmp(opc, ":sh", 3) == 0) { 1457 type = VAR_SHELL; 1458 *opc = '\0'; 1459 break; 1460 } 1461#endif 1462 type = VAR_NORMAL; 1463 break; 1464 } 1465 1466 while (isspace((unsigned char)*cp)) { 1467 cp++; 1468 } 1469 1470 if (type == VAR_APPEND) { 1471 Var_Append(line, cp, ctxt); 1472 1473 } else if (type == VAR_SUBST) { 1474 /* 1475 * Allow variables in the old value to be undefined, but leave 1476 * their invocation alone -- this is done by forcing oldVars 1477 * to be false. 1478 * XXX: This can cause recursive variables, but that's not 1479 * hard to do, and this allows someone to do something like 1480 * 1481 * CFLAGS = $(.INCLUDES) 1482 * CFLAGS := -I.. $(CFLAGS) 1483 * 1484 * And not get an error. 1485 */ 1486 Boolean oldOldVars = oldVars; 1487 1488 oldVars = FALSE; 1489 1490 /* 1491 * make sure that we set the variable the first time to nothing 1492 * so that it gets substituted! 1493 */ 1494 if (!Var_Exists(line, ctxt)) 1495 Var_Set(line, "", ctxt); 1496 1497 cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE)); 1498 1499 oldVars = oldOldVars; 1500 1501 Var_Set(line, cp, ctxt); 1502 free(cp); 1503 1504 } else if (type == VAR_SHELL) { 1505 /* 1506 * TRUE if the command needs to be freed, i.e. 1507 * if any variable expansion was performed 1508 */ 1509 Boolean freeCmd = FALSE; 1510 Buffer *buf; 1511 const char *error; 1512 1513 if (strchr(cp, '$') != NULL) { 1514 /* 1515 * There's a dollar sign in the command, so perform 1516 * variable expansion on the whole thing. The 1517 * resulting string will need freeing when we're done, 1518 * so set freeCmd to TRUE. 1519 */ 1520 cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE)); 1521 freeCmd = TRUE; 1522 } 1523 1524 buf = Cmd_Exec(cp, &error); 1525 Var_Set(line, Buf_Data(buf), ctxt); 1526 Buf_Destroy(buf, TRUE); 1527 1528 if (error) 1529 Parse_Error(PARSE_WARNING, error, cp); 1530 1531 if (freeCmd) 1532 free(cp); 1533 1534 } else { 1535 /* 1536 * Normal assignment -- just do it. 1537 */ 1538 Var_Set(line, cp, ctxt); 1539 } 1540 if (strcmp(line, MAKE_JOB_PREFIX) == 0) 1541 Job_SetPrefix(); 1542} 1543 1544/*- 1545 *----------------------------------------------------------------------- 1546 * ParseHasCommands -- 1547 * Callback procedure for Parse_File when destroying the list of 1548 * targets on the last dependency line. Marks a target as already 1549 * having commands if it does, to keep from having shell commands 1550 * on multiple dependency lines. 1551 * 1552 * Results: 1553 * None 1554 * 1555 * Side Effects: 1556 * OP_HAS_COMMANDS may be set for the target. 1557 * 1558 *----------------------------------------------------------------------- 1559 */ 1560static void 1561ParseHasCommands(void *gnp) 1562{ 1563 GNode *gn = gnp; 1564 1565 if (!Lst_IsEmpty(&gn->commands)) { 1566 gn->type |= OP_HAS_COMMANDS; 1567 } 1568} 1569 1570/*- 1571 *----------------------------------------------------------------------- 1572 * Parse_AddIncludeDir -- 1573 * Add a directory to the path searched for included makefiles 1574 * bracketed by double-quotes. Used by functions in main.c 1575 * 1576 * Results: 1577 * None. 1578 * 1579 * Side Effects: 1580 * The directory is appended to the list. 1581 * 1582 *----------------------------------------------------------------------- 1583 */ 1584void 1585Parse_AddIncludeDir(char *dir) 1586{ 1587 1588 Path_AddDir(&parseIncPath, dir); 1589} 1590 1591/*- 1592 *--------------------------------------------------------------------- 1593 * Parse_FromString -- 1594 * Start Parsing from the given string 1595 * 1596 * Results: 1597 * None 1598 * 1599 * Side Effects: 1600 * A structure is added to the includes Lst and readProc, curFile.lineno, 1601 * curFile.fname and curFile.F are altered for the new file 1602 *--------------------------------------------------------------------- 1603 */ 1604void 1605Parse_FromString(char *str, int lineno) 1606{ 1607 1608 DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 1609 1610 ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); 1611} 1612 1613#ifdef SYSVINCLUDE 1614/*- 1615 *--------------------------------------------------------------------- 1616 * ParseTraditionalInclude -- 1617 * Push to another file. 1618 * 1619 * The input is the line minus the "include". The file name is 1620 * the string following the "include". 1621 * 1622 * Results: 1623 * None 1624 * 1625 * Side Effects: 1626 * A structure is added to the includes Lst and readProc, curFile.lineno, 1627 * curFile.fname and curFile.F are altered for the new file 1628 *--------------------------------------------------------------------- 1629 */ 1630static void 1631ParseTraditionalInclude(char *file) 1632{ 1633 char *fullname; /* full pathname of file */ 1634 char *cp; /* current position in file spec */ 1635 1636 /* 1637 * Skip over whitespace 1638 */ 1639 while (*file == ' ' || *file == '\t') { 1640 file++; 1641 } 1642 1643 if (*file == '\0') { 1644 Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); 1645 return; 1646 } 1647 1648 /* 1649 * Skip to end of line or next whitespace 1650 */ 1651 for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1652 continue; 1653 } 1654 1655 *cp = '\0'; 1656 1657 /* 1658 * Substitute for any variables in the file name before trying to 1659 * find the thing. 1660 */ 1661 file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 1662 1663 /* 1664 * Now we know the file's name, we attempt to find the durn thing. 1665 * Search for it first on the -I search path, then on the .PATH 1666 * search path, if not found in a -I directory. 1667 */ 1668 fullname = Path_FindFile(file, &parseIncPath); 1669 if (fullname == NULL) { 1670 fullname = Path_FindFile(file, &dirSearchPath); 1671 } 1672 1673 if (fullname == NULL) { 1674 /* 1675 * Still haven't found the makefile. Look for it on the system 1676 * path as a last resort. 1677 */ 1678 fullname = Path_FindFile(file, &sysIncPath); 1679 } 1680 1681 if (fullname == NULL) { 1682 Parse_Error(PARSE_FATAL, "Could not find %s", file); 1683 /* XXXHB free(file) */ 1684 return; 1685 } 1686 1687 /* XXXHB free(file) */ 1688 1689 /* 1690 * We set up the name of the file to be the absolute 1691 * name of the include file so error messages refer to the right 1692 * place. 1693 */ 1694 ParsePushInput(fullname, NULL, NULL, 0); 1695} 1696#endif 1697 1698/*- 1699 *--------------------------------------------------------------------- 1700 * ParseReadc -- 1701 * Read a character from the current file 1702 * 1703 * Results: 1704 * The character that was read 1705 * 1706 * Side Effects: 1707 *--------------------------------------------------------------------- 1708 */ 1709static int 1710ParseReadc(void) 1711{ 1712 1713 if (CURFILE->F != NULL) 1714 return (fgetc(CURFILE->F)); 1715 1716 if (CURFILE->str != NULL && *CURFILE->ptr != '\0') 1717 return (*CURFILE->ptr++); 1718 1719 return (EOF); 1720} 1721 1722 1723/*- 1724 *--------------------------------------------------------------------- 1725 * ParseUnreadc -- 1726 * Put back a character to the current file 1727 * 1728 * Results: 1729 * None. 1730 * 1731 * Side Effects: 1732 *--------------------------------------------------------------------- 1733 */ 1734static void 1735ParseUnreadc(int c) 1736{ 1737 1738 if (CURFILE->F != NULL) { 1739 ungetc(c, CURFILE->F); 1740 return; 1741 } 1742 if (CURFILE->str != NULL) { 1743 *--(CURFILE->ptr) = c; 1744 return; 1745 } 1746} 1747 1748/* ParseSkipLine(): 1749 * Grab the next line unless it begins with a dot (`.') and we're told to 1750 * ignore such lines. 1751 */ 1752static char * 1753ParseSkipLine(int skip, int keep_newline) 1754{ 1755 char *line; 1756 int c, lastc; 1757 Buffer *buf; 1758 1759 buf = Buf_Init(MAKE_BSIZE); 1760 1761 do { 1762 Buf_Clear(buf); 1763 lastc = '\0'; 1764 1765 while (((c = ParseReadc()) != '\n' || lastc == '\\') 1766 && c != EOF) { 1767 if (skip && c == '#' && lastc != '\\') { 1768 /* 1769 * let a comment be terminated even by an 1770 * escaped \n. This is consistent to comment 1771 * handling in ParseReadLine 1772 */ 1773 while ((c = ParseReadc()) != '\n' && c != EOF) 1774 ; 1775 break; 1776 } 1777 if (c == '\n') { 1778 if (keep_newline) 1779 Buf_AddByte(buf, (Byte)c); 1780 else 1781 Buf_ReplaceLastByte(buf, (Byte)' '); 1782 CURFILE->lineno++; 1783 1784 while ((c = ParseReadc()) == ' ' || c == '\t') 1785 continue; 1786 1787 if (c == EOF) 1788 break; 1789 } 1790 1791 Buf_AddByte(buf, (Byte)c); 1792 lastc = c; 1793 } 1794 1795 if (c == EOF) { 1796 Parse_Error(PARSE_FATAL, 1797 "Unclosed conditional/for loop"); 1798 Buf_Destroy(buf, TRUE); 1799 return (NULL); 1800 } 1801 1802 CURFILE->lineno++; 1803 Buf_AddByte(buf, (Byte)'\0'); 1804 line = Buf_Data(buf); 1805 } while (skip == 1 && line[0] != '.'); 1806 1807 Buf_Destroy(buf, FALSE); 1808 return (line); 1809} 1810 1811/*- 1812 *--------------------------------------------------------------------- 1813 * ParseReadLine -- 1814 * Read an entire line from the input file. Called only by Parse_File. 1815 * To facilitate escaped newlines and what have you, a character is 1816 * buffered in 'lastc', which is '\0' when no characters have been 1817 * read. When we break out of the loop, c holds the terminating 1818 * character and lastc holds a character that should be added to 1819 * the line (unless we don't read anything but a terminator). 1820 * 1821 * Results: 1822 * A line w/o its newline 1823 * 1824 * Side Effects: 1825 * Only those associated with reading a character 1826 *--------------------------------------------------------------------- 1827 */ 1828static char * 1829ParseReadLine(void) 1830{ 1831 Buffer *buf; /* Buffer for current line */ 1832 int c; /* the current character */ 1833 int lastc; /* The most-recent character */ 1834 Boolean semiNL; /* treat semi-colons as newlines */ 1835 Boolean ignDepOp; /* TRUE if should ignore dependency operators 1836 * for the purposes of setting semiNL */ 1837 Boolean ignComment; /* TRUE if should ignore comments (in a 1838 * shell command */ 1839 char *line; /* Result */ 1840 char *ep; /* to strip trailing blanks */ 1841 1842 again: 1843 semiNL = FALSE; 1844 ignDepOp = FALSE; 1845 ignComment = FALSE; 1846 1847 lastc = '\0'; 1848 1849 /* 1850 * Handle tab at the beginning of the line. A leading tab (shell 1851 * command) forces us to ignore comments and dependency operators and 1852 * treat semi-colons as semi-colons (by leaving semiNL FALSE). 1853 * This also discards completely blank lines. 1854 */ 1855 for (;;) { 1856 c = ParseReadc(); 1857 if (c == EOF) { 1858 if (ParsePopInput() == DONE) { 1859 /* End of all inputs - return NULL */ 1860 return (NULL); 1861 } 1862 continue; 1863 } 1864 1865 if (c == '\t') { 1866 ignComment = ignDepOp = TRUE; 1867 lastc = c; 1868 break; 1869 } 1870 if (c != '\n') { 1871 ParseUnreadc(c); 1872 break; 1873 } 1874 CURFILE->lineno++; 1875 } 1876 1877 buf = Buf_Init(MAKE_BSIZE); 1878 1879 while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { 1880 test_char: 1881 switch (c) { 1882 case '\n': 1883 /* 1884 * Escaped newline: read characters until a 1885 * non-space or an unescaped newline and 1886 * replace them all by a single space. This is 1887 * done by storing the space over the backslash 1888 * and dropping through with the next nonspace. 1889 * If it is a semi-colon and semiNL is TRUE, 1890 * it will be recognized as a newline in the 1891 * code below this... 1892 */ 1893 CURFILE->lineno++; 1894 lastc = ' '; 1895 while ((c = ParseReadc()) == ' ' || c == '\t') { 1896 continue; 1897 } 1898 if (c == EOF || c == '\n') { 1899 goto line_read; 1900 } else { 1901 /* 1902 * Check for comments, semiNL's, etc. -- 1903 * easier than ParseUnreadc(c); 1904 * continue; 1905 */ 1906 goto test_char; 1907 } 1908 /*NOTREACHED*/ 1909 break; 1910 1911 case ';': 1912 /* 1913 * Semi-colon: Need to see if it should be 1914 * interpreted as a newline 1915 */ 1916 if (semiNL) { 1917 /* 1918 * To make sure the command that may 1919 * be following this semi-colon begins 1920 * with a tab, we push one back into the 1921 * input stream. This will overwrite the 1922 * semi-colon in the buffer. If there is 1923 * no command following, this does no 1924 * harm, since the newline remains in 1925 * the buffer and the 1926 * whole line is ignored. 1927 */ 1928 ParseUnreadc('\t'); 1929 goto line_read; 1930 } 1931 break; 1932 case '=': 1933 if (!semiNL) { 1934 /* 1935 * Haven't seen a dependency operator 1936 * before this, so this must be a 1937 * variable assignment -- don't pay 1938 * attention to dependency operators 1939 * after this. 1940 */ 1941 ignDepOp = TRUE; 1942 } else if (lastc == ':' || lastc == '!') { 1943 /* 1944 * Well, we've seen a dependency 1945 * operator already, but it was the 1946 * previous character, so this is really 1947 * just an expanded variable assignment. 1948 * Revert semi-colons to being just 1949 * semi-colons again and ignore any more 1950 * dependency operators. 1951 * 1952 * XXX: Note that a line like 1953 * "foo : a:=b" will blow up, but who'd 1954 * write a line like that anyway? 1955 */ 1956 ignDepOp = TRUE; 1957 semiNL = FALSE; 1958 } 1959 break; 1960 case '#': 1961 if (!ignComment) { 1962 if (lastc != '\\') { 1963 /* 1964 * If the character is a hash 1965 * mark and it isn't escaped 1966 * (or we're being compatible), 1967 * the thing is a comment. 1968 * Skip to the end of the line. 1969 */ 1970 do { 1971 c = ParseReadc(); 1972 } while (c != '\n' && c != EOF); 1973 goto line_read; 1974 } else { 1975 /* 1976 * Don't add the backslash. 1977 * Just let the # get copied 1978 * over. 1979 */ 1980 lastc = c; 1981 continue; 1982 } 1983 } 1984 break; 1985 1986 case ':': 1987 case '!': 1988 if (!ignDepOp) { 1989 /* 1990 * A semi-colon is recognized as a 1991 * newline only on dependency lines. 1992 * Dependency lines are lines with a 1993 * colon or an exclamation point. 1994 * Ergo... 1995 */ 1996 semiNL = TRUE; 1997 } 1998 break; 1999 2000 default: 2001 break; 2002 } 2003 /* 2004 * Copy in the previous character (there may be none if this 2005 * was the first character) and save this one in 2006 * lastc. 2007 */ 2008 if (lastc != '\0') 2009 Buf_AddByte(buf, (Byte)lastc); 2010 lastc = c; 2011 } 2012 line_read: 2013 CURFILE->lineno++; 2014 2015 if (lastc != '\0') { 2016 Buf_AddByte(buf, (Byte)lastc); 2017 } 2018 Buf_AddByte(buf, (Byte)'\0'); 2019 line = Buf_Peel(buf); 2020 2021 /* 2022 * Strip trailing blanks and tabs from the line. 2023 * Do not strip a blank or tab that is preceded by 2024 * a '\' 2025 */ 2026 ep = line; 2027 while (*ep) 2028 ++ep; 2029 while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { 2030 if (ep > line + 1 && ep[-2] == '\\') 2031 break; 2032 --ep; 2033 } 2034 *ep = 0; 2035 2036 if (line[0] == '\0') { 2037 /* empty line - just ignore */ 2038 free(line); 2039 goto again; 2040 } 2041 2042 return (line); 2043} 2044 2045/*- 2046 *----------------------------------------------------------------------- 2047 * ParseFinishLine -- 2048 * Handle the end of a dependency group. 2049 * 2050 * Results: 2051 * Nothing. 2052 * 2053 * Side Effects: 2054 * inLine set FALSE. 'targets' list destroyed. 2055 * 2056 *----------------------------------------------------------------------- 2057 */ 2058static void 2059ParseFinishLine(void) 2060{ 2061 const LstNode *ln; 2062 2063 if (inLine) { 2064 LST_FOREACH(ln, &targets) { 2065 if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) 2066 Suff_EndTransform(Lst_Datum(ln)); 2067 } 2068 Lst_Destroy(&targets, ParseHasCommands); 2069 inLine = FALSE; 2070 } 2071} 2072 2073/** 2074 * xparse_include 2075 * Parse an .include directive and push the file onto the input stack. 2076 * The input is the line minus the .include. A file spec is a string 2077 * enclosed in <> or "". The former is looked for only in sysIncPath. 2078 * The latter in . and the directories specified by -I command line 2079 * options 2080 */ 2081static void 2082xparse_include(char *file, int sinclude) 2083{ 2084 char *fullname; /* full pathname of file */ 2085 char endc; /* the character which ends the file spec */ 2086 char *cp; /* current position in file spec */ 2087 Boolean isSystem; /* TRUE if makefile is a system makefile */ 2088 char *prefEnd, *Fname; 2089 char *newName; 2090 2091 /* 2092 * Skip to delimiter character so we know where to look 2093 */ 2094 while (*file == ' ' || *file == '\t') { 2095 file++; 2096 } 2097 2098 if (*file != '"' && *file != '<') { 2099 Parse_Error(PARSE_FATAL, 2100 ".include filename must be delimited by '\"' or '<'"); 2101 return; 2102 } 2103 2104 /* 2105 * Set the search path on which to find the include file based on the 2106 * characters which bracket its name. Angle-brackets imply it's 2107 * a system Makefile while double-quotes imply it's a user makefile 2108 */ 2109 if (*file == '<') { 2110 isSystem = TRUE; 2111 endc = '>'; 2112 } else { 2113 isSystem = FALSE; 2114 endc = '"'; 2115 } 2116 2117 /* 2118 * Skip to matching delimiter 2119 */ 2120 for (cp = ++file; *cp != endc; cp++) { 2121 if (*cp == '\0') { 2122 Parse_Error(PARSE_FATAL, 2123 "Unclosed .include filename. '%c' expected", endc); 2124 return; 2125 } 2126 } 2127 *cp = '\0'; 2128 2129 /* 2130 * Substitute for any variables in the file name before trying to 2131 * find the thing. 2132 */ 2133 file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); 2134 2135 /* 2136 * Now we know the file's name and its search path, we attempt to 2137 * find the durn thing. A return of NULL indicates the file don't 2138 * exist. 2139 */ 2140 if (!isSystem) { 2141 /* 2142 * Include files contained in double-quotes are first searched 2143 * for relative to the including file's location. We don't want 2144 * to cd there, of course, so we just tack on the old file's 2145 * leading path components and call Path_FindFile to see if 2146 * we can locate the beast. 2147 */ 2148 2149 /* Make a temporary copy of this, to be safe. */ 2150 Fname = estrdup(CURFILE->fname); 2151 2152 prefEnd = strrchr(Fname, '/'); 2153 if (prefEnd != NULL) { 2154 *prefEnd = '\0'; 2155 if (file[0] == '/') 2156 newName = estrdup(file); 2157 else 2158 newName = str_concat(Fname, file, STR_ADDSLASH); 2159 fullname = Path_FindFile(newName, &parseIncPath); 2160 if (fullname == NULL) { 2161 fullname = Path_FindFile(newName, 2162 &dirSearchPath); 2163 } 2164 free(newName); 2165 *prefEnd = '/'; 2166 } else { 2167 fullname = NULL; 2168 } 2169 free(Fname); 2170 if (fullname == NULL) { 2171 /* 2172 * Makefile wasn't found in same directory as included 2173 * makefile. Search for it first on the -I search path, 2174 * then on the .PATH search path, if not found in a -I 2175 * directory. 2176 * XXX: Suffix specific? 2177 */ 2178 fullname = Path_FindFile(file, &parseIncPath); 2179 if (fullname == NULL) { 2180 fullname = Path_FindFile(file, &dirSearchPath); 2181 } 2182 } 2183 } else { 2184 fullname = NULL; 2185 } 2186 2187 if (fullname == NULL) { 2188 /* 2189 * System makefile or still haven't found the makefile. 2190 * Look for it on the system path. 2191 */ 2192 fullname = Path_FindFile(file, &sysIncPath); 2193 } 2194 2195 if (fullname == NULL) { 2196 *cp = endc; 2197 if (!sinclude) 2198 Parse_Error(PARSE_FATAL, "Could not find %s", file); 2199 else 2200 Main_AddSourceMakefile(file); 2201 free(file); 2202 return; 2203 } 2204 Main_AddSourceMakefile(fullname); 2205 free(file); 2206 2207 /* 2208 * We set up the name of the file to be the absolute 2209 * name of the include file so error messages refer to the right 2210 * place. 2211 */ 2212 ParsePushInput(fullname, NULL, NULL, 0); 2213 DEBUGF(DIR, (".include %s\n", fullname)); 2214} 2215 2216static void 2217parse_include(char *file, int code __unused, int lineno __unused) 2218{ 2219 xparse_include(file, 0); 2220} 2221 2222static void 2223parse_sinclude(char *file, int code __unused, int lineno __unused) 2224{ 2225 xparse_include(file, 1); 2226} 2227 2228/** 2229 * parse_message 2230 * Parse a .warning or .error directive 2231 * 2232 * The input is the line minus the ".error"/".warning". We substitute 2233 * variables, print the message and exit(1) (for .error) or just print 2234 * a warning if the directive is malformed. 2235 */ 2236static void 2237parse_message(char *line, int iserror, int lineno __unused) 2238{ 2239 2240 if (!isspace((u_char)*line)) { 2241 Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s", 2242 iserror ? "error" : "warning", line); 2243 return; 2244 } 2245 2246 while (isspace((u_char)*line)) 2247 line++; 2248 2249 line = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); 2250 Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); 2251 free(line); 2252 2253 if (iserror) { 2254 /* Terminate immediately. */ 2255 exit(1); 2256 } 2257} 2258 2259/** 2260 * parse_undef 2261 * Parse an .undef directive. 2262 */ 2263static void 2264parse_undef(char *line, int code __unused, int lineno __unused) 2265{ 2266 char *cp; 2267 2268 while (isspace((u_char)*line)) 2269 line++; 2270 2271 for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) { 2272 ; 2273 } 2274 *cp = '\0'; 2275 2276 cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); 2277 Var_Delete(cp, VAR_GLOBAL); 2278 free(cp); 2279} 2280 2281/** 2282 * parse_for 2283 * Parse a .for directive. 2284 */ 2285static void 2286parse_for(char *line, int code __unused, int lineno) 2287{ 2288 2289 if (!For_For(line)) { 2290 /* syntax error */ 2291 return; 2292 } 2293 line = NULL; 2294 2295 /* 2296 * Skip after the matching endfor. 2297 */ 2298 do { 2299 free(line); 2300 line = ParseSkipLine(0, 1); 2301 if (line == NULL) { 2302 Parse_Error(PARSE_FATAL, 2303 "Unexpected end of file in for loop.\n"); 2304 return; 2305 } 2306 } while (For_Eval(line)); 2307 free(line); 2308 2309 /* execute */ 2310 For_Run(lineno); 2311} 2312 2313/** 2314 * parse_endfor 2315 * Parse endfor. This may only happen if there was no matching .for. 2316 */ 2317static void 2318parse_endfor(char *line __unused, int code __unused, int lineno __unused) 2319{ 2320 2321 Parse_Error(PARSE_FATAL, "for-less endfor"); 2322} 2323 2324/** 2325 * parse_directive 2326 * Got a line starting with a '.'. Check if this is a directive 2327 * and parse it. 2328 * 2329 * return: 2330 * TRUE if line was a directive, FALSE otherwise. 2331 */ 2332static Boolean 2333parse_directive(char *line) 2334{ 2335 char *start; 2336 char *cp; 2337 int dir; 2338 2339 /* 2340 * Get the keyword: 2341 * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).* 2342 * \1 is the keyword. 2343 */ 2344 for (start = line; isspace((u_char)*start); start++) { 2345 ; 2346 } 2347 2348 if (!isalpha((u_char)*start)) { 2349 return (FALSE); 2350 } 2351 2352 cp = start + 1; 2353 while (isalnum((u_char)*cp) || *cp == '_') { 2354 cp++; 2355 } 2356 2357 dir = directive_hash(start, cp - start); 2358 if (dir < 0 || dir >= (int)NDIRECTS || 2359 (size_t)(cp - start) != strlen(directives[dir].name) || 2360 strncmp(start, directives[dir].name, cp - start) != 0) { 2361 /* not actually matched */ 2362 return (FALSE); 2363 } 2364 2365 if (!skipLine || directives[dir].skip_flag) 2366 (*directives[dir].func)(cp, directives[dir].code, 2367 CURFILE->lineno); 2368 return (TRUE); 2369} 2370 2371/*- 2372 *--------------------------------------------------------------------- 2373 * Parse_File -- 2374 * Parse a file into its component parts, incorporating it into the 2375 * current dependency graph. This is the main function and controls 2376 * almost every other function in this module 2377 * 2378 * Results: 2379 * None 2380 * 2381 * Side Effects: 2382 * Loads. Nodes are added to the list of all targets, nodes and links 2383 * are added to the dependency graph. etc. etc. etc. 2384 *--------------------------------------------------------------------- 2385 */ 2386void 2387Parse_File(const char *name, FILE *stream) 2388{ 2389 char *cp; /* pointer into the line */ 2390 char *line; /* the line we're working on */ 2391 2392 inLine = FALSE; 2393 fatals = 0; 2394 2395 ParsePushInput(estrdup(name), stream, NULL, 0); 2396 2397 while ((line = ParseReadLine()) != NULL) { 2398 if (*line == '.' && parse_directive(line + 1)) { 2399 /* directive consumed */ 2400 goto nextLine; 2401 } 2402 if (skipLine || *line == '#') { 2403 /* Skipping .if block or comment. */ 2404 goto nextLine; 2405 } 2406 2407 if (*line == '\t') { 2408 /* 2409 * If a line starts with a tab, it can only 2410 * hope to be a creation command. 2411 */ 2412 for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 2413 continue; 2414 } 2415 if (*cp) { 2416 if (inLine) { 2417 LstNode *ln; 2418 GNode *gn; 2419 2420 /* 2421 * So long as it's not a blank 2422 * line and we're actually in a 2423 * dependency spec, add the 2424 * command to the list of 2425 * commands of all targets in 2426 * the dependency spec. 2427 */ 2428 LST_FOREACH(ln, &targets) { 2429 gn = Lst_Datum(ln); 2430 2431 /* 2432 * if target already 2433 * supplied, ignore 2434 * commands 2435 */ 2436 if (!(gn->type & OP_HAS_COMMANDS)) 2437 Lst_AtEnd(&gn->commands, cp); 2438 else 2439 Parse_Error(PARSE_WARNING, "duplicate script " 2440 "for target \"%s\" ignored", gn->name); 2441 } 2442 continue; 2443 } else { 2444 Parse_Error(PARSE_FATAL, 2445 "Unassociated shell command \"%s\"", 2446 cp); 2447 } 2448 } 2449#ifdef SYSVINCLUDE 2450 } else if (strncmp(line, "include", 7) == 0 && 2451 isspace((unsigned char)line[7]) && 2452 strchr(line, ':') == NULL) { 2453 /* 2454 * It's an S3/S5-style "include". 2455 */ 2456 ParseTraditionalInclude(line + 7); 2457 goto nextLine; 2458#endif 2459 } else if (Parse_IsVar(line)) { 2460 ParseFinishLine(); 2461 Parse_DoVar(line, VAR_GLOBAL); 2462 2463 } else { 2464 /* 2465 * We now know it's a dependency line so it 2466 * needs to have all variables expanded before 2467 * being parsed. Tell the variable module to 2468 * complain if some variable is undefined... 2469 * To make life easier on novices, if the line 2470 * is indented we first make sure the line has 2471 * a dependency operator in it. If it doesn't 2472 * have an operator and we're in a dependency 2473 * line's script, we assume it's actually a 2474 * shell command and add it to the current 2475 * list of targets. XXX this comment seems wrong. 2476 */ 2477 cp = line; 2478 if (isspace((unsigned char)line[0])) { 2479 while (*cp != '\0' && 2480 isspace((unsigned char)*cp)) { 2481 cp++; 2482 } 2483 if (*cp == '\0') { 2484 goto nextLine; 2485 } 2486 } 2487 2488 ParseFinishLine(); 2489 2490 cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE)); 2491 2492 free(line); 2493 line = cp; 2494 2495 /* 2496 * Need a non-circular list for the target nodes 2497 */ 2498 Lst_Destroy(&targets, NOFREE); 2499 inLine = TRUE; 2500 2501 ParseDoDependency(line); 2502 } 2503 2504 nextLine: 2505 free(line); 2506 } 2507 2508 ParseFinishLine(); 2509 2510 /* 2511 * Make sure conditionals are clean 2512 */ 2513 Cond_End(); 2514 2515 if (fatals) 2516 errx(1, "fatal errors encountered -- cannot continue"); 2517} 2518 2519/*- 2520 *----------------------------------------------------------------------- 2521 * Parse_MainName -- 2522 * Return a Lst of the main target to create for main()'s sake. If 2523 * no such target exists, we Punt with an obnoxious error message. 2524 * 2525 * Results: 2526 * A Lst of the single node to create. 2527 * 2528 * Side Effects: 2529 * None. 2530 * 2531 *----------------------------------------------------------------------- 2532 */ 2533void 2534Parse_MainName(Lst *listmain) 2535{ 2536 2537 if (mainNode == NULL) { 2538 Punt("no target to make."); 2539 /*NOTREACHED*/ 2540 } else if (mainNode->type & OP_DOUBLEDEP) { 2541 Lst_AtEnd(listmain, mainNode); 2542 Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); 2543 } else 2544 Lst_AtEnd(listmain, mainNode); 2545} 2546