GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: main.c,v 1.122 2017/04/20 03:04:11 dlg Exp $ */ |
||
2 |
/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ |
||
3 |
|||
4 |
/* |
||
5 |
* Copyright (c) 1988, 1989, 1990, 1993 |
||
6 |
* The Regents of the University of California. All rights reserved. |
||
7 |
* Copyright (c) 1989 by Berkeley Softworks |
||
8 |
* All rights reserved. |
||
9 |
* |
||
10 |
* This code is derived from software contributed to Berkeley by |
||
11 |
* Adam de Boor. |
||
12 |
* |
||
13 |
* Redistribution and use in source and binary forms, with or without |
||
14 |
* modification, are permitted provided that the following conditions |
||
15 |
* are met: |
||
16 |
* 1. Redistributions of source code must retain the above copyright |
||
17 |
* notice, this list of conditions and the following disclaimer. |
||
18 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
19 |
* notice, this list of conditions and the following disclaimer in the |
||
20 |
* documentation and/or other materials provided with the distribution. |
||
21 |
* 3. Neither the name of the University nor the names of its contributors |
||
22 |
* may be used to endorse or promote products derived from this software |
||
23 |
* without specific prior written permission. |
||
24 |
* |
||
25 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
26 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
27 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
28 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
29 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
30 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
31 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
32 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
33 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
34 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
35 |
* SUCH DAMAGE. |
||
36 |
*/ |
||
37 |
|||
38 |
#include <sys/param.h> /* MACHINE MACHINE_ARCH */ |
||
39 |
#include <sys/types.h> |
||
40 |
#include <sys/stat.h> |
||
41 |
#include <sys/utsname.h> |
||
42 |
#include <err.h> |
||
43 |
#include <errno.h> |
||
44 |
#include <stdio.h> |
||
45 |
#include <stdlib.h> |
||
46 |
#include <string.h> |
||
47 |
#include <unistd.h> |
||
48 |
#include "config.h" |
||
49 |
#include "defines.h" |
||
50 |
#include "var.h" |
||
51 |
#include "lowparse.h" |
||
52 |
#include "parse.h" |
||
53 |
#include "parsevar.h" |
||
54 |
#include "dir.h" |
||
55 |
#include "direxpand.h" |
||
56 |
#include "error.h" |
||
57 |
#include "pathnames.h" |
||
58 |
#include "init.h" |
||
59 |
#include "job.h" |
||
60 |
#include "compat.h" |
||
61 |
#include "targ.h" |
||
62 |
#include "suff.h" |
||
63 |
#include "str.h" |
||
64 |
#include "main.h" |
||
65 |
#include "lst.h" |
||
66 |
#include "memory.h" |
||
67 |
#include "make.h" |
||
68 |
#include "dump.h" |
||
69 |
|||
70 |
#define MAKEFLAGS ".MAKEFLAGS" |
||
71 |
|||
72 |
static LIST to_create; /* Targets to be made */ |
||
73 |
Lst create = &to_create; |
||
74 |
bool allPrecious; /* .PRECIOUS given on line by itself */ |
||
75 |
|||
76 |
static bool noBuiltins; /* -r flag */ |
||
77 |
static LIST makefiles; /* ordered list of makefiles to read */ |
||
78 |
static LIST varstoprint; /* list of variables to print */ |
||
79 |
int maxJobs; /* -j argument */ |
||
80 |
bool compatMake; /* -B argument */ |
||
81 |
static bool forceJobs = false; |
||
82 |
int debug; /* -d flag */ |
||
83 |
bool noExecute; /* -n flag */ |
||
84 |
bool keepgoing; /* -k flag */ |
||
85 |
bool queryFlag; /* -q flag */ |
||
86 |
bool touchFlag; /* -t flag */ |
||
87 |
bool ignoreErrors; /* -i flag */ |
||
88 |
bool beSilent; /* -s flag */ |
||
89 |
bool dumpData; /* -p flag */ |
||
90 |
|||
91 |
struct dirs { |
||
92 |
char *current; |
||
93 |
char *object; |
||
94 |
}; |
||
95 |
|||
96 |
static void MainParseArgs(int, char **); |
||
97 |
static void add_dirpath(Lst, const char *); |
||
98 |
static void usage(void); |
||
99 |
static void posixParseOptLetter(int); |
||
100 |
static void record_option(int, const char *); |
||
101 |
|||
102 |
static char *figure_out_MACHINE(void); |
||
103 |
static char *figure_out_MACHINE_ARCH(void); |
||
104 |
static char *figure_out_MACHINE_CPU(void); |
||
105 |
|||
106 |
static char *chdir_verify_path(const char *, struct dirs *); |
||
107 |
static char *figure_out_CURDIR(void); |
||
108 |
static void setup_CURDIR_OBJDIR(struct dirs *); |
||
109 |
|||
110 |
static void setup_VPATH(void); |
||
111 |
|||
112 |
static void read_all_make_rules(bool, bool, Lst, struct dirs *); |
||
113 |
static void read_makefile_list(Lst, struct dirs *); |
||
114 |
static bool ReadMakefile(void *, void *); |
||
115 |
|||
116 |
static void |
||
117 |
record_option(int c, const char *arg) |
||
118 |
{ |
||
119 |
102 |
char opt[3]; |
|
120 |
|||
121 |
51 |
opt[0] = '-'; |
|
122 |
51 |
opt[1] = c; |
|
123 |
51 |
opt[2] = '\0'; |
|
124 |
51 |
Var_Append(MAKEFLAGS, opt); |
|
125 |
✓✗ | 51 |
if (arg != NULL) |
126 |
51 |
Var_Append(MAKEFLAGS, arg); |
|
127 |
51 |
} |
|
128 |
|||
129 |
static void |
||
130 |
posixParseOptLetter(int c) |
||
131 |
{ |
||
132 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✓ |
2 |
switch(c) { |
133 |
case 'B': |
||
134 |
compatMake = true; |
||
135 |
return; /* XXX don't pass to submakes. */ |
||
136 |
case 'S': |
||
137 |
keepgoing = false; |
||
138 |
break; |
||
139 |
case 'e': |
||
140 |
Var_setCheckEnvFirst(true); |
||
141 |
break; |
||
142 |
case 'i': |
||
143 |
ignoreErrors = true; |
||
144 |
break; |
||
145 |
case 'k': |
||
146 |
keepgoing = true; |
||
147 |
break; |
||
148 |
case 'n': |
||
149 |
noExecute = true; |
||
150 |
break; |
||
151 |
case 'p': |
||
152 |
dumpData = true; |
||
153 |
break; |
||
154 |
case 'q': |
||
155 |
queryFlag = true; |
||
156 |
/* Kind of nonsensical, wot? */ |
||
157 |
break; |
||
158 |
case 'r': |
||
159 |
noBuiltins = true; |
||
160 |
break; |
||
161 |
case 's': |
||
162 |
beSilent = true; |
||
163 |
break; |
||
164 |
case 't': |
||
165 |
touchFlag = true; |
||
166 |
break; |
||
167 |
default: |
||
168 |
case '?': |
||
169 |
1 |
usage(); |
|
170 |
1 |
} |
|
171 |
record_option(c, NULL); |
||
172 |
} |
||
173 |
|||
174 |
/*- |
||
175 |
* MainParseArgs -- |
||
176 |
* Parse a given argument vector. Called from main() and from |
||
177 |
* Main_ParseArgLine() when the .MAKEFLAGS target is used. |
||
178 |
* |
||
179 |
* XXX: Deal with command line overriding .MAKEFLAGS in makefile |
||
180 |
* |
||
181 |
* Side Effects: |
||
182 |
* Various global and local flags will be set depending on the flags |
||
183 |
* given |
||
184 |
*/ |
||
185 |
static void |
||
186 |
MainParseArgs(int argc, char **argv) |
||
187 |
{ |
||
188 |
int c, optend; |
||
189 |
|||
190 |
#define OPTFLAGS "BC:D:I:SV:d:ef:ij:km:npqrst" |
||
191 |
#define OPTLETTERS "BSiknpqrst" |
||
192 |
|||
193 |
✗✓ | 132202 |
if (pledge("stdio rpath wpath cpath fattr proc exec flock", NULL) == -1) |
194 |
err(2, "pledge"); |
||
195 |
|||
196 |
66101 |
optind = 1; /* since we're called more than once */ |
|
197 |
66101 |
optreset = 1; |
|
198 |
optend = 0; |
||
199 |
✓✓ | 292815 |
while (optind < argc) { |
200 |
✓✗✓✓ |
321228 |
if (!optend && argv[optind][0] == '-') { |
201 |
✗✓ | 12377 |
if (argv[optind][1] == '\0') |
202 |
optind++; /* ignore "-" */ |
||
203 |
✗✓✗✗ |
12377 |
else if (argv[optind][1] == '-' && |
204 |
argv[optind][2] == '\0') { |
||
205 |
optind++; /* ignore "--" */ |
||
206 |
optend++; /* "--" denotes end of flags */ |
||
207 |
} |
||
208 |
} |
||
209 |
✓✗ | 662164 |
c = optend ? -1 : getopt(argc, argv, OPTFLAGS); |
210 |
✓✗✗✓ ✗✓✗✗ ✓✓ |
340936 |
switch (c) { |
211 |
case 'C': |
||
212 |
break; |
||
213 |
case 'D': |
||
214 |
Var_Set(optarg, "1"); |
||
215 |
record_option(c, optarg); |
||
216 |
break; |
||
217 |
case 'I': |
||
218 |
Parse_AddIncludeDir(optarg); |
||
219 |
record_option(c, optarg); |
||
220 |
break; |
||
221 |
case 'V': |
||
222 |
51 |
Lst_AtEnd(&varstoprint, optarg); |
|
223 |
51 |
record_option(c, optarg); |
|
224 |
51 |
break; |
|
225 |
case 'd': { |
||
226 |
char *modules = optarg; |
||
227 |
|||
228 |
for (; *modules; ++modules) |
||
229 |
switch (*modules) { |
||
230 |
case 'A': |
||
231 |
debug = ~0; |
||
232 |
break; |
||
233 |
case 'a': |
||
234 |
debug |= DEBUG_ARCH; |
||
235 |
break; |
||
236 |
case 'c': |
||
237 |
debug |= DEBUG_COND; |
||
238 |
break; |
||
239 |
case 'd': |
||
240 |
debug |= DEBUG_DIR; |
||
241 |
break; |
||
242 |
case 'D': |
||
243 |
debug |= DEBUG_DOUBLE; |
||
244 |
break; |
||
245 |
case 'e': |
||
246 |
debug |= DEBUG_EXPENSIVE; |
||
247 |
break; |
||
248 |
case 'f': |
||
249 |
debug |= DEBUG_FOR; |
||
250 |
break; |
||
251 |
case 'g': |
||
252 |
if (modules[1] == '1') { |
||
253 |
debug |= DEBUG_GRAPH1; |
||
254 |
++modules; |
||
255 |
} |
||
256 |
else if (modules[1] == '2') { |
||
257 |
debug |= DEBUG_GRAPH2; |
||
258 |
++modules; |
||
259 |
} |
||
260 |
break; |
||
261 |
case 'h': |
||
262 |
debug |= DEBUG_HELDJOBS; |
||
263 |
break; |
||
264 |
case 'j': |
||
265 |
debug |= DEBUG_JOB | DEBUG_KILL; |
||
266 |
break; |
||
267 |
case 'J': |
||
268 |
/* ignore */ |
||
269 |
break; |
||
270 |
case 'k': |
||
271 |
debug |= DEBUG_KILL; |
||
272 |
break; |
||
273 |
case 'l': |
||
274 |
debug |= DEBUG_LOUD; |
||
275 |
break; |
||
276 |
case 'm': |
||
277 |
debug |= DEBUG_MAKE; |
||
278 |
break; |
||
279 |
case 'n': |
||
280 |
debug |= DEBUG_NAME_MATCHING; |
||
281 |
break; |
||
282 |
case 'p': |
||
283 |
debug |= DEBUG_PARALLEL; |
||
284 |
break; |
||
285 |
case 'q': |
||
286 |
debug |= DEBUG_QUICKDEATH; |
||
287 |
break; |
||
288 |
case 's': |
||
289 |
debug |= DEBUG_SUFF; |
||
290 |
break; |
||
291 |
case 't': |
||
292 |
debug |= DEBUG_TARG; |
||
293 |
break; |
||
294 |
case 'T': |
||
295 |
debug |= DEBUG_TARGGROUP; |
||
296 |
break; |
||
297 |
case 'v': |
||
298 |
debug |= DEBUG_VAR; |
||
299 |
break; |
||
300 |
default: |
||
301 |
(void)fprintf(stderr, |
||
302 |
"make: illegal argument to -d option -- %c\n", |
||
303 |
*modules); |
||
304 |
usage(); |
||
305 |
} |
||
306 |
record_option(c, optarg); |
||
307 |
break; |
||
308 |
} |
||
309 |
case 'f': |
||
310 |
57 |
Lst_AtEnd(&makefiles, optarg); |
|
311 |
57 |
break; |
|
312 |
case 'j': { |
||
313 |
const char *errstr; |
||
314 |
|||
315 |
forceJobs = true; |
||
316 |
maxJobs = strtonum(optarg, 1, INT_MAX, &errstr); |
||
317 |
if (errstr != NULL) { |
||
318 |
fprintf(stderr, |
||
319 |
"make: illegal argument to -j option" |
||
320 |
" -- %s -- %s\n", optarg, errstr); |
||
321 |
usage(); |
||
322 |
} |
||
323 |
record_option(c, optarg); |
||
324 |
break; |
||
325 |
} |
||
326 |
case 'm': |
||
327 |
Dir_AddDir(systemIncludePath, optarg); |
||
328 |
record_option(c, optarg); |
||
329 |
break; |
||
330 |
case -1: |
||
331 |
/* Check for variable assignments and targets. */ |
||
332 |
✓✗✓✓ |
296474 |
if (argv[optind] != NULL && |
333 |
148237 |
!Parse_CmdlineVar(argv[optind])) { |
|
334 |
✗✓ | 33842 |
if (!*argv[optind]) |
335 |
Punt("illegal (null) argument."); |
||
336 |
33842 |
Lst_AtEnd(create, estrdup(argv[optind])); |
|
337 |
33842 |
} |
|
338 |
148237 |
optind++; /* skip over non-option */ |
|
339 |
148237 |
break; |
|
340 |
default: |
||
341 |
1 |
posixParseOptLetter(c); |
|
342 |
1 |
} |
|
343 |
} |
||
344 |
66100 |
} |
|
345 |
|||
346 |
static void |
||
347 |
MainParseChdir(int argc, char **argv) |
||
348 |
{ |
||
349 |
int c, optend, oldopterr; |
||
350 |
|||
351 |
68256 |
optind = 1; /* since we're called more than once */ |
|
352 |
34128 |
optreset = 1; |
|
353 |
optend = 0; |
||
354 |
34128 |
oldopterr = opterr; |
|
355 |
34128 |
opterr = 0; |
|
356 |
✓✓ | 138597 |
while (optind < argc) { |
357 |
✓✗✓✓ |
140690 |
if (!optend && argv[optind][0] == '-') { |
358 |
✗✓ | 12381 |
if (argv[optind][1] == '\0') |
359 |
optind++; /* ignore "-" */ |
||
360 |
✗✓✗✗ |
12381 |
else if (argv[optind][1] == '-' && |
361 |
argv[optind][2] == '\0') { |
||
362 |
optind++; /* ignore "--" */ |
||
363 |
optend++; /* "--" denotes end of flags */ |
||
364 |
} |
||
365 |
} |
||
366 |
✓✗ | 281267 |
c = optend ? -1 : getopt(argc, argv, OPTFLAGS); |
367 |
✓✓✓ | 140577 |
switch (c) { |
368 |
case 'C': |
||
369 |
✓✓ | 12272 |
if (chdir(optarg) == -1) |
370 |
err(2, "chdir(%s)", optarg); |
||
371 |
break; |
||
372 |
case -1: |
||
373 |
57964 |
optind++; /* skip over non-option */ |
|
374 |
57964 |
break; |
|
375 |
default: |
||
376 |
break; |
||
377 |
} |
||
378 |
} |
||
379 |
34124 |
opterr = oldopterr; |
|
380 |
34124 |
} |
|
381 |
|||
382 |
/*- |
||
383 |
* Main_ParseArgLine -- |
||
384 |
* Used by the parse module when a .MFLAGS or .MAKEFLAGS target |
||
385 |
* is encountered and by main() when reading the .MAKEFLAGS envariable. |
||
386 |
* Takes a line of arguments and breaks it into its |
||
387 |
* component words and passes those words and the number of them to the |
||
388 |
* MainParseArgs function. |
||
389 |
* The line should have all its leading whitespace removed. |
||
390 |
* |
||
391 |
* Side Effects: |
||
392 |
* Only those that come from the various arguments. |
||
393 |
*/ |
||
394 |
void |
||
395 |
Main_ParseArgLine(const char *line) /* Line to fracture */ |
||
396 |
{ |
||
397 |
char **argv; /* Manufactured argument vector */ |
||
398 |
68248 |
int argc; /* Number of arguments in argv */ |
|
399 |
34124 |
char *args; /* Space used by the args */ |
|
400 |
char *buf; |
||
401 |
char *argv0; |
||
402 |
const char *s; |
||
403 |
size_t len; |
||
404 |
|||
405 |
|||
406 |
✓✓ | 34124 |
if (line == NULL) |
407 |
272 |
return; |
|
408 |
✓✓ | 101542 |
for (; *line == ' '; ++line) |
409 |
continue; |
||
410 |
✓✓ | 33852 |
if (!*line) |
411 |
1875 |
return; |
|
412 |
|||
413 |
/* POSIX rule: MAKEFLAGS can hold a set of option letters without |
||
414 |
* any blanks or dashes. */ |
||
415 |
63881 |
for (s = line;; s++) { |
|
416 |
✗✓ | 63881 |
if (*s == '\0') { |
417 |
while (line != s) |
||
418 |
posixParseOptLetter(*line++); |
||
419 |
return; |
||
420 |
} |
||
421 |
✓✓ | 63881 |
if (strchr(OPTLETTERS, *s) == NULL) |
422 |
break; |
||
423 |
} |
||
424 |
31977 |
argv0 = Var_Value(".MAKE"); |
|
425 |
31977 |
len = strlen(line) + strlen(argv0) + 2; |
|
426 |
31977 |
buf = emalloc(len); |
|
427 |
31977 |
(void)snprintf(buf, len, "%s %s", argv0, line); |
|
428 |
|||
429 |
31977 |
argv = brk_string(buf, &argc, &args); |
|
430 |
31977 |
free(buf); |
|
431 |
31977 |
MainParseArgs(argc, argv); |
|
432 |
|||
433 |
31977 |
free(args); |
|
434 |
31977 |
free(argv); |
|
435 |
66101 |
} |
|
436 |
|||
437 |
/* Add a :-separated path to a Lst of directories. */ |
||
438 |
static void |
||
439 |
add_dirpath(Lst l, const char *n) |
||
440 |
{ |
||
441 |
const char *start; |
||
442 |
const char *cp; |
||
443 |
|||
444 |
68280 |
for (start = n;;) { |
|
445 |
✓✓✓✗ |
1401321 |
for (cp = start; *cp != '\0' && *cp != ':';) |
446 |
444347 |
cp++; |
|
447 |
34140 |
Dir_AddDiri(l, start, cp); |
|
448 |
✗✓ | 34140 |
if (*cp == '\0') |
449 |
break; |
||
450 |
else |
||
451 |
start= cp+1; |
||
452 |
} |
||
453 |
34140 |
} |
|
454 |
|||
455 |
/* |
||
456 |
* Get the name of this type of MACHINE from utsname so we can share an |
||
457 |
* executable for similar machines. (i.e. m68k: amiga hp300, mac68k, sun3, ...) |
||
458 |
* |
||
459 |
* Note that MACHINE, MACHINE_ARCH and MACHINE_CPU are decided at |
||
460 |
* run-time. |
||
461 |
*/ |
||
462 |
static char * |
||
463 |
figure_out_MACHINE() |
||
464 |
{ |
||
465 |
68256 |
char *r = getenv("MACHINE"); |
|
466 |
✓✗ | 34128 |
if (r == NULL) { |
467 |
static struct utsname utsname; |
||
468 |
|||
469 |
✗✓ | 34128 |
if (uname(&utsname) == -1) |
470 |
err(2, "uname"); |
||
471 |
r = utsname.machine; |
||
472 |
34128 |
} |
|
473 |
34128 |
return r; |
|
474 |
} |
||
475 |
|||
476 |
static char * |
||
477 |
figure_out_MACHINE_ARCH() |
||
478 |
{ |
||
479 |
68256 |
char *r = getenv("MACHINE_ARCH"); |
|
480 |
34128 |
if (r == NULL) { |
|
481 |
#ifndef MACHINE_ARCH |
||
482 |
r = "unknown"; /* XXX: no uname -p yet */ |
||
483 |
#else |
||
484 |
r = MACHINE_ARCH; |
||
485 |
#endif |
||
486 |
} |
||
487 |
34128 |
return r; |
|
488 |
} |
||
489 |
static char * |
||
490 |
figure_out_MACHINE_CPU() |
||
491 |
{ |
||
492 |
68256 |
char *r = getenv("MACHINE_CPU"); |
|
493 |
34128 |
if (r == NULL) { |
|
494 |
#if !defined(MACHINE_CPU) && ! defined(MACHINE_ARCH) |
||
495 |
r = "unknown"; /* XXX: no uname -p yet */ |
||
496 |
#else |
||
497 |
#if defined(MACHINE_CPU) |
||
498 |
r = MACHINE_CPU; |
||
499 |
#else |
||
500 |
r = MACHINE_ARCH; |
||
501 |
#endif |
||
502 |
#endif |
||
503 |
} |
||
504 |
34128 |
return r; |
|
505 |
} |
||
506 |
|||
507 |
static char * |
||
508 |
figure_out_CURDIR() |
||
509 |
{ |
||
510 |
char *dir, *cwd; |
||
511 |
68248 |
struct stat sa, sb; |
|
512 |
|||
513 |
/* curdir is cwd... */ |
||
514 |
34124 |
cwd = dogetcwd(); |
|
515 |
✗✓ | 34124 |
if (cwd == NULL) |
516 |
err(2, "%s", strerror(errno)); |
||
517 |
|||
518 |
✗✓ | 34124 |
if (stat(cwd, &sa) == -1) |
519 |
err(2, "%s: %s", cwd, strerror(errno)); |
||
520 |
|||
521 |
/* ...but we can use the alias $PWD if we can prove it is the same |
||
522 |
* directory */ |
||
523 |
✓✗ | 34124 |
if ((dir = getenv("PWD")) != NULL) { |
524 |
✓✗✓✓ ✓✗ |
90106 |
if (stat(dir, &sb) == 0 && sa.st_ino == sb.st_ino && |
525 |
21858 |
sa.st_dev == sb.st_dev) { |
|
526 |
21858 |
free(cwd); |
|
527 |
21858 |
return estrdup(dir); |
|
528 |
} |
||
529 |
} |
||
530 |
|||
531 |
12266 |
return cwd; |
|
532 |
34124 |
} |
|
533 |
|||
534 |
static char * |
||
535 |
chdir_verify_path(const char *path, struct dirs *d) |
||
536 |
{ |
||
537 |
✓✓ | 68248 |
if (chdir(path) == 0) { |
538 |
✓✗ | 8 |
if (path[0] != '/') |
539 |
8 |
return Str_concat(d->current, path, '/'); |
|
540 |
else |
||
541 |
return estrdup(path); |
||
542 |
} |
||
543 |
34116 |
return NULL; |
|
544 |
34124 |
} |
|
545 |
|||
546 |
static void |
||
547 |
setup_CURDIR_OBJDIR(struct dirs *d) |
||
548 |
{ |
||
549 |
char *path; |
||
550 |
|||
551 |
68248 |
d->current = figure_out_CURDIR(); |
|
552 |
/* |
||
553 |
* If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory |
||
554 |
* exists, change into it and build there. |
||
555 |
* |
||
556 |
* Once things are initted, |
||
557 |
* have to add the original directory to the search path, |
||
558 |
* and modify the paths for the Makefiles appropriately. The |
||
559 |
* current directory is also placed as a variable for make scripts. |
||
560 |
*/ |
||
561 |
34124 |
if ((path = getenv("MAKEOBJDIR")) == NULL) { |
|
562 |
path = _PATH_OBJDIR; |
||
563 |
} |
||
564 |
34124 |
d->object = chdir_verify_path(path, d); |
|
565 |
✓✓ | 34124 |
if (d->object == NULL) |
566 |
34116 |
d->object = d->current; |
|
567 |
34124 |
} |
|
568 |
|||
569 |
/* |
||
570 |
* if the VPATH variable is defined, add its contents to the search path. |
||
571 |
* Uses the same format as the PATH env variable, i.e., |
||
572 |
* <directory>:<directory>:<directory>... |
||
573 |
*/ |
||
574 |
static void |
||
575 |
setup_VPATH() |
||
576 |
{ |
||
577 |
✓✓ | 68244 |
if (Var_Value("VPATH") != NULL) { |
578 |
char *vpath; |
||
579 |
|||
580 |
17 |
vpath = Var_Subst("${VPATH}", NULL, false); |
|
581 |
17 |
add_dirpath(defaultPath, vpath); |
|
582 |
17 |
(void)free(vpath); |
|
583 |
17 |
} |
|
584 |
34122 |
} |
|
585 |
|||
586 |
static void |
||
587 |
read_makefile_list(Lst mk, struct dirs *d) |
||
588 |
{ |
||
589 |
LstNode ln; |
||
590 |
68360 |
ln = Lst_Find(mk, ReadMakefile, d); |
|
591 |
✗✓ | 34180 |
if (ln != NULL) |
592 |
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); |
||
593 |
34180 |
} |
|
594 |
|||
595 |
static void |
||
596 |
read_all_make_rules(bool noBuiltins, bool read_depend, |
||
597 |
Lst makefiles, struct dirs *d) |
||
598 |
{ |
||
599 |
/* |
||
600 |
* Read in the built-in rules first, followed by the specified |
||
601 |
* makefile(s), or the default Makefile or makefile, in that order. |
||
602 |
*/ |
||
603 |
✓✗ | 34123 |
if (!noBuiltins) { |
604 |
34123 |
LIST sysMkPath; /* Path of sys.mk */ |
|
605 |
|||
606 |
34123 |
Lst_Init(&sysMkPath); |
|
607 |
34123 |
Dir_Expand(_PATH_DEFSYSMK, systemIncludePath, &sysMkPath); |
|
608 |
✗✓ | 34123 |
if (Lst_IsEmpty(&sysMkPath)) |
609 |
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); |
||
610 |
|||
611 |
34123 |
read_makefile_list(&sysMkPath, d); |
|
612 |
34123 |
} |
|
613 |
|||
614 |
✓✓ | 34123 |
if (!Lst_IsEmpty(makefiles)) { |
615 |
57 |
read_makefile_list(makefiles, d); |
|
616 |
✓✗ | 34123 |
} else if (!ReadMakefile("makefile", d)) |
617 |
34066 |
(void)ReadMakefile("Makefile", d); |
|
618 |
|||
619 |
/* read a .depend file, if it exists, and we're not building depend */ |
||
620 |
|||
621 |
✓✓ | 34122 |
if (read_depend) |
622 |
33660 |
(void)ReadMakefile(".depend", d); |
|
623 |
34122 |
Parse_End(); |
|
624 |
34122 |
} |
|
625 |
|||
626 |
|||
627 |
int main(int, char **); |
||
628 |
/*- |
||
629 |
* main -- |
||
630 |
* The main function, for obvious reasons. Initializes variables |
||
631 |
* and a few modules, then parses the arguments give it in the |
||
632 |
* environment and on the command line. Reads the system makefile |
||
633 |
* followed by either Makefile, makefile or the file given by the |
||
634 |
* -f argument. Sets the .MAKEFLAGS PMake variable based on all the |
||
635 |
* flags it has received by then uses either the Make or the Compat |
||
636 |
* module to create the initial list of targets. |
||
637 |
* |
||
638 |
* Results: |
||
639 |
* If -q was given, exits -1 if anything was out-of-date. Else it exits |
||
640 |
* 0. |
||
641 |
* |
||
642 |
* Side Effects: |
||
643 |
* The program exits when done. Targets are created. etc. etc. etc. |
||
644 |
*/ |
||
645 |
int |
||
646 |
main(int argc, char **argv) |
||
647 |
{ |
||
648 |
static LIST targs; /* target nodes to create */ |
||
649 |
bool outOfDate = true; /* false if all targets up to date */ |
||
650 |
68252 |
char *machine = figure_out_MACHINE(); |
|
651 |
34124 |
char *machine_arch = figure_out_MACHINE_ARCH(); |
|
652 |
34124 |
char *machine_cpu = figure_out_MACHINE_CPU(); |
|
653 |
const char *syspath = _PATH_DEFSYSPATH; |
||
654 |
char *p; |
||
655 |
static struct dirs d; |
||
656 |
bool read_depend = true;/* false if we don't want to read .depend */ |
||
657 |
|||
658 |
34124 |
MainParseChdir(argc, argv); |
|
659 |
34124 |
setup_CURDIR_OBJDIR(&d); |
|
660 |
|||
661 |
34124 |
esetenv("PWD", d.object); |
|
662 |
34124 |
unsetenv("CDPATH"); |
|
663 |
|||
664 |
Static_Lst_Init(create); |
||
665 |
Static_Lst_Init(&makefiles); |
||
666 |
Static_Lst_Init(&varstoprint); |
||
667 |
Static_Lst_Init(&targs); |
||
668 |
|||
669 |
34124 |
beSilent = false; /* Print commands as executed */ |
|
670 |
34124 |
ignoreErrors = false; /* Pay attention to non-zero returns */ |
|
671 |
34124 |
noExecute = false; /* Execute all commands */ |
|
672 |
34124 |
keepgoing = false; /* Stop on error */ |
|
673 |
34124 |
allPrecious = false; /* Remove targets when interrupted */ |
|
674 |
34124 |
queryFlag = false; /* This is not just a check-run */ |
|
675 |
34124 |
noBuiltins = false; /* Read the built-in rules */ |
|
676 |
34124 |
touchFlag = false; /* Actually update targets */ |
|
677 |
34124 |
debug = 0; /* No debug verbosity, please. */ |
|
678 |
|||
679 |
34124 |
maxJobs = DEFMAXJOBS; |
|
680 |
34124 |
compatMake = false; /* No compat mode */ |
|
681 |
|||
682 |
|||
683 |
/* |
||
684 |
* Initialize all external modules. |
||
685 |
*/ |
||
686 |
34124 |
Init(); |
|
687 |
|||
688 |
✓✓ | 34124 |
if (d.object != d.current) |
689 |
8 |
Dir_AddDir(defaultPath, d.current); |
|
690 |
34124 |
Var_Set(".CURDIR", d.current); |
|
691 |
34124 |
Var_Set(".OBJDIR", d.object); |
|
692 |
34124 |
Parse_setcurdir(d.current); |
|
693 |
34124 |
Targ_setdirs(d.current, d.object); |
|
694 |
|||
695 |
/* |
||
696 |
* Initialize various variables. |
||
697 |
* MAKE also gets this name, for compatibility |
||
698 |
* .MAKEFLAGS gets set to the empty string just in case. |
||
699 |
* MFLAGS also gets initialized empty, for compatibility. |
||
700 |
*/ |
||
701 |
34124 |
Var_Set("MAKE", argv[0]); |
|
702 |
34124 |
Var_Set(".MAKE", argv[0]); |
|
703 |
34124 |
Var_Set(MAKEFLAGS, ""); |
|
704 |
34124 |
Var_Set("MFLAGS", ""); |
|
705 |
34124 |
Var_Set("MACHINE", machine); |
|
706 |
34124 |
Var_Set("MACHINE_ARCH", machine_arch); |
|
707 |
34124 |
Var_Set("MACHINE_CPU", machine_cpu); |
|
708 |
|||
709 |
/* |
||
710 |
* First snag any flags out of the MAKEFLAGS environment variable. |
||
711 |
*/ |
||
712 |
34124 |
Main_ParseArgLine(getenv("MAKEFLAGS")); |
|
713 |
|||
714 |
34124 |
basedirectory = getenv("MAKEBASEDIRECTORY"); |
|
715 |
✓✓ | 34124 |
if (basedirectory == NULL) |
716 |
272 |
setenv("MAKEBASEDIRECTORY", d.current, 0); |
|
717 |
|||
718 |
34123 |
MainParseArgs(argc, argv); |
|
719 |
|||
720 |
/* |
||
721 |
* Be compatible if user did not specify -j |
||
722 |
*/ |
||
723 |
✓✗ | 34123 |
if (!forceJobs) |
724 |
34123 |
compatMake = true; |
|
725 |
|||
726 |
/* And set up everything for sub-makes */ |
||
727 |
34123 |
Var_AddCmdline(MAKEFLAGS); |
|
728 |
|||
729 |
|||
730 |
/* |
||
731 |
* Set up the .TARGETS variable to contain the list of targets to be |
||
732 |
* created. If none specified, make the variable empty -- the parser |
||
733 |
* will fill the thing in with the default or .MAIN target. |
||
734 |
*/ |
||
735 |
✓✓ | 34123 |
if (!Lst_IsEmpty(create)) { |
736 |
LstNode ln; |
||
737 |
|||
738 |
✓✓ | 135318 |
for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) { |
739 |
33842 |
char *name = Lst_Datum(ln); |
|
740 |
|||
741 |
✓✓ | 33842 |
if (strcmp(name, "depend") == 0) |
742 |
462 |
read_depend = false; |
|
743 |
|||
744 |
33842 |
Var_Append(".TARGETS", name); |
|
745 |
} |
||
746 |
33817 |
} else |
|
747 |
306 |
Var_Set(".TARGETS", ""); |
|
748 |
|||
749 |
|||
750 |
/* |
||
751 |
* If no user-supplied system path was given (through the -m option) |
||
752 |
* add the directories from the DEFSYSPATH (more than one may be given |
||
753 |
* as dir1:...:dirn) to the system include path. |
||
754 |
*/ |
||
755 |
✓✗ | 34123 |
if (Lst_IsEmpty(systemIncludePath)) |
756 |
34123 |
add_dirpath(systemIncludePath, syspath); |
|
757 |
|||
758 |
34122 |
read_all_make_rules(noBuiltins, read_depend, &makefiles, &d); |
|
759 |
|||
760 |
34122 |
Var_Append("MFLAGS", Var_Value(MAKEFLAGS)); |
|
761 |
|||
762 |
/* Install all the flags into the MAKEFLAGS env variable. */ |
||
763 |
✓✗✓✗ |
68244 |
if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) |
764 |
34122 |
esetenv("MAKEFLAGS", p); |
|
765 |
|||
766 |
34122 |
setup_VPATH(); |
|
767 |
|||
768 |
34122 |
process_suffixes_after_makefile_is_read(); |
|
769 |
|||
770 |
✗✓ | 34122 |
if (dumpData) { |
771 |
dump_data(); |
||
772 |
exit(0); |
||
773 |
} |
||
774 |
|||
775 |
/* Print the initial graph, if the user requested it. */ |
||
776 |
✗✓ | 34122 |
if (DEBUG(GRAPH1)) |
777 |
dump_data(); |
||
778 |
|||
779 |
/* Print the values of any variables requested by the user. */ |
||
780 |
✓✓ | 34122 |
if (!Lst_IsEmpty(&varstoprint)) { |
781 |
LstNode ln; |
||
782 |
|||
783 |
✓✓ | 204 |
for (ln = Lst_First(&varstoprint); ln != NULL; |
784 |
51 |
ln = Lst_Adv(ln)) { |
|
785 |
51 |
char *value = Var_Value(Lst_Datum(ln)); |
|
786 |
|||
787 |
51 |
printf("%s\n", value ? value : ""); |
|
788 |
} |
||
789 |
51 |
} else { |
|
790 |
/* Have now read the entire graph and need to make a list |
||
791 |
* of targets to create. If none was given on the command |
||
792 |
* line, we consult the parsing module to find the main |
||
793 |
* target(s) to create. */ |
||
794 |
✓✓ | 34071 |
if (Lst_IsEmpty(create)) |
795 |
50 |
Parse_MainName(&targs); |
|
796 |
else |
||
797 |
34021 |
Targ_FindList(&targs, create); |
|
798 |
|||
799 |
34068 |
Job_Init(maxJobs); |
|
800 |
/* If the user has defined a .BEGIN target, execute the commands |
||
801 |
* attached to it. */ |
||
802 |
✓✗ | 34068 |
if (!queryFlag) |
803 |
34068 |
Job_Begin(); |
|
804 |
✓✗ | 34068 |
if (compatMake) |
805 |
/* Compat_Init will take care of creating all the |
||
806 |
* targets as well as initializing the module. */ |
||
807 |
34068 |
Compat_Run(&targs); |
|
808 |
else { |
||
809 |
/* Traverse the graph, checking on all the targets. */ |
||
810 |
outOfDate = Make_Run(&targs); |
||
811 |
} |
||
812 |
} |
||
813 |
|||
814 |
/* print the graph now it's been processed if the user requested it */ |
||
815 |
✗✓ | 33372 |
if (DEBUG(GRAPH2)) |
816 |
post_mortem(); |
||
817 |
|||
818 |
✗✓✗✗ |
33372 |
if (queryFlag && outOfDate) |
819 |
return 1; |
||
820 |
else |
||
821 |
33372 |
return 0; |
|
822 |
33372 |
} |
|
823 |
|||
824 |
/*- |
||
825 |
* ReadMakefile -- |
||
826 |
* Open and parse the given makefile. |
||
827 |
* |
||
828 |
* Results: |
||
829 |
* true if ok. false if couldn't open file. |
||
830 |
* |
||
831 |
* Side Effects: |
||
832 |
* lots |
||
833 |
*/ |
||
834 |
static bool |
||
835 |
ReadMakefile(void *p, void *q) |
||
836 |
{ |
||
837 |
const char *fname = p; /* makefile to read */ |
||
838 |
271958 |
struct dirs *d = q; |
|
839 |
FILE *stream; |
||
840 |
char *name; |
||
841 |
|||
842 |
✓✓ | 135979 |
if (!strcmp(fname, "-")) { |
843 |
39 |
Var_Set("MAKEFILE", ""); |
|
844 |
39 |
Parse_File(estrdup("(stdin)"), stdin); |
|
845 |
39 |
} else { |
|
846 |
✓✓ | 135940 |
if ((stream = fopen(fname, "r")) != NULL) |
847 |
goto found; |
||
848 |
/* if we've chdir'd, rebuild the path name */ |
||
849 |
✓✓✓✗ |
67762 |
if (d->current != d->object && *fname != '/') { |
850 |
char *path; |
||
851 |
|||
852 |
24 |
path = Str_concat(d->current, fname, '/'); |
|
853 |
✓✓ | 24 |
if ((stream = fopen(path, "r")) == NULL) |
854 |
16 |
free(path); |
|
855 |
else { |
||
856 |
fname = path; |
||
857 |
✓✓✓ | 8 |
goto found; |
858 |
} |
||
859 |
16 |
} |
|
860 |
/* look in -I and system include directories. */ |
||
861 |
67730 |
name = Dir_FindFile(fname, userIncludePath); |
|
862 |
✓✗ | 67730 |
if (!name) |
863 |
67730 |
name = Dir_FindFile(fname, systemIncludePath); |
|
864 |
✗✓✗✗ |
67730 |
if (!name || !(stream = fopen(name, "r"))) |
865 |
67730 |
return false; |
|
866 |
fname = name; |
||
867 |
/* |
||
868 |
* set the MAKEFILE variable desired by System V fans -- the |
||
869 |
* placement of the setting here means it gets set to the last |
||
870 |
* makefile specified, as it is set by SysV make. |
||
871 |
*/ |
||
872 |
68210 |
found: Var_Set("MAKEFILE", fname); |
|
873 |
68210 |
Parse_File(fname, stream); |
|
874 |
} |
||
875 |
68248 |
return true; |
|
876 |
135978 |
} |
|
877 |
|||
878 |
|||
879 |
/* |
||
880 |
* usage -- |
||
881 |
* exit with usage message |
||
882 |
*/ |
||
883 |
static void |
||
884 |
usage() |
||
885 |
{ |
||
886 |
1 |
(void)fprintf(stderr, |
|
887 |
"usage: make [-BeiknpqrSst] [-C directory] [-D variable] [-d flags] [-f mk]\n\ |
||
888 |
[-I directory] [-j max_processes] [-m directory] [-V variable]\n\ |
||
889 |
[NAME=value] [target ...]\n"); |
||
890 |
exit(2); |
||
891 |
} |
||
892 |
|||
893 |
Generated by: GCOVR (Version 3.3) |