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