Print this page
.PARALLEL implies everything else is to be run in serial.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/read2.cc
+++ new/usr/src/cmd/make/bin/read2.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
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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 2005 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2017 RackTop Systems.
24 26 */
25 27
26 28 /*
27 29 * read.c
28 30 *
29 31 * This file contains the makefile reader.
30 32 */
31 33
32 34 /*
33 35 * Included files
34 36 */
35 37 #include <mk/defs.h>
36 38 #include <mksh/dosys.h> /* sh_command2string() */
37 39 #include <mksh/macro.h> /* expand_value() */
38 40 #include <mksh/misc.h> /* retmem() */
39 41 #include <stdarg.h> /* va_list, va_start(), va_end() */
40 42 #include <libintl.h>
41 43
42 44 /*
43 45 * Defined macros
44 46 */
45 47
46 48 /*
47 49 * typedefs & structs
48 50 */
49 51
50 52 /*
51 53 * Static variables
52 54 */
53 55 static Boolean built_last_make_run_seen;
54 56
55 57 /*
56 58 * File table of contents
57 59 */
58 60 static Name_vector enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names);
59 61 extern Name normalize_name(register wchar_t *name_string, register int length);
60 62 static void read_suffixes_list(register Name_vector depes);
61 63 static void make_relative(wchar_t *to, wchar_t *result);
62 64 static void print_rule(register Cmd_line command);
63 65 static void sh_transform(Name *name, Name *value);
64 66
65 67
66 68 /*
67 69 * enter_name(string, tail_present, string_start, string_end,
68 70 * current_names, extra_names, target_group_seen)
69 71 *
70 72 * Take one string and enter it as a name. The string is passed in
71 73 * two parts. A make string and possibly a C string to append to it.
72 74 * The result is stuffed in the vector current_names.
73 75 * extra_names points to a vector that is used if current_names overflows.
74 76 * This is allocad in the calling routine.
75 77 * Here we handle the "lib.a[members]" notation.
76 78 *
77 79 * Return value:
78 80 * The name vector that was used
79 81 *
80 82 * Parameters:
81 83 * tail_present Indicates if both C and make string was passed
82 84 * string_start C string
83 85 * string_end Pointer to char after last in C string
84 86 * string make style string with head of name
85 87 * current_names Vector to deposit the name in
86 88 * extra_names Where to get next name vector if we run out
87 89 * target_group_seen Pointer to boolean that is set if "+" is seen
88 90 *
89 91 * Global variables used:
90 92 * makefile_type When we read a report file we normalize paths
91 93 * plus Points to the Name "+"
92 94 */
93 95
94 96 Name_vector
95 97 enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen)
96 98 {
97 99 Name name;
98 100 register wchar_t *cp;
99 101 wchar_t ch;
100 102
101 103 /* If we were passed a separate tail of the name we append it to the */
102 104 /* make string with the rest of it */
103 105 if (tail_present) {
104 106 append_string(string_start, string, string_end - string_start);
105 107 string_start = string->buffer.start;
106 108 string_end = string->text.p;
107 109 }
108 110 ch = *string_end;
109 111 *string_end = (int) nul_char;
110 112 /*
111 113 * Check if there are any ( or [ that are not prefixed with $.
112 114 * If there are, we have to deal with the lib.a(members) format.
113 115 */
114 116 for (cp = (wchar_t *) wcschr(string_start, (int) parenleft_char);
115 117 cp != NULL;
116 118 cp = (wchar_t *) wcschr(cp + 1, (int) parenleft_char)) {
117 119 if (*(cp - 1) != (int) dollar_char) {
118 120 *string_end = ch;
119 121 return enter_member_name(string_start,
120 122 cp,
121 123 string_end,
122 124 current_names,
123 125 extra_names);
124 126 }
125 127 }
126 128 *string_end = ch;
127 129
128 130 if (makefile_type == reading_cpp_file) {
129 131 /* Remove extra ../ constructs if we are reading from a report file */
130 132 name = normalize_name(string_start, string_end - string_start);
131 133 } else {
132 134 /*
133 135 * /tolik, fix bug 1197477/
134 136 * Normalize every target name before entering.
135 137 * ..//obj/a.o and ../obj//a.o are not two different targets.
136 138 * There is only one target ../obj/a.o
137 139 */
138 140 /*name = GETNAME(string_start, string_end - string_start);*/
139 141 name = normalize_name(string_start, string_end - string_start);
140 142 }
141 143
142 144 /* Internalize the name. Detect the name "+" (target group here) */
143 145 if(current_names->used != 0 && current_names->names[current_names->used-1] == plus) {
144 146 if(name == plus) {
145 147 return current_names;
146 148 }
147 149 }
148 150 /* If the current_names vector is full we patch in the one from */
149 151 /* extra_names */
150 152 if (current_names->used == VSIZEOF(current_names->names)) {
151 153 if (current_names->next != NULL) {
152 154 current_names = current_names->next;
153 155 } else {
154 156 current_names->next = *extra_names;
155 157 *extra_names = NULL;
156 158 current_names = current_names->next;
157 159 current_names->used = 0;
158 160 current_names->next = NULL;
159 161 }
160 162 }
161 163 current_names->target_group[current_names->used] = NULL;
162 164 current_names->names[current_names->used++] = name;
163 165 if (name == plus) {
164 166 *target_group_seen = true;
165 167 }
166 168 if (tail_present && string->free_after_use) {
167 169 retmem(string->buffer.start);
168 170 }
169 171 return current_names;
170 172 }
171 173
172 174 /*
173 175 * enter_member_name(lib_start, member_start, string_end,
174 176 * current_names, extra_names)
175 177 *
176 178 * A string has been found to contain member names.
177 179 * (The "lib.a[members]" and "lib.a(members)" notation)
178 180 * Handle it pretty much as enter_name() does for simple names.
179 181 *
180 182 * Return value:
181 183 * The name vector that was used
182 184 *
183 185 * Parameters:
184 186 * lib_start Points to the of start of "lib.a(member.o)"
185 187 * member_start Points to "member.o" from above string.
186 188 * string_end Points to char after last of above string.
187 189 * current_names Vector to deposit the name in
188 190 * extra_names Where to get next name vector if we run out
189 191 *
190 192 * Global variables used:
191 193 */
192 194 static Name_vector
193 195 enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names)
194 196 {
195 197 register Boolean entry = false;
196 198 wchar_t buffer[STRING_BUFFER_LENGTH];
197 199 Name lib;
198 200 Name member;
199 201 Name name;
200 202 Property prop;
201 203 wchar_t *memberp;
202 204 wchar_t *q;
203 205 register int paren_count;
204 206 register Boolean has_dollar;
205 207 register wchar_t *cq;
206 208 Name long_member_name = NULL;
207 209
208 210 /* Internalize the name of the library */
209 211 lib = GETNAME(lib_start, member_start - lib_start);
210 212 lib->is_member = true;
211 213 member_start++;
212 214 if (*member_start == (int) parenleft_char) {
213 215 /* This is really the "lib.a((entries))" format */
214 216 entry = true;
215 217 member_start++;
216 218 }
217 219 /* Move the library name to the buffer where we intend to build the */
218 220 /* "lib.a(member)" for each member */
219 221 (void) wcsncpy(buffer, lib_start, member_start - lib_start);
220 222 memberp = buffer + (member_start-lib_start);
221 223 while (1) {
222 224 long_member_name = NULL;
223 225 /* Skip leading spaces */
224 226 for (;
225 227 (member_start < string_end) && iswspace(*member_start);
226 228 member_start++);
227 229 /* Find the end of the member name. Allow nested (). Detect $*/
228 230 for (cq = memberp, has_dollar = false, paren_count = 0;
229 231 (member_start < string_end) &&
230 232 ((*member_start != (int) parenright_char) ||
231 233 (paren_count > 0)) &&
232 234 !iswspace(*member_start);
233 235 *cq++ = *member_start++) {
234 236 switch (*member_start) {
235 237 case parenleft_char:
236 238 paren_count++;
237 239 break;
238 240 case parenright_char:
239 241 paren_count--;
240 242 break;
241 243 case dollar_char:
242 244 has_dollar = true;
243 245 }
244 246 }
245 247 /* Internalize the member name */
246 248 member = GETNAME(memberp, cq - memberp);
247 249 *cq = 0;
248 250 if ((q = (wchar_t *) wcsrchr(memberp, (int) slash_char)) == NULL) {
249 251 q = memberp;
250 252 }
251 253 if ((cq - q > (int) ar_member_name_len) &&
252 254 !has_dollar) {
253 255 *cq++ = (int) parenright_char;
254 256 if (entry) {
255 257 *cq++ = (int) parenright_char;
256 258 }
257 259 long_member_name = GETNAME(buffer, cq - buffer);
258 260 cq = q + (int) ar_member_name_len;
259 261 }
260 262 *cq++ = (int) parenright_char;
261 263 if (entry) {
262 264 *cq++ = (int) parenright_char;
263 265 }
264 266 /* Internalize the "lib.a(member)" notation for this member */
265 267 name = GETNAME(buffer, cq - buffer);
266 268 name->is_member = lib->is_member;
267 269 if (long_member_name != NULL) {
268 270 prop = append_prop(name, long_member_name_prop);
269 271 name->has_long_member_name = true;
270 272 prop->body.long_member_name.member_name =
271 273 long_member_name;
272 274 }
273 275 /* And add the member prop */
274 276 prop = append_prop(name, member_prop);
275 277 prop->body.member.library = lib;
276 278 if (entry) {
277 279 /* "lib.a((entry))" notation */
278 280 prop->body.member.entry = member;
279 281 prop->body.member.member = NULL;
280 282 } else {
281 283 /* "lib.a(member)" Notation */
282 284 prop->body.member.entry = NULL;
283 285 prop->body.member.member = member;
284 286 }
285 287 /* Handle overflow of current_names */
286 288 if (current_names->used == VSIZEOF(current_names->names)) {
287 289 if (current_names->next != NULL) {
288 290 current_names = current_names->next;
289 291 } else {
290 292 if (*extra_names == NULL) {
291 293 current_names =
292 294 current_names->next =
293 295 ALLOC(Name_vector);
294 296 } else {
295 297 current_names =
296 298 current_names->next =
297 299 *extra_names;
298 300 *extra_names = NULL;
299 301 }
300 302 current_names->used = 0;
301 303 current_names->next = NULL;
302 304 }
303 305 }
304 306 current_names->target_group[current_names->used] = NULL;
305 307 current_names->names[current_names->used++] = name;
306 308 while (iswspace(*member_start)) {
307 309 member_start++;
308 310 }
309 311 /* Check if there are more members */
310 312 if ((*member_start == (int) parenright_char) ||
311 313 (member_start >= string_end)) {
312 314 return current_names;
313 315 }
314 316 }
315 317 /* NOTREACHED */
316 318 }
317 319
318 320 /*
319 321 * normalize_name(name_string, length)
320 322 *
321 323 * Take a namestring and remove redundant ../, // and ./ constructs
322 324 *
323 325 * Return value:
324 326 * The normalized name
325 327 *
326 328 * Parameters:
327 329 * name_string Path string to normalize
328 330 * length Length of that string
329 331 *
330 332 * Global variables used:
331 333 * dot The Name ".", compared against
332 334 * dotdot The Name "..", compared against
333 335 */
334 336 Name
335 337 normalize_name(register wchar_t *name_string, register int length)
336 338 {
337 339 static Name dotdot;
338 340 register wchar_t *string = ALLOC_WC(length + 1);
339 341 register wchar_t *string2;
340 342 register wchar_t *cdp;
341 343 wchar_t *current_component;
342 344 Name name;
343 345 register int count;
344 346
345 347 if (dotdot == NULL) {
346 348 MBSTOWCS(wcs_buffer, "..");
347 349 dotdot = GETNAME(wcs_buffer, FIND_LENGTH);
348 350 }
349 351
350 352 /*
351 353 * Copy string removing ./ and //.
352 354 * First strip leading ./
353 355 */
354 356 while ((length > 1) &&
355 357 (name_string[0] == (int) period_char) &&
356 358 (name_string[1] == (int) slash_char)) {
357 359 name_string += 2;
358 360 length -= 2;
359 361 while ((length > 0) && (name_string[0] == (int) slash_char)) {
360 362 name_string++;
361 363 length--;
362 364 }
363 365 }
364 366 /* Then copy the rest of the string removing /./ & // */
365 367 cdp = string;
366 368 while (length > 0) {
367 369 if (((length > 2) &&
368 370 (name_string[0] == (int) slash_char) &&
369 371 (name_string[1] == (int) period_char) &&
370 372 (name_string[2] == (int) slash_char)) ||
371 373 ((length == 2) &&
372 374 (name_string[0] == (int) slash_char) &&
373 375 (name_string[1] == (int) period_char))) {
374 376 name_string += 2;
375 377 length -= 2;
376 378 continue;
377 379 }
378 380 if ((length > 1) &&
379 381 (name_string[0] == (int) slash_char) &&
380 382 (name_string[1] == (int) slash_char)) {
381 383 name_string++;
382 384 length--;
383 385 continue;
384 386 }
385 387 *cdp++ = *name_string++;
386 388 length--;
387 389 }
388 390 *cdp = (int) nul_char;
389 391 /*
390 392 * Now scan for <name>/../ and remove such combinations iff <name>
391 393 * is not another ..
392 394 * Each time something is removed, the whole process is restarted.
393 395 */
394 396 removed_one:
395 397 name_string = string;
396 398 string2 = name_string; /*save for free*/
397 399 current_component =
398 400 cdp =
399 401 string =
400 402 ALLOC_WC((length = wcslen(name_string)) + 1);
401 403 while (length > 0) {
402 404 if (((length > 3) &&
403 405 (name_string[0] == (int) slash_char) &&
404 406 (name_string[1] == (int) period_char) &&
405 407 (name_string[2] == (int) period_char) &&
406 408 (name_string[3] == (int) slash_char)) ||
407 409 ((length == 3) &&
408 410 (name_string[0] == (int) slash_char) &&
409 411 (name_string[1] == (int) period_char) &&
410 412 (name_string[2] == (int) period_char))) {
411 413 /* Positioned on the / that starts a /.. sequence */
412 414 if (((count = cdp - current_component) != 0) &&
413 415 (exists(name = GETNAME(string, cdp - string)) > file_doesnt_exist) &&
414 416 (!name->stat.is_sym_link)) {
415 417 name = GETNAME(current_component, count);
416 418 if(name != dotdot) {
417 419 cdp = current_component;
418 420 name_string += 3;
419 421 length -= 3;
420 422 if (length > 0) {
421 423 name_string++; /* skip slash */
422 424 length--;
423 425 while (length > 0) {
424 426 *cdp++ = *name_string++;
425 427 length--;
426 428 }
427 429 }
428 430 *cdp = (int) nul_char;
429 431 retmem(string2);
430 432 goto removed_one;
431 433 }
432 434 }
433 435 }
434 436 if ((*cdp++ = *name_string++) == (int) slash_char) {
435 437 current_component = cdp;
436 438 }
437 439 length--;
438 440 }
439 441 *cdp = (int) nul_char;
440 442 if (string[0] == (int) nul_char) {
441 443 name = dot;
442 444 } else {
443 445 name = GETNAME(string, FIND_LENGTH);
444 446 }
445 447 retmem(string);
446 448 retmem(string2);
447 449 return name;
448 450 }
449 451
450 452 /*
451 453 * find_target_groups(target_list)
452 454 *
453 455 * If a "+" was seen when the target list was scanned we need to extract
454 456 * the groups. Each target in the name vector that is a member of a
455 457 * group gets a pointer to a chain of all the members stuffed in its
456 458 * target_group vector slot
457 459 *
458 460 * Parameters:
459 461 * target_list The list of targets that contains "+"
460 462 *
461 463 * Global variables used:
462 464 * plus The Name "+", compared against
463 465 */
464 466 Chain
465 467 find_target_groups(register Name_vector target_list, register int i, Boolean reset)
466 468 {
467 469 static Chain target_group = NULL;
468 470 static Chain tail_target_group = NULL;
469 471 static Name *next;
470 472 static Boolean clear_target_group = false;
471 473
472 474 if (reset) {
473 475 target_group = NULL;
474 476 tail_target_group = NULL;
475 477 clear_target_group = false;
476 478 }
477 479
478 480 /* Scan the list of targets */
479 481 /* If the previous target terminated a group */
480 482 /* we flush the pointer to that member chain */
481 483 if (clear_target_group) {
482 484 clear_target_group = false;
483 485 target_group = NULL;
484 486 }
485 487 /* Pick up a pointer to the cell with */
486 488 /* the next target */
487 489 if (i + 1 != target_list->used) {
488 490 next = &target_list->names[i + 1];
489 491 } else {
490 492 next = (target_list->next != NULL) ?
491 493 &target_list->next->names[0] : NULL;
492 494 }
493 495 /* We have four states here :
494 496 * 0: No target group started and next element is not "+"
495 497 * This is not interesting.
496 498 * 1: A target group is being built and the next element
497 499 * is not "+". This terminates the group.
498 500 * 2: No target group started and the next member is "+"
499 501 * This is the first target in a group.
500 502 * 3: A target group started and the next member is a "+"
501 503 * The group continues.
502 504 */
503 505 switch ((target_group ? 1 : 0) +
504 506 (next && (*next == plus) ?
505 507 2 : 0)) {
506 508 case 0: /* Not target_group */
507 509 break;
508 510 case 1: /* Last group member */
509 511 /* We need to keep this pointer so */
510 512 /* we can stuff it for last member */
511 513 clear_target_group = true;
512 514 /* fall into */
513 515 case 3: /* Middle group member */
514 516 /* Add this target to the */
515 517 /* current chain */
516 518 tail_target_group->next = ALLOC(Chain);
517 519 tail_target_group = tail_target_group->next;
518 520 tail_target_group->next = NULL;
519 521 tail_target_group->name = target_list->names[i];
520 522 break;
521 523 case 2: /* First group member */
522 524 /* Start a new chain */
523 525 target_group = tail_target_group = ALLOC(Chain);
524 526 target_group->next = NULL;
525 527 target_group->name = target_list->names[i];
526 528 break;
527 529 }
528 530 /* Stuff the current chain, if any, in the */
529 531 /* targets group slot */
530 532 target_list->target_group[i] = target_group;
531 533 if ((next != NULL) &&
532 534 (*next == plus)) {
533 535 *next = NULL;
534 536 }
535 537 return (tail_target_group);
536 538 }
537 539
538 540 /*
539 541 * enter_dependencies(target, target_group, depes, command, separator)
540 542 *
541 543 * Take one target and a list of dependencies and process the whole thing.
542 544 * The target might be special in some sense in which case that is handled
543 545 *
544 546 * Parameters:
545 547 * target The target we want to enter
546 548 * target_group Non-NULL if target is part of a group this time
547 549 * depes A list of dependencies for the target
548 550 * command The command the target should be entered with
549 551 * separator Indicates if this is a ":" or a "::" rule
550 552 *
551 553 * Static variables used:
552 554 * built_last_make_run_seen If the previous target was
553 555 * .BUILT_LAST_MAKE_RUN we say to rewrite
554 556 * the state file later on
555 557 *
556 558 * Global variables used:
557 559 * command_changed Set to indicate if .make.state needs rewriting
558 560 * default_target_to_build Set to the target if reading makefile
559 561 * and this is the first regular target
560 562 * force The Name " FORCE", used with "::" targets
561 563 * makefile_type We do different things for makefile vs. report
562 564 * not_auto The Name ".NOT_AUTO", compared against
563 565 * recursive_name The Name ".RECURSIVE", compared against
564 566 * temp_file_number Used to figure out when to clear stale
565 567 * automatic dependencies
566 568 * trace_reader Indicates that we should echo stuff we read
567 569 */
568 570 void
569 571 enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator)
570 572 {
571 573 register int i;
572 574 register Property line;
573 575 Name name;
574 576 Name directory;
575 577 wchar_t *namep;
576 578 char *mb_namep;
577 579 Dependency dp;
578 580 Dependency *dpp;
579 581 Property line2;
580 582 wchar_t relative[MAXPATHLEN];
581 583 register int recursive_state;
582 584 Boolean register_as_auto;
583 585 Boolean not_auto_found;
584 586 char *slash;
585 587 Wstring depstr;
586 588
587 589 /* Check if this is a .RECURSIVE line */
588 590 if ((depes->used >= 3) &&
589 591 (depes->names[0] == recursive_name)) {
590 592 target->has_recursive_dependency = true;
591 593 depes->names[0] = NULL;
592 594 recursive_state = 0;
593 595 dp = NULL;
594 596 dpp = &dp;
595 597 /* Read the dependencies. They are "<directory> <target-made>*/
596 598 /* <makefile>*" */
597 599 for (; depes != NULL; depes = depes->next) {
598 600 for (i = 0; i < depes->used; i++) {
599 601 if (depes->names[i] != NULL) {
600 602 switch (recursive_state++) {
601 603 case 0: /* Directory */
602 604 {
603 605 depstr.init(depes->names[i]);
604 606 make_relative(depstr.get_string(),
605 607 relative);
606 608 directory =
607 609 GETNAME(relative,
608 610 FIND_LENGTH);
609 611 }
610 612 break;
611 613 case 1: /* Target */
612 614 name = depes->names[i];
613 615 break;
614 616 default: /* Makefiles */
615 617 *dpp = ALLOC(Dependency);
616 618 (*dpp)->next = NULL;
617 619 (*dpp)->name = depes->names[i];
618 620 (*dpp)->automatic = false;
619 621 (*dpp)->stale = false;
620 622 (*dpp)->built = false;
621 623 dpp = &((*dpp)->next);
622 624 break;
623 625 }
624 626 }
625 627 }
626 628 }
627 629 /* Check if this recursion already has been reported else */
628 630 /* enter the recursive prop for the target */
629 631 /* The has_built flag is used to tell if this .RECURSIVE */
630 632 /* was discovered from this run (read from a tmp file) */
631 633 /* or was from discovered from the original .make.state */
632 634 /* file */
633 635 for (line = get_prop(target->prop, recursive_prop);
634 636 line != NULL;
635 637 line = get_prop(line->next, recursive_prop)) {
636 638 if ((line->body.recursive.directory == directory) &&
637 639 (line->body.recursive.target == name)) {
638 640 line->body.recursive.makefiles = dp;
639 641 line->body.recursive.has_built =
640 642 (Boolean)
641 643 (makefile_type == reading_cpp_file);
642 644 return;
643 645 }
644 646 }
645 647 line2 = append_prop(target, recursive_prop);
646 648 line2->body.recursive.directory = directory;
647 649 line2->body.recursive.target = name;
648 650 line2->body.recursive.makefiles = dp;
649 651 line2->body.recursive.has_built =
650 652 (Boolean) (makefile_type == reading_cpp_file);
651 653 line2->body.recursive.in_depinfo = false;
652 654 return;
653 655 }
654 656 /* If this is the first target that doesnt start with a "." in the */
655 657 /* makefile we remember that */
656 658 Wstring tstr(target);
657 659 wchar_t * wcb = tstr.get_string();
658 660 if ((makefile_type == reading_makefile) &&
659 661 (default_target_to_build == NULL) &&
660 662 ((wcb[0] != (int) period_char) ||
661 663 wcschr(wcb, (int) slash_char))) {
662 664
663 665 /* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO):
664 666 ** The target with empty name cannot be default_target_to_build
665 667 */
666 668 if (target->hash.length != 0)
667 669 default_target_to_build = target;
668 670 }
669 671 /* Check if the line is ":" or "::" */
670 672 if (makefile_type == reading_makefile) {
671 673 if (target->colons == no_colon) {
672 674 target->colons = separator;
673 675 } else {
674 676 if (target->colons != separator) {
675 677 fatal_reader(gettext(":/:: conflict for target `%s'"),
676 678 target->string_mb);
677 679 }
678 680 }
679 681 if (target->colons == two_colon) {
680 682 if (depes->used == 0) {
681 683 /* If this is a "::" type line with no */
682 684 /* dependencies we add one "FRC" type */
683 685 /* dependency for free */
684 686 depes->used = 1; /* Force :: targets with no
685 687 * depes to always run */
686 688 depes->names[0] = force;
687 689 }
688 690 /* Do not delete "::" type targets when interrupted */
689 691 target->stat.is_precious = true;
690 692 /*
691 693 * Build a synthetic target "<number>%target"
692 694 * for "target".
693 695 */
694 696 mb_namep = getmem((int) (strlen(target->string_mb) + 10));
695 697 namep = ALLOC_WC((int) (target->hash.length + 10));
696 698 slash = strrchr(target->string_mb, (int) slash_char);
697 699 if (slash == NULL) {
698 700 (void) sprintf(mb_namep,
699 701 "%d@%s",
700 702 target->colon_splits++,
701 703 target->string_mb);
702 704 } else {
703 705 *slash = 0;
704 706 (void) sprintf(mb_namep,
705 707 "%s/%d@%s",
706 708 target->string_mb,
707 709 target->colon_splits++,
708 710 slash + 1);
709 711 *slash = (int) slash_char;
710 712 }
711 713 MBSTOWCS(namep, mb_namep);
712 714 retmem_mb(mb_namep);
713 715 name = GETNAME(namep, FIND_LENGTH);
714 716 retmem(namep);
715 717 if (trace_reader) {
716 718 (void) printf("%s:\t", target->string_mb);
717 719 }
718 720 /* Make "target" depend on "<number>%target */
719 721 line2 = maybe_append_prop(target, line_prop);
720 722 enter_dependency(line2, name, true);
721 723 line2->body.line.target = target;
722 724 /* Put a prop on "<number>%target that makes */
723 725 /* appear as "target" */
724 726 /* when it is processed */
725 727 maybe_append_prop(name, target_prop)->
726 728 body.target.target = target;
727 729 target->is_double_colon_parent = true;
728 730 name->is_double_colon = true;
729 731 name->has_target_prop = true;
730 732 if (trace_reader) {
731 733 (void) printf("\n");
732 734 }
733 735 (target = name)->stat.is_file = true;
734 736 }
735 737 }
736 738 /* This really is a regular dependency line. Just enter it */
737 739 line = maybe_append_prop(target, line_prop);
738 740 line->body.line.target = target;
739 741 /* Depending on what kind of makefile we are reading we have to */
740 742 /* treat things differently */
741 743 switch (makefile_type) {
742 744 case reading_makefile:
743 745 /* Reading regular makefile. Just notice whether this */
744 746 /* redefines the rule for the target */
745 747 if (command != NULL) {
746 748 if (line->body.line.command_template != NULL) {
747 749 line->body.line.command_template_redefined =
748 750 true;
749 751 if ((wcb[0] == (int) period_char) &&
750 752 !wcschr(wcb, (int) slash_char)) {
751 753 line->body.line.command_template =
752 754 command;
753 755 }
754 756 } else {
755 757 line->body.line.command_template = command;
756 758 }
757 759 } else {
758 760 if ((wcb[0] == (int) period_char) &&
759 761 !wcschr(wcb, (int) slash_char)) {
760 762 line->body.line.command_template = command;
761 763 }
762 764 }
763 765 break;
764 766 case rereading_statefile:
765 767 /* Rereading the statefile. We only enter thing that changed */
766 768 /* since the previous time we read it */
767 769 if (!built_last_make_run_seen) {
768 770 for (Cmd_line next, cmd = command; cmd != NULL; cmd = next) {
769 771 next = cmd->next;
770 772 free(cmd);
771 773 }
772 774 return;
773 775 }
774 776 built_last_make_run_seen = false;
775 777 command_changed = true;
776 778 target->ran_command = true;
777 779 case reading_statefile:
778 780 /* Reading the statefile for the first time. Enter the rules */
779 781 /* as "Commands used" not "templates to use" */
780 782 if (command != NULL) {
781 783 for (Cmd_line next, cmd = line->body.line.command_used;
782 784 cmd != NULL; cmd = next) {
783 785 next = cmd->next;
784 786 free(cmd);
785 787 }
786 788 line->body.line.command_used = command;
787 789 }
788 790 case reading_cpp_file:
789 791 /* Reading report file from programs that reports */
790 792 /* dependencies. If this is the first time the target is */
791 793 /* read from this reportfile we clear all old */
792 794 /* automatic depes */
793 795 if (target->temp_file_number == temp_file_number) {
794 796 break;
795 797 }
796 798 target->temp_file_number = temp_file_number;
797 799 command_changed = true;
798 800 if (line != NULL) {
799 801 for (dp = line->body.line.dependencies;
800 802 dp != NULL;
801 803 dp = dp->next) {
802 804 if (dp->automatic) {
803 805 dp->stale = true;
804 806 }
805 807 }
806 808 }
807 809 break;
808 810 default:
809 811 fatal_reader(gettext("Internal error. Unknown makefile type %d"),
810 812 makefile_type);
811 813 }
812 814 /* A target may only be involved in one target group */
813 815 if (line->body.line.target_group != NULL) {
814 816 if (target_group != NULL) {
815 817 fatal_reader(gettext("Too many target groups for target `%s'"),
816 818 target->string_mb);
817 819 }
818 820 } else {
819 821 line->body.line.target_group = target_group;
820 822 }
821 823
822 824 if (trace_reader) {
823 825 (void) printf("%s:\t", target->string_mb);
824 826 }
825 827 /* Enter the dependencies */
826 828 register_as_auto = BOOLEAN(makefile_type != reading_makefile);
827 829 not_auto_found = false;
828 830 for (;
829 831 (depes != NULL) && !not_auto_found;
830 832 depes = depes->next) {
831 833 for (i = 0; i < depes->used; i++) {
832 834 /* the dependency .NOT_AUTO signals beginning of
833 835 * explicit dependancies which were put at end of
834 836 * list in .make.state file - we stop entering
835 837 * dependencies at this point
836 838 */
837 839 if (depes->names[i] == not_auto) {
838 840 not_auto_found = true;
839 841 break;
840 842 }
841 843 enter_dependency(line,
842 844 depes->names[i],
843 845 register_as_auto);
844 846 }
845 847 }
846 848 if (trace_reader) {
847 849 (void) printf("\n");
848 850 print_rule(command);
849 851 }
850 852 }
851 853
852 854 /*
853 855 * enter_dependency(line, depe, automatic)
854 856 *
855 857 * Enter one dependency. Do not enter duplicates.
856 858 *
857 859 * Parameters:
858 860 * line The line block that the dependeny is
859 861 * entered for
860 862 * depe The dependency to enter
861 863 * automatic Used to set the field "automatic"
862 864 *
863 865 * Global variables used:
864 866 * makefile_type We do different things for makefile vs. report
865 867 * trace_reader Indicates that we should echo stuff we read
866 868 * wait_name The Name ".WAIT", compared against
867 869 */
868 870 void
869 871 enter_dependency(Property line, register Name depe, Boolean automatic)
870 872 {
871 873 register Dependency dp;
872 874 register Dependency *insert;
873 875
874 876 if (trace_reader) {
875 877 (void) printf("%s ", depe->string_mb);
876 878 }
877 879 /* Find the end of the list and check for duplicates */
878 880 for (insert = &line->body.line.dependencies, dp = *insert;
879 881 dp != NULL;
880 882 insert = &dp->next, dp = *insert) {
881 883 if ((dp->name == depe) && (depe != wait_name)) {
882 884 if (dp->automatic) {
883 885 dp->automatic = automatic;
884 886 if (automatic) {
885 887 dp->built = false;
886 888 depe->stat.is_file = true;
887 889 }
888 890 }
889 891 dp->stale = false;
890 892 return;
891 893 }
892 894 }
893 895 /* Insert the new dependency since we couldnt find it */
894 896 dp = *insert = ALLOC(Dependency);
895 897 dp->name = depe;
896 898 dp->next = NULL;
897 899 dp->automatic = automatic;
898 900 dp->stale = false;
899 901 dp->built = false;
900 902 depe->stat.is_file = true;
901 903
902 904 if ((makefile_type == reading_makefile) &&
903 905 (line != NULL) &&
904 906 (line->body.line.target != NULL)) {
905 907 line->body.line.target->has_regular_dependency = true;
906 908 }
907 909 }
908 910
909 911 /*
910 912 * enter_percent(target, depes, command)
911 913 *
912 914 * Enter "x%y : a%b" type lines
913 915 * % patterns are stored in four parts head and tail for target and source
914 916 *
915 917 * Parameters:
916 918 * target Left hand side of pattern
917 919 * depes The dependency list with the rh pattern
918 920 * command The command for the pattern
919 921 *
920 922 * Global variables used:
921 923 * empty_name The Name "", compared against
922 924 * percent_list The list of all percent rules, added to
923 925 * trace_reader Indicates that we should echo stuff we read
924 926 */
925 927 Percent
926 928 enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command)
927 929 {
928 930 register Percent result = ALLOC(Percent);
929 931 register Percent depe;
930 932 register Percent *depe_tail = &result->dependencies;
931 933 register Percent *insert;
932 934 register wchar_t *cp, *cp1;
933 935 Name_vector nvp;
934 936 int i;
935 937 int pattern;
936 938
937 939 result->next = NULL;
938 940 result->patterns = NULL;
939 941 result->patterns_total = 0;
940 942 result->command_template = command;
941 943 result->being_expanded = false;
942 944 result->name = target;
943 945 result->dependencies = NULL;
944 946 result->target_group = target_group;
945 947
946 948 /* get patterns count */
947 949 Wstring wcb(target);
948 950 cp = wcb.get_string();
949 951 while (true) {
950 952 cp = (wchar_t *) wcschr(cp, (int) percent_char);
951 953 if (cp != NULL) {
952 954 result->patterns_total++;
953 955 cp++;
954 956 } else {
955 957 break;
956 958 }
957 959 }
958 960 result->patterns_total++;
959 961
960 962 /* allocate storage for patterns */
961 963 result->patterns = (Name *) getmem(sizeof(Name) * result->patterns_total);
962 964
963 965 /* then create patterns */
964 966 cp = wcb.get_string();
965 967 pattern = 0;
966 968 while (true) {
967 969 cp1 = (wchar_t *) wcschr(cp, (int) percent_char);
968 970 if (cp1 != NULL) {
969 971 result->patterns[pattern] = GETNAME(cp, cp1 - cp);
970 972 cp = cp1 + 1;
971 973 pattern++;
972 974 } else {
973 975 result->patterns[pattern] = GETNAME(cp, (int) target->hash.length - (cp - wcb.get_string()));
974 976 break;
975 977 }
976 978 }
977 979
978 980 Wstring wcb1;
979 981
980 982 /* build dependencies list */
981 983 for (nvp = depes; nvp != NULL; nvp = nvp->next) {
982 984 for (i = 0; i < nvp->used; i++) {
983 985 depe = ALLOC(Percent);
984 986 depe->next = NULL;
985 987 depe->patterns = NULL;
986 988 depe->patterns_total = 0;
987 989 depe->name = nvp->names[i];
988 990 depe->dependencies = NULL;
989 991 depe->command_template = NULL;
990 992 depe->being_expanded = false;
991 993 depe->target_group = NULL;
992 994
993 995 *depe_tail = depe;
994 996 depe_tail = &depe->next;
995 997
996 998 if (depe->name->percent) {
997 999 /* get patterns count */
998 1000 wcb1.init(depe->name);
999 1001 cp = wcb1.get_string();
1000 1002 while (true) {
1001 1003 cp = (wchar_t *) wcschr(cp, (int) percent_char);
1002 1004 if (cp != NULL) {
1003 1005 depe->patterns_total++;
1004 1006 cp++;
1005 1007 } else {
1006 1008 break;
1007 1009 }
1008 1010 }
1009 1011 depe->patterns_total++;
1010 1012
1011 1013 /* allocate storage for patterns */
1012 1014 depe->patterns = (Name *) getmem(sizeof(Name) * depe->patterns_total);
1013 1015
1014 1016 /* then create patterns */
1015 1017 cp = wcb1.get_string();
1016 1018 pattern = 0;
1017 1019 while (true) {
1018 1020 cp1 = (wchar_t *) wcschr(cp, (int) percent_char);
1019 1021 if (cp1 != NULL) {
1020 1022 depe->patterns[pattern] = GETNAME(cp, cp1 - cp);
1021 1023 cp = cp1 + 1;
1022 1024 pattern++;
1023 1025 } else {
1024 1026 depe->patterns[pattern] = GETNAME(cp, (int) depe->name->hash.length - (cp - wcb1.get_string()));
1025 1027 break;
1026 1028 }
1027 1029 }
1028 1030 }
1029 1031 }
1030 1032 }
1031 1033
1032 1034 /* Find the end of the percent list and append the new pattern */
1033 1035 for (insert = &percent_list; (*insert) != NULL; insert = &(*insert)->next);
1034 1036 *insert = result;
1035 1037
1036 1038 if (trace_reader) {
1037 1039 (void) printf("%s:", result->name->string_mb);
1038 1040
1039 1041 for (depe = result->dependencies; depe != NULL; depe = depe->next) {
1040 1042 (void) printf(" %s", depe->name->string_mb);
1041 1043 }
1042 1044
1043 1045 (void) printf("\n");
1044 1046
1045 1047 print_rule(command);
1046 1048 }
1047 1049
1048 1050 return result;
1049 1051 }
1050 1052
1051 1053 /*
1052 1054 * enter_dyntarget(target)
1053 1055 *
1054 1056 * Enter "$$(MACRO) : b" type lines
1055 1057 *
1056 1058 * Parameters:
1057 1059 * target Left hand side of pattern
1058 1060 *
1059 1061 * Global variables used:
1060 1062 * dyntarget_list The list of all percent rules, added to
1061 1063 * trace_reader Indicates that we should echo stuff we read
1062 1064 */
1063 1065 Dyntarget
1064 1066 enter_dyntarget(register Name target)
1065 1067 {
1066 1068 register Dyntarget result = ALLOC(Dyntarget);
1067 1069 Dyntarget p;
1068 1070 Dyntarget *insert;
1069 1071 int i;
1070 1072
1071 1073 result->next = NULL;
1072 1074 result->name = target;
1073 1075
1074 1076
1075 1077 /* Find the end of the dyntarget list and append the new pattern */
1076 1078 for (insert = &dyntarget_list, p = *insert;
1077 1079 p != NULL;
1078 1080 insert = &p->next, p = *insert);
1079 1081 *insert = result;
1080 1082
1081 1083 if (trace_reader) {
1082 1084 (void) printf("Dynamic target %s:\n", result->name->string_mb);
1083 1085 }
1084 1086 return( result);
1085 1087 }
1086 1088
1087 1089
1088 1090 /*
1089 1091 * special_reader(target, depes, command)
1090 1092 *
1091 1093 * Read the pseudo targets make knows about
1092 1094 * This handles the special targets that should not be entered as regular
1093 1095 * target/dependency sets.
1094 1096 *
1095 1097 * Parameters:
1096 1098 * target The special target
1097 1099 * depes The list of dependencies it was entered with
1098 1100 * command The command it was entered with
1099 1101 *
1100 1102 * Static variables used:
1101 1103 * built_last_make_run_seen Set to indicate .BUILT_LAST... seen
1102 1104 *
1103 1105 * Global variables used:
1104 1106 * all_parallel Set to indicate that everything runs parallel
1105 1107 * svr4 Set when ".SVR4" target is read
1106 1108 * svr4_name The Name ".SVR4"
1107 1109 * posix Set when ".POSIX" target is read
1108 1110 * posix_name The Name ".POSIX"
1109 1111 * current_make_version The Name "<current version number>"
1110 1112 * default_rule Set when ".DEFAULT" target is read
1111 1113 * default_rule_name The Name ".DEFAULT", used for tracing
1112 1114 * dot_keep_state The Name ".KEEP_STATE", used for tracing
1113 1115 * ignore_errors Set if ".IGNORE" target is read
1114 1116 * ignore_name The Name ".IGNORE", used for tracing
1115 1117 * keep_state Set if ".KEEP_STATE" target is read
1116 1118 * no_parallel_name The Name ".NO_PARALLEL", used for tracing
1117 1119 * only_parallel Set to indicate only some targets runs parallel
1118 1120 * parallel_name The Name ".PARALLEL", used for tracing
1119 1121 * precious The Name ".PRECIOUS", used for tracing
1120 1122 * sccs_get_name The Name ".SCCS_GET", used for tracing
1121 1123 * sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing
1122 1124 * get_name The Name ".GET", used for tracing
1123 1125 * sccs_get_rule Set when ".SCCS_GET" target is read
1124 1126 * silent Set when ".SILENT" target is read
1125 1127 * silent_name The Name ".SILENT", used for tracing
1126 1128 * trace_reader Indicates that we should echo stuff we read
1127 1129 */
1128 1130 void
1129 1131 special_reader(Name target, register Name_vector depes, Cmd_line command)
1130 1132 {
1131 1133 register int n;
1132 1134
1133 1135 switch (target->special_reader) {
1134 1136
1135 1137 case svr4_special:
1136 1138 if (depes->used != 0) {
1137 1139 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1138 1140 target->string_mb);
1139 1141 }
1140 1142 svr4 = true;
1141 1143 posix = false;
1142 1144 keep_state = false;
1143 1145 all_parallel = false;
1144 1146 only_parallel = false;
1145 1147 if (trace_reader) {
1146 1148 (void) printf("%s:\n", svr4_name->string_mb);
1147 1149 }
1148 1150 break;
1149 1151
1150 1152 case posix_special:
1151 1153 if(svr4)
1152 1154 break;
1153 1155 if (depes->used != 0) {
1154 1156 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1155 1157 target->string_mb);
1156 1158 }
1157 1159 posix = true;
1158 1160 /* with posix on, use the posix get rule */
1159 1161 sccs_get_rule = sccs_get_posix_rule;
1160 1162 /* turn keep state off being SunPro make specific */
1161 1163 keep_state = false;
1162 1164 /* Use /usr/xpg4/bin/sh on Solaris */
1163 1165 MBSTOWCS(wcs_buffer, "/usr/xpg4/bin/sh");
1164 1166 (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
1165 1167 if (trace_reader) {
1166 1168 (void) printf("%s:\n", posix_name->string_mb);
1167 1169 }
1168 1170 break;
1169 1171
1170 1172 case built_last_make_run_special:
1171 1173 built_last_make_run_seen = true;
1172 1174 break;
1173 1175
1174 1176 case default_special:
1175 1177 if (depes->used != 0) {
1176 1178 warning(gettext("Illegal dependency list for target `%s'"),
1177 1179 target->string_mb);
1178 1180 }
1179 1181 default_rule = command;
1180 1182 if (trace_reader) {
1181 1183 (void) printf("%s:\n",
1182 1184 default_rule_name->string_mb);
1183 1185 print_rule(command);
1184 1186 }
1185 1187 break;
1186 1188
1187 1189
1188 1190 case ignore_special:
1189 1191 if ((depes->used != 0) &&(!posix)){
1190 1192 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1191 1193 target->string_mb);
1192 1194 }
1193 1195 if (depes->used == 0)
1194 1196 {
1195 1197 ignore_errors_all = true;
1196 1198 }
1197 1199 if(svr4) {
1198 1200 ignore_errors_all = true;
1199 1201 break;
1200 1202 }
1201 1203 for (; depes != NULL; depes = depes->next) {
1202 1204 for (n = 0; n < depes->used; n++) {
1203 1205 depes->names[n]->ignore_error_mode = true;
1204 1206 }
1205 1207 }
1206 1208 if (trace_reader) {
1207 1209 (void) printf("%s:\n", ignore_name->string_mb);
1208 1210 }
1209 1211 break;
1210 1212
1211 1213 case keep_state_special:
1212 1214 if(svr4)
1213 1215 break;
1214 1216 /* ignore keep state, being SunPro make specific */
1215 1217 if(posix)
1216 1218 break;
1217 1219 if (depes->used != 0) {
1218 1220 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1219 1221 target->string_mb);
1220 1222 }
1221 1223 keep_state = true;
1222 1224 if (trace_reader) {
1223 1225 (void) printf("%s:\n",
1224 1226 dot_keep_state->string_mb);
1225 1227 }
1226 1228 break;
1227 1229
1228 1230 case keep_state_file_special:
1229 1231 if(svr4)
1230 1232 break;
1231 1233 if(posix)
1232 1234 break;
1233 1235 /* it's not necessary to specify KEEP_STATE, if this
1234 1236 ** is given, so set the keep_state.
1235 1237 */
1236 1238 keep_state = true;
1237 1239 if (depes->used != 0) {
1238 1240 if((!make_state) ||(!strcmp(make_state->string_mb,".make.state"))) {
1239 1241 make_state = depes->names[0];
1240 1242 }
1241 1243 }
1242 1244 break;
1243 1245 case make_version_special:
1244 1246 if(svr4)
1245 1247 break;
1246 1248 if (depes->used != 1) {
1247 1249 fatal_reader(gettext("Illegal dependency list for target `%s'"),
1248 1250 target->string_mb);
1249 1251 }
1250 1252 if (depes->names[0] != current_make_version) {
1251 1253 /*
1252 1254 * Special case the fact that version 1.0 and 1.1
1253 1255 * are identical.
1254 1256 */
1255 1257 if (!IS_EQUAL(depes->names[0]->string_mb,
1256 1258 "VERSION-1.1") ||
1257 1259 !IS_EQUAL(current_make_version->string_mb,
1258 1260 "VERSION-1.0")) {
1259 1261 /*
1260 1262 * Version mismatches should cause the
1261 1263 * .make.state file to be skipped.
1262 1264 * This is currently not true - it is read
1263 1265 * anyway.
1264 1266 */
1265 1267 warning(gettext("Version mismatch between current version `%s' and `%s'"),
1266 1268 current_make_version->string_mb,
1267 1269 depes->names[0]->string_mb);
1268 1270 }
1269 1271 }
1270 1272 break;
↓ open down ↓ |
1237 lines elided |
↑ open up ↑ |
1271 1273
1272 1274 case no_parallel_special:
1273 1275 if(svr4)
1274 1276 break;
1275 1277 /* Set the no_parallel bit for all the targets on */
1276 1278 /* the dependency list */
1277 1279 if (depes->used == 0) {
1278 1280 /* only those explicitly made parallel */
1279 1281 only_parallel = true;
1280 1282 all_parallel = false;
1283 + } else {
1284 + only_parallel = false;
1285 + all_parallel = true;
1281 1286 }
1282 1287 for (; depes != NULL; depes = depes->next) {
1283 1288 for (n = 0; n < depes->used; n++) {
1284 1289 if (trace_reader) {
1285 1290 (void) printf("%s:\t%s\n",
1286 1291 no_parallel_name->string_mb,
1287 1292 depes->names[n]->string_mb);
1288 1293 }
1289 1294 depes->names[n]->no_parallel = true;
1290 1295 depes->names[n]->parallel = false;
1291 1296 }
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
1292 1297 }
1293 1298 break;
1294 1299
1295 1300 case parallel_special:
1296 1301 if(svr4)
1297 1302 break;
1298 1303 if (depes->used == 0) {
1299 1304 /* everything runs in parallel */
1300 1305 all_parallel = true;
1301 1306 only_parallel = false;
1307 + } else {
1308 + all_parallel = false;
1309 + only_parallel = true;
1302 1310 }
1303 1311 /* Set the parallel bit for all the targets on */
1304 1312 /* the dependency list */
1305 1313 for (; depes != NULL; depes = depes->next) {
1306 1314 for (n = 0; n < depes->used; n++) {
1307 1315 if (trace_reader) {
1308 1316 (void) printf("%s:\t%s\n",
1309 1317 parallel_name->string_mb,
1310 1318 depes->names[n]->string_mb);
1311 1319 }
1312 1320 depes->names[n]->parallel = true;
1313 1321 depes->names[n]->no_parallel = false;
1314 1322 }
1315 1323 }
1316 1324 break;
1317 1325
1318 1326 case localhost_special:
1319 1327 if(svr4)
1320 1328 break;
1321 1329 /* Set the no_parallel bit for all the targets on */
1322 1330 /* the dependency list */
1323 1331 if (depes->used == 0) {
1324 1332 /* only those explicitly made parallel */
1325 1333 only_parallel = true;
1326 1334 all_parallel = false;
1327 1335 }
1328 1336 for (; depes != NULL; depes = depes->next) {
1329 1337 for (n = 0; n < depes->used; n++) {
1330 1338 if (trace_reader) {
1331 1339 (void) printf("%s:\t%s\n",
1332 1340 localhost_name->string_mb,
1333 1341 depes->names[n]->string_mb);
1334 1342 }
1335 1343 depes->names[n]->no_parallel = true;
1336 1344 depes->names[n]->parallel = false;
1337 1345 depes->names[n]->localhost = true;
1338 1346 }
1339 1347 }
1340 1348 break;
1341 1349
1342 1350 case precious_special:
1343 1351 if (depes->used == 0) {
1344 1352 /* everything is precious */
1345 1353 all_precious = true;
1346 1354 } else {
1347 1355 all_precious = false;
1348 1356 }
1349 1357 if(svr4) {
1350 1358 all_precious = true;
1351 1359 break;
1352 1360 }
1353 1361 /* Set the precious bit for all the targets on */
1354 1362 /* the dependency list */
1355 1363 for (; depes != NULL; depes = depes->next) {
1356 1364 for (n = 0; n < depes->used; n++) {
1357 1365 if (trace_reader) {
1358 1366 (void) printf("%s:\t%s\n",
1359 1367 precious->string_mb,
1360 1368 depes->names[n]->string_mb);
1361 1369 }
1362 1370 depes->names[n]->stat.is_precious = true;
1363 1371 }
1364 1372 }
1365 1373 break;
1366 1374
1367 1375 case sccs_get_special:
1368 1376 if (depes->used != 0) {
1369 1377 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1370 1378 target->string_mb);
1371 1379 }
1372 1380 sccs_get_rule = command;
1373 1381 sccs_get_org_rule = command;
1374 1382 if (trace_reader) {
1375 1383 (void) printf("%s:\n", sccs_get_name->string_mb);
1376 1384 print_rule(command);
1377 1385 }
1378 1386 break;
1379 1387
1380 1388 case sccs_get_posix_special:
1381 1389 if (depes->used != 0) {
1382 1390 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1383 1391 target->string_mb);
1384 1392 }
1385 1393 sccs_get_posix_rule = command;
1386 1394 if (trace_reader) {
1387 1395 (void) printf("%s:\n", sccs_get_posix_name->string_mb);
1388 1396 print_rule(command);
1389 1397 }
1390 1398 break;
1391 1399
1392 1400 case get_posix_special:
1393 1401 if (depes->used != 0) {
1394 1402 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1395 1403 target->string_mb);
1396 1404 }
1397 1405 get_posix_rule = command;
1398 1406 if (trace_reader) {
1399 1407 (void) printf("%s:\n", get_posix_name->string_mb);
1400 1408 print_rule(command);
1401 1409 }
1402 1410 break;
1403 1411
1404 1412 case get_special:
1405 1413 if(!svr4) {
1406 1414 break;
1407 1415 }
1408 1416 if (depes->used != 0) {
1409 1417 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1410 1418 target->string_mb);
1411 1419 }
1412 1420 get_rule = command;
1413 1421 sccs_get_rule = command;
1414 1422 if (trace_reader) {
1415 1423 (void) printf("%s:\n", get_name->string_mb);
1416 1424 print_rule(command);
1417 1425 }
1418 1426 break;
1419 1427
1420 1428 case silent_special:
1421 1429 if ((depes->used != 0) && (!posix)){
1422 1430 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1423 1431 target->string_mb);
1424 1432 }
1425 1433 if (depes->used == 0)
1426 1434 {
1427 1435 silent_all = true;
1428 1436 }
1429 1437 if(svr4) {
1430 1438 silent_all = true;
1431 1439 break;
1432 1440 }
1433 1441 for (; depes != NULL; depes = depes->next) {
1434 1442 for (n = 0; n < depes->used; n++) {
1435 1443 depes->names[n]->silent_mode = true;
1436 1444 }
1437 1445 }
1438 1446 if (trace_reader) {
1439 1447 (void) printf("%s:\n", silent_name->string_mb);
1440 1448 }
1441 1449 break;
1442 1450
1443 1451 case suffixes_special:
1444 1452 read_suffixes_list(depes);
1445 1453 break;
1446 1454
1447 1455 default:
1448 1456
1449 1457 fatal_reader(gettext("Internal error: Unknown special reader"));
1450 1458 }
1451 1459 }
1452 1460
1453 1461 /*
1454 1462 * read_suffixes_list(depes)
1455 1463 *
1456 1464 * Read the special list .SUFFIXES. If it is empty the old list is
1457 1465 * cleared. Else the new one is appended. Suffixes with ~ are extracted
1458 1466 * and marked.
1459 1467 *
1460 1468 * Parameters:
1461 1469 * depes The list of suffixes
1462 1470 *
1463 1471 * Global variables used:
1464 1472 * hashtab The central hashtable for Names.
1465 1473 * suffixes The list of suffixes, set or appended to
1466 1474 * suffixes_name The Name ".SUFFIXES", used for tracing
1467 1475 * trace_reader Indicates that we should echo stuff we read
1468 1476 */
1469 1477 static void
1470 1478 read_suffixes_list(register Name_vector depes)
1471 1479 {
1472 1480 register int n;
1473 1481 register Dependency dp;
1474 1482 register Dependency *insert_dep;
1475 1483 register Name np;
1476 1484 Name np2;
1477 1485 register Boolean first = true;
1478 1486
1479 1487 if (depes->used == 0) {
1480 1488 /* .SUFFIXES with no dependency list clears the */
1481 1489 /* suffixes list */
1482 1490 for (Name_set::iterator np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
1483 1491 np->with_squiggle =
1484 1492 np->without_squiggle =
1485 1493 false;
1486 1494 }
1487 1495 suffixes = NULL;
1488 1496 if (trace_reader) {
1489 1497 (void) printf("%s:\n", suffixes_name->string_mb);
1490 1498 }
1491 1499 return;
1492 1500 }
1493 1501 Wstring str;
1494 1502 /* Otherwise we append to the list */
1495 1503 for (; depes != NULL; depes = depes->next) {
1496 1504 for (n = 0; n < depes->used; n++) {
1497 1505 np = depes->names[n];
1498 1506 /* Find the end of the list and check if the */
1499 1507 /* suffix already has been entered */
1500 1508 for (insert_dep = &suffixes, dp = *insert_dep;
1501 1509 dp != NULL;
1502 1510 insert_dep = &dp->next, dp = *insert_dep) {
1503 1511 if (dp->name == np) {
1504 1512 goto duplicate_suffix;
1505 1513 }
1506 1514 }
1507 1515 if (trace_reader) {
1508 1516 if (first) {
1509 1517 (void) printf("%s:\t",
1510 1518 suffixes_name->string_mb);
1511 1519 first = false;
1512 1520 }
1513 1521 (void) printf("%s ", depes->names[n]->string_mb);
1514 1522 }
1515 1523 if(!(posix|svr4)) {
1516 1524 /* If the suffix is suffixed with "~" we */
1517 1525 /* strip that and mark the suffix nameblock */
1518 1526 str.init(np);
1519 1527 wchar_t * wcb = str.get_string();
1520 1528 if (wcb[np->hash.length - 1] ==
1521 1529 (int) tilde_char) {
1522 1530 np2 = GETNAME(wcb,
1523 1531 (int)(np->hash.length - 1));
1524 1532 np2->with_squiggle = true;
1525 1533 if (np2->without_squiggle) {
1526 1534 continue;
1527 1535 }
1528 1536 np = np2;
1529 1537 }
1530 1538 }
1531 1539 np->without_squiggle = true;
1532 1540 /* Add the suffix to the list */
1533 1541 dp = *insert_dep = ALLOC(Dependency);
1534 1542 insert_dep = &dp->next;
1535 1543 dp->next = NULL;
1536 1544 dp->name = np;
1537 1545 dp->built = false;
1538 1546 duplicate_suffix:;
1539 1547 }
1540 1548 }
1541 1549 if (trace_reader) {
1542 1550 (void) printf("\n");
1543 1551 }
1544 1552 }
1545 1553
1546 1554 /*
1547 1555 * make_relative(to, result)
1548 1556 *
1549 1557 * Given a file name compose a relative path name from it to the
1550 1558 * current directory.
1551 1559 *
1552 1560 * Parameters:
1553 1561 * to The path we want to make relative
1554 1562 * result Where to put the resulting relative path
1555 1563 *
1556 1564 * Global variables used:
1557 1565 */
1558 1566 static void
1559 1567 make_relative(wchar_t *to, wchar_t *result)
1560 1568 {
1561 1569 wchar_t *from;
1562 1570 wchar_t *allocated;
1563 1571 wchar_t *cp;
1564 1572 wchar_t *tocomp;
1565 1573 int ncomps;
1566 1574 int i;
1567 1575 int len;
1568 1576
1569 1577 /* Check if the path is already relative. */
1570 1578 if (to[0] != (int) slash_char) {
1571 1579 (void) wcscpy(result, to);
1572 1580 return;
1573 1581 }
1574 1582
1575 1583 MBSTOWCS(wcs_buffer, get_current_path());
1576 1584 from = allocated = (wchar_t *) wcsdup(wcs_buffer);
1577 1585
1578 1586 /*
1579 1587 * Find the number of components in the from name.
1580 1588 * ncomp = number of slashes + 1.
1581 1589 */
1582 1590 ncomps = 1;
1583 1591 for (cp = from; *cp != (int) nul_char; cp++) {
1584 1592 if (*cp == (int) slash_char) {
1585 1593 ncomps++;
1586 1594 }
1587 1595 }
1588 1596
1589 1597 /*
1590 1598 * See how many components match to determine how many "..",
1591 1599 * if any, will be needed.
1592 1600 */
1593 1601 result[0] = (int) nul_char;
1594 1602 tocomp = to;
1595 1603 while ((*from != (int) nul_char) && (*from == *to)) {
1596 1604 if (*from == (int) slash_char) {
1597 1605 ncomps--;
1598 1606 tocomp = &to[1];
1599 1607 }
1600 1608 from++;
1601 1609 to++;
1602 1610 }
1603 1611
1604 1612 /*
1605 1613 * Now for some special cases. Check for exact matches and
1606 1614 * for either name terminating exactly.
1607 1615 */
1608 1616 if (*from == (int) nul_char) {
1609 1617 if (*to == (int) nul_char) {
1610 1618 MBSTOWCS(wcs_buffer, ".");
1611 1619 (void) wcscpy(result, wcs_buffer);
1612 1620 retmem(allocated);
1613 1621 return;
1614 1622 }
1615 1623 if (*to == (int) slash_char) {
1616 1624 ncomps--;
1617 1625 tocomp = &to[1];
1618 1626 }
1619 1627 } else if ((*from == (int) slash_char) && (*to == (int) nul_char)) {
1620 1628 ncomps--;
1621 1629 tocomp = to;
1622 1630 }
1623 1631 /* Add on the ".."s. */
1624 1632 for (i = 0; i < ncomps; i++) {
1625 1633 MBSTOWCS(wcs_buffer, "../");
1626 1634 (void) wcscat(result, wcs_buffer);
1627 1635 }
1628 1636
1629 1637 /* Add on the remainder of the to name, if any. */
1630 1638 if (*tocomp == (int) nul_char) {
1631 1639 len = wcslen(result);
1632 1640 result[len - 1] = (int) nul_char;
1633 1641 } else {
1634 1642 (void) wcscat(result, tocomp);
1635 1643 }
1636 1644 retmem(allocated);
1637 1645 return;
1638 1646 }
1639 1647
1640 1648 /*
1641 1649 * print_rule(command)
1642 1650 *
1643 1651 * Used when tracing the reading of rules
1644 1652 *
1645 1653 * Parameters:
1646 1654 * command Command to print
1647 1655 *
1648 1656 * Global variables used:
1649 1657 */
1650 1658 static void
1651 1659 print_rule(register Cmd_line command)
1652 1660 {
1653 1661 for (; command != NULL; command = command->next) {
1654 1662 (void) printf("\t%s\n", command->command_line->string_mb);
1655 1663 }
1656 1664 }
1657 1665
1658 1666 /*
1659 1667 * enter_conditional(target, name, value, append)
1660 1668 *
1661 1669 * Enter "target := MACRO= value" constructs
1662 1670 *
1663 1671 * Parameters:
1664 1672 * target The target the macro is for
1665 1673 * name The name of the macro
1666 1674 * value The value for the macro
1667 1675 * append Indicates if the assignment is appending or not
1668 1676 *
1669 1677 * Global variables used:
1670 1678 * conditionals A special Name that stores all conditionals
1671 1679 * where the target is a % pattern
1672 1680 * trace_reader Indicates that we should echo stuff we read
1673 1681 */
1674 1682 void
1675 1683 enter_conditional(register Name target, Name name, Name value, register Boolean append)
1676 1684 {
1677 1685 register Property conditional;
1678 1686 static int sequence;
1679 1687 Name orig_target = target;
1680 1688
1681 1689 if (name == target_arch) {
1682 1690 enter_conditional(target, virtual_root, virtual_root, false);
1683 1691 }
1684 1692
1685 1693 if (target->percent) {
1686 1694 target = conditionals;
1687 1695 }
1688 1696
1689 1697 if (name->colon) {
1690 1698 sh_transform(&name, &value);
1691 1699 }
1692 1700
1693 1701 /* Count how many conditionals we must activate before building the */
1694 1702 /* target */
1695 1703 if (target->percent) {
1696 1704 target = conditionals;
1697 1705 }
1698 1706
1699 1707 target->conditional_cnt++;
1700 1708 maybe_append_prop(name, macro_prop)->body.macro.is_conditional = true;
1701 1709 /* Add the property for the target */
1702 1710 conditional = append_prop(target, conditional_prop);
1703 1711 conditional->body.conditional.target = orig_target;
1704 1712 conditional->body.conditional.name = name;
1705 1713 conditional->body.conditional.value = value;
1706 1714 conditional->body.conditional.sequence = sequence++;
1707 1715 conditional->body.conditional.append = append;
1708 1716 if (trace_reader) {
1709 1717 if (value == NULL) {
1710 1718 (void) printf("%s := %s %c=\n",
1711 1719 target->string_mb,
1712 1720 name->string_mb,
1713 1721 append ?
1714 1722 (int) plus_char : (int) space_char);
1715 1723 } else {
1716 1724 (void) printf("%s := %s %c= %s\n",
1717 1725 target->string_mb,
1718 1726 name->string_mb,
1719 1727 append ?
1720 1728 (int) plus_char : (int) space_char,
1721 1729 value->string_mb);
1722 1730 }
1723 1731 }
1724 1732 }
1725 1733
1726 1734 /*
1727 1735 * enter_equal(name, value, append)
1728 1736 *
1729 1737 * Enter "MACRO= value" constructs
1730 1738 *
1731 1739 * Parameters:
1732 1740 * name The name of the macro
1733 1741 * value The value for the macro
1734 1742 * append Indicates if the assignment is appending or not
1735 1743 *
1736 1744 * Global variables used:
1737 1745 * trace_reader Indicates that we should echo stuff we read
1738 1746 */
1739 1747 void
1740 1748 enter_equal(Name name, Name value, register Boolean append)
1741 1749 {
1742 1750 wchar_t *string;
1743 1751 Name temp;
1744 1752
1745 1753 if (name->colon) {
1746 1754 sh_transform(&name, &value);
1747 1755 }
1748 1756 (void) SETVAR(name, value, append);
1749 1757
1750 1758 /* if we're setting FC, we want to set F77 to the same value. */
1751 1759 Wstring nms(name);
1752 1760 wchar_t * wcb = nms.get_string();
1753 1761 string = wcb;
1754 1762 if (string[0]=='F' &&
1755 1763 string[1]=='C' &&
1756 1764 string[2]=='\0') {
1757 1765 MBSTOWCS(wcs_buffer, "F77");
1758 1766 temp = GETNAME(wcs_buffer, FIND_LENGTH);
1759 1767 (void) SETVAR(temp, value, append);
1760 1768 /*
1761 1769 fprintf(stderr, gettext("warning: FC is obsolete, use F77 instead\n"));
1762 1770 */
1763 1771 }
1764 1772
1765 1773 if (trace_reader) {
1766 1774 if (value == NULL) {
1767 1775 (void) printf("%s %c=\n",
1768 1776 name->string_mb,
1769 1777 append ?
1770 1778 (int) plus_char : (int) space_char);
1771 1779 } else {
1772 1780 (void) printf("%s %c= %s\n",
1773 1781 name->string_mb,
1774 1782 append ?
1775 1783 (int) plus_char : (int) space_char,
1776 1784 value->string_mb);
1777 1785 }
1778 1786 }
1779 1787 }
1780 1788
1781 1789 /*
1782 1790 * sh_transform(name, value)
1783 1791 *
1784 1792 * Parameters:
1785 1793 * name The name of the macro we might transform
1786 1794 * value The value to transform
1787 1795 *
1788 1796 */
1789 1797 static void
1790 1798 sh_transform(Name *name, Name *value)
1791 1799 {
1792 1800 /* Check if we need :sh transform */
1793 1801 wchar_t *colon;
1794 1802 String_rec command;
1795 1803 String_rec destination;
1796 1804 wchar_t buffer[1000];
1797 1805 wchar_t buffer1[1000];
1798 1806
1799 1807 static wchar_t colon_sh[4];
1800 1808 static wchar_t colon_shell[7];
1801 1809
1802 1810 if (colon_sh[0] == (int) nul_char) {
1803 1811 MBSTOWCS(colon_sh, ":sh");
1804 1812 MBSTOWCS(colon_shell, ":shell");
1805 1813 }
1806 1814 Wstring nms((*name));
1807 1815 wchar_t * wcb = nms.get_string();
1808 1816
1809 1817 colon = (wchar_t *) wcsrchr(wcb, (int) colon_char);
1810 1818 if ((colon != NULL) && (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell))) {
1811 1819 INIT_STRING_FROM_STACK(destination, buffer);
1812 1820
1813 1821 if(*value == NULL) {
1814 1822 buffer[0] = 0;
1815 1823 } else {
1816 1824 Wstring wcb1((*value));
1817 1825 if (IS_WEQUAL(colon, colon_shell)) {
1818 1826 INIT_STRING_FROM_STACK(command, buffer1);
1819 1827 expand_value(*value, &command, false);
1820 1828 } else {
1821 1829 command.text.p = wcb1.get_string() + (*value)->hash.length;
1822 1830 command.text.end = command.text.p;
1823 1831 command.buffer.start = wcb1.get_string();
1824 1832 command.buffer.end = command.text.p;
1825 1833 }
1826 1834 sh_command2string(&command, &destination);
1827 1835 }
1828 1836
1829 1837 (*value) = GETNAME(destination.buffer.start, FIND_LENGTH);
1830 1838 *colon = (int) nul_char;
1831 1839 (*name) = GETNAME(wcb, FIND_LENGTH);
1832 1840 *colon = (int) colon_char;
1833 1841 }
1834 1842 }
1835 1843
1836 1844 /*
1837 1845 * fatal_reader(format, args...)
1838 1846 *
1839 1847 * Parameters:
1840 1848 * format printf style format string
1841 1849 * args arguments to match the format
1842 1850 *
1843 1851 * Global variables used:
1844 1852 * file_being_read Name of the makefile being read
1845 1853 * line_number Line that is being read
1846 1854 * report_pwd Indicates whether current path should be shown
1847 1855 * temp_file_name When reading tempfile we report that name
1848 1856 */
1849 1857 /*VARARGS*/
1850 1858 void
1851 1859 fatal_reader(char * pattern, ...)
1852 1860 {
1853 1861 va_list args;
1854 1862 char message[1000];
1855 1863
1856 1864 va_start(args, pattern);
1857 1865 if (file_being_read != NULL) {
1858 1866 WCSTOMBS(mbs_buffer, file_being_read);
1859 1867 if (line_number != 0) {
1860 1868 (void) sprintf(message,
1861 1869 gettext("%s, line %d: %s"),
1862 1870 mbs_buffer,
1863 1871 line_number,
1864 1872 pattern);
1865 1873 } else {
1866 1874 (void) sprintf(message,
1867 1875 "%s: %s",
1868 1876 mbs_buffer,
1869 1877 pattern);
1870 1878 }
1871 1879 pattern = message;
1872 1880 }
1873 1881
1874 1882 (void) fflush(stdout);
1875 1883 (void) fprintf(stderr, gettext("%s: Fatal error in reader: "),
1876 1884 getprogname());
1877 1885 (void) vfprintf(stderr, pattern, args);
1878 1886 (void) fprintf(stderr, "\n");
1879 1887 va_end(args);
1880 1888
1881 1889 if (temp_file_name != NULL) {
1882 1890 (void) fprintf(stderr,
1883 1891 gettext("%s: Temp-file %s not removed\n"),
1884 1892 getprogname(),
1885 1893 temp_file_name->string_mb);
1886 1894 temp_file_name = NULL;
1887 1895 }
1888 1896
1889 1897 if (report_pwd) {
1890 1898 (void) fprintf(stderr,
1891 1899 gettext("Current working directory %s\n"),
1892 1900 get_current_path());
1893 1901 }
1894 1902 (void) fflush(stderr);
1895 1903 exit_status = 1;
1896 1904 exit(1);
1897 1905 }
1898 1906
↓ open down ↓ |
587 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX