Print this page
make: unifdef for TEAMWARE_MAKE_CMN (defined)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/doname.cc
+++ new/usr/src/cmd/make/bin/doname.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * doname.c
28 28 *
29 29 * Figure out which targets are out of date and rebuild them
30 30 */
31 31
32 32 /*
33 33 * Included files
34 34 */
35 35 #include <alloca.h> /* alloca() */
36 36
37 37
38 38 #include <fcntl.h>
39 39 #include <mk/defs.h>
40 40 #include <mksh/i18n.h> /* get_char_semantics_value() */
41 41 #include <mksh/macro.h> /* getvar(), expand_value() */
42 42 #include <mksh/misc.h> /* getmem() */
43 43 #include <poll.h>
44 44
45 45
46 46 #include <signal.h>
47 47
48 48 # include <stropts.h>
49 49
50 50 #include <sys/errno.h>
51 51 #include <sys/stat.h>
52 52 #include <sys/types.h>
53 53 #include <sys/utsname.h> /* uname() */
54 54 #include <sys/wait.h>
55 55 #include <unistd.h> /* close() */
56 56
57 57 /*
58 58 * Defined macros
59 59 */
60 60 # define LOCALHOST "localhost"
61 61
62 62 #define MAXRULES 100
63 63
64 64 #define SEND_MTOOL_MSG(cmds)
65 65
66 66 // Sleep for .1 seconds between stat()'s
67 67 const int STAT_RETRY_SLEEP_TIME = 100000;
68 68
69 69 /*
70 70 * typedefs & structs
71 71 */
72 72
73 73 /*
74 74 * Static variables
75 75 */
76 76 static char hostName[MAXNAMELEN] = "";
77 77 static char userName[MAXNAMELEN] = "";
78 78
79 79
80 80 static int second_pass = 0;
81 81
82 82 /*
83 83 * File table of contents
84 84 */
85 85 extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
86 86 extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
87 87 static Boolean check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals);
88 88 void dynamic_dependencies(Name target);
89 89 static Doname run_command(register Property line, Boolean print_machine);
90 90 extern Doname execute_serial(Property line);
91 91 extern Name vpath_translation(register Name cmd);
92 92 extern void check_state(Name temp_file_name);
93 93 static void read_dependency_file(register Name filename);
94 94 static void check_read_state_file(void);
95 95 static void do_assign(register Name line, register Name target);
96 96 static void build_command_strings(Name target, register Property line);
97 97 static Doname touch_command(register Property line, register Name target, Doname result);
98 98 extern void update_target(Property line, Doname result);
99 99 static Doname sccs_get(register Name target, register Property *command);
100 100 extern void read_directory_of_file(register Name file);
101 101 static void add_pattern_conditionals(register Name target);
102 102 extern void set_locals(register Name target, register Property old_locals);
103 103 extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
104 104 extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics);
105 105 static void delete_query_chain(Chain ch);
106 106
107 107 // From read2.cc
108 108 extern Name normalize_name(register wchar_t *name_string, register int length);
109 109
110 110
111 111
112 112 /*
113 113 * DONE.
114 114 *
115 115 * doname_check(target, do_get, implicit, automatic)
116 116 *
117 117 * Will call doname() and then inspect the return value
118 118 *
119 119 * Return value:
120 120 * Indication if the build failed or not
121 121 *
122 122 * Parameters:
123 123 * target The target to build
124 124 * do_get Passed thru to doname()
125 125 * implicit Passed thru to doname()
126 126 * automatic Are we building a hidden dependency?
127 127 *
128 128 * Global variables used:
129 129 * build_failed_seen Set if -k is on and error occurs
130 130 * continue_after_error Indicates that -k is on
131 131 * report_dependencies No error msg if -P is on
132 132 */
133 133 Doname
134 134 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
135 135 {
136 136 int first_time = 1;
137 137 (void) fflush(stdout);
138 138 try_again:
139 139 switch (doname(target, do_get, implicit, automatic)) {
140 140 case build_ok:
141 141 second_pass = 0;
142 142 return build_ok;
143 143 case build_running:
144 144 second_pass = 0;
145 145 return build_running;
146 146 case build_failed:
147 147 if (!continue_after_error) {
148 148 fatal(catgets(catd, 1, 13, "Target `%s' not remade because of errors"),
149 149 target->string_mb);
150 150 }
151 151 build_failed_seen = true;
152 152 second_pass = 0;
153 153 return build_failed;
154 154 case build_dont_know:
155 155 /*
156 156 * If we can't figure out how to build an automatic
157 157 * (hidden) dependency, we just ignore it.
158 158 * We later declare the target to be out of date just in
159 159 * case something changed.
160 160 * Also, don't complain if just reporting the dependencies
161 161 * and not building anything.
162 162 */
163 163 if (automatic || (report_dependencies_level > 0)) {
164 164 second_pass = 0;
165 165 return build_dont_know;
166 166 }
167 167 if(first_time) {
168 168 first_time = 0;
169 169 second_pass = 1;
170 170 goto try_again;
171 171 }
172 172 second_pass = 0;
173 173 if (continue_after_error && !svr4) {
174 174 warning(catgets(catd, 1, 14, "Don't know how to make target `%s'"),
175 175 target->string_mb);
176 176 build_failed_seen = true;
177 177 return build_failed;
178 178 }
179 179 fatal(catgets(catd, 1, 15, "Don't know how to make target `%s'"), target->string_mb);
180 180 break;
181 181 }
182 182 #ifdef lint
183 183 return build_failed;
184 184 #endif
185 185 }
186 186
187 187
188 188 void
189 189 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
190 190 {
191 191 Property line, source_line;
192 192 Dependency dependency;
193 193
194 194 source_line = get_prop(source->prop, line_prop);
195 195 line = maybe_append_prop(target, line_prop);
196 196 line->body.line.sccs_command = false;
197 197 line->body.line.target = target;
198 198 if (line->body.line.command_template == NULL) {
199 199 line->body.line.command_template = source_line->body.line.command_template;
200 200 for (dependency = source_line->body.line.dependencies;
201 201 dependency != NULL;
202 202 dependency = dependency->next) {
203 203 enter_dependency(line, dependency->name, false);
204 204 }
205 205 line->body.line.less = target;
206 206 }
207 207 line->body.line.percent = NULL;
208 208 }
209 209
210 210
211 211
212 212 Name
213 213 find_dyntarget(Name target)
214 214 {
215 215 Dyntarget p;
216 216 int i;
217 217 String_rec string;
218 218 wchar_t buffer[STRING_BUFFER_LENGTH];
219 219 wchar_t *pp, * bufend;
220 220 wchar_t tbuffer[MAXPATHLEN];
221 221 Wstring wcb(target);
222 222
223 223 for (p = dyntarget_list; p != NULL; p = p->next) {
224 224 INIT_STRING_FROM_STACK(string, buffer);
225 225 expand_value(p->name, &string, false);
226 226 i = 0;
227 227 pp = string.buffer.start;
228 228 bufend = pp + STRING_BUFFER_LENGTH;
229 229 while((*pp != nul_char) && (pp < bufend)) {
230 230 if(iswspace(*pp)) {
231 231 tbuffer[i] = nul_char;
232 232 if(i > 0) {
233 233 if (wcb.equal(tbuffer)) {
234 234 enter_explicit_rule_from_dynamic_rule(target, p->name);
235 235 return(target);
236 236 }
237 237 }
238 238 pp++;
239 239 i = 0;
240 240 continue;
241 241 }
242 242 tbuffer[i] = *pp;
243 243 i++;
244 244 pp++;
245 245 if(*pp == nul_char) {
246 246 tbuffer[i] = nul_char;
247 247 if(i > 0) {
248 248 if (wcb.equal(tbuffer)) {
249 249 enter_explicit_rule_from_dynamic_rule(target, p->name);
250 250 return(target);
251 251 }
252 252 }
253 253 break;
254 254 }
255 255 }
256 256 }
257 257 return(NULL);
258 258 }
259 259
260 260 /*
261 261 * DONE.
262 262 *
263 263 * doname(target, do_get, implicit)
264 264 *
265 265 * Chases all files the target depends on and builds any that
266 266 * are out of date. If the target is out of date it is then rebuilt.
267 267 *
268 268 * Return value:
269 269 * Indiates if build failed or nt
270 270 *
271 271 * Parameters:
272 272 * target Target to build
273 273 * do_get Run sccs get is nessecary
274 274 * implicit doname is trying to find an implicit rule
275 275 *
276 276 * Global variables used:
277 277 * assign_done True if command line assgnment has happened
278 278 * commands_done Preserved for the case that we need local value
279 279 * debug_level Should we trace make's actions?
280 280 * default_rule The rule for ".DEFAULT", used as last resort
281 281 * empty_name The Name "", used when looking for single sfx
↓ open down ↓ |
281 lines elided |
↑ open up ↑ |
282 282 * keep_state Indicates that .KEEP_STATE is on
283 283 * parallel True if building in parallel
284 284 * recursion_level Used for tracing
285 285 * report_dependencies make -P is on
286 286 */
287 287 Doname
288 288 doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
289 289 {
290 290 Doname result = build_dont_know;
291 291 Chain out_of_date_list = NULL;
292 -#ifdef TEAMWARE_MAKE_CMN
293 292 Chain target_group;
294 -#endif
295 293 Property old_locals = NULL;
296 294 register Property line;
297 295 Property command = NULL;
298 296 register Dependency dependency;
299 297 Name less = NULL;
300 298 Name true_target = target;
301 299 Name *automatics = NULL;
302 300 register int auto_count;
303 301 Boolean rechecking_target = false;
304 302 Boolean saved_commands_done;
305 303 Boolean restart = false;
306 304 Boolean save_parallel = parallel;
307 305 Boolean doing_subtree = false;
308 306
309 307 Boolean recheck_conditionals = false;
310 308
311 309 if (target->state == build_running) {
312 310 return build_running;
313 311 }
314 312 line = get_prop(target->prop, line_prop);
315 -#ifdef TEAMWARE_MAKE_CMN
316 313 if (line != NULL) {
317 314 /*
318 315 * If this target is a member of target group and one of the
319 316 * other members of the group is running, mark this target
320 317 * as running.
321 318 */
322 319 for (target_group = line->body.line.target_group;
323 320 target_group != NULL;
324 321 target_group = target_group->next) {
325 322 if (is_running(target_group->name)) {
326 323 target->state = build_running;
327 324 add_pending(target,
328 325 recursion_level,
329 326 do_get,
330 327 implicit,
331 328 false);
332 329 return build_running;
333 330 }
334 331 }
335 332 }
336 -#endif
337 333 /*
338 334 * If the target is a constructed one for a "::" target,
339 335 * we need to consider that.
340 336 */
341 337 if (target->has_target_prop) {
342 338 true_target = get_prop(target->prop,
343 339 target_prop)->body.target.target;
344 340 if (true_target->colon_splits > 0) {
345 341 /* Make sure we have a valid time for :: targets */
346 342 Property time;
347 343
348 344 time = get_prop(true_target->prop, time_prop);
349 345 if (time != NULL) {
350 346 true_target->stat.time = time->body.time.time;
351 347 }
352 348 }
353 349 }
354 350 (void) exists(true_target);
355 351 /*
356 352 * If the target has been processed, we don't need to do it again,
357 353 * unless it depends on conditional macros or a delayed assignment,
358 354 * or it has been done when KEEP_STATE is on.
359 355 */
360 356 if (target->state == build_ok) {
361 357 if((!keep_state || (!target->depends_on_conditional && !assign_done))) {
362 358 return build_ok;
363 359 } else {
364 360 recheck_conditionals = true;
365 361 }
366 362 }
367 363 if (target->state == build_subtree) {
368 364 /* A dynamic macro subtree is being built */
369 365 target->state = build_dont_know;
370 366 doing_subtree = true;
371 367 if (!target->checking_subtree) {
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
372 368 /*
373 369 * This target has been started before and therefore
374 370 * not all dependencies have to be built.
375 371 */
376 372 restart = true;
377 373 }
378 374 } else if (target->state == build_pending) {
379 375 target->state = build_dont_know;
380 376 restart = true;
381 377 /*
382 -#ifdef TEAMWARE_MAKE_CMN
383 378 } else if (parallel &&
384 379 keep_state &&
385 380 (target->conditional_cnt > 0)) {
386 381 if (!parallel_ok(target, false)) {
387 382 add_subtree(target, recursion_level, do_get, implicit);
388 383 target->state = build_running;
389 384 return build_running;
390 385 }
391 -#endif
392 386 */
393 387 }
394 388 /*
395 389 * If KEEP_STATE is on, we have to rebuild the target if the
396 390 * building of it caused new automatic dependencies to be reported.
397 391 * This is where we restart the build.
398 392 */
399 393 if (line != NULL) {
400 394 line->body.line.percent = NULL;
401 395 }
402 396 recheck_target:
403 397 /* Init all local variables */
404 398 result = build_dont_know;
405 399 out_of_date_list = NULL;
406 400 command = NULL;
407 401 less = NULL;
408 402 auto_count = 0;
409 403 if (!restart && line != NULL) {
410 404 /*
411 405 * If this target has never been built before, mark all
412 406 * of the dependencies as never built.
413 407 */
414 408 for (dependency = line->body.line.dependencies;
415 409 dependency != NULL;
416 410 dependency = dependency->next) {
417 411 dependency->built = false;
418 412 }
419 413 }
420 414 /* Save the set of automatic depes defined for this target */
421 415 if (keep_state &&
422 416 (line != NULL) &&
423 417 (line->body.line.dependencies != NULL)) {
424 418 Name *p;
425 419
426 420 /*
427 421 * First run thru the dependency list to see how many
428 422 * autos there are.
429 423 */
430 424 for (dependency = line->body.line.dependencies;
431 425 dependency != NULL;
432 426 dependency = dependency->next) {
433 427 if (dependency->automatic && !dependency->stale) {
434 428 auto_count++;
435 429 }
436 430 }
437 431 /* Create vector to hold the current autos */
438 432 automatics =
439 433 (Name *) alloca((int) (auto_count * sizeof (Name)));
440 434 /* Copy them */
441 435 for (p = automatics, dependency = line->body.line.dependencies;
442 436 dependency != NULL;
443 437 dependency = dependency->next) {
444 438 if (dependency->automatic && !dependency->stale) {
445 439 *p++ = dependency->name;
446 440 }
447 441 }
448 442 }
449 443 if (debug_level > 1) {
450 444 (void) printf(NOCATGETS("%*sdoname(%s)\n"),
451 445 recursion_level,
452 446 "",
453 447 target->string_mb);
454 448 }
455 449 recursion_level++;
456 450 /* Avoid infinite loops */
457 451 if (target->state == build_in_progress) {
458 452 warning(catgets(catd, 1, 16, "Infinite loop: Target `%s' depends on itself"),
459 453 target->string_mb);
460 454 return build_ok;
461 455 }
462 456 target->state = build_in_progress;
463 457
464 458 /* Activate conditional macros for the target */
465 459 if (!target->added_pattern_conditionals) {
466 460 add_pattern_conditionals(target);
467 461 target->added_pattern_conditionals = true;
468 462 }
469 463 if (target->conditional_cnt > 0) {
470 464 old_locals = (Property) alloca(target->conditional_cnt *
471 465 sizeof (Property_rec));
472 466 set_locals(target, old_locals);
473 467 }
474 468
475 469 /*
476 470 * after making the call to dynamic_dependecies unconditional we can handle
477 471 * target names that are same as file name. In this case $$@ in the
478 472 * dependencies did not mean anything. WIth this change it expands it
479 473 * as expected.
480 474 */
481 475 if (!target->has_depe_list_expanded)
482 476 {
483 477 dynamic_dependencies(target);
484 478 }
485 479
486 480 /*
487 481 * FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT
488 482 * COMMANDS TO RUN
489 483 */
490 484 if ((line = get_prop(target->prop, line_prop)) != NULL) {
491 485 if (check_dependencies(&result,
492 486 line,
493 487 do_get,
494 488 target,
495 489 true_target,
496 490 doing_subtree,
497 491 &out_of_date_list,
498 492 old_locals,
499 493 implicit,
500 494 &command,
501 495 less,
502 496 rechecking_target,
503 497 recheck_conditionals)) {
504 498 return build_running;
505 499 }
506 500 if (line->body.line.query != NULL) {
507 501 delete_query_chain(line->body.line.query);
508 502 }
509 503 line->body.line.query = out_of_date_list;
510 504 }
511 505
512 506
513 507 /*
514 508 * If the target is a :: type, do not try to find the rule for the target,
515 509 * all actions will be taken by separate branches.
516 510 * Else, we try to find an implicit rule using various methods,
517 511 * we quit as soon as one is found.
518 512 *
519 513 * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target
520 514 * being rechecked - the target is being rechecked means that it already
521 515 * has explicit dependencies derived from an implicit rule found
522 516 * in previous step.
523 517 */
524 518 if (target->colon_splits == 0 && !rechecking_target) {
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
525 519 /* Look for percent matched rule */
526 520 if ((result == build_dont_know) &&
527 521 (command == NULL)) {
528 522 switch (find_percent_rule(
529 523 target,
530 524 &command,
531 525 recheck_conditionals)) {
532 526 case build_failed:
533 527 result = build_failed;
534 528 break;
535 -#ifdef TEAMWARE_MAKE_CMN
536 529 case build_running:
537 530 target->state = build_running;
538 531 add_pending(target,
539 532 --recursion_level,
540 533 do_get,
541 534 implicit,
542 535 false);
543 536 if (target->conditional_cnt > 0) {
544 537 reset_locals(target,
545 538 old_locals,
546 539 get_prop(target->prop,
547 540 conditional_prop),
548 541 0);
549 542 }
550 543 return build_running;
551 -#endif
552 544 case build_ok:
553 545 result = build_ok;
554 546 break;
555 547 }
556 548 }
557 549 /* Look for double suffix rule */
558 550 if (result == build_dont_know) {
559 551 Property member;
560 552
561 553 if (target->is_member &&
562 554 ((member = get_prop(target->prop, member_prop)) !=
563 555 NULL)) {
564 556 switch (find_ar_suffix_rule(target,
565 557 member->body.
566 558 member.member,
567 559 &command,
568 560 recheck_conditionals)) {
569 561 case build_failed:
570 562 result = build_failed;
571 563 break;
572 -#ifdef TEAMWARE_MAKE_CMN
573 564 case build_running:
574 565 target->state = build_running;
575 566 add_pending(target,
576 567 --recursion_level,
577 568 do_get,
578 569 implicit,
579 570 false);
580 571 if (target->conditional_cnt > 0) {
581 572 reset_locals(target,
582 573 old_locals,
583 574 get_prop(target->prop,
584 575 conditional_prop),
585 576 0);
586 577 }
587 578 return build_running;
588 -#endif
589 579 default:
590 580 /* ALWAYS bind $% for old style */
591 581 /* ar rules */
592 582 if (line == NULL) {
593 583 line =
594 584 maybe_append_prop(target,
595 585 line_prop);
596 586 }
597 587 line->body.line.percent =
598 588 member->body.member.member;
599 589 break;
600 590 }
601 591 } else {
602 592 switch (find_double_suffix_rule(target,
603 593 &command,
604 594 recheck_conditionals)) {
605 595 case build_failed:
606 596 result = build_failed;
607 597 break;
608 -#ifdef TEAMWARE_MAKE_CMN
609 598 case build_running:
610 599 target->state = build_running;
611 600 add_pending(target,
612 601 --recursion_level,
613 602 do_get,
614 603 implicit,
615 604 false);
616 605 if (target->conditional_cnt > 0) {
617 606 reset_locals(target,
618 607 old_locals,
619 608 get_prop(target->
620 609 prop,
621 610 conditional_prop),
622 611 0);
623 612 }
624 613 return build_running;
625 -#endif
626 614 }
627 615 }
628 616 }
629 617 /* Look for single suffix rule */
630 618
631 619 /* /tolik/
632 620 * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
633 621 * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc"
634 622 */
635 623 /* /tolik, 06.21.96/
636 624 * Regression! See BugId 1255360
637 625 * If more than one percent rules are defined for the same target then
638 626 * the behaviour of 'make' with my previous fix may be different from one
639 627 * of the 'old make'.
640 628 * The global variable second_pass (maybe it should be an argument to doname())
641 629 * is intended to avoid this regression. It is set in doname_check().
642 630 * First, 'make' will work as it worked before. Only when it is
643 631 * going to say "don't know how to make target" it sets second_pass to true and
644 632 * run 'doname' again but now trying to use Single Suffix Rules.
645 633 */
646 634 if ((result == build_dont_know) && !automatic && (!implicit || second_pass) &&
647 635 ((line == NULL) ||
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
648 636 ((line->body.line.target != NULL) &&
649 637 !line->body.line.target->has_regular_dependency))) {
650 638 switch (find_suffix_rule(target,
651 639 target,
652 640 empty_name,
653 641 &command,
654 642 recheck_conditionals)) {
655 643 case build_failed:
656 644 result = build_failed;
657 645 break;
658 -#ifdef TEAMWARE_MAKE_CMN
659 646 case build_running:
660 647 target->state = build_running;
661 648 add_pending(target,
662 649 --recursion_level,
663 650 do_get,
664 651 implicit,
665 652 false);
666 653 if (target->conditional_cnt > 0) {
667 654 reset_locals(target,
668 655 old_locals,
669 656 get_prop(target->prop,
670 657 conditional_prop),
671 658 0);
672 659 }
673 660 return build_running;
674 -#endif
675 661 }
676 662 }
677 663 /* Try to sccs get */
678 664 if ((command == NULL) &&
679 665 (result == build_dont_know) &&
680 666 do_get) {
681 667 result = sccs_get(target, &command);
682 668 }
683 669
684 670 /* Use .DEFAULT rule if it is defined. */
685 671 if ((command == NULL) &&
686 672 (result == build_dont_know) &&
687 673 (true_target->colons == no_colon) &&
688 674 default_rule &&
689 675 !implicit) {
690 676 /* Make sure we have a line prop */
691 677 line = maybe_append_prop(target, line_prop);
692 678 command = line;
693 679 Boolean out_of_date;
694 680 if (true_target->is_member) {
695 681 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
696 682 line->body.line.dependency_time);
697 683 } else {
698 684 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
699 685 line->body.line.dependency_time);
700 686 }
701 687 if (build_unconditional || out_of_date) {
702 688 line->body.line.is_out_of_date = true;
703 689 if (debug_level > 0) {
704 690 (void) printf(catgets(catd, 1, 17, "%*sBuilding %s using .DEFAULT because it is out of date\n"),
705 691 recursion_level,
706 692 "",
707 693 true_target->string_mb);
708 694 }
709 695 }
710 696 line->body.line.sccs_command = false;
711 697 line->body.line.command_template = default_rule;
712 698 line->body.line.target = true_target;
713 699 line->body.line.star = NULL;
714 700 line->body.line.less = true_target;
715 701 line->body.line.percent = NULL;
716 702 }
717 703 }
718 704
719 705 /* We say "target up to date" if no cmd were executed for the target */
720 706 if (!target->is_double_colon_parent) {
721 707 commands_done = false;
722 708 }
723 709
724 710 silent = silent_all;
725 711 ignore_errors = ignore_errors_all;
726 712 if (posix)
727 713 {
728 714 if (!silent)
729 715 {
730 716 silent = (Boolean) target->silent_mode;
731 717 }
732 718 if (!ignore_errors)
733 719 {
734 720 ignore_errors = (Boolean) target->ignore_error_mode;
735 721 }
736 722 }
737 723
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
738 724 int doname_dyntarget = 0;
739 725 r_command:
740 726 /* Run commands if any. */
741 727 if ((command != NULL) &&
742 728 (command->body.line.command_template != NULL)) {
743 729 if (result != build_failed) {
744 730 result = run_command(command,
745 731 (Boolean) ((parallel || save_parallel) && !silent));
746 732 }
747 733 switch (result) {
748 -#ifdef TEAMWARE_MAKE_CMN
749 734 case build_running:
750 735 add_running(target,
751 736 true_target,
752 737 command,
753 738 --recursion_level,
754 739 auto_count,
755 740 automatics,
756 741 do_get,
757 742 implicit);
758 743 target->state = build_running;
759 744 if ((line = get_prop(target->prop,
760 745 line_prop)) != NULL) {
761 746 if (line->body.line.query != NULL) {
762 747 delete_query_chain(line->body.line.query);
763 748 }
764 749 line->body.line.query = NULL;
765 750 }
766 751 if (target->conditional_cnt > 0) {
767 752 reset_locals(target,
768 753 old_locals,
769 754 get_prop(target->prop,
770 755 conditional_prop),
771 756 0);
772 757 }
773 758 return build_running;
774 759 case build_serial:
775 760 add_serial(target,
776 761 --recursion_level,
777 762 do_get,
778 763 implicit);
779 764 target->state = build_running;
780 765 line = get_prop(target->prop, line_prop);
781 766 if (line != NULL) {
782 767 if (line->body.line.query != NULL) {
783 768 delete_query_chain(line->body.line.query);
784 769 }
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
785 770 line->body.line.query = NULL;
786 771 }
787 772 if (target->conditional_cnt > 0) {
788 773 reset_locals(target,
789 774 old_locals,
790 775 get_prop(target->prop,
791 776 conditional_prop),
792 777 0);
793 778 }
794 779 return build_running;
795 -#endif
796 780 case build_ok:
797 781 /* If all went OK set a nice timestamp */
798 782 if (true_target->stat.time == file_doesnt_exist) {
799 783 true_target->stat.time = file_max_time;
800 784 }
801 785 break;
802 786 }
803 787 } else {
804 788 /*
805 789 * If no command was found for the target, and it doesn't
806 790 * exist, and it is mentioned as a target in the makefile,
807 791 * we say it is extremely new and that it is OK.
808 792 */
809 793 if (target->colons != no_colon) {
810 794 if (true_target->stat.time == file_doesnt_exist){
811 795 true_target->stat.time = file_max_time;
812 796 }
813 797 result = build_ok;
814 798 }
815 799 /*
816 800 * Trying dynamic targets.
817 801 */
818 802 if(!doname_dyntarget) {
819 803 doname_dyntarget = 1;
820 804 Name dtarg = find_dyntarget(target);
821 805 if(dtarg!=NULL) {
822 806 if (!target->has_depe_list_expanded) {
823 807 dynamic_dependencies(target);
824 808 }
825 809 if ((line = get_prop(target->prop, line_prop)) != NULL) {
826 810 if (check_dependencies(&result,
827 811 line,
828 812 do_get,
829 813 target,
830 814 true_target,
831 815 doing_subtree,
832 816 &out_of_date_list,
833 817 old_locals,
834 818 implicit,
835 819 &command,
836 820 less,
837 821 rechecking_target,
838 822 recheck_conditionals))
839 823 {
840 824 return build_running;
841 825 }
842 826 if (line->body.line.query != NULL) {
843 827 delete_query_chain(line->body.line.query);
844 828 }
845 829 line->body.line.query = out_of_date_list;
846 830 }
847 831 goto r_command;
848 832 }
849 833 }
850 834 /*
851 835 * If the file exists, it is OK that we couldnt figure
852 836 * out how to build it.
853 837 */
854 838 (void) exists(target);
855 839 if ((target->stat.time != file_doesnt_exist) &&
856 840 (result == build_dont_know)) {
857 841 result = build_ok;
858 842 }
859 843 }
860 844
861 845 /*
862 846 * Some of the following is duplicated in the function finish_doname.
863 847 * If anything is changed here, check to see if it needs to be
864 848 * changed there.
865 849 */
866 850 if ((line = get_prop(target->prop, line_prop)) != NULL) {
867 851 if (line->body.line.query != NULL) {
868 852 delete_query_chain(line->body.line.query);
869 853 }
870 854 line->body.line.query = NULL;
871 855 }
872 856 target->state = result;
873 857 parallel = save_parallel;
874 858 if (target->conditional_cnt > 0) {
875 859 reset_locals(target,
876 860 old_locals,
877 861 get_prop(target->prop, conditional_prop),
878 862 0);
879 863 }
880 864 recursion_level--;
881 865 if (target->is_member) {
882 866 Property member;
883 867
884 868 /* Propagate the timestamp from the member file to the member*/
885 869 if ((target->stat.time != file_max_time) &&
886 870 ((member = get_prop(target->prop, member_prop)) != NULL) &&
887 871 (exists(member->body.member.member) > file_doesnt_exist)) {
888 872 target->stat.time =
889 873 member->body.member.member->stat.time;
890 874 }
891 875 }
892 876 /*
893 877 * Check if we found any new auto dependencies when we
894 878 * built the target.
895 879 */
896 880 if ((result == build_ok) && check_auto_dependencies(target,
897 881 auto_count,
898 882 automatics)) {
899 883 if (debug_level > 0) {
900 884 (void) printf(catgets(catd, 1, 18, "%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
901 885 recursion_level,
902 886 "",
903 887 true_target->string_mb);
904 888 }
905 889 rechecking_target = true;
906 890 saved_commands_done = commands_done;
907 891 goto recheck_target;
908 892 }
909 893
910 894 if (rechecking_target && !commands_done) {
911 895 commands_done = saved_commands_done;
912 896 }
913 897
914 898 return result;
915 899 }
916 900
917 901 /*
918 902 * DONE.
919 903 *
920 904 * check_dependencies(result, line, do_get,
921 905 * target, true_target, doing_subtree, out_of_date_tail,
922 906 * old_locals, implicit, command, less, rechecking_target)
923 907 *
924 908 * Return value:
925 909 * True returned if some dependencies left running
926 910 *
927 911 * Parameters:
928 912 * result Pointer to cell we update if build failed
929 913 * line We get the dependencies from here
930 914 * do_get Allow use of sccs get in recursive doname()
931 915 * target The target to chase dependencies for
932 916 * true_target The real one for :: and lib(member)
933 917 * doing_subtree True if building a conditional macro subtree
934 918 * out_of_date_tail Used to set the $? list
935 919 * old_locals Used for resetting the local macros
936 920 * implicit Called when scanning for implicit rules?
937 921 * command Place to stuff command
938 922 * less Set to $< value
↓ open down ↓ |
133 lines elided |
↑ open up ↑ |
939 923 *
940 924 * Global variables used:
941 925 * command_changed Set if we suspect .make.state needs rewrite
942 926 * debug_level Should we trace actions?
943 927 * force The Name " FORCE", compared against
944 928 * recursion_level Used for tracing
945 929 * rewrite_statefile Set if .make.state needs rewriting
946 930 * wait_name The Name ".WAIT", compared against
947 931 */
948 932 static Boolean
949 -#ifdef TEAMWARE_MAKE_CMN
950 933 check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals)
951 -#else
952 -check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean, Chain *out_of_date_tail, Property, Boolean, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals)
953 -#endif
954 934 {
955 935 Boolean dependencies_running;
956 936 register Dependency dependency;
957 937 Doname dep_result;
958 938 Boolean dependency_changed = false;
959 939
960 940 line->body.line.dependency_time = file_doesnt_exist;
961 941 if (line->body.line.query != NULL) {
962 942 delete_query_chain(line->body.line.query);
963 943 }
964 944 line->body.line.query = NULL;
965 945 line->body.line.is_out_of_date = false;
966 946 dependencies_running = false;
967 947 /*
968 948 * Run thru all the dependencies and call doname() recursively
969 949 * on each of them.
970 950 */
971 951 for (dependency = line->body.line.dependencies;
972 952 dependency != NULL;
973 953 dependency = dependency->next) {
974 954 Boolean this_dependency_changed = false;
975 955
976 956 if (!dependency->automatic &&
977 957 (rechecking_target || target->rechecking_target)) {
978 958 /*
979 959 * We only bother with the autos when rechecking
980 960 */
981 961 continue;
982 962 }
983 963
984 964 if (dependency->name == wait_name) {
985 965 /*
986 966 * The special target .WAIT means finish all of
987 967 * the prior dependencies before continuing.
988 968 */
989 969 if (dependencies_running) {
990 970 break;
991 971 }
992 972 } else {
993 973 timestruc_t depe_time = file_doesnt_exist;
994 974
995 975
996 976 if (true_target->is_member) {
997 977 depe_time = exists(dependency->name);
998 978 }
999 979 if (dependency->built ||
1000 980 (dependency->name->state == build_failed)) {
1001 981 dep_result = (Doname) dependency->name->state;
1002 982 } else {
1003 983 dep_result = doname_check(dependency->name,
1004 984 do_get,
1005 985 false,
1006 986 (Boolean) dependency->automatic);
1007 987 }
1008 988 if (true_target->is_member || dependency->name->is_member) {
1009 989 /* should compare only secs, cause lib members does not have nsec time resolution */
1010 990 if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
1011 991 this_dependency_changed =
1012 992 dependency_changed =
1013 993 true;
1014 994 }
1015 995 } else {
1016 996 if (depe_time != dependency->name->stat.time) {
1017 997 this_dependency_changed =
1018 998 dependency_changed =
1019 999 true;
1020 1000 }
1021 1001 }
1022 1002 dependency->built = true;
1023 1003 switch (dep_result) {
1024 1004 case build_running:
1025 1005 dependencies_running = true;
1026 1006 continue;
1027 1007 case build_failed:
1028 1008 *result = build_failed;
1029 1009 break;
1030 1010 case build_dont_know:
1031 1011 /*
1032 1012 * If make can't figure out how to make a dependency, maybe the dependency
1033 1013 * is out of date. In this case, we just declare the target out of date
1034 1014 * and go on. If we really need the dependency, the make'ing of the target
1035 1015 * will fail. This will only happen for automatic (hidden) dependencies.
1036 1016 */
1037 1017 if(!recheck_conditionals) {
1038 1018 line->body.line.is_out_of_date = true;
1039 1019 }
1040 1020 /*
1041 1021 * Make sure the dependency is not saved
1042 1022 * in the state file.
1043 1023 */
1044 1024 dependency->stale = true;
1045 1025 rewrite_statefile =
1046 1026 command_changed =
1047 1027 true;
1048 1028 if (debug_level > 0) {
1049 1029 (void) printf(catgets(catd, 1, 19, "Target %s rebuilt because dependency %s does not exist\n"),
1050 1030 true_target->string_mb,
1051 1031 dependency->name->string_mb);
1052 1032 }
1053 1033 break;
1054 1034 }
1055 1035 if (dependency->name->depends_on_conditional) {
1056 1036 target->depends_on_conditional = true;
1057 1037 }
1058 1038 if (dependency->name == force) {
1059 1039 target->stat.time =
1060 1040 dependency->name->stat.time;
1061 1041 }
1062 1042 /*
1063 1043 * Propagate new timestamp from "member" to
1064 1044 * "lib.a(member)".
1065 1045 */
1066 1046 (void) exists(dependency->name);
1067 1047
1068 1048 /* Collect the timestamp of the youngest dependency */
1069 1049 line->body.line.dependency_time =
1070 1050 MAX(dependency->name->stat.time,
1071 1051 line->body.line.dependency_time);
1072 1052
1073 1053 /* Correction: do not consider nanosecs for members */
1074 1054 if(true_target->is_member || dependency->name->is_member) {
1075 1055 line->body.line.dependency_time.tv_nsec = 0;
1076 1056 }
1077 1057
1078 1058 if (debug_level > 1) {
1079 1059 (void) printf(catgets(catd, 1, 20, "%*sDate(%s)=%s \n"),
1080 1060 recursion_level,
1081 1061 "",
1082 1062 dependency->name->string_mb,
1083 1063 time_to_string(dependency->name->
1084 1064 stat.time));
1085 1065 if (dependency->name->stat.time > line->body.line.dependency_time) {
1086 1066 (void) printf(catgets(catd, 1, 21, "%*sDate-dependencies(%s) set to %s\n"),
1087 1067 recursion_level,
1088 1068 "",
1089 1069 true_target->string_mb,
1090 1070 time_to_string(line->body.line.
1091 1071 dependency_time));
1092 1072 }
1093 1073 }
1094 1074
1095 1075 /* Build the $? list */
1096 1076 if (true_target->is_member) {
1097 1077 if (this_dependency_changed == true) {
1098 1078 true_target->stat.time = dependency->name->stat.time;
1099 1079 true_target->stat.time.tv_sec--;
1100 1080 } else {
1101 1081 /* Dina:
1102 1082 * The next statement is commented
1103 1083 * out as a fix for bug #1051032.
1104 1084 * if dependency hasn't changed
1105 1085 * then there's no need to invalidate
1106 1086 * true_target. This statemnt causes
1107 1087 * make to take much longer to process
1108 1088 * an already-built archive. Soren
1109 1089 * said it was a quick fix for some
1110 1090 * problem he doesn't remember.
1111 1091 true_target->stat.time = file_no_time;
1112 1092 */
1113 1093 (void) exists(true_target);
1114 1094 }
1115 1095 } else {
1116 1096 (void) exists(true_target);
1117 1097 }
1118 1098 Boolean out_of_date;
1119 1099 if (true_target->is_member || dependency->name->is_member) {
1120 1100 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1121 1101 dependency->name->stat.time);
1122 1102 } else {
1123 1103 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1124 1104 dependency->name->stat.time);
1125 1105 }
1126 1106 if ((build_unconditional || out_of_date) &&
1127 1107 (dependency->name != force) &&
1128 1108 (dependency->stale == false)) {
1129 1109 *out_of_date_tail = ALLOC(Chain);
1130 1110 if (dependency->name->is_member &&
1131 1111 (get_prop(dependency->name->prop,
1132 1112 member_prop) != NULL)) {
1133 1113 (*out_of_date_tail)->name =
1134 1114 get_prop(dependency->name->prop,
1135 1115 member_prop)->
1136 1116 body.member.member;
1137 1117 } else {
1138 1118 (*out_of_date_tail)->name =
1139 1119 dependency->name;
1140 1120 }
1141 1121 (*out_of_date_tail)->next = NULL;
1142 1122 out_of_date_tail = &(*out_of_date_tail)->next;
1143 1123 if (debug_level > 0) {
1144 1124 if (dependency->name->stat.time == file_max_time) {
1145 1125 (void) printf(catgets(catd, 1, 22, "%*sBuilding %s because %s does not exist\n"),
1146 1126 recursion_level,
1147 1127 "",
1148 1128 true_target->string_mb,
1149 1129 dependency->name->string_mb);
1150 1130 } else {
1151 1131 (void) printf(catgets(catd, 1, 23, "%*sBuilding %s because it is out of date relative to %s\n"),
1152 1132 recursion_level,
1153 1133 "",
1154 1134 true_target->string_mb,
1155 1135 dependency->name->string_mb);
↓ open down ↓ |
192 lines elided |
↑ open up ↑ |
1156 1136 }
1157 1137 }
1158 1138 }
1159 1139 if (dependency->name == force) {
1160 1140 force->stat.time =
1161 1141 file_max_time;
1162 1142 force->state = build_dont_know;
1163 1143 }
1164 1144 }
1165 1145 }
1166 -#ifdef TEAMWARE_MAKE_CMN
1167 1146 if (dependencies_running) {
1168 1147 if (doing_subtree) {
1169 1148 if (target->conditional_cnt > 0) {
1170 1149 reset_locals(target,
1171 1150 old_locals,
1172 1151 get_prop(target->prop,
1173 1152 conditional_prop),
1174 1153 0);
1175 1154 }
1176 1155 return true;
1177 1156 } else {
1178 1157 target->state = build_running;
1179 1158 add_pending(target,
1180 1159 --recursion_level,
1181 1160 do_get,
1182 1161 implicit,
1183 1162 false);
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
1184 1163 if (target->conditional_cnt > 0) {
1185 1164 reset_locals(target,
1186 1165 old_locals,
1187 1166 get_prop(target->prop,
1188 1167 conditional_prop),
1189 1168 0);
1190 1169 }
1191 1170 return true;
1192 1171 }
1193 1172 }
1194 -#endif
1195 1173 /*
1196 1174 * Collect the timestamp of the youngest double colon target
1197 1175 * dependency.
1198 1176 */
1199 1177 if (target->is_double_colon_parent) {
1200 1178 for (dependency = line->body.line.dependencies;
1201 1179 dependency != NULL;
1202 1180 dependency = dependency->next) {
1203 1181 Property tmp_line;
1204 1182
1205 1183 if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1206 1184 if(tmp_line->body.line.dependency_time != file_max_time) {
1207 1185 target->stat.time =
1208 1186 MAX(tmp_line->body.line.dependency_time,
1209 1187 target->stat.time);
1210 1188 }
1211 1189 }
1212 1190 }
1213 1191 }
1214 1192 if ((true_target->is_member) && (dependency_changed == true)) {
1215 1193 true_target->stat.time = file_no_time;
1216 1194 }
1217 1195 /*
1218 1196 * After scanning all the dependencies, we check the rule
1219 1197 * if we found one.
1220 1198 */
1221 1199 if (line->body.line.command_template != NULL) {
1222 1200 if (line->body.line.command_template_redefined) {
1223 1201 warning(catgets(catd, 1, 24, "Too many rules defined for target %s"),
1224 1202 target->string_mb);
1225 1203 }
1226 1204 *command = line;
1227 1205 /* Check if the target is out of date */
1228 1206 Boolean out_of_date;
1229 1207 if (true_target->is_member) {
1230 1208 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1231 1209 line->body.line.dependency_time);
1232 1210 } else {
1233 1211 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1234 1212 line->body.line.dependency_time);
1235 1213 }
1236 1214 if (build_unconditional || out_of_date){
1237 1215 if(!recheck_conditionals) {
1238 1216 line->body.line.is_out_of_date = true;
1239 1217 }
1240 1218 }
1241 1219 line->body.line.sccs_command = false;
1242 1220 line->body.line.target = true_target;
1243 1221 if(gnu_style) {
1244 1222
1245 1223 // set $< for explicit rule
1246 1224 if(line->body.line.dependencies != NULL) {
1247 1225 less = line->body.line.dependencies->name;
1248 1226 }
1249 1227
1250 1228 // set $* for explicit rule
1251 1229 Name target_body;
1252 1230 Name tt = true_target;
1253 1231 Property member;
1254 1232 register wchar_t *target_end;
1255 1233 register Dependency suffix;
1256 1234 register int suffix_length;
1257 1235 Wstring targ_string;
1258 1236 Wstring suf_string;
1259 1237
1260 1238 if (true_target->is_member &&
1261 1239 ((member = get_prop(target->prop, member_prop)) !=
1262 1240 NULL)) {
1263 1241 tt = member->body.member.member;
1264 1242 }
1265 1243 targ_string.init(tt);
1266 1244 target_end = targ_string.get_string() + tt->hash.length;
1267 1245 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
1268 1246 suffix_length = suffix->name->hash.length;
1269 1247 suf_string.init(suffix->name);
1270 1248 if (tt->hash.length < suffix_length) {
1271 1249 continue;
1272 1250 } else if (!IS_WEQUALN(suf_string.get_string(),
1273 1251 (target_end - suffix_length),
1274 1252 suffix_length)) {
1275 1253 continue;
1276 1254 }
1277 1255 target_body = GETNAME(
1278 1256 targ_string.get_string(),
1279 1257 (int)(tt->hash.length - suffix_length)
1280 1258 );
1281 1259 line->body.line.star = target_body;
1282 1260 }
1283 1261
1284 1262 // set result = build_ok so that implicit rules are not used.
1285 1263 if(*result == build_dont_know) {
1286 1264 *result = build_ok;
1287 1265 }
1288 1266 }
1289 1267 if (less != NULL) {
1290 1268 line->body.line.less = less;
1291 1269 }
1292 1270 }
1293 1271
1294 1272 return false;
1295 1273 }
1296 1274
1297 1275 /*
1298 1276 * dynamic_dependencies(target)
1299 1277 *
1300 1278 * Checks if any dependency contains a macro ref
1301 1279 * If so, it replaces the dependency with the expanded version.
1302 1280 * Here, "$@" gets translated to target->string. That is
1303 1281 * the current name on the left of the colon in the
1304 1282 * makefile. Thus,
1305 1283 * xyz: s.$@.c
1306 1284 * translates into
1307 1285 * xyz: s.xyz.c
1308 1286 *
1309 1287 * Also, "$(@F)" translates to the same thing without a preceeding
1310 1288 * directory path (if one exists).
1311 1289 * Note, to enter "$@" on a dependency line in a makefile
1312 1290 * "$$@" must be typed. This is because make expands
1313 1291 * macros in dependency lists upon reading them.
1314 1292 * dynamic_dependencies() also expands file wildcards.
1315 1293 * If there are any Shell meta characters in the name,
1316 1294 * search the directory, and replace the dependency
1317 1295 * with the set of files the pattern matches
1318 1296 *
1319 1297 * Parameters:
1320 1298 * target Target to sanitize dependencies for
1321 1299 *
1322 1300 * Global variables used:
1323 1301 * c_at The Name "@", used to set macro value
1324 1302 * debug_level Should we trace actions?
1325 1303 * dot The Name ".", used to read directory
1326 1304 * recursion_level Used for tracing
1327 1305 */
1328 1306 void
1329 1307 dynamic_dependencies(Name target)
1330 1308 {
1331 1309 wchar_t pattern[MAXPATHLEN];
1332 1310 register wchar_t *p;
1333 1311 Property line;
1334 1312 register Dependency dependency;
1335 1313 register Dependency *remove;
1336 1314 String_rec string;
1337 1315 wchar_t buffer[MAXPATHLEN];
1338 1316 register Boolean set_at = false;
1339 1317 register wchar_t *start;
1340 1318 Dependency new_depe;
1341 1319 register Boolean reuse_cell;
1342 1320 Dependency first_member;
1343 1321 Name directory;
1344 1322 Name lib;
1345 1323 Name member;
1346 1324 Property prop;
1347 1325 Name true_target = target;
1348 1326 wchar_t *library;
1349 1327
1350 1328 if ((line = get_prop(target->prop, line_prop)) == NULL) {
1351 1329 return;
1352 1330 }
1353 1331 /* If the target is constructed from a "::" target we consider that */
1354 1332 if (target->has_target_prop) {
1355 1333 true_target = get_prop(target->prop,
1356 1334 target_prop)->body.target.target;
1357 1335 }
1358 1336 /* Scan all dependencies and process the ones that contain "$" chars */
1359 1337 for (dependency = line->body.line.dependencies;
1360 1338 dependency != NULL;
1361 1339 dependency = dependency->next) {
1362 1340 if (!dependency->name->dollar) {
1363 1341 continue;
1364 1342 }
1365 1343 target->has_depe_list_expanded = true;
1366 1344
1367 1345 /* The make macro $@ is bound to the target name once per */
1368 1346 /* invocation of dynamic_dependencies() */
1369 1347 if (!set_at) {
1370 1348 (void) SETVAR(c_at, true_target, false);
1371 1349 set_at = true;
1372 1350 }
1373 1351 /* Expand this dependency string */
1374 1352 INIT_STRING_FROM_STACK(string, buffer);
1375 1353 expand_value(dependency->name, &string, false);
1376 1354 /* Scan the expanded string. It could contain whitespace */
1377 1355 /* which mean it expands to several dependencies */
1378 1356 start = string.buffer.start;
1379 1357 while (iswspace(*start)) {
1380 1358 start++;
1381 1359 }
1382 1360 /* Remove the cell (later) if the macro was empty */
1383 1361 if (start[0] == (int) nul_char) {
1384 1362 dependency->name = NULL;
1385 1363 }
1386 1364
1387 1365 /* azv 10/26/95 to fix bug BID_1170218 */
1388 1366 if ((start[0] == (int) period_char) &&
1389 1367 (start[1] == (int) slash_char)) {
1390 1368 start += 2;
1391 1369 }
1392 1370 /* azv */
1393 1371
1394 1372 first_member = NULL;
1395 1373 /* We use the original dependency cell for the first */
1396 1374 /* dependency from the expansion */
1397 1375 reuse_cell = true;
1398 1376 /* We also have to deal with dependencies that expand to */
1399 1377 /* lib.a(members) notation */
1400 1378 for (p = start; *p != (int) nul_char; p++) {
1401 1379 if ((*p == (int) parenleft_char)) {
1402 1380 lib = GETNAME(start, p - start);
1403 1381 lib->is_member = true;
1404 1382 first_member = dependency;
1405 1383 start = p + 1;
1406 1384 while (iswspace(*start)) {
1407 1385 start++;
1408 1386 }
1409 1387 break;
1410 1388 }
1411 1389 }
1412 1390 do {
1413 1391 /* First skip whitespace */
1414 1392 for (p = start; *p != (int) nul_char; p++) {
1415 1393 if ((*p == (int) nul_char) ||
1416 1394 iswspace(*p) ||
1417 1395 (*p == (int) parenright_char)) {
1418 1396 break;
1419 1397 }
1420 1398 }
1421 1399 /* Enter dependency from expansion */
1422 1400 if (p != start) {
1423 1401 /* Create new dependency cell if */
1424 1402 /* this is not the first dependency */
1425 1403 /* picked from the expansion */
1426 1404 if (!reuse_cell) {
1427 1405 new_depe = ALLOC(Dependency);
1428 1406 new_depe->next = dependency->next;
1429 1407 new_depe->automatic = false;
1430 1408 new_depe->stale = false;
1431 1409 new_depe->built = false;
1432 1410 dependency->next = new_depe;
1433 1411 dependency = new_depe;
1434 1412 }
1435 1413 reuse_cell = false;
1436 1414 /* Internalize the dependency name */
1437 1415 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1438 1416 // include "//" and "/./"
1439 1417 //dependency->name = GETNAME(start, p - start);
1440 1418 dependency->name = normalize_name(start, p - start);
1441 1419 if ((debug_level > 0) &&
1442 1420 (first_member == NULL)) {
1443 1421 (void) printf(catgets(catd, 1, 25, "%*sDynamic dependency `%s' for target `%s'\n"),
1444 1422 recursion_level,
1445 1423 "",
1446 1424 dependency->name->string_mb,
1447 1425 true_target->string_mb);
1448 1426 }
1449 1427 for (start = p; iswspace(*start); start++);
1450 1428 p = start;
1451 1429 }
1452 1430 } while ((*p != (int) nul_char) &&
1453 1431 (*p != (int) parenright_char));
1454 1432 /* If the expansion was of lib.a(members) format we now */
1455 1433 /* enter the proper member cells */
1456 1434 if (first_member != NULL) {
1457 1435 /* Scan the new dependencies and transform them from */
1458 1436 /* "foo" to "lib.a(foo)" */
1459 1437 for (; 1; first_member = first_member->next) {
1460 1438 /* Build "lib.a(foo)" name */
1461 1439 INIT_STRING_FROM_STACK(string, buffer);
1462 1440 APPEND_NAME(lib,
1463 1441 &string,
1464 1442 (int) lib->hash.length);
1465 1443 append_char((int) parenleft_char, &string);
1466 1444 APPEND_NAME(first_member->name,
1467 1445 &string,
1468 1446 FIND_LENGTH);
1469 1447 append_char((int) parenright_char, &string);
1470 1448 member = first_member->name;
1471 1449 /* Replace "foo" with "lib.a(foo)" */
1472 1450 first_member->name =
1473 1451 GETNAME(string.buffer.start, FIND_LENGTH);
1474 1452 if (string.free_after_use) {
1475 1453 retmem(string.buffer.start);
1476 1454 }
1477 1455 if (debug_level > 0) {
1478 1456 (void) printf(catgets(catd, 1, 26, "%*sDynamic dependency `%s' for target `%s'\n"),
1479 1457 recursion_level,
1480 1458 "",
1481 1459 first_member->name->
1482 1460 string_mb,
1483 1461 true_target->string_mb);
1484 1462 }
1485 1463 first_member->name->is_member = lib->is_member;
1486 1464 /* Add member property to member */
1487 1465 prop = maybe_append_prop(first_member->name,
1488 1466 member_prop);
1489 1467 prop->body.member.library = lib;
1490 1468 prop->body.member.entry = NULL;
1491 1469 prop->body.member.member = member;
1492 1470 if (first_member == dependency) {
1493 1471 break;
1494 1472 }
1495 1473 }
1496 1474 }
1497 1475 }
1498 1476 Wstring wcb;
1499 1477 /* Then scan all the dependencies again. This time we want to expand */
1500 1478 /* shell file wildcards */
1501 1479 for (remove = &line->body.line.dependencies, dependency = *remove;
1502 1480 dependency != NULL;
1503 1481 dependency = *remove) {
1504 1482 if (dependency->name == NULL) {
1505 1483 dependency = *remove = (*remove)->next;
1506 1484 continue;
1507 1485 }
1508 1486 /* If dependency name string contains shell wildcards */
1509 1487 /* replace the name with the expansion */
1510 1488 if (dependency->name->wildcard) {
1511 1489 wcb.init(dependency->name);
1512 1490 if ((start = (wchar_t *) wschr(wcb.get_string(),
1513 1491 (int) parenleft_char)) != NULL) {
1514 1492 /* lib(*) type pattern */
1515 1493 library = buffer;
1516 1494 (void) wsncpy(buffer,
1517 1495 wcb.get_string(),
1518 1496 start - wcb.get_string());
1519 1497 buffer[start-wcb.get_string()] =
1520 1498 (int) nul_char;
1521 1499 (void) wsncpy(pattern,
1522 1500 start + 1,
1523 1501 (int) (dependency->name->hash.length-(start-wcb.get_string())-2));
1524 1502 pattern[dependency->name->hash.length -
1525 1503 (start-wcb.get_string()) - 2] =
1526 1504 (int) nul_char;
1527 1505 } else {
1528 1506 library = NULL;
1529 1507 (void) wsncpy(pattern,
1530 1508 wcb.get_string(),
1531 1509 (int) dependency->name->hash.length);
1532 1510 pattern[dependency->name->hash.length] =
1533 1511 (int) nul_char;
1534 1512 }
1535 1513 start = (wchar_t *) wsrchr(pattern, (int) slash_char);
1536 1514 if (start == NULL) {
1537 1515 directory = dot;
1538 1516 p = pattern;
1539 1517 } else {
1540 1518 directory = GETNAME(pattern, start-pattern);
1541 1519 p = start+1;
1542 1520 }
1543 1521 /* The expansion is handled by the read_dir() routine*/
1544 1522 if (read_dir(directory, p, line, library)) {
1545 1523 *remove = (*remove)->next;
1546 1524 } else {
1547 1525 remove = &dependency->next;
1548 1526 }
1549 1527 } else {
1550 1528 remove = &dependency->next;
1551 1529 }
1552 1530 }
1553 1531
1554 1532 /* Then unbind $@ */
1555 1533 (void) SETVAR(c_at, (Name) NULL, false);
1556 1534 }
1557 1535
1558 1536 /*
1559 1537 * DONE.
1560 1538 *
1561 1539 * run_command(line)
1562 1540 *
1563 1541 * Takes one Cmd_line and runs the commands from it.
1564 1542 *
1565 1543 * Return value:
1566 1544 * Indicates if the command failed or not
1567 1545 *
1568 1546 * Parameters:
1569 1547 * line The command line to run
1570 1548 *
1571 1549 * Global variables used:
1572 1550 * commands_done Set if we do run command
1573 1551 * current_line Set to the line we run a command from
1574 1552 * current_target Set to the target we run a command for
1575 1553 * file_number Used to form temp file name
1576 1554 * keep_state Indicates that .KEEP_STATE is on
1577 1555 * make_state The Name ".make.state", used to check timestamp
1578 1556 * parallel True if currently building in parallel
1579 1557 * parallel_process_cnt Count of parallel processes running
1580 1558 * quest Indicates that make -q is on
1581 1559 * rewrite_statefile Set if we do run a command
1582 1560 * sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value
1583 1561 * temp_file_directory Used to form temp fie name
1584 1562 * temp_file_name Set to the name of the temp file
1585 1563 * touch Indicates that make -t is on
1586 1564 */
1587 1565 static Doname
1588 1566 run_command(register Property line, Boolean)
1589 1567 {
1590 1568 register Doname result = build_ok;
1591 1569 register Boolean remember_only = false;
1592 1570 register Name target = line->body.line.target;
1593 1571 wchar_t *string;
1594 1572 char tmp_file_path[MAXPATHLEN];
1595 1573
1596 1574 if (!line->body.line.is_out_of_date && target->rechecking_target) {
1597 1575 target->rechecking_target = false;
1598 1576 return build_ok;
1599 1577 }
1600 1578
1601 1579 /*
1602 1580 * Build the command if we know the target is out of date,
1603 1581 * or if we want to check cmd consistency.
1604 1582 */
1605 1583 if (line->body.line.is_out_of_date || keep_state) {
1606 1584 /* Hack for handling conditional macros in DMake. */
1607 1585 if (!line->body.line.dont_rebuild_command_used) {
↓ open down ↓ |
403 lines elided |
↑ open up ↑ |
1608 1586 build_command_strings(target, line);
1609 1587 }
1610 1588 }
1611 1589 /* Never mind */
1612 1590 if (!line->body.line.is_out_of_date) {
1613 1591 return build_ok;
1614 1592 }
1615 1593 /* If quest, then exit(1) because the target is out of date */
1616 1594 if (quest) {
1617 1595 if (posix) {
1618 -#ifdef TEAMWARE_MAKE_CMN
1619 1596 result = execute_parallel(line, true);
1620 -#else
1621 - result = execute_serial(line);
1622 -#endif
1623 1597 }
1624 1598 exit_status = 1;
1625 1599 exit(1);
1626 1600 }
1627 1601 /* We actually had to do something this time */
1628 1602 rewrite_statefile = commands_done = true;
1629 1603 /*
1630 1604 * If this is an sccs command, we have to do some extra checking
1631 1605 * and possibly complain. If the file can't be gotten because it's
1632 1606 * checked out, we complain and behave as if the command was
1633 1607 * executed eventhough we ignored the command.
1634 1608 */
1635 1609 if (!touch &&
1636 1610 line->body.line.sccs_command &&
1637 1611 (target->stat.time != file_doesnt_exist) &&
1638 1612 ((target->stat.mode & 0222) != 0)) {
1639 1613 fatal(catgets(catd, 1, 27, "%s is writable so it cannot be sccs gotten"),
1640 1614 target->string_mb);
1641 1615 target->has_complained = remember_only = true;
1642 1616 }
1643 1617 /*
1644 1618 * If KEEP_STATE is on, we make sure we have the timestamp for
1645 1619 * .make.state. If .make.state changes during the command run,
1646 1620 * we reread .make.state after the command. We also setup the
1647 1621 * environment variable that asks utilities to report dependencies.
1648 1622 */
1649 1623 if (!touch &&
1650 1624 keep_state &&
1651 1625 !remember_only) {
1652 1626 (void) exists(make_state);
1653 1627 if((strlen(temp_file_directory) == 1) &&
1654 1628 (temp_file_directory[0] == '/')) {
1655 1629 tmp_file_path[0] = '\0';
1656 1630 } else {
1657 1631 strcpy(tmp_file_path, temp_file_directory);
1658 1632 }
1659 1633 sprintf(mbs_buffer,
1660 1634 NOCATGETS("%s/.make.dependency.%08x.%d.%d"),
1661 1635 tmp_file_path,
1662 1636 hostid,
1663 1637 getpid(),
1664 1638 file_number++);
1665 1639 MBSTOWCS(wcs_buffer, mbs_buffer);
1666 1640 Boolean fnd;
1667 1641 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1668 1642 temp_file_name->stat.is_file = true;
1669 1643 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1670 1644 wchar_t *to = string = ALLOC_WC(len);
1671 1645 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1672 1646 if (*from == (int) space_char) {
1673 1647 *to++ = (int) backslash_char;
1674 1648 }
1675 1649 *to++ = *from++;
1676 1650 }
1677 1651 *to++ = (int) space_char;
1678 1652 MBSTOWCS(to, target->string_mb);
1679 1653 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1680 1654 (void) SETVAR(sunpro_dependencies,
1681 1655 sprodep_name,
1682 1656 false);
1683 1657 retmem(string);
1684 1658 } else {
1685 1659 temp_file_name = NULL;
1686 1660 }
1687 1661
1688 1662 /*
1689 1663 * In case we are interrupted, we need to know what was going on.
1690 1664 */
1691 1665 current_target = target;
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
1692 1666 /*
1693 1667 * We also need to be able to save an empty command instead of the
1694 1668 * interrupted one in .make.state.
1695 1669 */
1696 1670 current_line = line;
1697 1671 if (remember_only) {
1698 1672 /* Empty block!!! */
1699 1673 } else if (touch) {
1700 1674 result = touch_command(line, target, result);
1701 1675 if (posix) {
1702 -#ifdef TEAMWARE_MAKE_CMN
1703 1676 result = execute_parallel(line, true);
1704 -#else
1705 - result = execute_serial(line);
1706 -#endif
1707 1677 }
1708 1678 } else {
1709 1679 /*
1710 1680 * If this is not a touch run, we need to execute the
1711 1681 * proper command(s) for the target.
1712 1682 */
1713 -#ifdef TEAMWARE_MAKE_CMN
1714 1683 if (parallel) {
1715 1684 if (!parallel_ok(target, true)) {
1716 1685 /*
1717 1686 * We are building in parallel, but
1718 1687 * this target must be built in serial.
1719 1688 */
1720 1689 /*
1721 1690 * If nothing else is building,
1722 1691 * do this one, else wait.
1723 1692 */
1724 1693 if (parallel_process_cnt == 0) {
1725 -#ifdef TEAMWARE_MAKE_CMN
1726 1694 result = execute_parallel(line, true, target->localhost);
1727 -#else
1728 - result = execute_serial(line);
1729 -#endif
1730 1695 } else {
1731 1696 current_target = NULL;
1732 1697 current_line = NULL;
1733 1698 /*
1734 1699 line->body.line.command_used = NULL;
1735 1700 */
1736 1701 line->body.line.dont_rebuild_command_used = true;
1737 1702 return build_serial;
1738 1703 }
1739 1704 } else {
1740 1705 result = execute_parallel(line, false);
1741 1706 switch (result) {
1742 1707 case build_running:
1743 1708 return build_running;
1744 1709 case build_serial:
1745 1710 if (parallel_process_cnt == 0) {
1746 -#ifdef TEAMWARE_MAKE_CMN
1747 1711 result = execute_parallel(line, true, target->localhost);
1748 -#else
1749 - result = execute_serial(line);
1750 -#endif
1751 1712 } else {
1752 1713 current_target = NULL;
1753 1714 current_line = NULL;
1754 1715 target->parallel = false;
1755 1716 line->body.line.command_used =
1756 1717 NULL;
1757 1718 return build_serial;
1758 1719 }
1759 1720 }
1760 1721 }
1761 1722 } else {
1762 -#endif
1763 -#ifdef TEAMWARE_MAKE_CMN
1764 1723 result = execute_parallel(line, true, target->localhost);
1765 -#else
1766 - result = execute_serial(line);
1767 -#endif
1768 -#ifdef TEAMWARE_MAKE_CMN
1769 1724 }
1770 -#endif
1771 1725 }
1772 1726 temp_file_name = NULL;
1773 1727 if (report_dependencies_level == 0){
1774 1728 update_target(line, result);
1775 1729 }
1776 1730 current_target = NULL;
1777 1731 current_line = NULL;
1778 1732 return result;
1779 1733 }
1780 1734
1781 1735 /*
1782 1736 * execute_serial(line)
1783 1737 *
1784 1738 * Runs thru the command line for the target and
1785 1739 * executes the rules one by one.
1786 1740 *
1787 1741 * Return value:
1788 1742 * The result of the command build
1789 1743 *
1790 1744 * Parameters:
1791 1745 * line The command to execute
1792 1746 *
1793 1747 * Static variables used:
1794 1748 *
1795 1749 * Global variables used:
1796 1750 * continue_after_error -k flag
1797 1751 * do_not_exec_rule -n flag
1798 1752 * report_dependencies -P flag
1799 1753 * silent Don't echo commands before executing
1800 1754 * temp_file_name Temp file for auto dependencies
1801 1755 * vpath_defined If true, translate path for command
1802 1756 */
1803 1757 Doname
1804 1758 execute_serial(Property line)
1805 1759 {
1806 1760 int child_pid = 0;
1807 1761 Boolean printed_serial;
1808 1762 Doname result = build_ok;
1809 1763 Cmd_line rule, cmd_tail, command = NULL;
1810 1764 char mbstring[MAXPATHLEN];
1811 1765 int filed;
1812 1766 Name target = line->body.line.target;
1813 1767
1814 1768 SEND_MTOOL_MSG(
1815 1769 if (!sent_rsrc_info_msg) {
1816 1770 if (userName[0] == '\0') {
1817 1771 avo_get_user(userName, NULL);
1818 1772 }
1819 1773 if (hostName[0] == '\0') {
1820 1774 strcpy(hostName, avo_hostname());
1821 1775 }
1822 1776 send_rsrc_info_msg(1, hostName, userName);
1823 1777 sent_rsrc_info_msg = 1;
1824 1778 }
1825 1779 send_job_start_msg(line);
1826 1780 job_result_msg = new Avo_MToolJobResultMsg();
1827 1781 );
1828 1782
1829 1783 target->has_recursive_dependency = false;
1830 1784 // We have to create a copy of the rules chain for processing because
1831 1785 // the original one can be destroyed during .make.state file rereading.
1832 1786 for (rule = line->body.line.command_used;
1833 1787 rule != NULL;
1834 1788 rule = rule->next) {
1835 1789 if (command == NULL) {
1836 1790 command = cmd_tail = ALLOC(Cmd_line);
1837 1791 } else {
1838 1792 cmd_tail->next = ALLOC(Cmd_line);
1839 1793 cmd_tail = cmd_tail->next;
1840 1794 }
1841 1795 *cmd_tail = *rule;
1842 1796 }
1843 1797 if (command) {
1844 1798 cmd_tail->next = NULL;
1845 1799 }
1846 1800 for (rule = command; rule != NULL; rule = rule->next) {
1847 1801 if (posix && (touch || quest) && !rule->always_exec) {
1848 1802 continue;
1849 1803 }
1850 1804 if (vpath_defined) {
1851 1805 rule->command_line =
1852 1806 vpath_translation(rule->command_line);
1853 1807 }
1854 1808 /* Echo command line, maybe. */
1855 1809 if ((rule->command_line->hash.length > 0) &&
1856 1810 !silent &&
1857 1811 (!rule->silent || do_not_exec_rule) &&
1858 1812 (report_dependencies_level == 0)) {
1859 1813 (void) printf("%s\n", rule->command_line->string_mb);
1860 1814 SEND_MTOOL_MSG(
1861 1815 job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb));
1862 1816 );
1863 1817 }
1864 1818 if (rule->command_line->hash.length > 0) {
1865 1819 SEND_MTOOL_MSG(
1866 1820 (void) sprintf(mbstring,
1867 1821 NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"),
1868 1822 tmpdir,
1869 1823 getpid(),
1870 1824 file_number++);
1871 1825
1872 1826 int tmp_fd = mkstemp(mbstring);
1873 1827 if(tmp_fd) {
1874 1828 (void) close(tmp_fd);
1875 1829 }
1876 1830
1877 1831 stdout_file = strdup(mbstring);
1878 1832 stderr_file = NULL;
1879 1833 child_pid = pollResults(stdout_file,
1880 1834 (char *)NULL,
1881 1835 (char *)NULL);
1882 1836 );
1883 1837 /* Do assignment if command line prefixed with "=" */
1884 1838 if (rule->assign) {
1885 1839 result = build_ok;
1886 1840 do_assign(rule->command_line, target);
1887 1841 } else if (report_dependencies_level == 0) {
1888 1842 /* Execute command line. */
1889 1843 setvar_envvar();
1890 1844 result = dosys(rule->command_line,
1891 1845 (Boolean) rule->ignore_error,
1892 1846 (Boolean) rule->make_refd,
1893 1847 /* ds 98.04.23 bug #4085164. make should always show error messages */
1894 1848 false,
1895 1849 /* BOOLEAN(rule->silent &&
1896 1850 rule->ignore_error), */
1897 1851 (Boolean) rule->always_exec,
1898 1852 target,
1899 1853 send_mtool_msgs);
1900 1854 check_state(temp_file_name);
1901 1855 }
1902 1856 SEND_MTOOL_MSG(
1903 1857 append_job_result_msg(job_result_msg);
1904 1858 if (child_pid > 0) {
1905 1859 kill(child_pid, SIGUSR1);
1906 1860 while (!((waitpid(child_pid, 0, 0) == -1)
1907 1861 && (errno == ECHILD)));
1908 1862 }
1909 1863 child_pid = 0;
1910 1864 (void) unlink(stdout_file);
1911 1865 retmem_mb(stdout_file);
1912 1866 stdout_file = NULL;
1913 1867 );
1914 1868 } else {
1915 1869 result = build_ok;
1916 1870 }
1917 1871 if (result == build_failed) {
1918 1872 if (silent || rule->silent) {
1919 1873 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"),
1920 1874 rule->command_line->string_mb);
1921 1875 SEND_MTOOL_MSG(
1922 1876 job_result_msg->appendOutput(AVO_STRDUP(catgets(catd, 1, 243, "The following command caused the error:")));
1923 1877 job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb));
1924 1878 );
1925 1879 }
1926 1880 if (!rule->ignore_error && !ignore_errors) {
1927 1881 if (!continue_after_error) {
1928 1882 SEND_MTOOL_MSG(
1929 1883 job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
1930 1884 xdr_msg = (RWCollectable*)
1931 1885 job_result_msg;
1932 1886 xdr(&xdrs, xdr_msg);
1933 1887 (void) fflush(mtool_msgs_fp);
1934 1888 delete job_result_msg;
1935 1889 );
1936 1890 fatal(catgets(catd, 1, 244, "Command failed for target `%s'"),
1937 1891 target->string_mb);
1938 1892 }
1939 1893 /*
1940 1894 * Make sure a failing command is not
1941 1895 * saved in .make.state.
1942 1896 */
1943 1897 line->body.line.command_used = NULL;
1944 1898 break;
1945 1899 } else {
1946 1900 result = build_ok;
1947 1901 }
1948 1902 }
1949 1903 }
1950 1904 for (rule = command; rule != NULL; rule = cmd_tail) {
1951 1905 cmd_tail = rule->next;
1952 1906 free(rule);
1953 1907 }
1954 1908 command = NULL;
1955 1909 SEND_MTOOL_MSG(
1956 1910 job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
1957 1911 xdr_msg = (RWCollectable*) job_result_msg;
1958 1912 xdr(&xdrs, xdr_msg);
1959 1913 (void) fflush(mtool_msgs_fp);
1960 1914
1961 1915 delete job_result_msg;
1962 1916 );
1963 1917 if (temp_file_name != NULL) {
1964 1918 free_name(temp_file_name);
1965 1919 }
1966 1920 temp_file_name = NULL;
1967 1921
1968 1922 Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
1969 1923 if(spro != NULL) {
1970 1924 Name val = spro->body.macro.value;
1971 1925 if(val != NULL) {
1972 1926 free_name(val);
1973 1927 spro->body.macro.value = NULL;
1974 1928 }
1975 1929 }
1976 1930 spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1977 1931 if(spro) {
1978 1932 char *val = spro->body.env_mem.value;
1979 1933 if(val != NULL) {
1980 1934 /*
1981 1935 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1982 1936 * It will be returned in setvar_daemon() in macro.cc
1983 1937 */
1984 1938 // retmem_mb(val);
1985 1939 spro->body.env_mem.value = NULL;
1986 1940 }
1987 1941 }
1988 1942
1989 1943 return result;
1990 1944 }
1991 1945
1992 1946
1993 1947
1994 1948 /*
1995 1949 * vpath_translation(cmd)
1996 1950 *
1997 1951 * Translates one command line by
1998 1952 * checking each word. If the word has an alias it is translated.
1999 1953 *
2000 1954 * Return value:
2001 1955 * The translated command
2002 1956 *
2003 1957 * Parameters:
2004 1958 * cmd Command to translate
2005 1959 *
2006 1960 * Global variables used:
2007 1961 */
2008 1962 Name
2009 1963 vpath_translation(register Name cmd)
2010 1964 {
2011 1965 wchar_t buffer[STRING_BUFFER_LENGTH];
2012 1966 String_rec new_cmd;
2013 1967 wchar_t *p;
2014 1968 wchar_t *start;
2015 1969
2016 1970 if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) {
2017 1971 return cmd;
2018 1972 }
2019 1973 INIT_STRING_FROM_STACK(new_cmd, buffer);
2020 1974
2021 1975 Wstring wcb(cmd);
2022 1976 p = wcb.get_string();
2023 1977
2024 1978 while (*p != (int) nul_char) {
2025 1979 while (iswspace(*p) && (*p != (int) nul_char)) {
2026 1980 append_char(*p++, &new_cmd);
2027 1981 }
2028 1982 start = p;
2029 1983 while (!iswspace(*p) && (*p != (int) nul_char)) {
2030 1984 p++;
2031 1985 }
2032 1986 cmd = GETNAME(start, p - start);
2033 1987 if (cmd->has_vpath_alias_prop) {
2034 1988 cmd = get_prop(cmd->prop, vpath_alias_prop)->
2035 1989 body.vpath_alias.alias;
2036 1990 APPEND_NAME(cmd,
2037 1991 &new_cmd,
2038 1992 (int) cmd->hash.length);
2039 1993 } else {
2040 1994 append_string(start, &new_cmd, p - start);
2041 1995 }
2042 1996 }
2043 1997 cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH);
2044 1998 if (new_cmd.free_after_use) {
2045 1999 retmem(new_cmd.buffer.start);
2046 2000 }
2047 2001 return cmd;
2048 2002 }
2049 2003
2050 2004 /*
2051 2005 * check_state(temp_file_name)
2052 2006 *
2053 2007 * Reads and checks the state changed by the previously executed command.
2054 2008 *
2055 2009 * Parameters:
2056 2010 * temp_file_name The auto dependency temp file
2057 2011 *
2058 2012 * Global variables used:
2059 2013 */
2060 2014 void
2061 2015 check_state(Name temp_file_name)
2062 2016 {
2063 2017 if (!keep_state) {
2064 2018 return;
2065 2019 }
2066 2020
2067 2021 /*
2068 2022 * Then read the temp file that now might
2069 2023 * contain dependency reports from utilities
2070 2024 */
2071 2025 read_dependency_file(temp_file_name);
2072 2026
2073 2027 /*
2074 2028 * And reread .make.state if it
2075 2029 * changed (the command ran recursive makes)
2076 2030 */
2077 2031 check_read_state_file();
2078 2032 if (temp_file_name != NULL) {
2079 2033 (void) unlink(temp_file_name->string_mb);
2080 2034 }
2081 2035 }
2082 2036
2083 2037 /*
2084 2038 * read_dependency_file(filename)
2085 2039 *
2086 2040 * Read the temp file used for reporting dependencies to make
2087 2041 *
2088 2042 * Parameters:
2089 2043 * filename The name of the file with the state info
2090 2044 *
2091 2045 * Global variables used:
2092 2046 * makefile_type The type of makefile being read
2093 2047 * read_trace_level Debug flag
2094 2048 * temp_file_number The always increasing number for unique files
2095 2049 * trace_reader Debug flag
2096 2050 */
2097 2051 static void
2098 2052 read_dependency_file(register Name filename)
2099 2053 {
2100 2054 register Makefile_type save_makefile_type;
2101 2055
2102 2056 if (filename == NULL) {
2103 2057 return;
2104 2058 }
2105 2059 filename->stat.time = file_no_time;
2106 2060 if (exists(filename) > file_doesnt_exist) {
2107 2061 save_makefile_type = makefile_type;
2108 2062 makefile_type = reading_cpp_file;
2109 2063 if (read_trace_level > 1) {
2110 2064 trace_reader = true;
2111 2065 }
2112 2066 temp_file_number++;
2113 2067 (void) read_simple_file(filename,
2114 2068 false,
2115 2069 false,
2116 2070 false,
2117 2071 false,
2118 2072 false,
2119 2073 false);
2120 2074 trace_reader = false;
2121 2075 makefile_type = save_makefile_type;
2122 2076 }
2123 2077 }
2124 2078
2125 2079 /*
2126 2080 * check_read_state_file()
2127 2081 *
2128 2082 * Check if .make.state has changed
2129 2083 * If it has we reread it
2130 2084 *
2131 2085 * Parameters:
2132 2086 *
2133 2087 * Global variables used:
2134 2088 * make_state Make state file name
2135 2089 * makefile_type Type of makefile being read
2136 2090 * read_trace_level Debug flag
2137 2091 * trace_reader Debug flag
2138 2092 */
2139 2093 static void
2140 2094 check_read_state_file(void)
2141 2095 {
2142 2096 timestruc_t previous = make_state->stat.time;
2143 2097 register Makefile_type save_makefile_type;
2144 2098 register Property makefile;
2145 2099
2146 2100 make_state->stat.time = file_no_time;
2147 2101 if ((exists(make_state) == file_doesnt_exist) ||
2148 2102 (make_state->stat.time == previous)) {
2149 2103 return;
2150 2104 }
2151 2105 save_makefile_type = makefile_type;
2152 2106 makefile_type = rereading_statefile;
2153 2107 /* Make sure we clear the old cached contents of .make.state */
2154 2108 makefile = maybe_append_prop(make_state, makefile_prop);
2155 2109 if (makefile->body.makefile.contents != NULL) {
2156 2110 retmem(makefile->body.makefile.contents);
2157 2111 makefile->body.makefile.contents = NULL;
2158 2112 }
2159 2113 if (read_trace_level > 1) {
2160 2114 trace_reader = true;
2161 2115 }
2162 2116 temp_file_number++;
2163 2117 (void) read_simple_file(make_state,
2164 2118 false,
2165 2119 false,
2166 2120 false,
2167 2121 false,
2168 2122 false,
2169 2123 true);
2170 2124 trace_reader = false;
2171 2125 makefile_type = save_makefile_type;
2172 2126 }
2173 2127
2174 2128 /*
2175 2129 * do_assign(line, target)
2176 2130 *
2177 2131 * Handles runtime assignments for command lines prefixed with "=".
2178 2132 *
2179 2133 * Parameters:
2180 2134 * line The command that contains an assignment
2181 2135 * target The Name of the target, used for error reports
2182 2136 *
2183 2137 * Global variables used:
2184 2138 * assign_done Set to indicate doname needs to reprocess
2185 2139 */
2186 2140 static void
2187 2141 do_assign(register Name line, register Name target)
2188 2142 {
2189 2143 Wstring wcb(line);
2190 2144 register wchar_t *string = wcb.get_string();
2191 2145 register wchar_t *equal;
2192 2146 register Name name;
2193 2147 register Boolean append = false;
2194 2148
2195 2149 /*
2196 2150 * If any runtime assignments are done, doname() must reprocess all
2197 2151 * targets in the future since the macro values used to build the
2198 2152 * command lines for the targets might have changed.
2199 2153 */
2200 2154 assign_done = true;
2201 2155 /* Skip white space. */
2202 2156 while (iswspace(*string)) {
2203 2157 string++;
2204 2158 }
2205 2159 equal = string;
2206 2160 /* Find "+=" or "=". */
2207 2161 while (!iswspace(*equal) &&
2208 2162 (*equal != (int) plus_char) &&
2209 2163 (*equal != (int) equal_char)) {
2210 2164 equal++;
2211 2165 }
2212 2166 /* Internalize macro name. */
2213 2167 name = GETNAME(string, equal - string);
2214 2168 /* Skip over "+=" "=". */
2215 2169 while (!((*equal == (int) nul_char) ||
2216 2170 (*equal == (int) equal_char) ||
2217 2171 (*equal == (int) plus_char))) {
2218 2172 equal++;
2219 2173 }
2220 2174 switch (*equal) {
2221 2175 case nul_char:
2222 2176 fatal(catgets(catd, 1, 31, "= expected in rule `%s' for target `%s'"),
2223 2177 line->string_mb,
2224 2178 target->string_mb);
2225 2179 case plus_char:
2226 2180 append = true;
2227 2181 equal++;
2228 2182 break;
2229 2183 }
2230 2184 equal++;
2231 2185 /* Skip over whitespace in front of value. */
2232 2186 while (iswspace(*equal)) {
2233 2187 equal++;
2234 2188 }
2235 2189 /* Enter new macro value. */
2236 2190 enter_equal(name,
2237 2191 GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2238 2192 append);
2239 2193 }
2240 2194
2241 2195 /*
2242 2196 * build_command_strings(target, line)
2243 2197 *
2244 2198 * Builds the command string to used when
2245 2199 * building a target. If the string is different from the previous one
2246 2200 * is_out_of_date is set.
2247 2201 *
2248 2202 * Parameters:
2249 2203 * target Target to build commands for
2250 2204 * line Where to stuff result
2251 2205 *
2252 2206 * Global variables used:
2253 2207 * c_at The Name "@", used to set macro value
2254 2208 * command_changed Set if command is different from old
2255 2209 * debug_level Should we trace activities?
2256 2210 * do_not_exec_rule Always echo when running -n
2257 2211 * empty_name The Name "", used for empty rule
2258 2212 * funny Semantics of characters
2259 2213 * ignore_errors Used to init field for line
2260 2214 * is_conditional Set to false befor evaling macro, checked
2261 2215 * after expanding macros
2262 2216 * keep_state Indicates that .KEEP_STATE is on
2263 2217 * make_word_mentioned Set by macro eval, inits field for cmd
2264 2218 * query The Name "?", used to set macro value
2265 2219 * query_mentioned Set by macro eval, inits field for cmd
2266 2220 * recursion_level Used for tracing
2267 2221 * silent Used to init field for line
2268 2222 */
2269 2223 static void
2270 2224 build_command_strings(Name target, register Property line)
2271 2225 {
2272 2226 String_rec command_line;
2273 2227 register Cmd_line command_template = line->body.line.command_template;
2274 2228 register Cmd_line *insert = &line->body.line.command_used;
2275 2229 register Cmd_line used = *insert;
2276 2230 wchar_t buffer[STRING_BUFFER_LENGTH];
2277 2231 wchar_t *start;
2278 2232 Name new_command_line;
2279 2233 register Boolean new_command_longer = false;
2280 2234 register Boolean ignore_all_command_dependency = true;
2281 2235 Property member;
2282 2236 static Name less_name;
2283 2237 static Name percent_name;
2284 2238 static Name star;
2285 2239 Name tmp_name;
2286 2240
2287 2241 if (less_name == NULL) {
2288 2242 MBSTOWCS(wcs_buffer, "<");
2289 2243 less_name = GETNAME(wcs_buffer, FIND_LENGTH);
2290 2244 MBSTOWCS(wcs_buffer, "%");
2291 2245 percent_name = GETNAME(wcs_buffer, FIND_LENGTH);
2292 2246 MBSTOWCS(wcs_buffer, "*");
2293 2247 star = GETNAME(wcs_buffer, FIND_LENGTH);
2294 2248 }
2295 2249
2296 2250 /* We have to check if a target depends on conditional macros */
2297 2251 /* Targets that do must be reprocessed by doname() each time around */
2298 2252 /* since the macro values used when building the target might have */
2299 2253 /* changed */
2300 2254 conditional_macro_used = false;
2301 2255 /* If we are building a lib.a(member) target $@ should be bound */
2302 2256 /* to lib.a */
2303 2257 if (target->is_member &&
2304 2258 ((member = get_prop(target->prop, member_prop)) != NULL)) {
2305 2259 target = member->body.member.library;
2306 2260 }
2307 2261 /* If we are building a "::" help target $@ should be bound to */
2308 2262 /* the real target name */
2309 2263 /* A lib.a(member) target is never :: */
2310 2264 if (target->has_target_prop) {
2311 2265 target = get_prop(target->prop, target_prop)->
2312 2266 body.target.target;
2313 2267 }
2314 2268 /* Bind the magic macros that make supplies */
2315 2269 tmp_name = target;
2316 2270 if(tmp_name != NULL) {
2317 2271 if (tmp_name->has_vpath_alias_prop) {
2318 2272 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2319 2273 body.vpath_alias.alias;
2320 2274 }
2321 2275 }
2322 2276 (void) SETVAR(c_at, tmp_name, false);
2323 2277
2324 2278 tmp_name = line->body.line.star;
2325 2279 if(tmp_name != NULL) {
2326 2280 if (tmp_name->has_vpath_alias_prop) {
2327 2281 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2328 2282 body.vpath_alias.alias;
2329 2283 }
2330 2284 }
2331 2285 (void) SETVAR(star, tmp_name, false);
2332 2286
2333 2287 tmp_name = line->body.line.less;
2334 2288 if(tmp_name != NULL) {
2335 2289 if (tmp_name->has_vpath_alias_prop) {
2336 2290 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2337 2291 body.vpath_alias.alias;
2338 2292 }
2339 2293 }
2340 2294 (void) SETVAR(less_name, tmp_name, false);
2341 2295
2342 2296 tmp_name = line->body.line.percent;
2343 2297 if(tmp_name != NULL) {
2344 2298 if (tmp_name->has_vpath_alias_prop) {
2345 2299 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2346 2300 body.vpath_alias.alias;
2347 2301 }
2348 2302 }
2349 2303 (void) SETVAR(percent_name, tmp_name, false);
2350 2304
2351 2305 /* $? is seldom used and it is expensive to build */
2352 2306 /* so we store the list form and build the string on demand */
2353 2307 Chain query_list = NULL;
2354 2308 Chain *query_list_tail = &query_list;
2355 2309
2356 2310 for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) {
2357 2311 *query_list_tail = ALLOC(Chain);
2358 2312 (*query_list_tail)->name = ch->name;
2359 2313 if ((*query_list_tail)->name->has_vpath_alias_prop) {
2360 2314 (*query_list_tail)->name =
2361 2315 get_prop((*query_list_tail)->name->prop,
2362 2316 vpath_alias_prop)->body.vpath_alias.alias;
2363 2317 }
2364 2318 (*query_list_tail)->next = NULL;
2365 2319 query_list_tail = &(*query_list_tail)->next;
2366 2320 }
2367 2321 (void) setvar_daemon(query,
2368 2322 (Name) query_list,
2369 2323 false,
2370 2324 chain_daemon,
2371 2325 false,
2372 2326 debug_level);
2373 2327
2374 2328 /* build $^ */
2375 2329 Chain hat_list = NULL;
2376 2330 Chain *hat_list_tail = &hat_list;
2377 2331
2378 2332 for (Dependency dependency = line->body.line.dependencies;
2379 2333 dependency != NULL;
2380 2334 dependency = dependency->next) {
2381 2335 /* skip automatic dependencies */
2382 2336 if (!dependency->automatic) {
2383 2337 if ((dependency->name != force) &&
2384 2338 (dependency->stale == false)) {
2385 2339 *hat_list_tail = ALLOC(Chain);
2386 2340
2387 2341 if (dependency->name->is_member &&
2388 2342 (get_prop(dependency->name->prop, member_prop) != NULL)) {
2389 2343 (*hat_list_tail)->name =
2390 2344 get_prop(dependency->name->prop,
2391 2345 member_prop)->body.member.member;
2392 2346 } else {
2393 2347 (*hat_list_tail)->name = dependency->name;
2394 2348 }
2395 2349
2396 2350 if((*hat_list_tail)->name != NULL) {
2397 2351 if ((*hat_list_tail)->name->has_vpath_alias_prop) {
2398 2352 (*hat_list_tail)->name =
2399 2353 get_prop((*hat_list_tail)->name->prop,
2400 2354 vpath_alias_prop)->body.vpath_alias.alias;
2401 2355 }
2402 2356 }
2403 2357
2404 2358 (*hat_list_tail)->next = NULL;
2405 2359 hat_list_tail = &(*hat_list_tail)->next;
2406 2360 }
2407 2361 }
2408 2362 }
2409 2363 (void) setvar_daemon(hat,
2410 2364 (Name) hat_list,
2411 2365 false,
2412 2366 chain_daemon,
2413 2367 false,
2414 2368 debug_level);
2415 2369
2416 2370 /* We have two command sequences we need to handle */
2417 2371 /* The old one that we probably read from .make.state */
2418 2372 /* and the new one we are building that will replace the old one */
2419 2373 /* Even when KEEP_STATE is not on we build a new command sequence and store */
2420 2374 /* it in the line prop. This command sequence is then executed by */
2421 2375 /* run_command(). If KEEP_STATE is on it is also later written to */
2422 2376 /* .make.state. The routine replaces the old command line by line with the */
2423 2377 /* new one trying to reuse Cmd_lines */
2424 2378
2425 2379 /* If there is no old command_used we have to start creating */
2426 2380 /* Cmd_lines to keep the new cmd in */
2427 2381 if (used == NULL) {
2428 2382 new_command_longer = true;
2429 2383 *insert = used = ALLOC(Cmd_line);
2430 2384 used->next = NULL;
2431 2385 used->command_line = NULL;
2432 2386 insert = &used->next;
2433 2387 }
2434 2388 /* Run thru the template for the new command and build the expanded */
2435 2389 /* new command lines */
2436 2390 for (;
2437 2391 command_template != NULL;
2438 2392 command_template = command_template->next, insert = &used->next, used = *insert) {
2439 2393 /* If there is no old command_used Cmd_line we need to */
2440 2394 /* create one and say that cmd consistency failed */
2441 2395 if (used == NULL) {
2442 2396 new_command_longer = true;
2443 2397 *insert = used = ALLOC(Cmd_line);
2444 2398 used->next = NULL;
2445 2399 used->command_line = empty_name;
2446 2400 }
2447 2401 /* Prepare the Cmd_line for the processing */
2448 2402 /* The command line prefixes "@-=?" are stripped and that */
2449 2403 /* information is saved in the Cmd_line */
2450 2404 used->assign = false;
2451 2405 used->ignore_error = ignore_errors;
2452 2406 used->silent = silent;
2453 2407 used->always_exec = false;
2454 2408 /* Expand the macros in the command line */
2455 2409 INIT_STRING_FROM_STACK(command_line, buffer);
2456 2410 make_word_mentioned =
2457 2411 query_mentioned =
2458 2412 false;
2459 2413 expand_value(command_template->command_line, &command_line, true);
2460 2414 /* If the macro $(MAKE) is mentioned in the command */
2461 2415 /* "make -n" runs actually execute the command */
2462 2416 used->make_refd = make_word_mentioned;
2463 2417 used->ignore_command_dependency = query_mentioned;
2464 2418 /* Strip the prefixes */
2465 2419 start = command_line.buffer.start;
2466 2420 for (;
2467 2421 iswspace(*start) ||
2468 2422 (get_char_semantics_value(*start) & (int) command_prefix_sem);
2469 2423 start++) {
2470 2424 switch (*start) {
2471 2425 case question_char:
2472 2426 used->ignore_command_dependency = true;
2473 2427 break;
2474 2428 case exclam_char:
2475 2429 used->ignore_command_dependency = false;
2476 2430 break;
2477 2431 case equal_char:
2478 2432 used->assign = true;
2479 2433 break;
2480 2434 case hyphen_char:
2481 2435 used->ignore_error = true;
2482 2436 break;
2483 2437 case at_char:
2484 2438 if (!do_not_exec_rule) {
2485 2439 used->silent = true;
2486 2440 }
2487 2441 break;
2488 2442 case plus_char:
2489 2443 if(posix) {
2490 2444 used->always_exec = true;
2491 2445 }
2492 2446 break;
2493 2447 }
2494 2448 }
2495 2449 /* If all command lines of the template are prefixed with "?"*/
2496 2450 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2497 2451 if (!used->ignore_command_dependency) {
2498 2452 ignore_all_command_dependency = false;
2499 2453 }
2500 2454 /* Internalize the expanded and stripped command line */
2501 2455 new_command_line = GETNAME(start, FIND_LENGTH);
2502 2456 if ((used->command_line == NULL) &&
2503 2457 (line->body.line.sccs_command)) {
2504 2458 used->command_line = new_command_line;
2505 2459 new_command_longer = false;
2506 2460 }
2507 2461 /* Compare it with the old one for command consistency */
2508 2462 if (used->command_line != new_command_line) {
2509 2463 Name vpath_translated = vpath_translation(new_command_line);
2510 2464 if (keep_state &&
2511 2465 !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2512 2466 if (debug_level > 0) {
2513 2467 if (used->command_line != NULL
2514 2468 && *used->command_line->string_mb !=
2515 2469 '\0') {
2516 2470 (void) printf(catgets(catd, 1, 32, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2517 2471 recursion_level,
2518 2472 "",
2519 2473 target->string_mb,
2520 2474 vpath_translated->string_mb,
2521 2475 recursion_level,
2522 2476 "",
2523 2477 used->
2524 2478 command_line->
2525 2479 string_mb);
2526 2480 } else {
2527 2481 (void) printf(catgets(catd, 1, 33, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2528 2482 recursion_level,
2529 2483 "",
2530 2484 target->string_mb,
2531 2485 vpath_translated->string_mb,
2532 2486 recursion_level,
2533 2487 "");
2534 2488 }
2535 2489 }
2536 2490 command_changed = true;
2537 2491 line->body.line.is_out_of_date = true;
2538 2492 }
2539 2493 used->command_line = new_command_line;
2540 2494 }
2541 2495 if (command_line.free_after_use) {
2542 2496 retmem(command_line.buffer.start);
2543 2497 }
2544 2498 }
2545 2499 /* Check if the old command is longer than the new for */
2546 2500 /* command consistency */
2547 2501 if (used != NULL) {
2548 2502 *insert = NULL;
2549 2503 if (keep_state &&
2550 2504 !ignore_all_command_dependency) {
2551 2505 if (debug_level > 0) {
2552 2506 (void) printf(catgets(catd, 1, 34, "%*sBuilding %s because new command shorter than old\n"),
2553 2507 recursion_level,
2554 2508 "",
2555 2509 target->string_mb);
2556 2510 }
2557 2511 command_changed = true;
2558 2512 line->body.line.is_out_of_date = true;
2559 2513 }
2560 2514 }
2561 2515 /* Check if the new command is longer than the old command for */
2562 2516 /* command consistency */
2563 2517 if (new_command_longer &&
2564 2518 !ignore_all_command_dependency &&
2565 2519 keep_state) {
2566 2520 if (debug_level > 0) {
2567 2521 (void) printf(catgets(catd, 1, 35, "%*sBuilding %s because new command longer than old\n"),
2568 2522 recursion_level,
2569 2523 "",
2570 2524 target->string_mb);
2571 2525 }
2572 2526 command_changed = true;
2573 2527 line->body.line.is_out_of_date = true;
2574 2528 }
2575 2529 /* Unbind the magic macros */
2576 2530 (void) SETVAR(c_at, (Name) NULL, false);
2577 2531 (void) SETVAR(star, (Name) NULL, false);
2578 2532 (void) SETVAR(less_name, (Name) NULL, false);
2579 2533 (void) SETVAR(percent_name, (Name) NULL, false);
2580 2534 (void) SETVAR(query, (Name) NULL, false);
2581 2535 if (query_list != NULL) {
2582 2536 delete_query_chain(query_list);
2583 2537 }
2584 2538 (void) SETVAR(hat, (Name) NULL, false);
2585 2539 if (hat_list != NULL) {
2586 2540 delete_query_chain(hat_list);
2587 2541 }
2588 2542
2589 2543 if (conditional_macro_used) {
2590 2544 target->conditional_macro_list = cond_macro_list;
2591 2545 cond_macro_list = NULL;
2592 2546 target->depends_on_conditional = true;
2593 2547 }
2594 2548 }
2595 2549
2596 2550 /*
2597 2551 * touch_command(line, target, result)
2598 2552 *
2599 2553 * If this is an "make -t" run we do this.
2600 2554 * We touch all targets in the target group ("foo + fie:") if any.
2601 2555 *
2602 2556 * Return value:
2603 2557 * Indicates if the command failed or not
2604 2558 *
2605 2559 * Parameters:
2606 2560 * line The command line to update
2607 2561 * target The target we are touching
2608 2562 * result Initial value for the result we return
2609 2563 *
2610 2564 * Global variables used:
2611 2565 * do_not_exec_rule Indicates that -n is on
2612 2566 * silent Do not echo commands
2613 2567 */
2614 2568 static Doname
2615 2569 touch_command(register Property line, register Name target, Doname result)
2616 2570 {
2617 2571 Name name;
2618 2572 register Chain target_group;
2619 2573 String_rec touch_string;
2620 2574 wchar_t buffer[MAXPATHLEN];
2621 2575 Name touch_cmd;
2622 2576 Cmd_line rule;
2623 2577
2624 2578
2625 2579 SEND_MTOOL_MSG(
2626 2580 if (!sent_rsrc_info_msg) {
2627 2581 if (userName[0] == '\0') {
2628 2582 avo_get_user(userName, NULL);
2629 2583 }
2630 2584 if (hostName[0] == '\0') {
2631 2585 strcpy(hostName, avo_hostname());
2632 2586 }
2633 2587 send_rsrc_info_msg(1, hostName, userName);
2634 2588 sent_rsrc_info_msg = 1;
2635 2589 }
2636 2590 send_job_start_msg(line);
2637 2591 job_result_msg = new Avo_MToolJobResultMsg();
2638 2592 );
2639 2593 for (name = target, target_group = NULL; name != NULL;) {
2640 2594 if (!name->is_member) {
2641 2595 /*
2642 2596 * Build a touch command that can be passed
2643 2597 * to dosys(). If KEEP_STATE is on, "make -t"
2644 2598 * will save the proper command, not the
2645 2599 * "touch" in .make.state.
2646 2600 */
2647 2601 INIT_STRING_FROM_STACK(touch_string, buffer);
2648 2602 MBSTOWCS(wcs_buffer, NOCATGETS("touch "));
2649 2603 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2650 2604 touch_cmd = name;
2651 2605 if (name->has_vpath_alias_prop) {
2652 2606 touch_cmd = get_prop(name->prop,
2653 2607 vpath_alias_prop)->
2654 2608 body.vpath_alias.alias;
2655 2609 }
2656 2610 APPEND_NAME(touch_cmd,
2657 2611 &touch_string,
2658 2612 FIND_LENGTH);
2659 2613 touch_cmd = GETNAME(touch_string.buffer.start,
2660 2614 FIND_LENGTH);
2661 2615 if (touch_string.free_after_use) {
2662 2616 retmem(touch_string.buffer.start);
2663 2617 }
2664 2618 if (!silent ||
2665 2619 do_not_exec_rule &&
2666 2620 (target_group == NULL)) {
2667 2621 (void) printf("%s\n", touch_cmd->string_mb);
2668 2622 SEND_MTOOL_MSG(
2669 2623 job_result_msg->appendOutput(AVO_STRDUP(touch_cmd->string_mb));
2670 2624 );
2671 2625 }
2672 2626 /* Run the touch command, or simulate it */
2673 2627 if (!do_not_exec_rule) {
2674 2628
2675 2629 SEND_MTOOL_MSG(
2676 2630 (void) sprintf(mbstring,
2677 2631 NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"),
2678 2632 tmpdir,
2679 2633 getpid(),
2680 2634 file_number++);
2681 2635
2682 2636 int tmp_fd = mkstemp(mbstring);
2683 2637 if(tmp_fd) {
2684 2638 (void) close(tmp_fd);
2685 2639 }
2686 2640
2687 2641 stdout_file = strdup(mbstring);
2688 2642 stderr_file = NULL;
2689 2643 child_pid = pollResults(stdout_file,
2690 2644 (char *)NULL,
2691 2645 (char *)NULL);
2692 2646 );
2693 2647
2694 2648 result = dosys(touch_cmd,
2695 2649 false,
2696 2650 false,
2697 2651 false,
2698 2652 false,
2699 2653 name,
2700 2654 send_mtool_msgs);
2701 2655
2702 2656 SEND_MTOOL_MSG(
2703 2657 append_job_result_msg(job_result_msg);
2704 2658 if (child_pid > 0) {
2705 2659 kill(child_pid, SIGUSR1);
2706 2660 while (!((waitpid(child_pid, 0, 0) == -1)
2707 2661 && (errno == ECHILD)));
2708 2662 }
2709 2663 child_pid = 0;
2710 2664 (void) unlink(stdout_file);
2711 2665 retmem_mb(stdout_file);
2712 2666 stdout_file = NULL;
2713 2667 );
2714 2668
2715 2669 } else {
2716 2670 result = build_ok;
2717 2671 }
2718 2672 } else {
2719 2673 result = build_ok;
2720 2674 }
2721 2675 if (target_group == NULL) {
2722 2676 target_group = line->body.line.target_group;
2723 2677 } else {
2724 2678 target_group = target_group->next;
2725 2679 }
2726 2680 if (target_group != NULL) {
2727 2681 name = target_group->name;
2728 2682 } else {
2729 2683 name = NULL;
2730 2684 }
2731 2685 }
2732 2686 SEND_MTOOL_MSG(
2733 2687 job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
2734 2688 xdr_msg = (RWCollectable*) job_result_msg;
2735 2689 xdr(&xdrs, xdr_msg);
2736 2690 (void) fflush(mtool_msgs_fp);
2737 2691 delete job_result_msg;
2738 2692 );
2739 2693 return result;
2740 2694 }
2741 2695
2742 2696 /*
2743 2697 * update_target(line, result)
2744 2698 *
2745 2699 * updates the status of a target after executing its commands.
2746 2700 *
2747 2701 * Parameters:
2748 2702 * line The command line block to update
2749 2703 * result Indicates that build is OK so can update
2750 2704 *
2751 2705 * Global variables used:
2752 2706 * do_not_exec_rule Indicates that -n is on
2753 2707 * touch Fake the new timestamp if we are just touching
2754 2708 */
2755 2709 void
2756 2710 update_target(Property line, Doname result)
2757 2711 {
2758 2712 Name target;
2759 2713 Chain target_group;
2760 2714 Property line2;
2761 2715 timestruc_t old_stat_time;
2762 2716 Property member;
2763 2717
2764 2718 /*
2765 2719 * [tolik] Additional fix for bug 1063790. It was fixed
2766 2720 * for serial make long ago, but DMake dumps core when
2767 2721 * target is a symlink and sccs file is newer then target.
2768 2722 * In this case, finish_children() calls update_target()
2769 2723 * with line==NULL.
2770 2724 */
2771 2725 if(line == NULL) {
2772 2726 /* XXX. Should we do anything here? */
2773 2727 return;
2774 2728 }
2775 2729
2776 2730 target = line->body.line.target;
2777 2731
2778 2732 if ((result == build_ok) && (line->body.line.command_used != NULL)) {
2779 2733 if (do_not_exec_rule ||
2780 2734 touch ||
2781 2735 (target->is_member &&
2782 2736 (line->body.line.command_template != NULL) &&
2783 2737 (line->body.line.command_template->command_line->string_mb[0] == 0) &&
2784 2738 (line->body.line.command_template->next == NULL))) {
2785 2739 /* If we are simulating execution we need to fake a */
2786 2740 /* new timestamp for the target we didnt build */
2787 2741 target->stat.time = file_max_time;
2788 2742 } else {
2789 2743 /*
2790 2744 * If we really built the target we read the new
2791 2745 * timestamp.
2792 2746 * Fix for bug #1110906: if .c file is newer than
2793 2747 * the corresponding .o file which is in an archive
2794 2748 * file, make will compile the .c file but it won't
2795 2749 * update the object in the .a file.
2796 2750 */
2797 2751 old_stat_time = target->stat.time;
2798 2752 target->stat.time = file_no_time;
2799 2753 (void) exists(target);
2800 2754 if ((target->is_member) &&
2801 2755 (target->stat.time == old_stat_time)) {
2802 2756 member = get_prop(target->prop, member_prop);
2803 2757 if (member != NULL) {
2804 2758 target->stat.time = member->body.member.library->stat.time;
2805 2759 target->stat.time.tv_sec++;
2806 2760 }
2807 2761 }
2808 2762 }
2809 2763 /* If the target is part of a group we need to propagate the */
2810 2764 /* result of the run to all members */
2811 2765 for (target_group = line->body.line.target_group;
2812 2766 target_group != NULL;
2813 2767 target_group = target_group->next) {
2814 2768 target_group->name->stat.time = target->stat.time;
2815 2769 line2 = maybe_append_prop(target_group->name,
2816 2770 line_prop);
2817 2771 line2->body.line.command_used =
2818 2772 line->body.line.command_used;
2819 2773 line2->body.line.target = target_group->name;
2820 2774 }
2821 2775 }
2822 2776 target->has_built = true;
2823 2777 }
2824 2778
2825 2779 /*
2826 2780 * sccs_get(target, command)
2827 2781 *
2828 2782 * Figures out if it possible to sccs get a file
2829 2783 * and builds the command to do it if it is.
2830 2784 *
2831 2785 * Return value:
2832 2786 * Indicates if sccs get failed or not
2833 2787 *
2834 2788 * Parameters:
2835 2789 * target Target to get
2836 2790 * command Where to deposit command to use
2837 2791 *
2838 2792 * Global variables used:
2839 2793 * debug_level Should we trace activities?
2840 2794 * recursion_level Used for tracing
2841 2795 * sccs_get_rule The rule to used for sccs getting
2842 2796 */
2843 2797 static Doname
2844 2798 sccs_get(register Name target, register Property *command)
2845 2799 {
2846 2800 register int result;
2847 2801 char link[MAXPATHLEN];
2848 2802 String_rec string;
2849 2803 wchar_t name[MAXPATHLEN];
2850 2804 register wchar_t *p;
2851 2805 timestruc_t sccs_time;
2852 2806 register Property line;
2853 2807 int sym_link_depth = 0;
2854 2808
2855 2809 /* For sccs, we need to chase symlinks. */
2856 2810 while (target->stat.is_sym_link) {
2857 2811 if (sym_link_depth++ > 90) {
2858 2812 fatal(catgets(catd, 1, 95, "Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2859 2813 target->string_mb);
2860 2814 }
2861 2815 /* Read the value of the link. */
2862 2816 result = readlink_vroot(target->string_mb,
2863 2817 link,
2864 2818 sizeof(link),
2865 2819 NULL,
2866 2820 VROOT_DEFAULT);
2867 2821 if (result == -1) {
2868 2822 fatal(catgets(catd, 1, 36, "Can't read symbolic link `%s': %s"),
2869 2823 target->string_mb, errmsg(errno));
2870 2824 }
2871 2825 link[result] = 0;
2872 2826 /* Use the value to build the proper filename. */
2873 2827 INIT_STRING_FROM_STACK(string, name);
2874 2828
2875 2829 Wstring wcb(target);
2876 2830 if ((link[0] != slash_char) &&
2877 2831 ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) {
2878 2832 append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2879 2833 }
2880 2834 append_string(link, &string, result);
2881 2835 /* Replace the old name with the translated name. */
2882 2836 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2883 2837 (void) exists(target);
2884 2838 if (string.free_after_use) {
2885 2839 retmem(string.buffer.start);
2886 2840 }
2887 2841 }
2888 2842
2889 2843 /*
2890 2844 * read_dir() also reads the ?/SCCS dir and saves information
2891 2845 * about which files have SCSC/s. files.
2892 2846 */
2893 2847 if (target->stat.has_sccs == DONT_KNOW_SCCS) {
2894 2848 read_directory_of_file(target);
2895 2849 }
2896 2850 switch (target->stat.has_sccs) {
2897 2851 case DONT_KNOW_SCCS:
2898 2852 /* We dont know by now there is no SCCS/s.* */
2899 2853 target->stat.has_sccs = NO_SCCS;
2900 2854 case NO_SCCS:
2901 2855 /*
2902 2856 * If there is no SCCS/s.* but the plain file exists,
2903 2857 * we say things are OK.
2904 2858 */
2905 2859 if (target->stat.time > file_doesnt_exist) {
2906 2860 return build_ok;
2907 2861 }
2908 2862 /* If we cant find the plain file, we give up. */
2909 2863 return build_dont_know;
2910 2864 case HAS_SCCS:
2911 2865 /*
2912 2866 * Pay dirt. We now need to figure out if the plain file
2913 2867 * is out of date relative to the SCCS/s.* file.
2914 2868 */
2915 2869 sccs_time = exists(get_prop(target->prop,
2916 2870 sccs_prop)->body.sccs.file);
2917 2871 break;
2918 2872 }
2919 2873
2920 2874 if ((!target->has_complained &&
2921 2875 (sccs_time != file_doesnt_exist) &&
2922 2876 (sccs_get_rule != NULL))) {
2923 2877 /* only checking */
2924 2878 if (command == NULL) {
2925 2879 return build_ok;
2926 2880 }
2927 2881 /*
2928 2882 * We provide a command line for the target. The line is a
2929 2883 * "sccs get" command from default.mk.
2930 2884 */
2931 2885 line = maybe_append_prop(target, line_prop);
2932 2886 *command = line;
2933 2887 if (sccs_time > target->stat.time) {
2934 2888 /*
2935 2889 * And only if the plain file is out of date do we
2936 2890 * request execution of the command.
2937 2891 */
2938 2892 line->body.line.is_out_of_date = true;
2939 2893 if (debug_level > 0) {
2940 2894 (void) printf(catgets(catd, 1, 37, "%*sSccs getting %s because s. file is younger than source file\n"),
2941 2895 recursion_level,
2942 2896 "",
2943 2897 target->string_mb);
2944 2898 }
2945 2899 }
2946 2900 line->body.line.sccs_command = true;
2947 2901 line->body.line.command_template = sccs_get_rule;
2948 2902 if(!svr4 && (!allrules_read || posix)) {
2949 2903 if((target->prop) &&
2950 2904 (target->prop->body.sccs.file) &&
2951 2905 (target->prop->body.sccs.file->string_mb)) {
2952 2906 if((strlen(target->prop->body.sccs.file->string_mb) ==
2953 2907 strlen(target->string_mb) + 2) &&
2954 2908 (target->prop->body.sccs.file->string_mb[0] == 's') &&
2955 2909 (target->prop->body.sccs.file->string_mb[1] == '.')) {
2956 2910
2957 2911 line->body.line.command_template = get_posix_rule;
2958 2912 }
2959 2913 }
2960 2914 }
2961 2915 line->body.line.target = target;
2962 2916 /*
2963 2917 * Also make sure the rule is build with $* and $<
2964 2918 * bound properly.
2965 2919 */
2966 2920 line->body.line.star = NULL;
2967 2921 line->body.line.less = NULL;
2968 2922 line->body.line.percent = NULL;
2969 2923 return build_ok;
2970 2924 }
2971 2925 return build_dont_know;
2972 2926 }
2973 2927
2974 2928 /*
2975 2929 * read_directory_of_file(file)
2976 2930 *
2977 2931 * Reads the directory the specified file lives in.
2978 2932 *
2979 2933 * Parameters:
2980 2934 * file The file we need to read dir for
2981 2935 *
2982 2936 * Global variables used:
2983 2937 * dot The Name ".", used as the default dir
2984 2938 */
2985 2939 void
2986 2940 read_directory_of_file(register Name file)
2987 2941 {
2988 2942
2989 2943 Wstring file_string(file);
2990 2944 wchar_t * wcb = file_string.get_string();
2991 2945 wchar_t usr_include_buf[MAXPATHLEN];
2992 2946 wchar_t usr_include_sys_buf[MAXPATHLEN];
2993 2947
2994 2948 register Name directory = dot;
2995 2949 register wchar_t *p = (wchar_t *) wsrchr(wcb,
2996 2950 (int) slash_char);
2997 2951 register int length = p - wcb;
2998 2952 static Name usr_include;
2999 2953 static Name usr_include_sys;
3000 2954
3001 2955 if (usr_include == NULL) {
3002 2956 MBSTOWCS(usr_include_buf, NOCATGETS("/usr/include"));
3003 2957 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
3004 2958 MBSTOWCS(usr_include_sys_buf, NOCATGETS("/usr/include/sys"));
3005 2959 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
3006 2960 }
3007 2961
3008 2962 /*
3009 2963 * If the filename contains a "/" we have to extract the path
3010 2964 * Else the path defaults to ".".
3011 2965 */
3012 2966 if (p != NULL) {
3013 2967 /*
3014 2968 * Check some popular directories first to possibly
3015 2969 * save time. Compare string length first to gain speed.
3016 2970 */
3017 2971 if ((usr_include->hash.length == length) &&
3018 2972 IS_WEQUALN(usr_include_buf,
3019 2973 wcb,
3020 2974 length)) {
3021 2975 directory = usr_include;
3022 2976 } else if ((usr_include_sys->hash.length == length) &&
3023 2977 IS_WEQUALN(usr_include_sys_buf,
3024 2978 wcb,
3025 2979 length)) {
3026 2980 directory = usr_include_sys;
3027 2981 } else {
3028 2982 directory = GETNAME(wcb, length);
3029 2983 }
3030 2984 }
3031 2985 (void) read_dir(directory,
3032 2986 (wchar_t *) NULL,
3033 2987 (Property) NULL,
3034 2988 (wchar_t *) NULL);
3035 2989 }
3036 2990
3037 2991 /*
3038 2992 * add_pattern_conditionals(target)
3039 2993 *
3040 2994 * Scan the list of conditionals defined for pattern targets and add any
3041 2995 * that match this target to its list of conditionals.
3042 2996 *
3043 2997 * Parameters:
3044 2998 * target The target we should add conditionals for
3045 2999 *
3046 3000 * Global variables used:
3047 3001 * conditionals The list of pattern conditionals
3048 3002 */
3049 3003 static void
3050 3004 add_pattern_conditionals(register Name target)
3051 3005 {
3052 3006 register Property conditional;
3053 3007 Property new_prop;
3054 3008 Property *previous;
3055 3009 Name_rec dummy;
3056 3010 wchar_t *pattern;
3057 3011 wchar_t *percent;
3058 3012 int length;
3059 3013
3060 3014 Wstring wcb(target);
3061 3015 Wstring wcb1;
3062 3016
3063 3017 for (conditional = get_prop(conditionals->prop, conditional_prop);
3064 3018 conditional != NULL;
3065 3019 conditional = get_prop(conditional->next, conditional_prop)) {
3066 3020 wcb1.init(conditional->body.conditional.target);
3067 3021 pattern = wcb1.get_string();
3068 3022 if (pattern[1] != 0) {
3069 3023 percent = (wchar_t *) wschr(pattern, (int) percent_char);
3070 3024 if (!wcb.equaln(pattern, percent-pattern) ||
3071 3025 !IS_WEQUAL(wcb.get_string(wcb.length()-wslen(percent+1)), percent+1)) {
3072 3026 continue;
3073 3027 }
3074 3028 }
3075 3029 for (previous = &target->prop;
3076 3030 *previous != NULL;
3077 3031 previous = &(*previous)->next) {
3078 3032 if (((*previous)->type == conditional_prop) &&
3079 3033 ((*previous)->body.conditional.sequence >
3080 3034 conditional->body.conditional.sequence)) {
3081 3035 break;
3082 3036 }
3083 3037 }
3084 3038 if (*previous == NULL) {
3085 3039 new_prop = append_prop(target, conditional_prop);
3086 3040 } else {
3087 3041 dummy.prop = NULL;
3088 3042 new_prop = append_prop(&dummy, conditional_prop);
3089 3043 new_prop->next = *previous;
3090 3044 *previous = new_prop;
3091 3045 }
3092 3046 target->conditional_cnt++;
3093 3047 new_prop->body.conditional = conditional->body.conditional;
3094 3048 }
3095 3049 }
3096 3050
3097 3051 /*
3098 3052 * set_locals(target, old_locals)
3099 3053 *
3100 3054 * Sets any conditional macros for the target.
3101 3055 * Each target carries a possibly empty set of conditional properties.
3102 3056 *
3103 3057 * Parameters:
3104 3058 * target The target to set conditional macros for
3105 3059 * old_locals Space to store old values in
3106 3060 *
3107 3061 * Global variables used:
3108 3062 * debug_level Should we trace activity?
3109 3063 * is_conditional We need to preserve this value
3110 3064 * recursion_level Used for tracing
3111 3065 */
3112 3066 void
3113 3067 set_locals(register Name target, register Property old_locals)
3114 3068 {
3115 3069 register Property conditional;
3116 3070 register int i;
3117 3071 register Boolean saved_conditional_macro_used;
3118 3072 Chain cond_name;
3119 3073 Chain cond_chain;
3120 3074
3121 3075 if (target->dont_activate_cond_values) {
3122 3076 return;
3123 3077 }
3124 3078
3125 3079 saved_conditional_macro_used = conditional_macro_used;
3126 3080
3127 3081 /* Scan the list of conditional properties and apply each one */
3128 3082 for (conditional = get_prop(target->prop, conditional_prop), i = 0;
3129 3083 conditional != NULL;
3130 3084 conditional = get_prop(conditional->next, conditional_prop),
3131 3085 i++) {
3132 3086 /* Save the old value */
3133 3087 old_locals[i].body.macro =
3134 3088 maybe_append_prop(conditional->body.conditional.name,
3135 3089 macro_prop)->body.macro;
3136 3090 if (debug_level > 1) {
3137 3091 (void) printf(catgets(catd, 1, 38, "%*sActivating conditional value: "),
3138 3092 recursion_level,
3139 3093 "");
3140 3094 }
3141 3095 /* Set the conditional value. Macros are expanded when the */
3142 3096 /* macro is refd as usual */
3143 3097 if ((conditional->body.conditional.name != virtual_root) ||
3144 3098 (conditional->body.conditional.value != virtual_root)) {
3145 3099 (void) SETVAR(conditional->body.conditional.name,
3146 3100 conditional->body.conditional.value,
3147 3101 (Boolean) conditional->body.conditional.append);
3148 3102 }
3149 3103 cond_name = ALLOC(Chain);
3150 3104 cond_name->name = conditional->body.conditional.name;
3151 3105 }
3152 3106 /* Put this target on the front of the chain of conditional targets */
3153 3107 cond_chain = ALLOC(Chain);
3154 3108 cond_chain->name = target;
3155 3109 cond_chain->next = conditional_targets;
3156 3110 conditional_targets = cond_chain;
3157 3111 conditional_macro_used = saved_conditional_macro_used;
3158 3112 }
3159 3113
3160 3114 /*
3161 3115 * reset_locals(target, old_locals, conditional, index)
3162 3116 *
3163 3117 * Removes any conditional macros for the target.
3164 3118 *
3165 3119 * Parameters:
3166 3120 * target The target we are retoring values for
3167 3121 * old_locals The values to restore
3168 3122 * conditional The first conditional block for the target
3169 3123 * index into the old_locals vector
3170 3124 * Global variables used:
3171 3125 * debug_level Should we trace activities?
3172 3126 * recursion_level Used for tracing
3173 3127 */
3174 3128 void
3175 3129 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3176 3130 {
3177 3131 register Property this_conditional;
3178 3132 Chain cond_chain;
3179 3133
3180 3134 if (target->dont_activate_cond_values) {
3181 3135 return;
3182 3136 }
3183 3137
3184 3138 /* Scan the list of conditional properties and restore the old value */
3185 3139 /* to each one Reverse the order relative to when we assigned macros */
3186 3140 this_conditional = get_prop(conditional->next, conditional_prop);
3187 3141 if (this_conditional != NULL) {
3188 3142 reset_locals(target, old_locals, this_conditional, index+1);
3189 3143 } else {
3190 3144 /* Remove conditional target from chain */
3191 3145 if (conditional_targets == NULL ||
3192 3146 conditional_targets->name != target) {
3193 3147 warning(catgets(catd, 1, 39, "Internal error: reset target not at head of condtional_targets chain"));
3194 3148 } else {
3195 3149 cond_chain = conditional_targets->next;
3196 3150 retmem_mb((caddr_t) conditional_targets);
3197 3151 conditional_targets = cond_chain;
3198 3152 }
3199 3153 }
3200 3154 get_prop(conditional->body.conditional.name->prop,
3201 3155 macro_prop)->body.macro = old_locals[index].body.macro;
3202 3156 if (conditional->body.conditional.name == virtual_root) {
3203 3157 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3204 3158 }
3205 3159 if (debug_level > 1) {
3206 3160 if (old_locals[index].body.macro.value != NULL) {
3207 3161 (void) printf(catgets(catd, 1, 40, "%*sdeactivating conditional value: %s= %s\n"),
3208 3162 recursion_level,
3209 3163 "",
3210 3164 conditional->body.conditional.name->
3211 3165 string_mb,
3212 3166 old_locals[index].body.macro.value->
3213 3167 string_mb);
3214 3168 } else {
3215 3169 (void) printf(catgets(catd, 1, 41, "%*sdeactivating conditional value: %s =\n"),
3216 3170 recursion_level,
3217 3171 "",
3218 3172 conditional->body.conditional.name->
3219 3173 string_mb);
3220 3174 }
3221 3175 }
3222 3176 }
3223 3177
3224 3178 /*
3225 3179 * check_auto_dependencies(target, auto_count, automatics)
3226 3180 *
3227 3181 * Returns true if the target now has a dependency
3228 3182 * it didn't previously have (saved on automatics).
3229 3183 *
3230 3184 * Return value:
3231 3185 * true if new dependency found
3232 3186 *
3233 3187 * Parameters:
3234 3188 * target Target we check
3235 3189 * auto_count Number of old automatic vars
3236 3190 * automatics Saved old automatics
3237 3191 *
3238 3192 * Global variables used:
3239 3193 * keep_state Indicates that .KEEP_STATE is on
3240 3194 */
3241 3195 Boolean
3242 3196 check_auto_dependencies(Name target, int auto_count, Name *automatics)
3243 3197 {
3244 3198 Name *p;
3245 3199 int n;
3246 3200 Property line;
3247 3201 Dependency dependency;
3248 3202
3249 3203 if (keep_state) {
3250 3204 if ((line = get_prop(target->prop, line_prop)) == NULL) {
3251 3205 return false;
3252 3206 }
3253 3207 /* Go thru new list of automatic depes */
3254 3208 for (dependency = line->body.line.dependencies;
3255 3209 dependency != NULL;
3256 3210 dependency = dependency->next) {
3257 3211 /* And make sure that each one existed before we */
3258 3212 /* built the target */
3259 3213 if (dependency->automatic && !dependency->stale) {
3260 3214 for (n = auto_count, p = automatics;
3261 3215 n > 0;
3262 3216 n--) {
3263 3217 if (*p++ == dependency->name) {
3264 3218 /* If we can find it on the */
3265 3219 /* saved list of autos we */
3266 3220 /* are OK */
3267 3221 goto not_new;
3268 3222 }
3269 3223 }
3270 3224 /* But if we scan over the old list */
3271 3225 /* of auto. without finding it it is */
3272 3226 /* new and we must check it */
3273 3227 return true;
3274 3228 }
3275 3229 not_new:;
3276 3230 }
3277 3231 return false;
3278 3232 } else {
3279 3233 return false;
3280 3234 }
3281 3235 }
3282 3236
3283 3237
3284 3238 // Recursively delete each of the Chain struct on the chain.
3285 3239
3286 3240 static void
3287 3241 delete_query_chain(Chain ch)
3288 3242 {
3289 3243 if (ch == NULL) {
3290 3244 return;
3291 3245 } else {
3292 3246 delete_query_chain(ch->next);
3293 3247 retmem_mb((char *) ch);
3294 3248 }
3295 3249 }
3296 3250
3297 3251 Doname
3298 3252 target_can_be_built(register Name target) {
3299 3253 Doname result = build_dont_know;
3300 3254 Name true_target = target;
3301 3255 Property line;
3302 3256
3303 3257 if (target == wait_name) {
3304 3258 return(build_ok);
3305 3259 }
3306 3260 /*
3307 3261 * If the target is a constructed one for a "::" target,
3308 3262 * we need to consider that.
3309 3263 */
3310 3264 if (target->has_target_prop) {
3311 3265 true_target = get_prop(target->prop,
3312 3266 target_prop)->body.target.target;
3313 3267 }
3314 3268
3315 3269 (void) exists(true_target);
3316 3270
3317 3271 if (true_target->state == build_running) {
3318 3272 return(build_running);
3319 3273 }
3320 3274 if (true_target->stat.time != file_doesnt_exist) {
3321 3275 result = build_ok;
3322 3276 }
3323 3277
3324 3278 /* get line property for the target */
3325 3279 line = get_prop(true_target->prop, line_prop);
3326 3280
3327 3281 /* first check for explicit rule */
3328 3282 if (line != NULL && line->body.line.command_template != NULL) {
3329 3283 result = build_ok;
3330 3284 }
3331 3285 /* try to find pattern rule */
3332 3286 if (result == build_dont_know) {
3333 3287 result = find_percent_rule(target, NULL, false);
3334 3288 }
3335 3289
3336 3290 /* try to find double suffix rule */
3337 3291 if (result == build_dont_know) {
3338 3292 if (target->is_member) {
3339 3293 Property member = get_prop(target->prop, member_prop);
3340 3294 if (member != NULL && member->body.member.member != NULL) {
3341 3295 result = find_ar_suffix_rule(target, member->body.member.member, NULL, false);
3342 3296 } else {
3343 3297 result = find_double_suffix_rule(target, NULL, false);
3344 3298 }
3345 3299 } else {
3346 3300 result = find_double_suffix_rule(target, NULL, false);
3347 3301 }
3348 3302 }
3349 3303
3350 3304 /* try to find suffix rule */
3351 3305 if ((result == build_dont_know) && second_pass) {
3352 3306 result = find_suffix_rule(target, target, empty_name, NULL, false);
3353 3307 }
3354 3308
3355 3309 /* check for sccs */
3356 3310 if (result == build_dont_know) {
3357 3311 result = sccs_get(target, NULL);
3358 3312 }
3359 3313
3360 3314 /* try to find dyn target */
3361 3315 if (result == build_dont_know) {
3362 3316 Name dtarg = find_dyntarget(target);
3363 3317 if (dtarg != NULL) {
3364 3318 result = target_can_be_built(dtarg);
3365 3319 }
3366 3320 }
3367 3321
3368 3322 /* check whether target was mentioned in makefile */
3369 3323 if (result == build_dont_know) {
3370 3324 if (target->colons != no_colon) {
3371 3325 result = build_ok;
3372 3326 }
3373 3327 }
3374 3328
3375 3329 /* result */
3376 3330 return result;
3377 3331 }
↓ open down ↓ |
1597 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX