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 | } |