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