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