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.
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.
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]
22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * This file contains the makefile reader.
36 #include <mksh/dosys.h> /* sh_command2string() */
37 #include <mksh/macro.h> /* expand_value() */
38 #include <mksh/misc.h> /* retmem() */
39 #include <stdarg.h> /* va_list, va_start(), va_end() */
53 static Boolean built_last_make_run_seen
;
56 * File table of contents
58 static Name_vector
enter_member_name(register wchar_t *lib_start
, register wchar_t *member_start
, register wchar_t *string_end
, Name_vector current_names
, Name_vector
*extra_names
);
59 extern Name
normalize_name(register wchar_t *name_string
, register int length
);
60 static void read_suffixes_list(register Name_vector depes
);
61 static void make_relative(wchar_t *to
, wchar_t *result
);
62 static void print_rule(register Cmd_line command
);
63 static void sh_transform(Name
*name
, Name
*value
);
67 * enter_name(string, tail_present, string_start, string_end,
68 * current_names, extra_names, target_group_seen)
70 * Take one string and enter it as a name. The string is passed in
71 * two parts. A make string and possibly a C string to append to it.
72 * The result is stuffed in the vector current_names.
73 * extra_names points to a vector that is used if current_names overflows.
74 * This is allocad in the calling routine.
75 * Here we handle the "lib.a[members]" notation.
78 * The name vector that was used
81 * tail_present Indicates if both C and make string was passed
82 * string_start C string
83 * string_end Pointer to char after last in C string
84 * string make style string with head of name
85 * current_names Vector to deposit the name in
86 * extra_names Where to get next name vector if we run out
87 * target_group_seen Pointer to boolean that is set if "+" is seen
89 * Global variables used:
90 * makefile_type When we read a report file we normalize paths
91 * plus Points to the Name "+"
95 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
)
101 /* If we were passed a separate tail of the name we append it to the */
102 /* make string with the rest of it */
104 append_string(string_start
, string
, string_end
- string_start
);
105 string_start
= string
->buffer
.start
;
106 string_end
= string
->text
.p
;
109 *string_end
= (int) nul_char
;
111 * Check if there are any ( or [ that are not prefixed with $.
112 * If there are, we have to deal with the lib.a(members) format.
114 for (cp
= (wchar_t *) wcschr(string_start
, (int) parenleft_char
);
116 cp
= (wchar_t *) wcschr(cp
+ 1, (int) parenleft_char
)) {
117 if (*(cp
- 1) != (int) dollar_char
) {
119 return enter_member_name(string_start
,
128 if (makefile_type
== reading_cpp_file
) {
129 /* Remove extra ../ constructs if we are reading from a report file */
130 name
= normalize_name(string_start
, string_end
- string_start
);
133 * /tolik, fix bug 1197477/
134 * Normalize every target name before entering.
135 * ..//obj/a.o and ../obj//a.o are not two different targets.
136 * There is only one target ../obj/a.o
138 /*name = GETNAME(string_start, string_end - string_start);*/
139 name
= normalize_name(string_start
, string_end
- string_start
);
142 /* Internalize the name. Detect the name "+" (target group here) */
143 if(current_names
->used
!= 0 && current_names
->names
[current_names
->used
-1] == plus
) {
145 return current_names
;
148 /* If the current_names vector is full we patch in the one from */
150 if (current_names
->used
== VSIZEOF(current_names
->names
)) {
151 if (current_names
->next
!= NULL
) {
152 current_names
= current_names
->next
;
154 current_names
->next
= *extra_names
;
156 current_names
= current_names
->next
;
157 current_names
->used
= 0;
158 current_names
->next
= NULL
;
161 current_names
->target_group
[current_names
->used
] = NULL
;
162 current_names
->names
[current_names
->used
++] = name
;
164 *target_group_seen
= true;
166 if (tail_present
&& string
->free_after_use
) {
167 retmem(string
->buffer
.start
);
169 return current_names
;
173 * enter_member_name(lib_start, member_start, string_end,
174 * current_names, extra_names)
176 * A string has been found to contain member names.
177 * (The "lib.a[members]" and "lib.a(members)" notation)
178 * Handle it pretty much as enter_name() does for simple names.
181 * The name vector that was used
184 * lib_start Points to the of start of "lib.a(member.o)"
185 * member_start Points to "member.o" from above string.
186 * string_end Points to char after last of above string.
187 * current_names Vector to deposit the name in
188 * extra_names Where to get next name vector if we run out
190 * Global variables used:
193 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
)
195 register Boolean entry
= false;
196 wchar_t buffer
[STRING_BUFFER_LENGTH
];
203 register int paren_count
;
204 register Boolean has_dollar
;
205 register wchar_t *cq
;
206 Name long_member_name
= NULL
;
208 /* Internalize the name of the library */
209 lib
= GETNAME(lib_start
, member_start
- lib_start
);
210 lib
->is_member
= true;
212 if (*member_start
== (int) parenleft_char
) {
213 /* This is really the "lib.a((entries))" format */
217 /* Move the library name to the buffer where we intend to build the */
218 /* "lib.a(member)" for each member */
219 (void) wcsncpy(buffer
, lib_start
, member_start
- lib_start
);
220 memberp
= buffer
+ (member_start
-lib_start
);
222 long_member_name
= NULL
;
223 /* Skip leading spaces */
225 (member_start
< string_end
) && iswspace(*member_start
);
227 /* Find the end of the member name. Allow nested (). Detect $*/
228 for (cq
= memberp
, has_dollar
= false, paren_count
= 0;
229 (member_start
< string_end
) &&
230 ((*member_start
!= (int) parenright_char
) ||
231 (paren_count
> 0)) &&
232 !iswspace(*member_start
);
233 *cq
++ = *member_start
++) {
234 switch (*member_start
) {
238 case parenright_char
:
245 /* Internalize the member name */
246 member
= GETNAME(memberp
, cq
- memberp
);
248 if ((q
= (wchar_t *) wcsrchr(memberp
, (int) slash_char
)) == NULL
) {
251 if ((cq
- q
> (int) ar_member_name_len
) &&
253 *cq
++ = (int) parenright_char
;
255 *cq
++ = (int) parenright_char
;
257 long_member_name
= GETNAME(buffer
, cq
- buffer
);
258 cq
= q
+ (int) ar_member_name_len
;
260 *cq
++ = (int) parenright_char
;
262 *cq
++ = (int) parenright_char
;
264 /* Internalize the "lib.a(member)" notation for this member */
265 name
= GETNAME(buffer
, cq
- buffer
);
266 name
->is_member
= lib
->is_member
;
267 if (long_member_name
!= NULL
) {
268 prop
= append_prop(name
, long_member_name_prop
);
269 name
->has_long_member_name
= true;
270 prop
->body
.long_member_name
.member_name
=
273 /* And add the member prop */
274 prop
= append_prop(name
, member_prop
);
275 prop
->body
.member
.library
= lib
;
277 /* "lib.a((entry))" notation */
278 prop
->body
.member
.entry
= member
;
279 prop
->body
.member
.member
= NULL
;
281 /* "lib.a(member)" Notation */
282 prop
->body
.member
.entry
= NULL
;
283 prop
->body
.member
.member
= member
;
285 /* Handle overflow of current_names */
286 if (current_names
->used
== VSIZEOF(current_names
->names
)) {
287 if (current_names
->next
!= NULL
) {
288 current_names
= current_names
->next
;
290 if (*extra_names
== NULL
) {
292 current_names
->next
=
296 current_names
->next
=
300 current_names
->used
= 0;
301 current_names
->next
= NULL
;
304 current_names
->target_group
[current_names
->used
] = NULL
;
305 current_names
->names
[current_names
->used
++] = name
;
306 while (iswspace(*member_start
)) {
309 /* Check if there are more members */
310 if ((*member_start
== (int) parenright_char
) ||
311 (member_start
>= string_end
)) {
312 return current_names
;
319 * normalize_name(name_string, length)
321 * Take a namestring and remove redundant ../, // and ./ constructs
324 * The normalized name
327 * name_string Path string to normalize
328 * length Length of that string
330 * Global variables used:
331 * dot The Name ".", compared against
332 * dotdot The Name "..", compared against
335 normalize_name(register wchar_t *name_string
, register int length
)
338 register wchar_t *string
= ALLOC_WC(length
+ 1);
339 register wchar_t *string2
;
340 register wchar_t *cdp
;
341 wchar_t *current_component
;
345 if (dotdot
== NULL
) {
346 MBSTOWCS(wcs_buffer
, "..");
347 dotdot
= GETNAME(wcs_buffer
, FIND_LENGTH
);
351 * Copy string removing ./ and //.
352 * First strip leading ./
354 while ((length
> 1) &&
355 (name_string
[0] == (int) period_char
) &&
356 (name_string
[1] == (int) slash_char
)) {
359 while ((length
> 0) && (name_string
[0] == (int) slash_char
)) {
364 /* Then copy the rest of the string removing /./ & // */
368 (name_string
[0] == (int) slash_char
) &&
369 (name_string
[1] == (int) period_char
) &&
370 (name_string
[2] == (int) slash_char
)) ||
372 (name_string
[0] == (int) slash_char
) &&
373 (name_string
[1] == (int) period_char
))) {
379 (name_string
[0] == (int) slash_char
) &&
380 (name_string
[1] == (int) slash_char
)) {
385 *cdp
++ = *name_string
++;
388 *cdp
= (int) nul_char
;
390 * Now scan for <name>/../ and remove such combinations iff <name>
392 * Each time something is removed, the whole process is restarted.
395 name_string
= string
;
396 string2
= name_string
; /*save for free*/
400 ALLOC_WC((length
= wcslen(name_string
)) + 1);
403 (name_string
[0] == (int) slash_char
) &&
404 (name_string
[1] == (int) period_char
) &&
405 (name_string
[2] == (int) period_char
) &&
406 (name_string
[3] == (int) slash_char
)) ||
408 (name_string
[0] == (int) slash_char
) &&
409 (name_string
[1] == (int) period_char
) &&
410 (name_string
[2] == (int) period_char
))) {
411 /* Positioned on the / that starts a /.. sequence */
412 if (((count
= cdp
- current_component
) != 0) &&
413 (exists(name
= GETNAME(string
, cdp
- string
)) > file_doesnt_exist
) &&
414 (!name
->stat
.is_sym_link
)) {
415 name
= GETNAME(current_component
, count
);
417 cdp
= current_component
;
421 name_string
++; /* skip slash */
424 *cdp
++ = *name_string
++;
428 *cdp
= (int) nul_char
;
434 if ((*cdp
++ = *name_string
++) == (int) slash_char
) {
435 current_component
= cdp
;
439 *cdp
= (int) nul_char
;
440 if (string
[0] == (int) nul_char
) {
443 name
= GETNAME(string
, FIND_LENGTH
);
451 * find_target_groups(target_list)
453 * If a "+" was seen when the target list was scanned we need to extract
454 * the groups. Each target in the name vector that is a member of a
455 * group gets a pointer to a chain of all the members stuffed in its
456 * target_group vector slot
459 * target_list The list of targets that contains "+"
461 * Global variables used:
462 * plus The Name "+", compared against
465 find_target_groups(register Name_vector target_list
, register int i
, Boolean reset
)
467 static Chain target_group
= NULL
;
468 static Chain tail_target_group
= NULL
;
470 static Boolean clear_target_group
= false;
474 tail_target_group
= NULL
;
475 clear_target_group
= false;
478 /* Scan the list of targets */
479 /* If the previous target terminated a group */
480 /* we flush the pointer to that member chain */
481 if (clear_target_group
) {
482 clear_target_group
= false;
485 /* Pick up a pointer to the cell with */
486 /* the next target */
487 if (i
+ 1 != target_list
->used
) {
488 next
= &target_list
->names
[i
+ 1];
490 next
= (target_list
->next
!= NULL
) ?
491 &target_list
->next
->names
[0] : NULL
;
493 /* We have four states here :
494 * 0: No target group started and next element is not "+"
495 * This is not interesting.
496 * 1: A target group is being built and the next element
497 * is not "+". This terminates the group.
498 * 2: No target group started and the next member is "+"
499 * This is the first target in a group.
500 * 3: A target group started and the next member is a "+"
501 * The group continues.
503 switch ((target_group
? 1 : 0) +
504 (next
&& (*next
== plus
) ?
506 case 0: /* Not target_group */
508 case 1: /* Last group member */
509 /* We need to keep this pointer so */
510 /* we can stuff it for last member */
511 clear_target_group
= true;
513 case 3: /* Middle group member */
514 /* Add this target to the */
516 tail_target_group
->next
= ALLOC(Chain
);
517 tail_target_group
= tail_target_group
->next
;
518 tail_target_group
->next
= NULL
;
519 tail_target_group
->name
= target_list
->names
[i
];
521 case 2: /* First group member */
522 /* Start a new chain */
523 target_group
= tail_target_group
= ALLOC(Chain
);
524 target_group
->next
= NULL
;
525 target_group
->name
= target_list
->names
[i
];
528 /* Stuff the current chain, if any, in the */
529 /* targets group slot */
530 target_list
->target_group
[i
] = target_group
;
531 if ((next
!= NULL
) &&
535 return (tail_target_group
);
539 * enter_dependencies(target, target_group, depes, command, separator)
541 * Take one target and a list of dependencies and process the whole thing.
542 * The target might be special in some sense in which case that is handled
545 * target The target we want to enter
546 * target_group Non-NULL if target is part of a group this time
547 * depes A list of dependencies for the target
548 * command The command the target should be entered with
549 * separator Indicates if this is a ":" or a "::" rule
551 * Static variables used:
552 * built_last_make_run_seen If the previous target was
553 * .BUILT_LAST_MAKE_RUN we say to rewrite
554 * the state file later on
556 * Global variables used:
557 * command_changed Set to indicate if .make.state needs rewriting
558 * default_target_to_build Set to the target if reading makefile
559 * and this is the first regular target
560 * force The Name " FORCE", used with "::" targets
561 * makefile_type We do different things for makefile vs. report
562 * not_auto The Name ".NOT_AUTO", compared against
563 * recursive_name The Name ".RECURSIVE", compared against
564 * temp_file_number Used to figure out when to clear stale
565 * automatic dependencies
566 * trace_reader Indicates that we should echo stuff we read
569 enter_dependencies(register Name target
, Chain target_group
, register Name_vector depes
, register Cmd_line command
, register Separator separator
)
572 register Property line
;
580 wchar_t relative
[MAXPATHLEN
];
581 register int recursive_state
;
582 Boolean register_as_auto
;
583 Boolean not_auto_found
;
587 /* Check if this is a .RECURSIVE line */
588 if ((depes
->used
>= 3) &&
589 (depes
->names
[0] == recursive_name
)) {
590 target
->has_recursive_dependency
= true;
591 depes
->names
[0] = NULL
;
595 /* Read the dependencies. They are "<directory> <target-made>*/
597 for (; depes
!= NULL
; depes
= depes
->next
) {
598 for (i
= 0; i
< depes
->used
; i
++) {
599 if (depes
->names
[i
] != NULL
) {
600 switch (recursive_state
++) {
601 case 0: /* Directory */
603 depstr
.init(depes
->names
[i
]);
604 make_relative(depstr
.get_string(),
612 name
= depes
->names
[i
];
614 default: /* Makefiles */
615 *dpp
= ALLOC(Dependency
);
617 (*dpp
)->name
= depes
->names
[i
];
618 (*dpp
)->automatic
= false;
619 (*dpp
)->stale
= false;
620 (*dpp
)->built
= false;
621 dpp
= &((*dpp
)->next
);
627 /* Check if this recursion already has been reported else */
628 /* enter the recursive prop for the target */
629 /* The has_built flag is used to tell if this .RECURSIVE */
630 /* was discovered from this run (read from a tmp file) */
631 /* or was from discovered from the original .make.state */
633 for (line
= get_prop(target
->prop
, recursive_prop
);
635 line
= get_prop(line
->next
, recursive_prop
)) {
636 if ((line
->body
.recursive
.directory
== directory
) &&
637 (line
->body
.recursive
.target
== name
)) {
638 line
->body
.recursive
.makefiles
= dp
;
639 line
->body
.recursive
.has_built
=
641 (makefile_type
== reading_cpp_file
);
645 line2
= append_prop(target
, recursive_prop
);
646 line2
->body
.recursive
.directory
= directory
;
647 line2
->body
.recursive
.target
= name
;
648 line2
->body
.recursive
.makefiles
= dp
;
649 line2
->body
.recursive
.has_built
=
650 (Boolean
) (makefile_type
== reading_cpp_file
);
651 line2
->body
.recursive
.in_depinfo
= false;
654 /* If this is the first target that doesnt start with a "." in the */
655 /* makefile we remember that */
656 Wstring
tstr(target
);
657 wchar_t * wcb
= tstr
.get_string();
658 if ((makefile_type
== reading_makefile
) &&
659 (default_target_to_build
== NULL
) &&
660 ((wcb
[0] != (int) period_char
) ||
661 wcschr(wcb
, (int) slash_char
))) {
663 /* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO):
664 ** The target with empty name cannot be default_target_to_build
666 if (target
->hash
.length
!= 0)
667 default_target_to_build
= target
;
669 /* Check if the line is ":" or "::" */
670 if (makefile_type
== reading_makefile
) {
671 if (target
->colons
== no_colon
) {
672 target
->colons
= separator
;
674 if (target
->colons
!= separator
) {
675 fatal_reader(gettext(":/:: conflict for target `%s'"),
679 if (target
->colons
== two_colon
) {
680 if (depes
->used
== 0) {
681 /* If this is a "::" type line with no */
682 /* dependencies we add one "FRC" type */
683 /* dependency for free */
684 depes
->used
= 1; /* Force :: targets with no
685 * depes to always run */
686 depes
->names
[0] = force
;
688 /* Do not delete "::" type targets when interrupted */
689 target
->stat
.is_precious
= true;
691 * Build a synthetic target "<number>%target"
694 mb_namep
= getmem((int) (strlen(target
->string_mb
) + 10));
695 namep
= ALLOC_WC((int) (target
->hash
.length
+ 10));
696 slash
= strrchr(target
->string_mb
, (int) slash_char
);
698 (void) sprintf(mb_namep
,
700 target
->colon_splits
++,
704 (void) sprintf(mb_namep
,
707 target
->colon_splits
++,
709 *slash
= (int) slash_char
;
711 MBSTOWCS(namep
, mb_namep
);
713 name
= GETNAME(namep
, FIND_LENGTH
);
716 (void) printf("%s:\t", target
->string_mb
);
718 /* Make "target" depend on "<number>%target */
719 line2
= maybe_append_prop(target
, line_prop
);
720 enter_dependency(line2
, name
, true);
721 line2
->body
.line
.target
= target
;
722 /* Put a prop on "<number>%target that makes */
723 /* appear as "target" */
724 /* when it is processed */
725 maybe_append_prop(name
, target_prop
)->
726 body
.target
.target
= target
;
727 target
->is_double_colon_parent
= true;
728 name
->is_double_colon
= true;
729 name
->has_target_prop
= true;
733 (target
= name
)->stat
.is_file
= true;
736 /* This really is a regular dependency line. Just enter it */
737 line
= maybe_append_prop(target
, line_prop
);
738 line
->body
.line
.target
= target
;
739 /* Depending on what kind of makefile we are reading we have to */
740 /* treat things differently */
741 switch (makefile_type
) {
742 case reading_makefile
:
743 /* Reading regular makefile. Just notice whether this */
744 /* redefines the rule for the target */
745 if (command
!= NULL
) {
746 if (line
->body
.line
.command_template
!= NULL
) {
747 line
->body
.line
.command_template_redefined
=
749 if ((wcb
[0] == (int) period_char
) &&
750 !wcschr(wcb
, (int) slash_char
)) {
751 line
->body
.line
.command_template
=
755 line
->body
.line
.command_template
= command
;
758 if ((wcb
[0] == (int) period_char
) &&
759 !wcschr(wcb
, (int) slash_char
)) {
760 line
->body
.line
.command_template
= command
;
764 case rereading_statefile
:
765 /* Rereading the statefile. We only enter thing that changed */
766 /* since the previous time we read it */
767 if (!built_last_make_run_seen
) {
768 for (Cmd_line next
, cmd
= command
; cmd
!= NULL
; cmd
= next
) {
774 built_last_make_run_seen
= false;
775 command_changed
= true;
776 target
->ran_command
= true;
777 case reading_statefile
:
778 /* Reading the statefile for the first time. Enter the rules */
779 /* as "Commands used" not "templates to use" */
780 if (command
!= NULL
) {
781 for (Cmd_line next
, cmd
= line
->body
.line
.command_used
;
782 cmd
!= NULL
; cmd
= next
) {
786 line
->body
.line
.command_used
= command
;
788 case reading_cpp_file
:
789 /* Reading report file from programs that reports */
790 /* dependencies. If this is the first time the target is */
791 /* read from this reportfile we clear all old */
792 /* automatic depes */
793 if (target
->temp_file_number
== temp_file_number
) {
796 target
->temp_file_number
= temp_file_number
;
797 command_changed
= true;
799 for (dp
= line
->body
.line
.dependencies
;
809 fatal_reader(gettext("Internal error. Unknown makefile type %d"),
812 /* A target may only be involved in one target group */
813 if (line
->body
.line
.target_group
!= NULL
) {
814 if (target_group
!= NULL
) {
815 fatal_reader(gettext("Too many target groups for target `%s'"),
819 line
->body
.line
.target_group
= target_group
;
823 (void) printf("%s:\t", target
->string_mb
);
825 /* Enter the dependencies */
826 register_as_auto
= BOOLEAN(makefile_type
!= reading_makefile
);
827 not_auto_found
= false;
829 (depes
!= NULL
) && !not_auto_found
;
830 depes
= depes
->next
) {
831 for (i
= 0; i
< depes
->used
; i
++) {
832 /* the dependency .NOT_AUTO signals beginning of
833 * explicit dependancies which were put at end of
834 * list in .make.state file - we stop entering
835 * dependencies at this point
837 if (depes
->names
[i
] == not_auto
) {
838 not_auto_found
= true;
841 enter_dependency(line
,
853 * enter_dependency(line, depe, automatic)
855 * Enter one dependency. Do not enter duplicates.
858 * line The line block that the dependeny is
860 * depe The dependency to enter
861 * automatic Used to set the field "automatic"
863 * Global variables used:
864 * makefile_type We do different things for makefile vs. report
865 * trace_reader Indicates that we should echo stuff we read
866 * wait_name The Name ".WAIT", compared against
869 enter_dependency(Property line
, register Name depe
, Boolean automatic
)
871 register Dependency dp
;
872 register Dependency
*insert
;
875 (void) printf("%s ", depe
->string_mb
);
877 /* Find the end of the list and check for duplicates */
878 for (insert
= &line
->body
.line
.dependencies
, dp
= *insert
;
880 insert
= &dp
->next
, dp
= *insert
) {
881 if ((dp
->name
== depe
) && (depe
!= wait_name
)) {
883 dp
->automatic
= automatic
;
886 depe
->stat
.is_file
= true;
893 /* Insert the new dependency since we couldnt find it */
894 dp
= *insert
= ALLOC(Dependency
);
897 dp
->automatic
= automatic
;
900 depe
->stat
.is_file
= true;
902 if ((makefile_type
== reading_makefile
) &&
904 (line
->body
.line
.target
!= NULL
)) {
905 line
->body
.line
.target
->has_regular_dependency
= true;
910 * enter_percent(target, depes, command)
912 * Enter "x%y : a%b" type lines
913 * % patterns are stored in four parts head and tail for target and source
916 * target Left hand side of pattern
917 * depes The dependency list with the rh pattern
918 * command The command for the pattern
920 * Global variables used:
921 * empty_name The Name "", compared against
922 * percent_list The list of all percent rules, added to
923 * trace_reader Indicates that we should echo stuff we read
926 enter_percent(register Name target
, Chain target_group
, register Name_vector depes
, Cmd_line command
)
928 register Percent result
= ALLOC(Percent
);
929 register Percent depe
;
930 register Percent
*depe_tail
= &result
->dependencies
;
931 register Percent
*insert
;
932 register wchar_t *cp
, *cp1
;
938 result
->patterns
= NULL
;
939 result
->patterns_total
= 0;
940 result
->command_template
= command
;
941 result
->being_expanded
= false;
942 result
->name
= target
;
943 result
->dependencies
= NULL
;
944 result
->target_group
= target_group
;
946 /* get patterns count */
948 cp
= wcb
.get_string();
950 cp
= (wchar_t *) wcschr(cp
, (int) percent_char
);
952 result
->patterns_total
++;
958 result
->patterns_total
++;
960 /* allocate storage for patterns */
961 result
->patterns
= (Name
*) getmem(sizeof(Name
) * result
->patterns_total
);
963 /* then create patterns */
964 cp
= wcb
.get_string();
967 cp1
= (wchar_t *) wcschr(cp
, (int) percent_char
);
969 result
->patterns
[pattern
] = GETNAME(cp
, cp1
- cp
);
973 result
->patterns
[pattern
] = GETNAME(cp
, (int) target
->hash
.length
- (cp
- wcb
.get_string()));
980 /* build dependencies list */
981 for (nvp
= depes
; nvp
!= NULL
; nvp
= nvp
->next
) {
982 for (i
= 0; i
< nvp
->used
; i
++) {
983 depe
= ALLOC(Percent
);
985 depe
->patterns
= NULL
;
986 depe
->patterns_total
= 0;
987 depe
->name
= nvp
->names
[i
];
988 depe
->dependencies
= NULL
;
989 depe
->command_template
= NULL
;
990 depe
->being_expanded
= false;
991 depe
->target_group
= NULL
;
994 depe_tail
= &depe
->next
;
996 if (depe
->name
->percent
) {
997 /* get patterns count */
998 wcb1
.init(depe
->name
);
999 cp
= wcb1
.get_string();
1001 cp
= (wchar_t *) wcschr(cp
, (int) percent_char
);
1003 depe
->patterns_total
++;
1009 depe
->patterns_total
++;
1011 /* allocate storage for patterns */
1012 depe
->patterns
= (Name
*) getmem(sizeof(Name
) * depe
->patterns_total
);
1014 /* then create patterns */
1015 cp
= wcb1
.get_string();
1018 cp1
= (wchar_t *) wcschr(cp
, (int) percent_char
);
1020 depe
->patterns
[pattern
] = GETNAME(cp
, cp1
- cp
);
1024 depe
->patterns
[pattern
] = GETNAME(cp
, (int) depe
->name
->hash
.length
- (cp
- wcb1
.get_string()));
1032 /* Find the end of the percent list and append the new pattern */
1033 for (insert
= &percent_list
; (*insert
) != NULL
; insert
= &(*insert
)->next
);
1037 (void) printf("%s:", result
->name
->string_mb
);
1039 for (depe
= result
->dependencies
; depe
!= NULL
; depe
= depe
->next
) {
1040 (void) printf(" %s", depe
->name
->string_mb
);
1043 (void) printf("\n");
1045 print_rule(command
);
1052 * enter_dyntarget(target)
1054 * Enter "$$(MACRO) : b" type lines
1057 * target Left hand side of pattern
1059 * Global variables used:
1060 * dyntarget_list The list of all percent rules, added to
1061 * trace_reader Indicates that we should echo stuff we read
1064 enter_dyntarget(register Name target
)
1066 register Dyntarget result
= ALLOC(Dyntarget
);
1071 result
->next
= NULL
;
1072 result
->name
= target
;
1075 /* Find the end of the dyntarget list and append the new pattern */
1076 for (insert
= &dyntarget_list
, p
= *insert
;
1078 insert
= &p
->next
, p
= *insert
);
1082 (void) printf("Dynamic target %s:\n", result
->name
->string_mb
);
1089 * special_reader(target, depes, command)
1091 * Read the pseudo targets make knows about
1092 * This handles the special targets that should not be entered as regular
1093 * target/dependency sets.
1096 * target The special target
1097 * depes The list of dependencies it was entered with
1098 * command The command it was entered with
1100 * Static variables used:
1101 * built_last_make_run_seen Set to indicate .BUILT_LAST... seen
1103 * Global variables used:
1104 * all_parallel Set to indicate that everything runs parallel
1105 * svr4 Set when ".SVR4" target is read
1106 * svr4_name The Name ".SVR4"
1107 * posix Set when ".POSIX" target is read
1108 * posix_name The Name ".POSIX"
1109 * current_make_version The Name "<current version number>"
1110 * default_rule Set when ".DEFAULT" target is read
1111 * default_rule_name The Name ".DEFAULT", used for tracing
1112 * dot_keep_state The Name ".KEEP_STATE", used for tracing
1113 * ignore_errors Set if ".IGNORE" target is read
1114 * ignore_name The Name ".IGNORE", used for tracing
1115 * keep_state Set if ".KEEP_STATE" target is read
1116 * no_parallel_name The Name ".NO_PARALLEL", used for tracing
1117 * only_parallel Set to indicate only some targets runs parallel
1118 * parallel_name The Name ".PARALLEL", used for tracing
1119 * precious The Name ".PRECIOUS", used for tracing
1120 * sccs_get_name The Name ".SCCS_GET", used for tracing
1121 * sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing
1122 * get_name The Name ".GET", used for tracing
1123 * sccs_get_rule Set when ".SCCS_GET" target is read
1124 * silent Set when ".SILENT" target is read
1125 * silent_name The Name ".SILENT", used for tracing
1126 * trace_reader Indicates that we should echo stuff we read
1129 special_reader(Name target
, register Name_vector depes
, Cmd_line command
)
1133 switch (target
->special_reader
) {
1136 if (depes
->used
!= 0) {
1137 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1143 all_parallel
= false;
1144 only_parallel
= false;
1146 (void) printf("%s:\n", svr4_name
->string_mb
);
1153 if (depes
->used
!= 0) {
1154 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1158 /* with posix on, use the posix get rule */
1159 sccs_get_rule
= sccs_get_posix_rule
;
1160 /* turn keep state off being SunPro make specific */
1162 MBSTOWCS(wcs_buffer
, "/usr/bin/sh");
1163 (void) SETVAR(shell_name
, GETNAME(wcs_buffer
, FIND_LENGTH
), false);
1165 (void) printf("%s:\n", posix_name
->string_mb
);
1169 case built_last_make_run_special
:
1170 built_last_make_run_seen
= true;
1173 case default_special
:
1174 if (depes
->used
!= 0) {
1175 warning(gettext("Illegal dependency list for target `%s'"),
1178 default_rule
= command
;
1180 (void) printf("%s:\n",
1181 default_rule_name
->string_mb
);
1182 print_rule(command
);
1187 case ignore_special
:
1188 if ((depes
->used
!= 0) &&(!posix
)){
1189 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1192 if (depes
->used
== 0)
1194 ignore_errors_all
= true;
1197 ignore_errors_all
= true;
1200 for (; depes
!= NULL
; depes
= depes
->next
) {
1201 for (n
= 0; n
< depes
->used
; n
++) {
1202 depes
->names
[n
]->ignore_error_mode
= true;
1206 (void) printf("%s:\n", ignore_name
->string_mb
);
1210 case keep_state_special
:
1213 /* ignore keep state, being SunPro make specific */
1216 if (depes
->used
!= 0) {
1217 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1222 (void) printf("%s:\n",
1223 dot_keep_state
->string_mb
);
1227 case keep_state_file_special
:
1232 /* it's not necessary to specify KEEP_STATE, if this
1233 ** is given, so set the keep_state.
1236 if (depes
->used
!= 0) {
1237 if((!make_state
) ||(!strcmp(make_state
->string_mb
,".make.state"))) {
1238 make_state
= depes
->names
[0];
1242 case make_version_special
:
1245 if (depes
->used
!= 1) {
1246 fatal_reader(gettext("Illegal dependency list for target `%s'"),
1249 if (depes
->names
[0] != current_make_version
) {
1251 * Special case the fact that version 1.0 and 1.1
1254 if (!IS_EQUAL(depes
->names
[0]->string_mb
,
1256 !IS_EQUAL(current_make_version
->string_mb
,
1259 * Version mismatches should cause the
1260 * .make.state file to be skipped.
1261 * This is currently not true - it is read
1264 warning(gettext("Version mismatch between current version `%s' and `%s'"),
1265 current_make_version
->string_mb
,
1266 depes
->names
[0]->string_mb
);
1271 case no_parallel_special
:
1274 /* Set the no_parallel bit for all the targets on */
1275 /* the dependency list */
1276 if (depes
->used
== 0) {
1277 /* only those explicitly made parallel */
1278 only_parallel
= true;
1279 all_parallel
= false;
1281 for (; depes
!= NULL
; depes
= depes
->next
) {
1282 for (n
= 0; n
< depes
->used
; n
++) {
1284 (void) printf("%s:\t%s\n",
1285 no_parallel_name
->string_mb
,
1286 depes
->names
[n
]->string_mb
);
1288 depes
->names
[n
]->no_parallel
= true;
1289 depes
->names
[n
]->parallel
= false;
1294 case parallel_special
:
1297 if (depes
->used
== 0) {
1298 /* everything runs in parallel */
1299 all_parallel
= true;
1300 only_parallel
= false;
1302 /* Set the parallel bit for all the targets on */
1303 /* the dependency list */
1304 for (; depes
!= NULL
; depes
= depes
->next
) {
1305 for (n
= 0; n
< depes
->used
; n
++) {
1307 (void) printf("%s:\t%s\n",
1308 parallel_name
->string_mb
,
1309 depes
->names
[n
]->string_mb
);
1311 depes
->names
[n
]->parallel
= true;
1312 depes
->names
[n
]->no_parallel
= false;
1317 case localhost_special
:
1320 /* Set the no_parallel bit for all the targets on */
1321 /* the dependency list */
1322 if (depes
->used
== 0) {
1323 /* only those explicitly made parallel */
1324 only_parallel
= true;
1325 all_parallel
= false;
1327 for (; depes
!= NULL
; depes
= depes
->next
) {
1328 for (n
= 0; n
< depes
->used
; n
++) {
1330 (void) printf("%s:\t%s\n",
1331 localhost_name
->string_mb
,
1332 depes
->names
[n
]->string_mb
);
1334 depes
->names
[n
]->no_parallel
= true;
1335 depes
->names
[n
]->parallel
= false;
1336 depes
->names
[n
]->localhost
= true;
1341 case precious_special
:
1342 if (depes
->used
== 0) {
1343 /* everything is precious */
1344 all_precious
= true;
1346 all_precious
= false;
1349 all_precious
= true;
1352 /* Set the precious bit for all the targets on */
1353 /* the dependency list */
1354 for (; depes
!= NULL
; depes
= depes
->next
) {
1355 for (n
= 0; n
< depes
->used
; n
++) {
1357 (void) printf("%s:\t%s\n",
1358 precious
->string_mb
,
1359 depes
->names
[n
]->string_mb
);
1361 depes
->names
[n
]->stat
.is_precious
= true;
1366 case sccs_get_special
:
1367 if (depes
->used
!= 0) {
1368 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1371 sccs_get_rule
= command
;
1372 sccs_get_org_rule
= command
;
1374 (void) printf("%s:\n", sccs_get_name
->string_mb
);
1375 print_rule(command
);
1379 case sccs_get_posix_special
:
1380 if (depes
->used
!= 0) {
1381 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1384 sccs_get_posix_rule
= command
;
1386 (void) printf("%s:\n", sccs_get_posix_name
->string_mb
);
1387 print_rule(command
);
1391 case get_posix_special
:
1392 if (depes
->used
!= 0) {
1393 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1396 get_posix_rule
= command
;
1398 (void) printf("%s:\n", get_posix_name
->string_mb
);
1399 print_rule(command
);
1407 if (depes
->used
!= 0) {
1408 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1412 sccs_get_rule
= command
;
1414 (void) printf("%s:\n", get_name
->string_mb
);
1415 print_rule(command
);
1419 case silent_special
:
1420 if ((depes
->used
!= 0) && (!posix
)){
1421 fatal_reader(gettext("Illegal dependencies for target `%s'"),
1424 if (depes
->used
== 0)
1432 for (; depes
!= NULL
; depes
= depes
->next
) {
1433 for (n
= 0; n
< depes
->used
; n
++) {
1434 depes
->names
[n
]->silent_mode
= true;
1438 (void) printf("%s:\n", silent_name
->string_mb
);
1442 case suffixes_special
:
1443 read_suffixes_list(depes
);
1448 fatal_reader(gettext("Internal error: Unknown special reader"));
1453 * read_suffixes_list(depes)
1455 * Read the special list .SUFFIXES. If it is empty the old list is
1456 * cleared. Else the new one is appended. Suffixes with ~ are extracted
1460 * depes The list of suffixes
1462 * Global variables used:
1463 * hashtab The central hashtable for Names.
1464 * suffixes The list of suffixes, set or appended to
1465 * suffixes_name The Name ".SUFFIXES", used for tracing
1466 * trace_reader Indicates that we should echo stuff we read
1469 read_suffixes_list(register Name_vector depes
)
1472 register Dependency dp
;
1473 register Dependency
*insert_dep
;
1476 register Boolean first
= true;
1478 if (depes
->used
== 0) {
1479 /* .SUFFIXES with no dependency list clears the */
1481 for (Name_set::iterator np
= hashtab
.begin(), e
= hashtab
.end(); np
!= e
; np
++) {
1483 np
->without_squiggle
=
1488 (void) printf("%s:\n", suffixes_name
->string_mb
);
1493 /* Otherwise we append to the list */
1494 for (; depes
!= NULL
; depes
= depes
->next
) {
1495 for (n
= 0; n
< depes
->used
; n
++) {
1496 np
= depes
->names
[n
];
1497 /* Find the end of the list and check if the */
1498 /* suffix already has been entered */
1499 for (insert_dep
= &suffixes
, dp
= *insert_dep
;
1501 insert_dep
= &dp
->next
, dp
= *insert_dep
) {
1502 if (dp
->name
== np
) {
1503 goto duplicate_suffix
;
1508 (void) printf("%s:\t",
1509 suffixes_name
->string_mb
);
1512 (void) printf("%s ", depes
->names
[n
]->string_mb
);
1515 /* If the suffix is suffixed with "~" we */
1516 /* strip that and mark the suffix nameblock */
1518 wchar_t * wcb
= str
.get_string();
1519 if (wcb
[np
->hash
.length
- 1] ==
1522 (int)(np
->hash
.length
- 1));
1523 np2
->with_squiggle
= true;
1524 if (np2
->without_squiggle
) {
1530 np
->without_squiggle
= true;
1531 /* Add the suffix to the list */
1532 dp
= *insert_dep
= ALLOC(Dependency
);
1533 insert_dep
= &dp
->next
;
1541 (void) printf("\n");
1546 * make_relative(to, result)
1548 * Given a file name compose a relative path name from it to the
1549 * current directory.
1552 * to The path we want to make relative
1553 * result Where to put the resulting relative path
1555 * Global variables used:
1558 make_relative(wchar_t *to
, wchar_t *result
)
1568 /* Check if the path is already relative. */
1569 if (to
[0] != (int) slash_char
) {
1570 (void) wcscpy(result
, to
);
1574 MBSTOWCS(wcs_buffer
, get_current_path());
1575 from
= allocated
= (wchar_t *) wcsdup(wcs_buffer
);
1578 * Find the number of components in the from name.
1579 * ncomp = number of slashes + 1.
1582 for (cp
= from
; *cp
!= (int) nul_char
; cp
++) {
1583 if (*cp
== (int) slash_char
) {
1589 * See how many components match to determine how many "..",
1590 * if any, will be needed.
1592 result
[0] = (int) nul_char
;
1594 while ((*from
!= (int) nul_char
) && (*from
== *to
)) {
1595 if (*from
== (int) slash_char
) {
1604 * Now for some special cases. Check for exact matches and
1605 * for either name terminating exactly.
1607 if (*from
== (int) nul_char
) {
1608 if (*to
== (int) nul_char
) {
1609 MBSTOWCS(wcs_buffer
, ".");
1610 (void) wcscpy(result
, wcs_buffer
);
1614 if (*to
== (int) slash_char
) {
1618 } else if ((*from
== (int) slash_char
) && (*to
== (int) nul_char
)) {
1622 /* Add on the ".."s. */
1623 for (i
= 0; i
< ncomps
; i
++) {
1624 MBSTOWCS(wcs_buffer
, "../");
1625 (void) wcscat(result
, wcs_buffer
);
1628 /* Add on the remainder of the to name, if any. */
1629 if (*tocomp
== (int) nul_char
) {
1630 len
= wcslen(result
);
1631 result
[len
- 1] = (int) nul_char
;
1633 (void) wcscat(result
, tocomp
);
1640 * print_rule(command)
1642 * Used when tracing the reading of rules
1645 * command Command to print
1647 * Global variables used:
1650 print_rule(register Cmd_line command
)
1652 for (; command
!= NULL
; command
= command
->next
) {
1653 (void) printf("\t%s\n", command
->command_line
->string_mb
);
1658 * enter_conditional(target, name, value, append)
1660 * Enter "target := MACRO= value" constructs
1663 * target The target the macro is for
1664 * name The name of the macro
1665 * value The value for the macro
1666 * append Indicates if the assignment is appending or not
1668 * Global variables used:
1669 * conditionals A special Name that stores all conditionals
1670 * where the target is a % pattern
1671 * trace_reader Indicates that we should echo stuff we read
1674 enter_conditional(register Name target
, Name name
, Name value
, register Boolean append
)
1676 register Property conditional
;
1677 static int sequence
;
1678 Name orig_target
= target
;
1680 if (name
== target_arch
) {
1681 enter_conditional(target
, virtual_root
, virtual_root
, false);
1684 if (target
->percent
) {
1685 target
= conditionals
;
1689 sh_transform(&name
, &value
);
1692 /* Count how many conditionals we must activate before building the */
1694 if (target
->percent
) {
1695 target
= conditionals
;
1698 target
->conditional_cnt
++;
1699 maybe_append_prop(name
, macro_prop
)->body
.macro
.is_conditional
= true;
1700 /* Add the property for the target */
1701 conditional
= append_prop(target
, conditional_prop
);
1702 conditional
->body
.conditional
.target
= orig_target
;
1703 conditional
->body
.conditional
.name
= name
;
1704 conditional
->body
.conditional
.value
= value
;
1705 conditional
->body
.conditional
.sequence
= sequence
++;
1706 conditional
->body
.conditional
.append
= append
;
1708 if (value
== NULL
) {
1709 (void) printf("%s := %s %c=\n",
1713 (int) plus_char
: (int) space_char
);
1715 (void) printf("%s := %s %c= %s\n",
1719 (int) plus_char
: (int) space_char
,
1726 * enter_equal(name, value, append)
1728 * Enter "MACRO= value" constructs
1731 * name The name of the macro
1732 * value The value for the macro
1733 * append Indicates if the assignment is appending or not
1735 * Global variables used:
1736 * trace_reader Indicates that we should echo stuff we read
1739 enter_equal(Name name
, Name value
, register Boolean append
)
1745 sh_transform(&name
, &value
);
1747 (void) SETVAR(name
, value
, append
);
1749 /* if we're setting FC, we want to set F77 to the same value. */
1751 wchar_t * wcb
= nms
.get_string();
1753 if (string
[0]=='F' &&
1756 MBSTOWCS(wcs_buffer
, "F77");
1757 temp
= GETNAME(wcs_buffer
, FIND_LENGTH
);
1758 (void) SETVAR(temp
, value
, append
);
1760 fprintf(stderr, gettext("warning: FC is obsolete, use F77 instead\n"));
1765 if (value
== NULL
) {
1766 (void) printf("%s %c=\n",
1769 (int) plus_char
: (int) space_char
);
1771 (void) printf("%s %c= %s\n",
1774 (int) plus_char
: (int) space_char
,
1781 * sh_transform(name, value)
1784 * name The name of the macro we might transform
1785 * value The value to transform
1789 sh_transform(Name
*name
, Name
*value
)
1791 /* Check if we need :sh transform */
1794 String_rec destination
;
1795 wchar_t buffer
[1000];
1796 wchar_t buffer1
[1000];
1798 static wchar_t colon_sh
[4];
1799 static wchar_t colon_shell
[7];
1801 if (colon_sh
[0] == (int) nul_char
) {
1802 MBSTOWCS(colon_sh
, ":sh");
1803 MBSTOWCS(colon_shell
, ":shell");
1805 Wstring
nms((*name
));
1806 wchar_t * wcb
= nms
.get_string();
1808 colon
= (wchar_t *) wcsrchr(wcb
, (int) colon_char
);
1809 if ((colon
!= NULL
) && (IS_WEQUAL(colon
, colon_sh
) || IS_WEQUAL(colon
, colon_shell
))) {
1810 INIT_STRING_FROM_STACK(destination
, buffer
);
1812 if(*value
== NULL
) {
1815 Wstring
wcb1((*value
));
1816 if (IS_WEQUAL(colon
, colon_shell
)) {
1817 INIT_STRING_FROM_STACK(command
, buffer1
);
1818 expand_value(*value
, &command
, false);
1820 command
.text
.p
= wcb1
.get_string() + (*value
)->hash
.length
;
1821 command
.text
.end
= command
.text
.p
;
1822 command
.buffer
.start
= wcb1
.get_string();
1823 command
.buffer
.end
= command
.text
.p
;
1825 sh_command2string(&command
, &destination
);
1828 (*value
) = GETNAME(destination
.buffer
.start
, FIND_LENGTH
);
1829 *colon
= (int) nul_char
;
1830 (*name
) = GETNAME(wcb
, FIND_LENGTH
);
1831 *colon
= (int) colon_char
;
1836 * fatal_reader(format, args...)
1839 * format printf style format string
1840 * args arguments to match the format
1842 * Global variables used:
1843 * file_being_read Name of the makefile being read
1844 * line_number Line that is being read
1845 * report_pwd Indicates whether current path should be shown
1846 * temp_file_name When reading tempfile we report that name
1850 fatal_reader(char * pattern
, ...)
1855 va_start(args
, pattern
);
1856 if (file_being_read
!= NULL
) {
1857 WCSTOMBS(mbs_buffer
, file_being_read
);
1858 if (line_number
!= 0) {
1859 (void) sprintf(message
,
1860 gettext("%s, line %d: %s"),
1865 (void) sprintf(message
,
1873 (void) fflush(stdout
);
1874 (void) fprintf(stderr
, gettext("%s: Fatal error in reader: "),
1876 (void) vfprintf(stderr
, pattern
, args
);
1877 (void) fprintf(stderr
, "\n");
1880 if (temp_file_name
!= NULL
) {
1881 (void) fprintf(stderr
,
1882 gettext("%s: Temp-file %s not removed\n"),
1884 temp_file_name
->string_mb
);
1885 temp_file_name
= NULL
;
1889 (void) fprintf(stderr
,
1890 gettext("Current working directory %s\n"),
1891 get_current_path());
1893 (void) fflush(stderr
);