Print this page
make: unifdef for TEAMWARE_MAKE_CMN (defined)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/implicit.cc
+++ new/usr/src/cmd/make/bin/implicit.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 2004 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * implicit.c
28 28 *
29 29 * Handle suffix and percent rules
30 30 */
31 31
32 32 /*
33 33 * Included files
34 34 */
35 35 #include <mk/defs.h>
36 36 #include <mksh/macro.h> /* expand_value() */
37 37 #include <mksh/misc.h> /* retmem() */
38 38
39 39 /*
40 40 * Defined macros
41 41 */
42 42
43 43 /*
44 44 * typedefs & structs
45 45 */
46 46
47 47 /*
48 48 * Static variables
49 49 */
50 50 static wchar_t WIDE_NULL[1] = {(wchar_t) nul_char};
51 51
52 52 /*
53 53 * File table of contents
54 54 */
55 55 extern Doname find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking);
56 56 extern Doname find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking);
57 57 extern Doname find_double_suffix_rule(register Name target, Property *command, Boolean rechecking);
58 58 extern void build_suffix_list(register Name target_suffix);
59 59 extern Doname find_percent_rule(register Name target, Property *command, Boolean rechecking);
60 60 static void create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent);
61 61 static Boolean match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf);
62 62 static void construct_string_from_pattern(Percent pat_rule, String percent, String result);
63 63 static Boolean dependency_exists(Name target, Property line);
64 64 extern Property maybe_append_prop(Name, Property_id);
65 65 extern void add_target_to_chain(Name target, Chain * query);
66 66
67 67 /*
68 68 * find_suffix_rule(target, target_body, target_suffix, command, rechecking)
69 69 *
70 70 * Does the lookup for single and double suffix rules.
71 71 * It calls build_suffix_list() to build the list of possible suffixes
72 72 * for the given target.
73 73 * It then scans the list to find the first possible source file that
74 74 * exists. This is done by concatenating the body of the target name
75 75 * (target name less target suffix) and the source suffix and checking
76 76 * if the resulting file exists.
77 77 *
78 78 * Return value:
79 79 * Indicates if search failed or not
80 80 *
81 81 * Parameters:
82 82 * target The target we need a rule for
83 83 * target_body The target name without the suffix
84 84 * target_suffix The suffix of the target
85 85 * command Pointer to slot to deposit cmd in if found
86 86 * rechecking true if we are rechecking target which depends
87 87 * on conditional macro and keep_state is set
88 88 *
89 89 * Global variables used:
90 90 * debug_level Indicates how much tracing to do
91 91 * recursion_level Used for tracing
92 92 */
93 93
94 94 extern int printf (const char *, ...);
95 95
96 96 static Boolean actual_doname = false;
97 97
98 98 /* /tolik/
99 99 * fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
100 100 * When make attemps to apply % rule it didn't look for a single suffix rule because
101 101 * if "doname" is called from "find_percent_rule" argument "implicit" is set to true
102 102 * and find_suffix_rule was not called. I've commented the checking of "implicit"
103 103 * in "doname" and make got infinite recursion for SVR4 tilde rules.
104 104 * Usage of "we_are_in_tilde" is intended to avoid this recursion.
105 105 */
106 106
107 107 static Boolean we_are_in_tilde = false;
108 108
109 109 Doname
110 110 find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking)
111 111 {
112 112 static wchar_t static_string_buf_3M [ 3 * MAXPATHLEN ];
113 113 Name true_target = target;
114 114 wchar_t *sourcename = (wchar_t*)static_string_buf_3M;
115 115 register wchar_t *put_suffix;
116 116 register Property source_suffix;
117 117 register Name source;
118 118 Doname result;
119 119 register Property line;
120 120 extern Boolean tilde_rule;
121 121 Boolean name_found = true;
122 122 Boolean posix_tilde_attempt = true;
123 123 int src_len = MAXPATHLEN + strlen(target_body->string_mb);
124 124
125 125 /*
126 126 * To avoid infinite recursion
127 127 */
128 128 if(we_are_in_tilde) {
129 129 we_are_in_tilde = false;
130 130 return(build_dont_know);
131 131 }
132 132
133 133 /*
134 134 * If the target is a constructed one for a "::" target,
135 135 * we need to consider that.
136 136 */
137 137 if (target->has_target_prop) {
138 138 true_target = get_prop(target->prop,
139 139 target_prop)->body.target.target;
140 140 }
141 141 if (debug_level > 1) {
142 142 (void) printf(NOCATGETS("%*sfind_suffix_rule(%s,%s,%s)\n"),
143 143 recursion_level,
144 144 "",
145 145 true_target->string_mb,
146 146 target_body->string_mb,
147 147 target_suffix->string_mb);
148 148 }
149 149 if (command != NULL) {
150 150 if ((true_target->suffix_scan_done == true) && (*command == NULL)) {
151 151 return build_ok;
152 152 }
153 153 }
154 154 true_target->suffix_scan_done = true;
155 155 /*
156 156 * Enter all names from the directory where the target lives as
157 157 * files that makes sense.
158 158 * This will make finding the synthesized source possible.
159 159 */
160 160 read_directory_of_file(target_body);
161 161 /* Cache the suffixes for this target suffix if not done. */
162 162 if (!target_suffix->has_read_suffixes) {
163 163 build_suffix_list(target_suffix);
164 164 }
165 165 /* Preload the sourcename vector with the head of the target name. */
166 166 if (src_len >= sizeof(static_string_buf_3M)) {
167 167 sourcename = ALLOC_WC(src_len);
168 168 }
169 169 (void) mbstowcs(sourcename,
170 170 target_body->string_mb,
171 171 (int) target_body->hash.length);
172 172 put_suffix = sourcename + target_body->hash.length;
173 173 /* Scan the suffix list for the target if one exists. */
174 174 if (target_suffix->has_suffixes) {
175 175 posix_attempts:
176 176 for (source_suffix = get_prop(target_suffix->prop,
177 177 suffix_prop);
178 178 source_suffix != NULL;
179 179 source_suffix = get_prop(source_suffix->next,
180 180 suffix_prop)) {
181 181 /* Build the synthesized source name. */
182 182 (void) mbstowcs(put_suffix,
183 183 source_suffix->body.
184 184 suffix.suffix->string_mb,
185 185 (int) source_suffix->body.
186 186 suffix.suffix->hash.length);
187 187 put_suffix[source_suffix->body.
188 188 suffix.suffix->hash.length] =
189 189 (int) nul_char;
190 190 if (debug_level > 1) {
191 191 WCSTOMBS(mbs_buffer, sourcename);
192 192 (void) printf(catgets(catd, 1, 218, "%*sTrying %s\n"),
193 193 recursion_level,
194 194 "",
195 195 mbs_buffer);
196 196 }
197 197 source = getname_fn(sourcename, FIND_LENGTH, false, &name_found);
198 198 /*
199 199 * If the source file is not registered as
200 200 * a file, this source suffix did not match.
201 201 */
202 202 if(vpath_defined && !posix && !svr4) {
203 203 (void) exists(source);
204 204 }
205 205 if (!source->stat.is_file) {
206 206 if(!(posix|svr4))
207 207 {
208 208 if(!name_found) {
209 209 free_name(source);
210 210 }
211 211 continue;
212 212 }
213 213
214 214 /* following code will ensure that the corresponding
215 215 ** tilde rules are executed when corresponding s. file
216 216 ** exists in the current directory. Though the current
217 217 ** target ends with a ~ character, there wont be any
218 218 ** any file in the current directory with that suffix
219 219 ** as it's fictitious. Even if it exists, it'll
220 220 ** execute all the rules for the ~ target.
221 221 */
222 222
223 223 if(source->string_mb[source->hash.length - 1] == '~' &&
224 224 ( svr4 || posix_tilde_attempt ) )
225 225 {
226 226 char *p, *np;
227 227 char *tmpbuf;
228 228
229 229 tmpbuf = getmem(source->hash.length + 8);
230 230 /* + 8 to add "s." or "SCCS/s." */
231 231 memset(tmpbuf,0,source->hash.length + 8);
232 232 source->string_mb[source->hash.length - 1] = '\0';
233 233 if(p = (char *) memchr((char *)source->string_mb,'/',source->hash.length))
234 234 {
235 235 while(1) {
236 236 if(np = (char *) memchr((char *)p+1,'/',source->hash.length - (p - source->string_mb))) {
237 237 p = np;
238 238 } else {break;}
239 239 }
240 240 /* copy everything including '/' */
241 241 strncpy(tmpbuf, source->string_mb, p - source->string_mb + 1);
242 242 strcat(tmpbuf, NOCATGETS("s."));
243 243 strcat(tmpbuf, p+1);
244 244 retmem((wchar_t *) source->string_mb);
245 245 source->string_mb = tmpbuf;
246 246
247 247 } else {
248 248 strcpy(tmpbuf, NOCATGETS("s."));
249 249 strcat(tmpbuf, source->string_mb);
250 250 retmem((wchar_t *) source->string_mb);
251 251 source->string_mb = tmpbuf;
252 252
253 253 }
254 254 source->hash.length = strlen(source->string_mb);
255 255 if(exists(source) == file_doesnt_exist)
256 256 continue;
257 257 tilde_rule = true;
258 258 we_are_in_tilde = true;
259 259 } else {
260 260 if(!name_found) {
261 261 free_name(source);
262 262 }
263 263 continue;
264 264 }
265 265 } else {
266 266 if(posix && posix_tilde_attempt) {
267 267 if(exists(source) == file_doesnt_exist) {
268 268 if(!name_found) {
269 269 free_name(source);
270 270 }
271 271 continue;
272 272 }
273 273 }
274 274 }
275 275
276 276 if (command != NULL) {
277 277 if(!name_found) {
278 278 store_name(source);
279 279 }
280 280 /*
281 281 * The source file is a file.
282 282 * Make sure it is up to date.
283 283 */
284 284 if (dependency_exists(source,
285 285 get_prop(target->prop,
286 286 line_prop))) {
287 287 result = (Doname) source->state;
288 288 } else {
289 289 #if 0 /* with_squiggle sends false, which is buggy. : djay */
290 290 result = doname(source,
291 291 (Boolean) source_suffix->body.
292 292 suffix.suffix->with_squiggle,
293 293 true);
294 294 #else
295 295 result = doname(source,
296 296 true,
297 297 true);
298 298 #endif
299 299 }
300 300 } else {
301 301 result = target_can_be_built(source);
302 302
303 303 if (result == build_ok) {
304 304 return result;
305 305 } else {
306 306 if(!name_found) {
307 307 free_name(source);
308 308 }
309 309 continue;
310 310 }
311 311 }
312 312
313 313 switch (result) {
314 314 case build_dont_know:
315 315 /*
316 316 * If we still can't build the source,
317 317 * this rule is not a match,
318 318 * try the next one.
319 319 */
320 320 if (source->stat.time == file_doesnt_exist) {
321 321 if(!name_found) {
322 322 free_name(source);
323 323 }
324 324 continue;
325 325 }
326 326 case build_running:
327 327 if(!name_found) {
328 328 store_name(source);
329 329 }
330 330 true_target->suffix_scan_done = false;
331 331 line = maybe_append_prop(target, line_prop);
332 332 enter_dependency(line, source, false);
333 333 line->body.line.target = true_target;
334 334 return build_running;
335 335 case build_ok:
336 336 if(!name_found) {
337 337 store_name(source);
338 338 }
339 339 break;
340 340 case build_failed:
341 341 if(!name_found) {
342 342 store_name(source);
343 343 }
344 344 if (sourcename != static_string_buf_3M) {
345 345 retmem(sourcename);
346 346 }
347 347 return build_failed;
348 348 }
349 349
350 350 if (debug_level > 1) {
351 351 WCSTOMBS(mbs_buffer, sourcename);
352 352 (void) printf(catgets(catd, 1, 219, "%*sFound %s\n"),
353 353 recursion_level,
354 354 "",
355 355 mbs_buffer);
356 356 }
357 357
358 358 if (source->depends_on_conditional) {
359 359 target->depends_on_conditional = true;
360 360 }
361 361 /*
362 362 * Since it is possible that the same target is built several times during
363 363 * the make run, we have to patch the target with all information we found
364 364 * here. Thus, the target will have an explicit rule the next time around.
365 365 */
366 366 line = maybe_append_prop(target, line_prop);
367 367 if (*command == NULL) {
368 368 *command = line;
369 369 }
370 370 if ((source->stat.time > (*command)->body.line.dependency_time) &&
371 371 (debug_level > 1)) {
372 372 (void) printf(catgets(catd, 1, 220, "%*sDate(%s)=%s Date-dependencies(%s)=%s\n"),
373 373 recursion_level,
374 374 "",
375 375 source->string_mb,
376 376 time_to_string(source->
377 377 stat.time),
378 378 true_target->string_mb,
379 379 time_to_string((*command)->
380 380 body.line.
381 381 dependency_time));
382 382 }
383 383 /*
384 384 * Determine if this new dependency made the
385 385 * target out of date.
386 386 */
387 387 (*command)->body.line.dependency_time =
388 388 MAX((*command)->body.line.dependency_time,
389 389 source->stat.time);
390 390 Boolean out_of_date;
391 391 if (target->is_member) {
392 392 out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time,
393 393 (*command)->body.line.dependency_time);
394 394 } else {
395 395 out_of_date = (Boolean) OUT_OF_DATE(target->stat.time,
396 396 (*command)->body.line.dependency_time);
397 397 }
398 398 if (build_unconditional || out_of_date) {
399 399 if(!rechecking) {
400 400 line->body.line.is_out_of_date = true;
401 401 }
402 402 if (debug_level > 0) {
403 403 (void) printf(catgets(catd, 1, 221, "%*sBuilding %s using suffix rule for %s%s because it is out of date relative to %s\n"),
404 404 recursion_level,
405 405 "",
406 406 true_target->string_mb,
407 407 source_suffix->body.suffix.suffix->string_mb,
408 408 target_suffix->string_mb,
409 409 source->string_mb);
410 410 }
411 411 }
412 412 /*
413 413 * Add the implicit rule as the target's explicit
414 414 * rule if none actually given, and register
415 415 * dependency.
416 416 * The time checking above really should be
417 417 * conditional on actual use of implicit rule
418 418 * as well.
419 419 */
420 420 line->body.line.sccs_command = false;
421 421 if (line->body.line.command_template == NULL) {
422 422 line->body.line.command_template =
423 423 source_suffix->body.suffix.command_template;
424 424 }
425 425 enter_dependency(line, source, false);
426 426 line->body.line.target = true_target;
427 427 /*
428 428 * Also make sure the rule is built with
429 429 * $* and $< bound properly.
430 430 */
431 431 line->body.line.star = target_body;
432 432 if(svr4|posix) {
433 433 char * p;
434 434 char tstr[256];
435 435 extern Boolean dollarless_flag;
436 436 extern Name dollarless_value;
437 437
438 438 if(tilde_rule) {
439 439 MBSTOWCS(wcs_buffer, NOCATGETS(source->string_mb));
440 440 dollarless_value = GETNAME(wcs_buffer,FIND_LENGTH);
441 441 }
442 442 else {
443 443 dollarless_flag = false;
444 444 }
445 445 }
446 446 line->body.line.less = source;
447 447 line->body.line.percent = NULL;
448 448 add_target_to_chain(source, &(line->body.line.query));
449 449 if (sourcename != static_string_buf_3M) {
450 450 retmem(sourcename);
451 451 }
452 452 return build_ok;
453 453 }
454 454 if(posix && posix_tilde_attempt) {
455 455 posix_tilde_attempt = false;
456 456 goto posix_attempts;
457 457 }
458 458 if ((command != NULL) &&
459 459 ((*command) != NULL) &&
460 460 ((*command)->body.line.star == NULL)) {
461 461 (*command)->body.line.star = target_body;
462 462 }
463 463 }
464 464 if (sourcename != static_string_buf_3M) {
465 465 retmem(sourcename);
466 466 }
467 467 /* Return here in case no rule matched the target */
468 468 return build_dont_know;
469 469 }
470 470
471 471 /*
472 472 * find_ar_suffix_rule(target, true_target, command, rechecking)
473 473 *
474 474 * Scans the .SUFFIXES list and tries
475 475 * to find a suffix on it that matches the tail of the target member name.
476 476 * If it finds a matching suffix it calls find_suffix_rule() to find
477 477 * a rule for the target using the suffix ".a".
478 478 *
479 479 * Return value:
480 480 * Indicates if search failed or not
481 481 *
482 482 * Parameters:
483 483 * target The target we need a rule for
484 484 * true_target The proper name
485 485 * command Pointer to slot where we stuff cmd, if found
486 486 * rechecking true if we are rechecking target which depends
487 487 * on conditional macro and keep_state is set
488 488 *
489 489 * Global variables used:
490 490 * debug_level Indicates how much tracing to do
491 491 * dot_a The Name ".a", compared against
492 492 * recursion_level Used for tracing
493 493 * suffixes List of suffixes used for scan (from .SUFFIXES)
494 494 */
495 495 Doname
496 496 find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking)
497 497 {
498 498 wchar_t *target_end;
499 499 register Dependency suffix;
500 500 register int suffix_length;
501 501 Property line;
502 502 Name body;
503 503 static Name dot_a;
504 504
505 505 Wstring targ_string(true_target);
506 506 Wstring suf_string;
507 507
508 508 if (dot_a == NULL) {
509 509 MBSTOWCS(wcs_buffer, NOCATGETS(".a"));
510 510 dot_a = GETNAME(wcs_buffer, FIND_LENGTH);
511 511 }
512 512 target_end = targ_string.get_string() + true_target->hash.length;
513 513
514 514 /*
515 515 * We compare the tail of the target name with the suffixes
516 516 * from .SUFFIXES.
517 517 */
518 518 if (debug_level > 1) {
519 519 (void) printf(NOCATGETS("%*sfind_ar_suffix_rule(%s)\n"),
520 520 recursion_level,
521 521 "",
522 522 true_target->string_mb);
523 523 }
524 524 /*
525 525 * Scan the .SUFFIXES list to see if the target matches any of
526 526 * those suffixes.
527 527 */
528 528 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
529 529 /* Compare one suffix. */
530 530 suffix_length = suffix->name->hash.length;
531 531 suf_string.init(suffix->name);
532 532 if (!IS_WEQUALN(suf_string.get_string(),
533 533 target_end - suffix_length,
534 534 suffix_length)) {
535 535 goto not_this_one;
536 536 }
537 537 /*
538 538 * The target tail matched a suffix from the .SUFFIXES list.
539 539 * Now check for a rule to match.
540 540 */
541 541 target->suffix_scan_done = false;
542 542 body = GETNAME(targ_string.get_string(),
543 543 (int)(true_target->hash.length -
544 544 suffix_length));
545 545 we_are_in_tilde = false;
546 546 switch (find_suffix_rule(target,
547 547 body,
548 548 dot_a,
549 549 command,
550 550 rechecking)) {
551 551 case build_ok:
552 552 line = get_prop(target->prop, line_prop);
553 553 line->body.line.star = body;
554 554 return build_ok;
555 555 case build_running:
556 556 return build_running;
557 557 }
558 558 /*
559 559 * If no rule was found, we try the next suffix to see
560 560 * if it matches the target tail, and so on.
561 561 * Go here if the suffix did not match the target tail.
562 562 */
563 563 not_this_one:;
564 564 }
565 565 return build_dont_know;
566 566 }
567 567
568 568 /*
569 569 * find_double_suffix_rule(target, command, rechecking)
570 570 *
571 571 * Scans the .SUFFIXES list and tries
572 572 * to find a suffix on it that matches the tail of the target name.
573 573 * If it finds a matching suffix it calls find_suffix_rule() to find
574 574 * a rule for the target.
575 575 *
576 576 * Return value:
577 577 * Indicates if scan failed or not
578 578 *
579 579 * Parameters:
580 580 * target Target we need a rule for
581 581 * command Pointer to slot where we stuff cmd, if found
582 582 * rechecking true if we are rechecking target which depends
583 583 * on conditional macro and keep_state is set
584 584 *
585 585 * Global variables used:
586 586 * debug_level Indicates how much tracing to do
587 587 * recursion_level Used for tracing
588 588 * suffixes List of suffixes used for scan (from .SUFFIXES)
589 589 */
590 590 Doname
591 591 find_double_suffix_rule(register Name target, Property *command, Boolean rechecking)
592 592 {
593 593 Name true_target = target;
594 594 Name target_body;
595 595 register wchar_t *target_end;
596 596 register Dependency suffix;
597 597 register int suffix_length;
598 598 Boolean scanned_once = false;
599 599 Boolean name_found = true;
600 600
601 601 Wstring targ_string;
602 602 Wstring suf_string;
603 603
604 604 /*
605 605 * If the target is a constructed one for a "::" target,
606 606 * we need to consider that.
607 607 */
608 608 if (target->has_target_prop) {
609 609 true_target = get_prop(target->prop,
610 610 target_prop)->body.target.target;
611 611 }
612 612 targ_string.init(true_target);
613 613
614 614 /*
615 615 * We compare the tail of the target name with the
616 616 * suffixes from .SUFFIXES.
617 617 */
618 618 target_end = targ_string.get_string() + true_target->hash.length;
619 619 if (debug_level > 1) {
620 620 (void) printf(NOCATGETS("%*sfind_double_suffix_rule(%s)\n"),
621 621 recursion_level,
622 622 "",
623 623 true_target->string_mb);
624 624 }
625 625 /*
626 626 * Scan the .SUFFIXES list to see if the target matches
627 627 * any of those suffixes.
628 628 */
629 629 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
630 630 target->suffix_scan_done = false;
631 631 true_target->suffix_scan_done = false;
632 632 /* Compare one suffix. */
633 633 suffix_length = suffix->name->hash.length;
634 634 suf_string.init(suffix->name);
635 635 /* Check the lengths, or else RTC will report rua. */
636 636 if (true_target->hash.length < suffix_length) {
637 637 goto not_this_one;
638 638 } else if (!IS_WEQUALN(suf_string.get_string(),
639 639 (target_end - suffix_length),
640 640 suffix_length)) {
641 641 goto not_this_one;
642 642 }
643 643 /*
644 644 * The target tail matched a suffix from the .SUFFIXES list.
645 645 * Now check for a rule to match.
646 646 */
647 647 we_are_in_tilde = false;
648 648 target_body = GETNAME(
649 649 targ_string.get_string(),
650 650 (int)(true_target->hash.length - suffix_length)
651 651 );
652 652 switch (find_suffix_rule(target,
653 653 target_body,
654 654 suffix->name,
655 655 command,
656 656 rechecking)) {
657 657 case build_ok:
658 658 return build_ok;
659 659 case build_running:
660 660 return build_running;
661 661 }
662 662 if (true_target->suffix_scan_done == true) {
663 663 scanned_once = true;
664 664 }
665 665 /*
666 666 * If no rule was found, we try the next suffix to see
667 667 * if it matches the target tail. And so on.
668 668 * Go here if the suffix did not match the target tail.
669 669 */
670 670 not_this_one:;
671 671 }
672 672 if (scanned_once)
673 673 true_target->suffix_scan_done = true;
674 674 return build_dont_know;
675 675 }
676 676
677 677 /*
678 678 * build_suffix_list(target_suffix)
679 679 *
680 680 * Scans the .SUFFIXES list and figures out
681 681 * which suffixes this target can be derived from.
682 682 * The target itself is not know here, we just know the suffix of the
683 683 * target. For each suffix on the list the target can be derived iff
684 684 * a rule exists for the name "<suffix-on-list><target-suffix>".
685 685 * A list of all possible building suffixes is built, with the rule for
686 686 * each, and tacked to the target suffix nameblock.
687 687 *
688 688 * Parameters:
689 689 * target_suffix The suffix we build a match list for
690 690 *
691 691 * Global variables used:
692 692 * debug_level Indicates how much tracing to do
693 693 * recursion_level Used for tracing
694 694 * suffixes List of suffixes used for scan (from .SUFFIXES)
695 695 * working_on_targets Indicates that this is a real target
696 696 */
697 697 void
698 698 build_suffix_list(register Name target_suffix)
699 699 {
700 700 register Dependency source_suffix;
701 701 wchar_t rule_name[MAXPATHLEN];
702 702 register Property line;
703 703 register Property suffix;
704 704 Name rule;
705 705
706 706 /* If this is before default.mk has been read we just return to try */
707 707 /* again later */
708 708 if ((suffixes == NULL) || !working_on_targets) {
709 709 return;
710 710 }
711 711 if (debug_level > 1) {
712 712 (void) printf(NOCATGETS("%*sbuild_suffix_list(%s) "),
713 713 recursion_level,
714 714 "",
715 715 target_suffix->string_mb);
716 716 }
717 717 /* Mark the target suffix saying we cashed its list */
718 718 target_suffix->has_read_suffixes = true;
719 719 /* Scan the .SUFFIXES list */
720 720 for (source_suffix = suffixes;
721 721 source_suffix != NULL;
722 722 source_suffix = source_suffix->next) {
723 723 /*
724 724 * Build the name "<suffix-on-list><target-suffix>".
725 725 * (a popular one would be ".c.o").
726 726 */
727 727 (void) mbstowcs(rule_name,
728 728 source_suffix->name->string_mb,
729 729 (int) source_suffix->name->hash.length);
730 730 (void) mbstowcs(rule_name + source_suffix->name->hash.length,
731 731 target_suffix->string_mb,
732 732 (int) target_suffix->hash.length);
733 733 /*
734 734 * Check if that name has a rule. If not, it cannot match
735 735 * any implicit rule scan and is ignored.
736 736 * The GETNAME() call only checks for presence, it will not
737 737 * enter the name if it is not defined.
738 738 */
739 739 if (((rule = getname_fn(rule_name,
740 740 (int) (source_suffix->name->
741 741 hash.length +
742 742 target_suffix->hash.length),
743 743 true)) != NULL) &&
744 744 ((line = get_prop(rule->prop, line_prop)) != NULL)) {
745 745 if (debug_level > 1) {
746 746 (void) printf("%s ", rule->string_mb);
747 747 }
748 748 /*
749 749 * This makes it possible to quickly determine if
750 750 * it will pay to look for a suffix property.
751 751 */
752 752 target_suffix->has_suffixes = true;
753 753 /*
754 754 * Add the suffix property to the target suffix
755 755 * and save the rule with it.
756 756 * All information the implicit rule scanner need
757 757 * is saved in the suffix property.
758 758 */
759 759 suffix = append_prop(target_suffix, suffix_prop);
760 760 suffix->body.suffix.suffix = source_suffix->name;
761 761 suffix->body.suffix.command_template =
762 762 line->body.line.command_template;
763 763 }
764 764 }
765 765 if (debug_level > 1) {
766 766 (void) printf("\n");
767 767 }
768 768 }
769 769
770 770 /*
771 771 * find_percent_rule(target, command, rechecking)
772 772 *
773 773 * Tries to find a rule from the list of wildcard matched rules.
774 774 * It scans the list attempting to match the target.
775 775 * For each target match it checks if the corresponding source exists.
776 776 * If it does the match is returned.
777 777 * The percent_list is built at makefile read time.
778 778 * Each percent rule get one entry on the list.
779 779 *
780 780 * Return value:
781 781 * Indicates if the scan failed or not
782 782 *
783 783 * Parameters:
784 784 * target The target we need a rule for
785 785 * command Pointer to slot where we stuff cmd, if found
786 786 * rechecking true if we are rechecking target which depends
787 787 * on conditional macro and keep_state is set
788 788 *
789 789 * Global variables used:
790 790 * debug_level Indicates how much tracing to do
791 791 * percent_list List of all percent rules
792 792 * recursion_level Used for tracing
793 793 * empty_name
794 794 */
795 795 Doname
796 796 find_percent_rule(register Name target, Property *command, Boolean rechecking)
797 797 {
798 798 register Percent pat_rule, pat_depe;
799 799 register Name depe_to_check;
800 800 register Dependency depe;
801 801 register Property line;
802 802 String_rec string;
803 803 wchar_t string_buf[STRING_BUFFER_LENGTH];
804 804 String_rec percent;
805 805 wchar_t percent_buf[STRING_BUFFER_LENGTH];
806 806 Name true_target = target;
807 807 Name less;
808 808 Boolean nonpattern_less;
809 809 Boolean dep_name_found = false;
810 810 Doname result = build_dont_know;
811 811 Percent rule_candidate = NULL;
812 812 Boolean rule_maybe_ok;
813 813 Boolean is_pattern;
814 814
815 815 /* If the target is constructed for a "::" target we consider that */
816 816 if (target->has_target_prop) {
817 817 true_target = get_prop(target->prop,
818 818 target_prop)->body.target.target;
819 819 }
820 820 if (target->has_long_member_name) {
821 821 true_target = get_prop(target->prop,
822 822 long_member_name_prop)->body.long_member_name.member_name;
823 823 }
824 824 if (debug_level > 1) {
825 825 (void) printf(catgets(catd, 1, 222, "%*sLooking for %% rule for %s\n"),
826 826 recursion_level,
827 827 "",
828 828 true_target->string_mb);
829 829 }
830 830 for (pat_rule = percent_list;
831 831 pat_rule != NULL;
832 832 pat_rule = pat_rule->next) {
833 833 /* Avoid infinite recursion when expanding patterns */
834 834 if (pat_rule->being_expanded == true) {
835 835 continue;
836 836 }
837 837
838 838 /* Mark this pat_rule as "maybe ok". If no % rule is found
839 839 make will use this rule. The following algorithm is used:
840 840 1) make scans all pattern rules in order to find the rule
841 841 where ALL dependencies, including nonpattern ones, exist or
842 842 can be built (GNU behaviour). If such rule is found make
843 843 will apply it.
844 844 2) During this check make also remembers the first pattern rule
845 845 where all PATTERN dependencies can be build (no matter what
846 846 happens with nonpattern dependencies).
847 847 3) If no rule satisfying 1) is found, make will apply the rule
848 848 remembered in 2) if there is one.
849 849 */
850 850 rule_maybe_ok = true;
851 851
852 852 /* used to track first percent dependency */
853 853 less = NULL;
854 854 nonpattern_less = true;
855 855
856 856 /* check whether pattern matches.
857 857 if it matches, percent string will contain matched percent part of pattern */
858 858 if (!match_found_with_pattern(true_target, pat_rule, &percent, percent_buf)) {
859 859 continue;
860 860 }
861 861 if (pat_rule->dependencies != NULL) {
862 862 for (pat_depe = pat_rule->dependencies;
863 863 pat_depe != NULL;
864 864 pat_depe = pat_depe->next) {
865 865 /* checking result for dependency */
866 866 result = build_dont_know;
867 867
868 868 dep_name_found = true;
869 869 if (pat_depe->name->percent) {
870 870 is_pattern = true;
871 871 /* build dependency name */
872 872 INIT_STRING_FROM_STACK(string, string_buf);
873 873 construct_string_from_pattern(pat_depe, &percent, &string);
874 874 depe_to_check = getname_fn(string.buffer.start,
875 875 FIND_LENGTH,
876 876 false,
877 877 &dep_name_found
878 878 );
879 879
880 880 if ((less == NULL) || nonpattern_less) {
881 881 less = depe_to_check;
882 882 nonpattern_less = false;
883 883 }
884 884 } else {
885 885 /* nonpattern dependency */
886 886 is_pattern = false;
887 887 depe_to_check = pat_depe->name;
888 888 if(depe_to_check->dollar) {
889 889 INIT_STRING_FROM_STACK(string, string_buf);
890 890 expand_value(depe_to_check, &string, false);
891 891 depe_to_check = getname_fn(string.buffer.start,
892 892 FIND_LENGTH,
893 893 false,
894 894 &dep_name_found
895 895 );
896 896 }
897 897 if (less == NULL) {
898 898 less = depe_to_check;
899 899 }
900 900 }
901 901
902 902 if (depe_to_check == empty_name) {
903 903 result = build_ok;
904 904 } else {
905 905 if (debug_level > 1) {
906 906 (void) printf(catgets(catd, 1, 223, "%*sTrying %s\n"),
907 907 recursion_level,
908 908 "",
909 909 depe_to_check->string_mb);
910 910 }
911 911
912 912 pat_rule->being_expanded = true;
913 913
914 914 /* suppress message output */
915 915 int save_debug_level = debug_level;
916 916 debug_level = 0;
917 917
918 918 /* check whether dependency can be built */
919 919 if (dependency_exists(depe_to_check,
920 920 get_prop(target->prop,
921 921 line_prop)))
922 922 {
923 923 result = (Doname) depe_to_check->state;
924 924 } else {
925 925 if(actual_doname) {
926 926 result = doname(depe_to_check, true, true);
927 927 } else {
928 928 result = target_can_be_built(depe_to_check);
929 929 }
930 930 if(!dep_name_found) {
931 931 if(result != build_ok && result != build_running) {
932 932 free_name(depe_to_check);
933 933 } else {
934 934 store_name(depe_to_check);
935 935 }
936 936 }
937 937 }
938 938 if(result != build_ok && is_pattern) {
939 939 rule_maybe_ok = false;
940 940 }
941 941
942 942 /* restore debug_level */
943 943 debug_level = save_debug_level;
944 944 }
945 945
946 946 if (pat_depe->name->percent) {
947 947 if (string.free_after_use) {
948 948 retmem(string.buffer.start);
949 949 }
950 950 }
951 951 /* make can't figure out how to make this dependency */
952 952 if (result != build_ok && result != build_running) {
953 953 pat_rule->being_expanded = false;
954 954 break;
955 955 }
956 956 }
957 957 } else {
958 958 result = build_ok;
959 959 }
960 960
961 961 /* this pattern rule is the needed one since all dependencies could be built */
962 962 if (result == build_ok || result == build_running) {
963 963 break;
964 964 }
965 965
966 966 /* Make does not know how to build some of dependencies from this rule.
967 967 But if all "pattern" dependencies can be built, we remember this rule
968 968 as a candidate for the case if no other pattern rule found.
969 969 */
970 970 if(rule_maybe_ok && rule_candidate == NULL) {
971 971 rule_candidate = pat_rule;
972 972 }
973 973 }
974 974
975 975 /* if no pattern matching rule was found, use the remembered candidate
976 976 or return build_dont_know if there is no candidate.
977 977 */
978 978 if (result != build_ok && result != build_running) {
979 979 if(rule_candidate) {
980 980 pat_rule = rule_candidate;
981 981 } else {
982 982 return build_dont_know;
983 983 }
984 984 }
985 985
986 986 /* if we are performing only check whether dependency could be built with existing rules,
987 987 return success */
988 988 if (command == NULL) {
989 989 if(pat_rule != NULL) {
990 990 pat_rule->being_expanded = false;
991 991 }
992 992 return result;
993 993 }
994 994
995 995 if (debug_level > 1) {
996 996 (void) printf(catgets(catd, 1, 224, "%*sMatched %s:"),
997 997 recursion_level,
998 998 "",
999 999 target->string_mb);
1000 1000
1001 1001 for (pat_depe = pat_rule->dependencies;
1002 1002 pat_depe != NULL;
1003 1003 pat_depe = pat_depe->next) {
1004 1004 if (pat_depe->name->percent) {
1005 1005 INIT_STRING_FROM_STACK(string, string_buf);
1006 1006 construct_string_from_pattern(pat_depe, &percent, &string);
1007 1007 depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH);
1008 1008 } else {
1009 1009 depe_to_check = pat_depe->name;
1010 1010 if(depe_to_check->dollar) {
1011 1011 INIT_STRING_FROM_STACK(string, string_buf);
1012 1012 expand_value(depe_to_check, &string, false);
1013 1013 depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH);
1014 1014 }
1015 1015 }
1016 1016
1017 1017 if (depe_to_check != empty_name) {
1018 1018 (void) printf(" %s", depe_to_check->string_mb);
1019 1019 }
1020 1020 }
1021 1021
1022 1022 (void) printf(catgets(catd, 1, 225, " from: %s:"),
1023 1023 pat_rule->name->string_mb);
1024 1024
1025 1025 for (pat_depe = pat_rule->dependencies;
1026 1026 pat_depe != NULL;
1027 1027 pat_depe = pat_depe->next) {
1028 1028 (void) printf(" %s", pat_depe->name->string_mb);
1029 1029 }
1030 1030
1031 1031 (void) printf("\n");
1032 1032 }
1033 1033
1034 1034 if (true_target->colons == no_colon) {
1035 1035 true_target->colons = one_colon;
1036 1036 }
1037 1037
1038 1038 /* create deppendency list and target group from matched pattern rule */
1039 1039 create_target_group_and_dependencies_list(target, pat_rule, &percent);
1040 1040
1041 1041 /* save command */
1042 1042 line = get_prop(target->prop, line_prop);
1043 1043 *command = line;
1044 1044
1045 1045 /* free query chain if one exist */
1046 1046 while(line->body.line.query != NULL) {
1047 1047 Chain to_free = line->body.line.query;
1048 1048 line->body.line.query = line->body.line.query->next;
1049 1049 retmem_mb((char *) to_free);
1050 1050 }
1051 1051
1052 1052 if (line->body.line.dependencies != NULL) {
1053 1053 /* build all collected dependencies */
1054 1054 for (depe = line->body.line.dependencies;
1055 1055 depe != NULL;
1056 1056 depe = depe->next) {
1057 1057 actual_doname = true;
1058 1058 result = doname_check(depe->name, true, true, depe->automatic);
1059 1059
1060 1060 actual_doname = false;
1061 1061 if (result == build_failed) {
1062 1062 pat_rule->being_expanded = false;
1063 1063 return build_failed;
1064 1064 }
1065 1065 if (result == build_running) {
1066 1066 pat_rule->being_expanded = false;
1067 1067 return build_running;
1068 1068 }
1069 1069
1070 1070 if ((depe->name->stat.time > line->body.line.dependency_time) &&
1071 1071 (debug_level > 1)) {
1072 1072 (void) printf(catgets(catd, 1, 226, "%*sDate(%s)=%s Date-dependencies(%s)=%s\n"),
1073 1073 recursion_level,
1074 1074 "",
1075 1075 depe->name->string_mb,
1076 1076 time_to_string(depe->name->stat.time),
1077 1077 true_target->string_mb,
1078 1078 time_to_string(line->body.line.dependency_time));
1079 1079 }
1080 1080
1081 1081 line->body.line.dependency_time =
1082 1082 MAX(line->body.line.dependency_time, depe->name->stat.time);
1083 1083
1084 1084 /* determine whether this dependency made target out of date */
1085 1085 Boolean out_of_date;
1086 1086 if (target->is_member || depe->name->is_member) {
1087 1087 out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, depe->name->stat.time);
1088 1088 } else {
1089 1089 out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, depe->name->stat.time);
1090 1090 }
1091 1091 if (build_unconditional || out_of_date) {
1092 1092 if(!rechecking) {
1093 1093 line->body.line.is_out_of_date = true;
1094 1094 }
1095 1095 add_target_to_chain(depe->name, &(line->body.line.query));
1096 1096
1097 1097 if (debug_level > 0) {
1098 1098 (void) printf(catgets(catd, 1, 227, "%*sBuilding %s using pattern rule %s:"),
1099 1099 recursion_level,
1100 1100 "",
1101 1101 true_target->string_mb,
1102 1102 pat_rule->name->string_mb);
1103 1103
1104 1104 for (pat_depe = pat_rule->dependencies;
1105 1105 pat_depe != NULL;
1106 1106 pat_depe = pat_depe->next) {
1107 1107 (void) printf(" %s", pat_depe->name->string_mb);
1108 1108 }
1109 1109
1110 1110 (void) printf(catgets(catd, 1, 228, " because it is out of date relative to %s\n"),
1111 1111 depe->name->string_mb);
1112 1112 }
1113 1113 }
1114 1114 }
1115 1115 } else {
1116 1116 if ((true_target->stat.time <= file_doesnt_exist) ||
1117 1117 (true_target->stat.time < line->body.line.dependency_time)) {
1118 1118 if(!rechecking) {
1119 1119 line->body.line.is_out_of_date = true;
1120 1120 }
1121 1121 if (debug_level > 0) {
1122 1122 (void) printf(catgets(catd, 1, 229, "%*sBuilding %s using pattern rule %s: "),
1123 1123 recursion_level,
1124 1124 "",
1125 1125 true_target->string_mb,
1126 1126 pat_rule->name->string_mb,
1127 1127 (target->stat.time > file_doesnt_exist) ?
1128 1128 catgets(catd, 1, 230, "because it is out of date") :
1129 1129 catgets(catd, 1, 236, "because it does not exist"));
1130 1130 }
1131 1131 }
1132 1132 }
1133 1133
1134 1134 /* enter explicit rule from percent rule */
1135 1135 Name lmn_target = true_target;
1136 1136 if (true_target->has_long_member_name) {
1137 1137 lmn_target = get_prop(true_target->prop, long_member_name_prop)->body.long_member_name.member_name;
1138 1138 }
1139 1139 line->body.line.sccs_command = false;
1140 1140 line->body.line.target = true_target;
1141 1141 line->body.line.command_template = pat_rule->command_template;
1142 1142 line->body.line.star = GETNAME(percent.buffer.start, FIND_LENGTH);
1143 1143 line->body.line.less = less;
1144 1144
1145 1145 if (lmn_target->parenleft) {
1146 1146 Wstring lmn_string(lmn_target);
1147 1147
1148 1148 wchar_t *left = (wchar_t *) wschr(lmn_string.get_string(), (int) parenleft_char);
1149 1149 wchar_t *right = (wchar_t *) wschr(lmn_string.get_string(), (int) parenright_char);
1150 1150
↓ open down ↓ |
1150 lines elided |
↑ open up ↑ |
1151 1151 if ((left == NULL) || (right == NULL)) {
1152 1152 line->body.line.percent = NULL;
1153 1153 } else {
1154 1154 line->body.line.percent = GETNAME(left + 1, right - left - 1);
1155 1155 }
1156 1156 } else {
1157 1157 line->body.line.percent = NULL;
1158 1158 }
1159 1159 pat_rule->being_expanded = false;
1160 1160
1161 -#ifdef TEAMWARE_MAKE_CMN
1162 - /*
1163 - * This #ifdef fixes a dmake bug, but introduces bugid 1136156.
1164 - */
1165 1161 return result;
1166 -#else
1167 - return build_ok;
1168 -#endif
1169 1162 }
1170 1163
1171 1164 /*
1172 1165 * match_found_with_pattern
1173 1166 * ( target, pat_rule, percent, percent_buf)
1174 1167 *
1175 1168 * matches "target->string" with a % pattern.
1176 1169 * If pattern contains a MACRO definition, it's expanded first.
1177 1170 *
1178 1171 * Return value:
1179 1172 * true if a match was found
1180 1173 *
1181 1174 * Parameters:
1182 1175 * target The target we're trying to match
1183 1176 * pattern
1184 1177 * percent record that contains "percent_buf" below
1185 1178 * percent_buf This is where the patched % part of pattern is stored
1186 1179 *
1187 1180 */
1188 1181
1189 1182 static Boolean
1190 1183 match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf) {
1191 1184 String_rec string;
1192 1185 wchar_t string_buf[STRING_BUFFER_LENGTH];
1193 1186
1194 1187 /* construct prefix string and check whether prefix matches */
1195 1188 Name prefix = pat_rule->patterns[0];
1196 1189 int prefix_length;
1197 1190
1198 1191 Wstring targ_string(target);
1199 1192 Wstring pref_string(prefix);
1200 1193 Wstring suf_string;
1201 1194
1202 1195 if (prefix->dollar) {
1203 1196 INIT_STRING_FROM_STACK(string, string_buf);
1204 1197 expand_value(prefix, &string, false);
1205 1198 prefix_length = string.text.p - string.buffer.start;
1206 1199 if ((string.buffer.start[0] == (int) period_char) &&
1207 1200 (string.buffer.start[1] == (int) slash_char)) {
1208 1201 string.buffer.start += 2;
1209 1202 prefix_length -= 2;
1210 1203 }
1211 1204 if (!targ_string.equaln(string.buffer.start, prefix_length)) {
1212 1205 return false;
1213 1206 }
1214 1207 } else {
1215 1208 prefix_length = prefix->hash.length;
1216 1209 if (!targ_string.equaln(&pref_string, prefix_length)) {
1217 1210 return false;
1218 1211 }
1219 1212 }
1220 1213
1221 1214 /* do the same with pattern suffix */
1222 1215 Name suffix = pat_rule->patterns[pat_rule->patterns_total - 1];
1223 1216 suf_string.init(suffix);
1224 1217
1225 1218 int suffix_length;
1226 1219 if (suffix->dollar) {
1227 1220 INIT_STRING_FROM_STACK(string, string_buf);
1228 1221 expand_value(suffix, &string, false);
1229 1222 suffix_length = string.text.p - string.buffer.start;
1230 1223 if(suffix_length > target->hash.length) {
1231 1224 return false;
1232 1225 }
1233 1226 if (!targ_string.equal(string.buffer.start, target->hash.length - suffix_length)) {
1234 1227 return false;
1235 1228 }
1236 1229 } else {
1237 1230 suffix_length = (int) suffix->hash.length;
1238 1231 if(suffix_length > target->hash.length) {
1239 1232 return false;
1240 1233 }
1241 1234 if (!targ_string.equal(&suf_string, target->hash.length - suffix_length)) {
1242 1235 return false;
1243 1236 }
1244 1237 }
1245 1238
1246 1239 Boolean match_found = false;
1247 1240 int percent_length = target->hash.length - prefix_length - suffix_length;
1248 1241
1249 1242 while (!match_found && (percent_length >= 0)) {
1250 1243 /* init result string */
1251 1244 INIT_STRING_FROM_STACK(string, string_buf);
1252 1245
1253 1246 /* init percent string */
1254 1247 percent->buffer.start = percent_buf;
1255 1248 percent->text.p = percent_buf;
1256 1249 percent->text.end = NULL;
1257 1250 percent->free_after_use = false;
1258 1251 percent->buffer.end = percent_buf + STRING_BUFFER_LENGTH;
1259 1252
1260 1253 /* construct percent and result strings */
1261 1254 targ_string.append_to_str(percent, prefix_length, percent_length);
1262 1255 construct_string_from_pattern(pat_rule, percent, &string);
1263 1256
1264 1257 /* check for match */
1265 1258 if (targ_string.equal(string.buffer.start, 0)) {
1266 1259 match_found = true;
1267 1260 } else {
1268 1261 percent_length--;
1269 1262 }
1270 1263 }
1271 1264
1272 1265 /* result */
1273 1266 return match_found;
1274 1267 }
1275 1268
1276 1269
1277 1270 /*
1278 1271 * create_target_group_and_dependencies_list
1279 1272 * (target, pat_rule, percent)
1280 1273 *
1281 1274 * constructs dependency list and a target group from pattern.
1282 1275 *
1283 1276 * If we have the lines
1284 1277 * %/%.a + %/%.b + C%/CC%.c: yyy %.d bb%/BB%.e
1285 1278 * commands
1286 1279 *
1287 1280 * and we have matched the pattern xx/xx.a with %/%.a, then we
1288 1281 * construct a target group that looks like this:
1289 1282 * xx/xx.a + xx/xx.b + Cxx/CCxx.c: dependencies
1290 1283 *
1291 1284 * and construct dependency list that looks like this:
1292 1285 * yyy xx.d bbxx/BBxx.e + already existed dependencies
1293 1286 *
1294 1287 * Return value:
1295 1288 * none
1296 1289 *
1297 1290 * Parameters:
1298 1291 * target The target we are building, in the previous
1299 1292 * example, this is xx/xx.a
1300 1293 * pat_rule the % pattern that matched "target", here %/%.a
1301 1294 * percent string containing matched % part. In the example=xx.
1302 1295 *
1303 1296 * Global variables used:
1304 1297 * empty_name
1305 1298 */
1306 1299
1307 1300 static void
1308 1301 create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent) {
1309 1302 String_rec string;
1310 1303 wchar_t string_buf[STRING_BUFFER_LENGTH];
1311 1304 Percent pat_depe;
1312 1305 Name depe;
1313 1306 Property line = maybe_append_prop(target, line_prop);
1314 1307 Chain new_target_group = NULL;
1315 1308 Chain *new_target_group_tail = &new_target_group;
1316 1309 Chain group_member;
1317 1310
1318 1311 /* create and append dependencies from rule */
1319 1312 for (pat_depe = pat_rule->dependencies; pat_depe != NULL; pat_depe = pat_depe->next) {
1320 1313 if (pat_depe->name->percent) {
1321 1314 INIT_STRING_FROM_STACK(string, string_buf);
1322 1315 construct_string_from_pattern(pat_depe, percent, &string);
1323 1316 depe = GETNAME(string.buffer.start, FIND_LENGTH);
1324 1317 if (depe != empty_name) {
1325 1318 enter_dependency(line, depe, false);
1326 1319 }
1327 1320 } else {
1328 1321 depe = pat_depe->name;
1329 1322 if(depe->dollar) {
1330 1323 INIT_STRING_FROM_STACK(string, string_buf);
1331 1324 expand_value(depe, &string, false);
1332 1325 depe = GETNAME(string.buffer.start, FIND_LENGTH);
1333 1326 }
1334 1327 enter_dependency(line, depe, false);
1335 1328 }
1336 1329 }
1337 1330
1338 1331 /* if matched pattern is a group member, create new target group */
1339 1332 for (group_member = pat_rule->target_group; group_member != NULL; group_member = group_member->next) {
1340 1333 Name new_target = group_member->name;
1341 1334 if (group_member->name->percent) {
1342 1335 INIT_STRING_FROM_STACK(string, string_buf);
1343 1336 construct_string_from_pattern(group_member->percent_member, percent, &string);
1344 1337 new_target = GETNAME(string.buffer.start, FIND_LENGTH);
1345 1338 if (new_target == empty_name) {
1346 1339 continue;
1347 1340 }
1348 1341 }
1349 1342
1350 1343 /* check for duplicates */
1351 1344 Chain tgm;
1352 1345 for (tgm = new_target_group; tgm != NULL; tgm = tgm->next) {
1353 1346 if (new_target == tgm->name) {
1354 1347 break;
1355 1348 }
1356 1349 }
1357 1350 if (tgm != NULL) {
1358 1351 continue;
1359 1352 }
1360 1353
1361 1354 /* insert it into the targets list */
1362 1355 (*new_target_group_tail) = ALLOC(Chain);
1363 1356 (*new_target_group_tail)->name = new_target;
1364 1357 (*new_target_group_tail)->next = NULL;
1365 1358 new_target_group_tail = &(*new_target_group_tail)->next;
1366 1359 }
1367 1360
1368 1361 /* now we gathered all dependencies and created target group */
1369 1362 line->body.line.target_group = new_target_group;
1370 1363
1371 1364 /* update properties for group members */
1372 1365 for (group_member = new_target_group; group_member != NULL; group_member = group_member->next) {
1373 1366 if (group_member->name != target) {
1374 1367 group_member->name->prop = target->prop;
1375 1368 group_member->name->conditional_cnt = target->conditional_cnt;
1376 1369 }
1377 1370 }
1378 1371 }
1379 1372
1380 1373 /*
1381 1374 * construct_string_from_pattern
1382 1375 * (pat_rule, percent, result)
1383 1376 *
1384 1377 * after pattern matched a target this routine is called to construct targets and dependencies
1385 1378 * strings from this matched pattern rule and a string (percent) with substitutes % sign in pattern.
1386 1379 *
1387 1380 * Return value:
1388 1381 * none
1389 1382 *
1390 1383 * Parameters:
1391 1384 * pat_rule matched pattern rule
1392 1385 * percent string containing matched % sign part.
1393 1386 * result holds the result of string construction.
1394 1387 *
1395 1388 */
1396 1389 static void
1397 1390 construct_string_from_pattern(Percent pat_rule, String percent, String result) {
1398 1391 for (int i = 0; i < pat_rule->patterns_total; i++) {
1399 1392 if (pat_rule->patterns[i]->dollar) {
1400 1393 expand_value(pat_rule->patterns[i],
1401 1394 result,
1402 1395 false);
1403 1396
1404 1397 } else {
1405 1398 append_string(pat_rule->patterns[i]->string_mb,
1406 1399 result,
1407 1400 pat_rule->patterns[i]->hash.length);
1408 1401 }
1409 1402
1410 1403 if (i < pat_rule->patterns_total - 1) {
1411 1404 append_string(percent->buffer.start,
1412 1405 result,
1413 1406 percent->text.p - percent->buffer.start);
1414 1407 }
1415 1408 }
1416 1409
1417 1410 if ((result->buffer.start[0] == (int) period_char) &&
1418 1411 (result->buffer.start[1] == (int) slash_char)) {
1419 1412 result->buffer.start += 2;
1420 1413 }
1421 1414 }
1422 1415
1423 1416 /*
1424 1417 * dependency_exists(target, line)
1425 1418 *
1426 1419 * Returns true if the target exists in the
1427 1420 * dependency list of the line.
1428 1421 *
1429 1422 * Return value:
1430 1423 * True if target is on dependency list
1431 1424 *
1432 1425 * Parameters:
1433 1426 * target Target we scan for
1434 1427 * line We get the dependency list from here
1435 1428 *
1436 1429 * Global variables used:
1437 1430 */
1438 1431 static Boolean
1439 1432 dependency_exists(Name target, Property line)
1440 1433 {
1441 1434 Dependency dp;
1442 1435
1443 1436 if (line == NULL) {
1444 1437 return false;
1445 1438 }
1446 1439 for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
1447 1440 if (dp->name == target) {
1448 1441 return true;
1449 1442 }
1450 1443 }
1451 1444 return false;
1452 1445 }
1453 1446
1454 1447 void
1455 1448 add_target_to_chain(Name target, Chain * query)
1456 1449 {
1457 1450 if (target->is_member && (get_prop(target->prop, member_prop) != NULL)) {
1458 1451 target = get_prop(target->prop, member_prop)->body.member.member;
1459 1452 }
1460 1453 Chain *query_tail;
1461 1454 for (query_tail = query; *query_tail != NULL; query_tail = &(*query_tail)->next) {
1462 1455 if ((*query_tail)->name == target) {
1463 1456 return;
1464 1457 }
1465 1458 }
1466 1459 *query_tail = ALLOC(Chain);
1467 1460 (*query_tail)->name = target;
1468 1461 (*query_tail)->next = NULL;
1469 1462 }
1470 1463
↓ open down ↓ |
292 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX