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