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