4 * Copyright (c) 1988 The Regents of the University of California.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 #if defined(__RCSID) && !defined(lint)
36 static char sccsid
[] = "@(#)mkmake.y 4.2 (Berkeley) 4/26/91";
43 typedef
struct string {
54 * The deal with these is that they exist on various lists.
56 * First off, they are on a temporary list during the time they
57 * are in the active focus of the parser.
59 * Secondly, they live on one of three queues:
63 * (and, we restrict any given one to live on one and only one such list)
65 * Also, they may live on the list of values for someone else's variable,
66 * or as someone's dependency.
71 *string; /* My name */
73 *nexttoken
, /* Next pointer */
74 *lasttoken
, /* Back pointer */
75 *depend_list
, /* If target, dependancies */
76 *action_list
, /* If target, actions */
77 *value_list
, /* If variable, value list */
78 *shell_item
; /* If a shell variable, current value */
91 %token
<string> TOKEN QUOTED_STRING
92 %token
<intval
> FOR IN DO DONE
93 %token
<intval
> MACRO_CHAR NL WHITE_SPACE
94 %token
<intval
> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
95 %type
<same
> target target1 assignment assign1 actions action
96 %type
<same
> command_list list list_element
97 %type
<same
> for_statement maybe_at_minus tokens token
98 %type
<same
> maybe_white_space
99 %type
<intval
> white_space macro_char
113 assignment
: assign1 tokens NL
119 assign
($1, same_copy
(null
));
123 assign1: token maybe_white_space
'=' maybe_white_space
126 target_action: target actions
128 add_targets_actions
($1, $2);
132 add_targets_actions
($1, 0);
136 target
: target1 tokens NL
138 $$
= add_depends
($1, $2);
142 $$
= add_depends
($1, same_copy
(null
));
146 target1: tokens maybe_white_space
':' maybe_white_space
155 $$
= same_cat
(same_cat
($1, same_copy
(newline
)), $2);
159 action: white_space command_list NL
163 | white_space for_statement do command_list semi_colon done NL
165 $$
= do_command
($2, $4);
169 for_statement: maybe_at_minus FOR white_space token
172 $$
= for_statement
($1, $4, ws_merge
(expand_variables
($6, 0)));
176 in: white_space IN white_space
177 do: white_space DO white_space
180 done: white_space DONE
187 |
'(' list maybe_white_space
')'
189 $$
= same_cat
($2, same_copy
(cwd_line
));
196 $$
= same_cat
($1, $2);
198 | list white_space list_element
200 $$
= same_cat
($1, same_cat
(same_copy
(blank
), $3));
207 $$
= same_copy
(newline
);
211 maybe_at_minus: /* empty */
213 $$
= same_copy
(null
);
221 $$
= same_item
(string_lookup
(buffer
));
229 $$
= same_item
(string_lookup
(buffer
));
234 | tokens maybe_white_space token
236 $$
= same_cat
($1, same_cat
($2, $3));
256 $$
= same_item
(string_lookup
(buffer
));
260 $$
= shell_variable
(same_item
($3));
268 $$
= variable
(same_item
($3));
272 $$
= variable
(same_item
($3));
276 $$
= variable
(same_item
($2));
288 macro_char: MACRO_CHAR
294 $$
= same_copy
(null
);
302 white_space
: WHITE_SPACE
303 | white_space WHITE_SPACE
311 void yyerror(char *);
312 void assign
(same_t
*, same_t
*);
314 extern
int yyparse(void);
315 int main
(int, char *[]);
317 static int visitcheck
(same_t
*);
318 static int string_hashof
(char *, int);
319 static int string_same
(string_t
*, string_t
*);
320 static string_t
*string_lookup
(char *);
321 static same_t
*same_search
(same_t
*, same_t
*);
322 static same_t
*same_cat
(same_t
*, same_t
*);
323 static same_t
*same_item
(string_t
*);
324 static same_t
*same_copy
(same_t
*);
325 static same_t
*same_merge
(same_t
*, same_t
*);
326 static void same_free
(same_t
*);
327 static same_t
*same_unlink
(same_t
*);
328 static void same_replace
(same_t
*, same_t
*);
329 static same_t
*same_char
(int);
330 static void add_target
(same_t
*, same_t
*);
331 static same_t
*add_targets_actions
(same_t
*, same_t
*);
332 static same_t
*add_depends
(same_t
*, same_t
*);
333 static same_t
*value_of
(same_t
*);
334 static same_t
*expand_variables
(same_t
*, int);
335 static same_t
*ws_merge
(same_t
*);
336 static same_t
*variable
(same_t
*);
337 static same_t
*shell_variable
(same_t
*);
338 static same_t
*for_statement
(same_t
*, same_t
*, same_t
*);
339 static same_t
*do_command
(same_t
*, same_t
*);
340 static int Getchar
(void);
341 static int token_type
(char *);
343 static void dump_same
(same_t
*);
345 static void do_dump
(void);
346 static int last_char
, last_saved
= 0;
347 static int column
= 0, lineno
= 1;
369 } visit_stack
[20]; /* 20 maximum */
371 #define visit(what,via) \
372 (visit_stack
[++clock
].next
= 0, visit_stack
[clock
].first
= via
= what
)
373 #define visited(via) (visitcheck(via) || ((via) == 0) \
374 ||
(visit_stack
[clock
].next
&& (via
== visit_stack
[clock
].first
)))
375 #define visit_next(via) (visit_stack[clock].next = 1, (via) = (via)->nexttoken)
376 #define visit_end() (clock--)
382 fprintf
(stderr
, "line %d, character %d: %s\n", lineno
, column
, s
);
390 if
(same
->string == 0) {
391 yyerror("BUG - freed 'same' in use...");
398 string_hashof
(string, length
)
405 i
= ((i
<<3) + *string) ^
((i
>>28)&0x7);
415 if
((s1
->hashval
== s2
->hashval
) && (s1
->length
== s2
->length
)
416 && (memcmp
(s1
->string, s2
->string, s1
->length
) == 0)) {
424 string_lookup
(string)
430 ours.length
= strlen
(string);
431 ours.hashval
= string_hashof
(string, ours.length
);
432 ours.
string = string;
434 for
(ptr
= strings
; ptr
; ptr
= ptr
->next
) {
435 if
(string_same
(&ours
, ptr
)) {
439 if
((ptr
= (string_t
*)malloc
(sizeof
*ptr
)) == 0) {
440 fprintf
(stderr
, "No space to add string *%s*!\n", string);
443 ptr
->hashval
= ours.hashval
;
444 ptr
->length
= ours.length
;
445 if
((ptr
->string = malloc
(ours.length
+1)) == 0) {
446 fprintf
(stderr
, "No space to add literal *%s*!\n", string);
449 memcpy
(ptr
->string, string, ours.length
+1);
455 #define same_singleton(s) ((s)->nexttoken == (s))
458 same_search
(list
, token
)
466 for
(visit
(list
, ptr
); !visited
(ptr
); visit_next
(ptr
)) {
469 string = ptr
->string;
470 if
(string_same
(string, token
->string)) {
480 same_cat
(list
, tokens
)
491 last
= tokens
->lasttoken
;
492 tokens
->lasttoken
= list
->lasttoken
;
493 list
->lasttoken
= last
;
494 tokens
->lasttoken
->nexttoken
= tokens
;
495 last
->nexttoken
= list
;
508 if
((ptr
= (same_t
*)malloc
(sizeof
*ptr
)) == 0) {
509 fprintf
(stderr
, "No more space for tokens!\n");
512 memset
((char *)ptr
, 0, sizeof
*ptr
);
513 ptr
->nexttoken
= ptr
->lasttoken
= ptr
;
514 ptr
->string = string;
525 for
(visit
(same
, copy
); !visited
(copy
); visit_next
(copy
)) {
528 ptr
= same_item
(copy
->string);
529 head
= same_cat
(head
, ptr
);
542 if
(same_singleton
(t1
) && same_singleton
(t2
)) {
543 int length
= strlen
(t1
->string->string)+strlen
(t2
->string->string);
544 char *buffer
= malloc
(length
+1);
548 yyerror("No space to merge strings in same_merge!");
551 strcpy
(buffer
, t1
->string->string);
552 strcat
(buffer
, t2
->string->string);
553 value
= same_item
(string_lookup
(buffer
));
557 yyerror("Internal error - same_merge with non-singletons");
575 ptr
= token
->nexttoken
;
577 (void) free
((char *)token
);
579 } while
(token
!= list
);
592 if
((tmp
= token
->nexttoken
) == token
) {
595 token
->lasttoken
->nexttoken
= token
->nexttoken
;
596 token
->nexttoken
->lasttoken
= token
->lasttoken
;
597 token
->nexttoken
= token
->lasttoken
= token
;
602 same_replace
(old
, new
)
607 new
->lasttoken
->nexttoken
= old
->nexttoken
;
608 old
->nexttoken
->lasttoken
= new
->lasttoken
;
609 new
->lasttoken
= old
->lasttoken
;
611 * old->lasttoken->nexttoken = new
612 * we update in place (for the case where there isn't anything else)
627 return same_item
(string_lookup
(buffer
));
632 add_target
(target
, actions
)
639 if
((ptr
= same_search
(targets
, target
)) == 0) {
640 targets
= same_cat
(targets
, target
);
643 ptr
->depend_list
= same_cat
(ptr
->depend_list
, target
->depend_list
);
646 if
(ptr
->action_list
) {
647 same_free
(ptr
->action_list
);
649 ptr
->action_list
= same_copy
(actions
);
655 add_targets_actions
(target
, actions
)
666 ptr
= same_unlink
(target
);
667 add_target
(target
, actions
);
676 add_depends
(target
, depends
)
681 same_t
*original
= target
;
683 depends
= same_cat
(depends
, same_copy
(blank
)); /* Separator */
685 for
(visit
(original
, target
); !visited
(target
); visit_next
(target
)) {
686 target
->depend_list
= same_cat
(target
->depend_list
, same_copy
(depends
));
696 * We know that variable is a singleton
700 assign
(variable
, value
)
707 if
((ptr
= same_search
(variables
, variable
)) != 0) {
708 same_free
(ptr
->value_list
);
709 variables
= same_unlink
(ptr
);
712 variable
->value_list
= value
;
713 variables
= same_cat
(variables
, variable
);
720 same_t
*ptr
= same_search
(variables
, variable
);
723 return same_copy
(null
);
725 return same_copy
(ptr
->value_list
);
731 expand_variables
(token
, free
)
738 token
= same_copy
(token
); /* Get our private copy */
742 char *string = token
->string->string;
743 same_t
*tmp
= same_unlink
(token
);
745 if
((string[0] == '$') && (string[1] == '{')) { /* Expand time */
746 int len
= strlen
(string);
749 head
= same_cat
(head
, expand_variables
(
750 value_of
(same_item
(string_lookup
(string+2))), 1));
753 head
= same_cat
(head
, token
);
765 same_t
*newlist
= 0, *item
= NULL
;
771 if
(isspace
(list
->string->string[0])) {
774 item
= same_item
(list
->string);
779 if
(isspace
(list
->string->string[0])) {
780 newlist
= same_cat
(newlist
, item
);
784 item
= same_merge
(item
, same_item
(list
->string));
789 list
= same_unlink
(list
);
791 return same_cat
(newlist
, item
);
799 int length
= strlen
(var_name
->string->string);
803 if
((newname
= malloc
(length
+1+3)) == 0) {
804 fprintf
(stderr
, "Out of space for a variable name.\n");
809 strcpy
(newname
+2, var_name
->string->string);
810 strcat
(newname
, "}");
811 resolved
= same_item
(string_lookup
(newname
));
819 shell_variable
(var_name
)
822 int length
= strlen
(var_name
->string->string);
826 if
((newname
= malloc
(length
+1+2)) == 0) {
827 fprintf
(stderr
, "Out of space for a variable name.\n");
832 strcpy
(newname
+2, var_name
->string->string);
833 resolved
= same_item
(string_lookup
(newname
));
840 for_statement
(special
, variable
, list
)
846 variable
->shell_item
= special
;
847 variable
->value_list
= list
;
852 do_command
(forlist
, commands
)
863 *value_list
= forlist
->value_list
;
866 *variable_name
= forlist
->string->string;
868 special
= forlist
->shell_item
;
869 if
(same_unlink
(forlist
->shell_item
) != 0) {
870 yyerror("Unexpected second item in special part of do_command");
874 while
((shell_item
= value_list
) != 0) {
875 value_list
= same_unlink
(shell_item
);
876 /* Visit each item in commands. For each shell variable which
877 * matches ours, replace it with ours.
879 new_commands
= same_copy
(commands
);
880 for
(visit
(new_commands
, tmp
); !visited
(tmp
); visit_next
(tmp
)) {
881 tmpstr
= tmp
->string->string;
882 if
((tmpstr
[0] == '$') && (tmpstr
[1] == '$')) {
883 if
(strcmp
(tmpstr
+2, variable_name
) == 0) {
884 same_replace
(tmp
, same_copy
(shell_item
));
889 command_list
= same_cat
(command_list
, new_commands
);
891 return same_cat
(command_list
, same_copy
(newline
));
923 if
(strcmp
(string, "for") == 0) {
928 if
(string[1] == 'o') {
929 if
(strcmp
(string, "do") == 0) {
931 } else if
(strcmp
(string, "done") == 0) {
937 if
(strcmp
(string, "in") == 0) {
951 #define ret_token(c) if (bufptr != buffer) { \
955 yylval.
string = string_lookup
(buffer
); \
956 return token_type
(buffer
); \
958 #define save(c) { last_char = c; last_saved = 1; }
960 #define Return(y,c) if (yydebug) { \
966 #else /* defined(YYDEBUG) */
967 #define Return(y,c) { yylval.intval = c; return y; }
968 #endif /* defined(YYDEBUG) */
971 static char buffer
[500], *bufptr
= buffer
;
972 static int eof_found
= 0;
975 if
(eof_found
!= 0) {
978 fprintf
(stderr
, "End of file ignored.\n");
983 while
((c
= Getchar
()) != EOF
) {
987 while
(((c
= Getchar
()) != EOF
) && (c
!= '\n')) {
995 Return
(MACRO_CHAR
, c
);
999 Return
(WHITE_SPACE
, c
);
1014 if
(bufptr
!= buffer
) {
1015 if
(bufptr
[-1] == '\\') {
1024 while
(((newc
= Getchar
()) != EOF
) && (newc
!= c
)) {
1030 yylval.
string = string_lookup
(buffer
);
1031 return QUOTED_STRING
;
1034 if
(bufptr
!= buffer
) {
1035 if
(bufptr
[-1] == '\\') {
1037 if
((c
= Getchar
()) != '\t') {
1038 yyerror("continuation line doesn't begin with a tab");
1042 Return
(WHITE_SPACE
, c
);
1064 null
= same_item
(string_lookup
(""));
1065 newline
= same_item
(string_lookup
("\n"));
1066 blank
= same_item
(string_lookup
(" "));
1067 cwd_line
= same_cat
(same_copy
(newline
),
1068 same_cat
(same_item
(string_lookup
("cd ${CWD}")),
1069 same_copy
(newline
)));
1085 for
(visit
(same
, same2
); !visited
(same2
); visit_next
(same2
)) {
1086 printf
("%s", same2
->string->string);
1096 same_t
*same
, *same2
;
1099 printf
("strings...\n");
1100 for
(string = strings
; string; string = string->next
) {
1101 printf
("\t%s\n", string->string);
1105 printf
("# variables...\n");
1106 for
(visit
(variables
, same
); !visited
(same
); visit_next
(same
)) {
1107 printf
("%s =\t", same
->string->string);
1108 for
(visit
(same
->value_list
, same2
); !visited
(same2
);
1109 visit_next
(same2
)) {
1110 printf
("%s", same2
->string->string);
1117 printf
("\n\n#targets...\n");
1118 for
(visit
(targets
, same
); !visited
(same
); visit_next
(same
)) {
1119 printf
("\n%s:\t", same
->string->string);
1120 for
(visit
(same
->depend_list
, same2
); !visited
(same2
);
1121 visit_next
(same2
)) {
1122 printf
("%s", same2
->string->string);
1126 for
(visit
(same
->action_list
, same2
); !visited
(same2
);
1127 visit_next
(same2
)) {
1128 printf
("%s", same2
->string->string);
1129 if
(same2
->string->string[0] == '\n') {