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