| File: | dmake/dmake.c |
| Location: | line 682, column 47 |
| Description: | Value stored to 'fname' is never read |
| 1 | /* |
| 2 | -- |
| 3 | -- SYNOPSIS |
| 4 | -- The main program. |
| 5 | -- |
| 6 | -- DESCRIPTION |
| 7 | -- |
| 8 | -- dmake [-#dbug_string] [ options ] |
| 9 | -- [ macro definitions ] [ target ... ] |
| 10 | -- |
| 11 | -- This file contains the main command line parser for the |
| 12 | -- make utility. The valid flags recognized are as follows: |
| 13 | -- |
| 14 | -- -f file - use file as the makefile |
| 15 | -- -C file - duplicate console output to file (MSDOS only) |
| 16 | -- -K file - .KEEP_STATE file |
| 17 | -- -#dbug_string - dump out debugging info, see below |
| 18 | -- -v[cdfimrtw] - verbose, print what we are doing, as we do it |
| 19 | -- -m[trae] - measure timing information |
| 20 | -- |
| 21 | -- options: (can be catenated, ie -irn == -i -r -n) |
| 22 | -- |
| 23 | -- -A - enable AUGMAKE special target mapping |
| 24 | -- -B - enable non-use of TABS to start recipe lines |
| 25 | -- -c - use non-standard comment scanning |
| 26 | -- -d - do not use directory cache |
| 27 | -- -i - ignore errors |
| 28 | -- -n - trace and print, do not execute commands |
| 29 | -- -t - touch, update dates without executing commands |
| 30 | -- -T - do not apply transitive closure on inference rules |
| 31 | -- -r - don't use internal rules |
| 32 | -- -s - do your work silently |
| 33 | -- -S - force Sequential make, overrides -P |
| 34 | -- -q - check if target is up to date. Does not |
| 35 | -- do anything. Returns 0 if up to date, -1 |
| 36 | -- otherwise. |
| 37 | -- -p - print out a version of the makefile |
| 38 | -- -P# - set value of MAXPROCESS |
| 39 | -- -E - define environment strings as macros |
| 40 | -- -e - as -E but done after parsing makefile |
| 41 | -- -u - force unconditional update of target |
| 42 | -- -k - make all independent targets even if errors |
| 43 | -- -V - print out this make version number |
| 44 | -- -M - Microsoft make compatibility, (* disabled *) |
| 45 | -- -h - print out usage info |
| 46 | -- -x - export macro defs to environment |
| 47 | -- -X - ignore #! lines found in makefile |
| 48 | -- |
| 49 | -- NOTE: - #ddbug_string is only availabe for versions of dmake that |
| 50 | -- have been compiled with -DDBUG switch on. Not the case for |
| 51 | -- distributed versions. Any such versions must be linked |
| 52 | -- together with a version of Fred Fish's debug code. |
| 53 | -- |
| 54 | -- NOTE: - in order to compile the code the include file stddef.h |
| 55 | -- must be shipped with the bundled code. |
| 56 | -- |
| 57 | -- AUTHOR |
| 58 | -- Dennis Vadura, dvadura@dmake.wticorp.com |
| 59 | -- |
| 60 | -- WWW |
| 61 | -- http://dmake.wticorp.com/ |
| 62 | -- |
| 63 | -- COPYRIGHT |
| 64 | -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved. |
| 65 | -- |
| 66 | -- This program is NOT free software; you can redistribute it and/or |
| 67 | -- modify it under the terms of the Software License Agreement Provided |
| 68 | -- in the file <distribution-root>/readme/license.txt. |
| 69 | -- |
| 70 | -- LOG |
| 71 | -- Use cvs log to obtain detailed change logs. |
| 72 | */ |
| 73 | |
| 74 | /* Set this flag to one, and the global variables in vextern.h will not |
| 75 | * be defined as 'extern', instead they will be defined as global vars |
| 76 | * when this module is compiled. */ |
| 77 | #define _DEFINE_GLOBALS_1 1 |
| 78 | |
| 79 | #include "extern.h" /* this includes config.h */ |
| 80 | #include "sysintf.h" |
| 81 | |
| 82 | #ifndef MSDOS |
| 83 | #define USAGE"Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n" \ |
| 84 | "Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n" |
| 85 | #define USAGE2"%s [-v[cdfimrtw]] [-m[trae]] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n" \ |
| 86 | "%s [-v[cdfimrtw]] [-m[trae]] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n" |
| 87 | #else |
| 88 | #define USAGE"Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n" \ |
| 89 | "Usage:\n%s [-P#] [-{f|C|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n" |
| 90 | #define USAGE2"%s [-v[cdfimrtw]] [-m[trae]] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n" \ |
| 91 | "%s [-v[cdfimrtw]] [-m[trae]] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n" |
| 92 | #endif |
| 93 | |
| 94 | /* We don't use va_end at all, so define it out so that it doesn't produce |
| 95 | * lots of "Value not used" warnings. */ |
| 96 | #ifdef va_end |
| 97 | #undef va_end |
| 98 | #endif |
| 99 | #define va_end(expand_to_null) |
| 100 | |
| 101 | /* Make certain that ARG macro is correctly defined. */ |
| 102 | #ifdef ARG |
| 103 | #undef ARG |
| 104 | #endif |
| 105 | #define ARG(a,b)a b a b |
| 106 | |
| 107 | static char *sccid = "Copyright (c) 1990,...,1997 by WTI Corp."; |
| 108 | static char _warn = TRUE1; /* warnings on by default */ |
| 109 | |
| 110 | static void _do_VPATH(); |
| 111 | static void _do_ReadEnvironment(); |
| 112 | #if !defined(__GNUC__4) && !defined(__IBMC__) |
| 113 | static void _do_f_flag ANSI((char, char *, char **))(char, char *, char **); |
| 114 | #else |
| 115 | static void _do_f_flag ANSI((int, char *, char **))(int, char *, char **); |
| 116 | #endif |
| 117 | |
| 118 | PUBLIC int |
| 119 | main(argc, argv) |
| 120 | int argc; |
| 121 | char **argv; |
| 122 | { |
| 123 | #ifdef MSDOS |
| 124 | char* std_fil_name = NIL(char)((char*)((void*)0)); |
| 125 | #endif |
| 126 | |
| 127 | char* fil_name = NIL(char)((char*)((void*)0)); |
| 128 | char* state_name = NIL(char)((char*)((void*)0)); |
| 129 | char* whatif = NIL(char)((char*)((void*)0)); |
| 130 | char* cmdmacs; |
| 131 | char* targets; |
| 132 | STRINGPTR cltarget = NIL(STRING)((STRING*)((void*)0)); /* list of targets from command line. */ |
| 133 | STRINGPTR cltarget_first = NIL(STRING)((STRING*)((void*)0)); /* Pointer to first element. */ |
| 134 | FILE* mkfil; |
| 135 | int ex_val; |
| 136 | int m_export; |
| 137 | |
| 138 | /* Uncomment the following line to pass commands to the DBUG engine |
| 139 | * before the command line switches (-#..) are evaluated. */ |
| 140 | /* |
| 141 | DB_PUSH("d,path"); |
| 142 | */ |
| 143 | DB_ENTER("main"); |
| 144 | |
| 145 | /* Initialize Global variables to their default values */ |
| 146 | Prolog(argc, argv); |
| 147 | /* Set internal macros to their initial values, some are changed |
| 148 | * later again by Make_rules() that parses the values from ruletab.c. */ |
| 149 | Create_macro_vars(); |
| 150 | Catch_signals(Quit); |
| 151 | |
| 152 | /* This macro is only defined for some OSs, see sysintf.c for details * |
| 153 | * and NULL if undefined. */ |
| 154 | Def_macro("ABSMAKECMD", AbsPname, M_PRECIOUS0x0002|M_NOEXPORT0x0040|M_EXPANDED0x0008 ); |
| 155 | |
| 156 | Def_macro( "MAKECMD", Pname, M_PRECIOUS0x0002|M_NOEXPORT0x0040|M_EXPANDED0x0008 ); |
| 157 | Pname = Basename(Pname); |
| 158 | |
| 159 | DB_PROCESS(Pname); |
| 160 | (void) setvbuf(stdoutstdout, NULL((void*)0), _IOLBF1, BUFSIZ8192); /* stdout line buffered */ |
| 161 | |
| 162 | Continue = FALSE0; |
| 163 | Comment = FALSE0; |
| 164 | Get_env = FALSE0; |
| 165 | Force = FALSE0; |
| 166 | Target = FALSE0; |
| 167 | If_expand = FALSE0; |
| 168 | Listing = FALSE0; |
| 169 | Readenv = FALSE0; |
| 170 | Rules = TRUE1; |
| 171 | Trace = FALSE0; |
| 172 | Touch = FALSE0; |
| 173 | Check = FALSE0; |
| 174 | Microsoft = FALSE0; |
| 175 | Makemkf = FALSE0; |
| 176 | UseWinpath= FALSE0; |
| 177 | No_exec = FALSE0; |
| 178 | m_export = FALSE0; |
| 179 | cmdmacs = NIL(char)((char*)((void*)0)); |
| 180 | targets = NIL(char)((char*)((void*)0)); |
| 181 | Is_exec_shell = FALSE0; |
| 182 | Shell_exec_target = NIL(CELL)((CELL*)((void*)0)); |
| 183 | stdout_redir = NIL(FILE)((FILE*)((void*)0)); |
| 184 | |
| 185 | /* Get fd for for @@-recipe silencing. */ |
| 186 | if( (zerofd = open(NULLDEV"/dev/null", O_WRONLY01)) == -1 ) |
| 187 | Fatal( "Error opening %s !", NULLDEV"/dev/null" ); |
| 188 | |
| 189 | Verbose = V_NOFLAG0x00; |
| 190 | Measure = M_NOFLAG0x00; |
| 191 | Transitive = TRUE1; |
| 192 | Nest_level = 0; |
| 193 | Line_number = 0; |
| 194 | Suppress_temp_file = FALSE0; |
| 195 | Skip_to_eof = FALSE0; |
| 196 | |
| 197 | while( --argc > 0 ) { |
| 198 | register char *p; |
| 199 | char *q; |
| 200 | |
| 201 | if( *(p = *++argv) == '-' ) { |
| 202 | if( p[1] == '\0' ) Fatal("Missing option letter"); |
| 203 | |
| 204 | /* copy options to Buffer for $(MFLAGS), strip 'f' and 'C'*/ |
| 205 | q = strchr(Buffer, '\0'); |
| 206 | while (*p != '\0') { |
| 207 | char c = (*q++ = *p++); |
| 208 | if( c == 'f' || c == 'C' ) q--; |
| 209 | } |
| 210 | |
| 211 | if( *(q-1) == '-' ) |
| 212 | q--; |
| 213 | else |
| 214 | *q++ = ' '; |
| 215 | |
| 216 | *q = '\0'; |
| 217 | |
| 218 | for( p = *argv+1; *p; p++) switch (*p) { |
| 219 | case 'f': |
| 220 | _do_f_flag( 'f', *++argv, &fil_name ); argc--; |
| 221 | break; |
| 222 | |
| 223 | #if defined(MSDOS) && !defined(OS2) |
| 224 | case 'C': |
| 225 | _do_f_flag( 'C', *++argv, &std_fil_name ); argc--; |
| 226 | Hook_std_writes( std_fil_name ); |
| 227 | break; |
| 228 | #endif |
| 229 | |
| 230 | case 'K': |
| 231 | _do_f_flag( 'K', *++argv, &state_name ); argc--; |
| 232 | Def_macro(".KEEP_STATE", state_name, M_EXPANDED0x0008|M_PRECIOUS0x0002); |
| 233 | break; |
| 234 | |
| 235 | case 'W': |
| 236 | case 'w': { |
| 237 | CELLPTR wif; |
| 238 | _do_f_flag( 'w', *++argv, &whatif ); argc--; |
| 239 | wif = Def_cell(whatif); |
| 240 | wif->ce_attr |= A_WHATIF0x04000000; |
| 241 | whatif = NIL(char)((char*)((void*)0)); |
| 242 | |
| 243 | if ( *p == 'W') |
| 244 | break; |
| 245 | } |
| 246 | /*FALLTHRU*/ |
| 247 | |
| 248 | case 'n': |
| 249 | Trace = TRUE1; |
| 250 | break; |
| 251 | |
| 252 | case 'k': Continue = TRUE1; break; |
| 253 | case 'c': Comment = TRUE1; break; |
| 254 | case 'p': Listing = TRUE1; break; |
| 255 | case 'r': Rules = FALSE0; break; |
| 256 | case 't': Touch = TRUE1; break; |
| 257 | case 'q': Check = TRUE1; break; |
| 258 | case 'u': Force = TRUE1; break; |
| 259 | case 'x': m_export = TRUE1; break; |
| 260 | case 'X': No_exec = TRUE1; break; |
| 261 | case 'T': Transitive = FALSE0; break; |
| 262 | case 'e': Get_env = 'e'; break; |
| 263 | case 'E': Get_env = 'E'; break; |
| 264 | |
| 265 | case 'V': Version(); Quit(0); break; |
| 266 | case 'A': Def_macro("AUGMAKE", "y", M_EXPANDED0x0008); break; |
| 267 | case 'B': Def_macro(".NOTABS", "y", M_EXPANDED0x0008); break; |
| 268 | case 'i': Def_macro(".IGNORE", "y", M_EXPANDED0x0008); break; |
| 269 | case 's': Def_macro(".SILENT", "y", M_EXPANDED0x0008); break; |
| 270 | case 'S': Def_macro(".SEQUENTIAL", "y", M_EXPANDED0x0008); break; |
| 271 | case 'g': Def_macro(".IGNOREGROUP","y", M_EXPANDED0x0008); break; |
| 272 | case 'd': Def_macro(".DIRCACHE",NIL(char)((char*)((void*)0)),M_EXPANDED0x0008); break; |
| 273 | |
| 274 | case 'v': |
| 275 | if( p[-1] != '-' ) Usage(TRUE1); |
| 276 | while( p[1] ) switch( *++p ) { |
| 277 | case 'c': Verbose |= V_DIR_CACHE0x04; break; |
| 278 | case 'd': Verbose |= V_DIR_SET0x02; break; |
| 279 | case 'f': Verbose |= V_FILE_IO0x20; break; |
| 280 | case 'i': Verbose |= V_INFER0x08; break; |
| 281 | case 'm': Verbose |= V_MAKE0x10; break; |
| 282 | case 'r': Verbose |= V_FORCEECHO0x80; break; |
| 283 | case 't': Verbose |= V_LEAVE_TMP0x01; break; |
| 284 | case 'w': Verbose |= V_WARNALL0x40; break; |
| 285 | |
| 286 | default: Usage(TRUE1); break; |
| 287 | } |
| 288 | if( !Verbose ) Verbose = V_ALL(0x01 | 0x02 | 0x08 | 0x10 | 0x20 | 0x04 | 0x40 | 0x80); |
| 289 | if( Verbose & V_FORCEECHO0x80 ) { |
| 290 | HASHPTR hp; |
| 291 | /* This cleans the .SILENT setting */ |
| 292 | hp = Def_macro(".SILENT", "", M_EXPANDED0x0008); |
| 293 | /* This overrides the bitmask for further occurrences of |
| 294 | * .SILENT to "no bits allowed", see bit variables in the |
| 295 | * set_macro_value() definition in dag.c. |
| 296 | * The bitmask is already set by Create_macro_vars() in |
| 297 | * imacs.c and is overridden for the V_FORCEECHO case. */ |
| 298 | hp->MV_MASKvar.mv_mask = A_DEFAULT0x00000; |
| 299 | } |
| 300 | break; |
| 301 | |
| 302 | case 'm': |
| 303 | if( p[-1] != '-' ) Usage(TRUE1); |
| 304 | while( p[1] ) switch( *++p ) { |
| 305 | case 't': Measure |= M_TARGET0x01; break; |
| 306 | case 'r': Measure |= M_RECIPE0x02; break; |
| 307 | case 'a': Measure |= M_ABSPATH0x04; break; |
| 308 | case 'e': Measure |= M_SHELLESC0x08; break; |
| 309 | |
| 310 | default: Usage(TRUE1); break; |
| 311 | } |
| 312 | if( !Measure ) Measure = M_TARGET0x01; |
| 313 | break; |
| 314 | |
| 315 | case 'P': |
| 316 | if( p[1] ) { |
| 317 | /* Only set MAXPROCESS if -S flag is *not* used. */ |
| 318 | if( !(Glob_attr & A_SEQ0x00200) ) { |
| 319 | Def_macro( "MAXPROCESS", p+1, M_MULTI0x0004|M_EXPANDED0x0008 ); |
| 320 | } |
| 321 | p += strlen(p)-1; |
| 322 | } |
| 323 | else |
| 324 | Fatal( "Missing number for -P flag" ); |
| 325 | break; |
| 326 | |
| 327 | #ifdef DBUG |
| 328 | case '#': |
| 329 | DB_PUSH(p+1); |
| 330 | p += strlen(p)-1; |
| 331 | break; |
| 332 | #endif |
| 333 | |
| 334 | case 'h': Usage(FALSE0); break; |
| 335 | case 0: break; /* lone - */ |
| 336 | default: Usage(TRUE1); break; |
| 337 | } |
| 338 | } |
| 339 | else if( (q = strchr(p, '=')) != NIL(char)((char*)((void*)0)) ) { |
| 340 | cmdmacs = DmStrAdd( cmdmacs, DmStrDup2(p), TRUE1 ); |
| 341 | /* Macros defined on the command line are marked precious. |
| 342 | * FIXME: The exception for += appears to be bogus. */ |
| 343 | Parse_macro( p, (q[-1]!='+')?M_PRECIOUS0x0002:M_DEFAULT0x0000 ); |
| 344 | } |
| 345 | else { |
| 346 | /* Remember the targets from the command line. */ |
| 347 | register STRINGPTR nsp; |
| 348 | |
| 349 | targets = DmStrAdd( targets, DmStrDup(p), TRUE1 ); |
| 350 | |
| 351 | TALLOC(nsp, 1, STRING)if ((nsp = (STRING*) calloc((unsigned int)(1), (size_t)sizeof (STRING))) == (STRING*)0) {No_ram();}; |
| 352 | nsp->st_string = DmStrDup( p ); |
| 353 | nsp->st_next = NIL(STRING)((STRING*)((void*)0)); |
| 354 | |
| 355 | if(cltarget != NIL(STRING)((STRING*)((void*)0)) ) |
| 356 | cltarget->st_next = nsp; |
| 357 | else |
| 358 | cltarget_first = nsp; |
| 359 | |
| 360 | cltarget = nsp; |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | Def_macro( "MAKEMACROS", cmdmacs, M_PRECIOUS0x0002|M_NOEXPORT0x0040 ); |
| 365 | Def_macro( "MAKETARGETS", targets, M_PRECIOUS0x0002|M_NOEXPORT0x0040 ); |
| 366 | if( cmdmacs != NIL(char)((char*)((void*)0)) ) FREE(cmdmacs)free((char*)(cmdmacs)); |
| 367 | if( targets != NIL(char)((char*)((void*)0)) ) FREE(targets)free((char*)(targets)); |
| 368 | |
| 369 | Def_macro( "MFLAGS", Buffer, M_PRECIOUS0x0002|M_NOEXPORT0x0040 ); |
| 370 | Def_macro( "%", "$@", M_PRECIOUS0x0002|M_NOEXPORT0x0040 ); |
| 371 | |
| 372 | if( *Buffer ) Def_macro( "MAKEFLAGS", Buffer+1, M_PRECIOUS0x0002|M_NOEXPORT0x0040 ); |
| 373 | |
| 374 | _warn = FALSE0; /* disable warnings for builtin rules */ |
| 375 | Target = TRUE1; /* make sure we don't mark any of the default rules as |
| 376 | * potential targets. */ |
| 377 | Make_rules(); /* Parse the strings stored in Rule_tab. */ |
| 378 | _warn = TRUE1; |
| 379 | |
| 380 | /* If -r was not given find and parse startup-makefile. */ |
| 381 | if( Rules ) |
| 382 | { |
| 383 | char *fname = NIL(char)((char*)((void*)0)); |
| 384 | |
| 385 | /* Search_file() also checks the environment variable. */ |
| 386 | if( (mkfil=Search_file("MAKESTARTUP", &fname)) != NIL(FILE)((FILE*)((void*)0)) ) |
| 387 | { |
| 388 | Parse(mkfil); |
| 389 | Def_macro( "MAKESTARTUP", fname, M_EXPANDED0x0008|M_MULTI0x0004|M_FORCE0x0080 ); |
| 390 | } |
| 391 | else |
| 392 | Fatal( "Configuration file `%s' not found", fname ); |
| 393 | if ( fname != NIL(char)((char*)((void*)0))) { FREE( fname )free((char*)(fname)); fname = NIL(char)((char*)((void*)0)); } |
| 394 | } |
| 395 | |
| 396 | /* Define the targets set on the command line now. */ |
| 397 | Target = FALSE0; /* Will be set to TRUE when the default targets are set. */ |
| 398 | for( cltarget = cltarget_first; cltarget != NIL(STRING)((STRING*)((void*)0)); ) { |
| 399 | CELLPTR cp; |
| 400 | STRINGPTR nta = cltarget->st_next; |
| 401 | |
| 402 | Add_prerequisite(Targets, cp = Def_cell(cltarget->st_string), |
| 403 | FALSE0, FALSE0); |
| 404 | cp->ce_flag |= F_TARGET0x0008; |
| 405 | cp->ce_attr |= A_FRINGE0x100000; |
| 406 | Target = TRUE1; |
| 407 | |
| 408 | FREE(cltarget->st_string)free((char*)(cltarget->st_string)); |
| 409 | FREE(cltarget)free((char*)(cltarget)); |
| 410 | cltarget = nta; |
| 411 | } |
| 412 | |
| 413 | if( Get_env == 'E' ) _do_ReadEnvironment(); |
| 414 | |
| 415 | /* Search for and parse user makefile. */ |
| 416 | if( fil_name != NIL(char)((char*)((void*)0)) ) |
| 417 | mkfil = Openfile( fil_name, FALSE0, TRUE1 ); |
| 418 | else { |
| 419 | /* Search .MAKEFILES dependent list looking for a makefile. |
| 420 | */ |
| 421 | register CELLPTR cp; |
| 422 | |
| 423 | cp = Def_cell( ".MAKEFILES" ); |
| 424 | mkfil = TryFiles(cp->CE_PRQce_prq); |
| 425 | } |
| 426 | |
| 427 | if( mkfil != NIL(FILE)((FILE*)((void*)0)) ) { |
| 428 | char *f = Filename(); |
| 429 | char *p; |
| 430 | |
| 431 | if( strcmp(f, "stdin") == 0 ) f = "-"; |
| 432 | Def_macro( "MAKEFILE", p = DmStrAdd( "-f", f, FALSE0 ), M_PRECIOUS0x0002|M_NOEXPORT0x0040 ); FREE(p)free((char*)(p)); |
| 433 | Parse( mkfil ); |
| 434 | } |
| 435 | else if( !Rules ) |
| 436 | Fatal( "No `makefile' present" ); |
| 437 | |
| 438 | if( Nest_level ) Fatal( "Missing .END for .IF" ); |
| 439 | if( Get_env == 'e' ) _do_ReadEnvironment(); |
| 440 | |
| 441 | _do_VPATH(); /* kludge it up with .SOURCE */ |
| 442 | |
| 443 | if( Listing ) Dump(); /* print out the structures */ |
| 444 | if( Trace ) Glob_attr &= ~A_SILENT0x00002; /* make sure we see the trace */ |
| 445 | |
| 446 | if( !Target ) |
| 447 | Fatal( "No target" ); |
| 448 | else { |
| 449 | Test_circle( Root, TRUE1 ); |
| 450 | Check_circle_dfa(); |
| 451 | } |
| 452 | |
| 453 | if( m_export ) { |
| 454 | int i; |
| 455 | |
| 456 | for( i=0; i<HASH_TABLE_SIZE200; ++i ) { |
| 457 | HASHPTR hp = Macs[i]; |
| 458 | |
| 459 | while( hp ) { |
| 460 | if( !(hp->ht_flag & M_NOEXPORT0x0040) && hp->ht_value != NIL(char)((char*)((void*)0)) ) |
| 461 | if( Write_env_string(hp->ht_name, hp->ht_value) != 0 ) |
| 462 | Warning( "Could not export %s", hp->ht_name ); |
| 463 | hp = hp->ht_next; |
| 464 | } |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | if( Buffer != NIL(char)((char*)((void*)0)) ) {FREE( Buffer )free((char*)(Buffer)); Buffer = NIL(char)((char*)((void*)0));} |
| 469 | if( Trace ) Def_macro(".SEQUENTIAL", "y", M_EXPANDED0x0008); |
| 470 | |
| 471 | ex_val = Make_targets(); |
| 472 | |
| 473 | Clear_signals(); |
| 474 | |
| 475 | /* Close fd for for @@-recipe silencing. */ |
| 476 | if( close(zerofd) ) |
| 477 | Fatal( "Error closing %s !", NULLDEV"/dev/null" ); |
| 478 | Epilog(ex_val); /* Does not return -- EVER */ |
| 479 | return 0; |
| 480 | } |
| 481 | |
| 482 | |
| 483 | static void |
| 484 | _do_f_flag( flag, name, fname ) |
| 485 | char flag; |
| 486 | char *name; |
| 487 | char **fname; |
| 488 | { |
| 489 | if( *fname == NIL(char)((char*)((void*)0)) ) { |
| 490 | if( name != NIL(char)((char*)((void*)0)) ) { |
| 491 | *fname = name; |
| 492 | } else |
| 493 | Fatal("No file name for -%c", flag); |
| 494 | } else |
| 495 | Fatal("Only one `-%c file' allowed", flag); |
| 496 | } |
| 497 | |
| 498 | |
| 499 | static void |
| 500 | _do_ReadEnvironment() |
| 501 | { |
| 502 | t_attr saveattr = Glob_attr; |
| 503 | |
| 504 | Glob_attr |= A_SILENT0x00002; |
| 505 | ReadEnvironment(); |
| 506 | Glob_attr = saveattr; |
| 507 | } |
| 508 | |
| 509 | |
| 510 | static void |
| 511 | _do_VPATH() |
| 512 | { |
| 513 | HASHPTR hp; |
| 514 | char *_rl[2]; |
| 515 | extern char **Rule_tab; |
| 516 | |
| 517 | hp = GET_MACRO("VPATH")Get_name("VPATH", Macs, 0); |
| 518 | if( hp == NIL(HASH)((HASH*)((void*)0)) ) return; |
| 519 | |
| 520 | _rl[0] = ".SOURCE :^ $(VPATH:s/:/ /)"; |
| 521 | _rl[1] = NIL(char)((char*)((void*)0)); |
| 522 | |
| 523 | Rule_tab = _rl; |
| 524 | Parse( NIL(FILE)((FILE*)((void*)0)) ); |
| 525 | } |
| 526 | |
| 527 | |
| 528 | /* The file table and pointer to the next FREE slot for use by both |
| 529 | Openfile and Closefile. Each open stacks the new file onto the open |
| 530 | file stack, and a corresponding close will close the passed file, and |
| 531 | return the next file on the stack. The maximum number of nested |
| 532 | include files is limited by the value of MAX_INC_DEPTH */ |
| 533 | |
| 534 | static struct { |
| 535 | FILE *file; /* file pointer */ |
| 536 | char *name; /* name of file */ |
| 537 | int numb; /* line number */ |
| 538 | } ftab[ MAX_INC_DEPTH10 ]; |
| 539 | |
| 540 | static int next_file_slot = 0; |
| 541 | |
| 542 | /* Set the proper macro value to reflect the depth of the .INCLUDE directives |
| 543 | * and the name of the file we are reading. |
| 544 | */ |
| 545 | static void |
| 546 | _set_inc_depth() |
| 547 | { |
| 548 | char buf[10]; |
| 549 | sprintf( buf, "%d", next_file_slot ); |
| 550 | Def_macro( "INCDEPTH", buf, M_MULTI0x0004|M_NOEXPORT0x0040 ); |
| 551 | Def_macro( "INCFILENAME", |
| 552 | next_file_slot ? ftab[next_file_slot-1].name : "", |
| 553 | M_MULTI0x0004|M_NOEXPORT0x0040|M_EXPANDED0x0008 ); |
| 554 | } |
| 555 | |
| 556 | |
| 557 | PUBLIC FILE * |
| 558 | Openfile(name, mode, err)/* |
| 559 | =========================== |
| 560 | This routine opens a file for input or output depending on mode. |
| 561 | If the file name is `-' then it returns standard input. |
| 562 | The file is pushed onto the open file stack. */ |
| 563 | char *name; |
| 564 | int mode; |
| 565 | int err; |
| 566 | { |
| 567 | FILE *fil; |
| 568 | |
| 569 | DB_ENTER("Openfile"); |
| 570 | |
| 571 | if( name == NIL(char)((char*)((void*)0)) || !*name ) { |
| 572 | if( !err ) |
| 573 | DB_RETURN(NIL(FILE))return (((FILE*)((void*)0))); |
| 574 | else |
| 575 | Fatal( "Openfile: NIL filename" ); |
| 576 | } |
| 577 | |
| 578 | if( next_file_slot == MAX_INC_DEPTH10 ) |
| 579 | Fatal( "Too many open files. Max nesting level is %d.", MAX_INC_DEPTH10); |
| 580 | |
| 581 | DB_PRINT( "io", ("Opening file [%s], in slot %d", name, next_file_slot) ); |
| 582 | |
| 583 | if( strcmp("-", name) == 0 ) { |
| 584 | name = "stdin"; |
| 585 | fil = stdinstdin; |
| 586 | } |
| 587 | else |
| 588 | fil = fopen( name, mode ? "w":"r" ); |
| 589 | |
| 590 | if( Verbose & V_FILE_IO0x20 ) |
| 591 | printf( "%s: Openning [%s] for %s", Pname, name, mode?"write":"read" ); |
| 592 | |
| 593 | if( fil == NIL(FILE)((FILE*)((void*)0)) ) { |
| 594 | if( Verbose & V_FILE_IO0x20 ) printf( " (fail)\n" ); |
| 595 | if( err ) |
| 596 | Fatal( mode ? "Cannot open file %s for write" : "File %s not found", |
| 597 | name ); |
| 598 | } |
| 599 | else { |
| 600 | if( Verbose & V_FILE_IO0x20 ) printf( " (success)\n" ); |
| 601 | ftab[next_file_slot].file = fil; |
| 602 | ftab[next_file_slot].numb = Line_number; |
| 603 | ftab[next_file_slot++].name = DmStrDup(name); |
| 604 | Line_number = 0; |
| 605 | _set_inc_depth(); |
| 606 | } |
| 607 | |
| 608 | DB_RETURN(fil)return (fil); |
| 609 | } |
| 610 | |
| 611 | |
| 612 | PUBLIC FILE * |
| 613 | Closefile()/* |
| 614 | ============= |
| 615 | This routine is used to close the last file opened. This forces make |
| 616 | to open files in a last open first close fashion. It returns the |
| 617 | file pointer to the next file on the stack, and NULL if the stack is empty.*/ |
| 618 | { |
| 619 | DB_ENTER("Closefile"); |
| 620 | |
| 621 | if( !next_file_slot ) |
| 622 | DB_RETURN( NIL(FILE) )return (((FILE*)((void*)0))); |
| 623 | |
| 624 | if( ftab[--next_file_slot].file != stdinstdin ) { |
| 625 | DB_PRINT( "io", ("Closing file in slot %d", next_file_slot) ); |
| 626 | |
| 627 | if( Verbose & V_FILE_IO0x20 ) |
| 628 | printf( "%s: Closing [%s]\n", Pname, ftab[next_file_slot].name ); |
| 629 | |
| 630 | fclose( ftab[next_file_slot].file ); |
| 631 | FREE( ftab[next_file_slot].name )free((char*)(ftab[next_file_slot].name)); |
| 632 | } |
| 633 | |
| 634 | _set_inc_depth(); |
| 635 | |
| 636 | if( next_file_slot > 0 ) { |
| 637 | Line_number = ftab[next_file_slot].numb; |
| 638 | DB_RETURN( ftab[next_file_slot-1].file )return (ftab[next_file_slot-1].file); |
| 639 | } |
| 640 | else |
| 641 | Line_number = 0; |
| 642 | |
| 643 | DB_RETURN( NIL(FILE) )return (((FILE*)((void*)0))); |
| 644 | } |
| 645 | |
| 646 | |
| 647 | PUBLIC FILE * |
| 648 | Search_file( macname, rname ) |
| 649 | char *macname; |
| 650 | char **rname; |
| 651 | { |
| 652 | HASHPTR hp; |
| 653 | FILE *fil = NIL(FILE)((FILE*)((void*)0)); |
| 654 | char *fname = NIL(char)((char*)((void*)0)); |
| 655 | char *ename = NIL(char)((char*)((void*)0)); |
| 656 | |
| 657 | /* order of precedence is: |
| 658 | * |
| 659 | * MACNAME from command line (precious is marked) |
| 660 | * ... via MACNAME:=filename definition. |
| 661 | * MACNAME from environment |
| 662 | * MACNAME from builtin rules (not precious) |
| 663 | */ |
| 664 | |
| 665 | if( (hp = GET_MACRO(macname)Get_name(macname, Macs, 0)) != NIL(HASH)((HASH*)((void*)0)) ) { |
| 666 | /* Only expand if needed. */ |
| 667 | if( hp->ht_flag & M_EXPANDED0x0008 ) { |
| 668 | ename = fname = DmStrDup(hp->ht_value); |
| 669 | } else { |
| 670 | ename = fname = Expand(hp->ht_value); |
| 671 | } |
| 672 | |
| 673 | if( hp->ht_flag & M_PRECIOUS0x0002 ) fil = Openfile(fname, FALSE0, FALSE0); |
| 674 | } |
| 675 | |
| 676 | if( fil == NIL(FILE)((FILE*)((void*)0)) ) { |
| 677 | fname=Expand(Read_env_string(macname)); |
| 678 | if( (fil = Openfile(fname, FALSE0, FALSE0)) != NIL(FILE)((FILE*)((void*)0)) ) FREE(ename)free((char*)(ename)); |
| 679 | } |
| 680 | |
| 681 | if( fil == NIL(FILE)((FILE*)((void*)0)) && hp != NIL(HASH)((HASH*)((void*)0)) ) { |
| 682 | if ( fname != NIL(char)((char*)((void*)0)) ) { FREE(fname)free((char*)(fname)); fname = NIL(char)((char*)((void*)0)); } |
Value stored to 'fname' is never read | |
| 683 | fil = Openfile(fname=ename, FALSE0, FALSE0); |
| 684 | } |
| 685 | |
| 686 | if( rname ) *rname = fname; |
| 687 | |
| 688 | return(fil); |
| 689 | } |
| 690 | |
| 691 | |
| 692 | PUBLIC char * |
| 693 | Filename()/* |
| 694 | ============ |
| 695 | Return name of file on top of stack */ |
| 696 | { |
| 697 | return( next_file_slot==0 ? NIL(char)((char*)((void*)0)) : ftab[next_file_slot-1].name ); |
| 698 | } |
| 699 | |
| 700 | |
| 701 | PUBLIC int |
| 702 | Nestlevel()/* |
| 703 | ============= |
| 704 | Return the file nesting level */ |
| 705 | { |
| 706 | return( next_file_slot ); |
| 707 | } |
| 708 | |
| 709 | |
| 710 | PUBLIC FILE * |
| 711 | TryFiles(lp)/* |
| 712 | ============== |
| 713 | Try to open a makefile, try to make it if needed and return a |
| 714 | filepointer to the first successful found or generated file. |
| 715 | The function returns NIL(FILE) if nothing was found. */ |
| 716 | LINKPTR lp; |
| 717 | { |
| 718 | FILE *mkfil = NIL(FILE)((FILE*)((void*)0)); |
| 719 | |
| 720 | if( lp != NIL(LINK)((LINK*)((void*)0)) ) { |
| 721 | int s_n, s_t, s_q; |
| 722 | |
| 723 | s_n = Trace; |
| 724 | s_t = Touch; |
| 725 | s_q = Check; |
| 726 | |
| 727 | Trace = Touch = Check = FALSE0; |
| 728 | /* We are making a makefile. Wait for it. */ |
| 729 | Makemkf = Wait_for_completion = TRUE1; |
| 730 | mkfil = NIL(FILE)((FILE*)((void*)0)); |
| 731 | |
| 732 | for(; lp != NIL(LINK)((LINK*)((void*)0)) && mkfil == NIL(FILE)((FILE*)((void*)0)); lp=lp->cl_next) { |
| 733 | if( lp->cl_prq->ce_attr & A_FRINGE0x100000 ) continue; |
| 734 | |
| 735 | mkfil = Openfile( lp->cl_prq->CE_NAMEce_name->ht_name, FALSE0, FALSE0 ); |
| 736 | |
| 737 | /* Note that no error handling for failed Make() calls is possible |
| 738 | * as expected errors (no rule to make the makefile) or unexpected |
| 739 | * errors both return -1. */ |
| 740 | if( mkfil == NIL(FILE)((FILE*)((void*)0)) && Make(lp->cl_prq, NIL(CELL)((CELL*)((void*)0))) != -1 ) { |
| 741 | mkfil = Openfile( lp->cl_prq->CE_NAMEce_name->ht_name, FALSE0, FALSE0 ); |
| 742 | /* Remove flags that indicate that the target was already made. |
| 743 | * This is also needed to avoid conflicts with the circular |
| 744 | * dependency check in rulparse(), see issues 62118 and 81296 |
| 745 | * for details. */ |
| 746 | Unmake(lp->cl_prq); |
| 747 | } |
| 748 | } |
| 749 | |
| 750 | Trace = s_n; |
| 751 | Touch = s_t; |
| 752 | Check = s_q; |
| 753 | Makemkf = Wait_for_completion = FALSE0; |
| 754 | } |
| 755 | |
| 756 | return(mkfil); |
| 757 | } |
| 758 | |
| 759 | |
| 760 | /* |
| 761 | ** print error message from variable arg list |
| 762 | */ |
| 763 | |
| 764 | static int errflg = TRUE1; |
| 765 | static int warnflg = FALSE0; |
| 766 | |
| 767 | static void |
| 768 | errargs(fmt, args) |
| 769 | char *fmt; |
| 770 | va_list args; |
| 771 | { |
| 772 | int warn = _warn && warnflg && !(Glob_attr & A_SILENT0x00002); |
| 773 | |
| 774 | if( errflg || warn ) { |
| 775 | char *f = Filename(); |
| 776 | |
| 777 | fprintf( stderrstderr, "%s: ", Pname ); |
| 778 | if( f != NIL(char)((char*)((void*)0)) ) fprintf(stderrstderr, "%s: line %d: ", f, Line_number); |
| 779 | |
| 780 | if( errflg ) |
| 781 | fprintf(stderrstderr, "Error: -- "); |
| 782 | else if( warn ) |
| 783 | fprintf(stderrstderr, "Warning: -- "); |
| 784 | |
| 785 | vfprintf( stderrstderr, fmt, args ); |
| 786 | putc( '\n', stderr )_IO_putc ('\n', stderr); |
| 787 | if( errflg && !Continue ) Quit(0); |
| 788 | } |
| 789 | } |
| 790 | |
| 791 | |
| 792 | /* |
| 793 | ** Print error message and abort |
| 794 | */ |
| 795 | PUBLIC void |
| 796 | Fatal(ARG(char *,fmt)char * fmt, ARG(va_alist_type,va_alist)...) |
| 797 | DARG(char *,fmt) |
| 798 | DARG(va_alist_type,va_alist) |
| 799 | { |
| 800 | va_list args; |
| 801 | |
| 802 | va_start(args, fmt)__builtin_va_start(args, fmt); |
| 803 | Continue = FALSE0; |
| 804 | errargs(fmt, args); |
| 805 | va_end(args); |
| 806 | } |
| 807 | |
| 808 | /* |
| 809 | ** error message and exit (unless -k) |
| 810 | */ |
| 811 | PUBLIC void |
| 812 | Error(ARG(char *,fmt)char * fmt, ARG(va_alist_type,va_alist)...) |
| 813 | DARG(char *,fmt) |
| 814 | DARG(va_alist_type,va_alist) |
| 815 | { |
| 816 | va_list args; |
| 817 | |
| 818 | va_start(args, fmt)__builtin_va_start(args, fmt); |
| 819 | errargs(fmt, args); |
| 820 | va_end(args); |
| 821 | } |
| 822 | |
| 823 | |
| 824 | /* |
| 825 | ** non-fatal message |
| 826 | */ |
| 827 | PUBLIC void |
| 828 | Warning(ARG(char *,fmt)char * fmt, ARG(va_alist_type,va_alist)...) |
| 829 | DARG(char *,fmt) |
| 830 | DARG(va_alist_type,va_alist) |
| 831 | { |
| 832 | va_list args; |
| 833 | |
| 834 | va_start(args, fmt)__builtin_va_start(args, fmt); |
| 835 | warnflg = TRUE1; |
| 836 | errflg = FALSE0; |
| 837 | errargs(fmt, args); |
| 838 | errflg = TRUE1; |
| 839 | warnflg = FALSE0; |
| 840 | va_end(args); |
| 841 | } |
| 842 | |
| 843 | |
| 844 | PUBLIC void |
| 845 | No_ram() |
| 846 | { |
| 847 | Fatal( "No more memory" ); |
| 848 | } |
| 849 | |
| 850 | |
| 851 | PUBLIC void |
| 852 | Usage( eflag ) |
| 853 | int eflag; |
| 854 | { |
| 855 | register char *p; |
| 856 | char *fill; |
| 857 | |
| 858 | fill = DmStrDup(Pname); |
| 859 | for(p=fill; *p; p++) *p=' '; |
| 860 | |
| 861 | if( eflag ) { |
| 862 | fprintf(stderrstderr, USAGE"Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n", Pname); |
| 863 | fprintf(stderrstderr, USAGE2"%s [-v[cdfimrtw]] [-m[trae]] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n", fill); |
| 864 | } |
| 865 | else { |
| 866 | printf(USAGE"Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n", Pname); |
| 867 | printf(USAGE2"%s [-v[cdfimrtw]] [-m[trae]] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n", fill); |
| 868 | puts(" -P# - set max number of child processes for parallel make"); |
| 869 | puts(" -f file - use file as the makefile"); |
| 870 | #ifdef MSDOS |
| 871 | puts(" -C [+]file - duplicate console output to file, ('+' => append)"); |
| 872 | #endif |
| 873 | puts(" -K file - use file as the .KEEP_STATE file"); |
| 874 | puts(" -w target - show what you would do if 'target' were out of date"); |
| 875 | puts(" -W target - rebuild pretending that 'target' is out of date"); |
| 876 | puts(" -v[cdfimrtw] - verbose, indicate what we are doing, (-v => -vcdfimrtw)"); |
| 877 | puts(" c => dump directory cache info only" ); |
| 878 | puts(" d => dump change of directory info only" ); |
| 879 | puts(" f => dump file open/close info only" ); |
| 880 | puts(" i => dump inference information only" ); |
| 881 | puts(" m => dump make of target information only" ); |
| 882 | puts(" r => Force output of recipe lines and warnings," ); |
| 883 | puts(" overrides -s" ); |
| 884 | puts(" t => keep temporary files when done" ); |
| 885 | puts(" w => issue non-essential warnings\n" ); |
| 886 | |
| 887 | puts(" -m[trae] - Measure timing information, (-m => -mt)"); |
| 888 | puts(" t => display the start and end time of each target" ); |
| 889 | puts(" r => display the start and end time of each recipe" ); |
| 890 | puts(" a => display the target as an absolute path" ); |
| 891 | puts(" e => display the timing of shell escape macros\n" ); |
| 892 | |
| 893 | puts("Options: (can be catenated, ie -irn == -i -r -n)"); |
| 894 | puts(" -A - enable AUGMAKE special target mapping"); |
| 895 | puts(" -B - enable the use of spaces instead of tabs to start recipes"); |
| 896 | puts(" -c - use non standard comment scanning"); |
| 897 | puts(" -d - do not use directory cache"); |
| 898 | puts(" -E - define environment strings as macros"); |
| 899 | puts(" -e - same as -E but done after parsing makefile"); |
| 900 | puts(" -g - disable the special meaning of [ ... ] for group recipes"); |
| 901 | puts(" -h - print out usage info"); |
| 902 | puts(" -i - ignore errors"); |
| 903 | puts(" -k - make independent targets, even if errors"); |
| 904 | puts(" -n - trace and print, do not execute commands"); |
| 905 | puts(" -p - print out a version of the makefile"); |
| 906 | puts(" -q - check if target is up to date. Does not do"); |
| 907 | puts(" anything. Returns 0 if up to date, 1 otherwise"); |
| 908 | puts(" -r - don't use internal rules"); |
| 909 | puts(" -s - do your work silently"); |
| 910 | puts(" -S - disable parallel (force sequential) make, overrides -P"); |
| 911 | puts(" -t - touch, update time stamps without executing commands"); |
| 912 | puts(" -T - do not apply transitive closure on inference rules"); |
| 913 | puts(" -u - force unconditional update of target"); |
| 914 | puts(" -V - print out version number"); |
| 915 | puts(" -x - export macro values to environment"); |
| 916 | puts(" -X - ignore #! lines at start of makefile"); |
| 917 | } |
| 918 | FREE(fill)free((char*)(fill)); |
| 919 | |
| 920 | Quit(0); |
| 921 | } |
| 922 | |
| 923 | |
| 924 | PUBLIC void |
| 925 | Version() |
| 926 | { |
| 927 | extern char **Rule_tab; |
| 928 | char **p; |
| 929 | |
| 930 | printf("%s - Version %s (%s)\n", Pname, VERSION"4.12", BUILDINFO"i686-pc-linux-gnu"); |
| 931 | printf("%s\n\n", sccid); |
| 932 | |
| 933 | puts("Default Configuration:"); |
| 934 | for (p=Rule_tab; *p != NIL(char)((char*)((void*)0)); p++) |
| 935 | printf("\t%s\n", *p); |
| 936 | |
| 937 | printf("\n"); |
| 938 | |
| 939 | #if defined(HAVE_SPAWN_H1) || defined(__CYGWIN__) |
| 940 | /* Only systems that have spawn ar concerned whether spawn or fork/exec |
| 941 | * are used. */ |
| 942 | #if ENABLE_SPAWN |
| 943 | printf("Subprocesses are executed using: spawn.\n\n"); |
| 944 | #else |
| 945 | printf("Subprocesses are executed using: fork/exec.\n\n"); |
| 946 | #endif |
| 947 | #endif |
| 948 | |
| 949 | printf("Please read the NEWS file for the latest release notes.\n"); |
| 950 | } |