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