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