%{
+
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)mkmake.y 4.1 (Berkeley) %G%
+ */
+
typedef struct string {
int
hashval,
%token <intval> MACRO_CHAR NL WHITE_SPACE
%token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
%type <same> target target1 assignment assign1 actions action
-%type <same> command_list command list
+%type <same> command_list list list_element
%type <same> for_statement maybe_at_minus tokens token
%type <same> maybe_white_space
%type <intval> white_space macro_char
| target_action
;
-assignment :
- assign1 tokens NL
+assignment : assign1 tokens NL
{
assign($1, $2);
}
}
;
-assign1: tokens maybe_white_space '=' maybe_white_space
+assign1: token maybe_white_space '=' maybe_white_space
;
target_action: target actions
}
| target
{
- add_targets_actions($1, same_copy(null));
+ add_targets_actions($1, 0);
}
;
-target :
- target1 tokens NL
+target : target1 tokens NL
{
$$ = add_depends($1, $2);
}
;
target1: tokens maybe_white_space ':' maybe_white_space
+ {
+ $$ = ws_merge($1);
+ }
;
actions: action
| actions action
{
- $$ = same_cat($1, $2);
+ $$ = same_cat(same_cat($1, same_copy(newline)), $2);
}
;
}
| white_space for_statement do command_list semi_colon done NL
{
- $$ = $2;
+ $$ = do_command($2, $4);
}
;
for_statement: maybe_at_minus FOR white_space token
in tokens semi_colon
{
- $$ = for_statement($1, $4, expand_variables($6, 0));
+ $$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
}
;
command_list: list
| '(' list maybe_white_space ')'
{
- $$ = $2;
+ $$ = same_cat($2, same_copy(cwd_line));
}
;
-list: command
+list: token
+ | list list_element
{
- $$ = $1;
+ $$ = same_cat($1, $2);
}
- | list semi_colon white_space command
+ | list white_space list_element
{
- $$ = same_cat($1, same_cat(same_char('\n'), $4));
+ $$ = same_cat($1, same_cat(same_copy(blank), $3));
}
;
-command: tokens
+list_element: token
+ | semi_colon
+ {
+ $$ = same_copy(newline);
+ }
;
maybe_at_minus: /* empty */
$$ = same_item(string_lookup(buffer));
}
- | '$' '$' token
+ | '$' '$' TOKEN
{
- $$ = shell_variable($3);
+ $$ = shell_variable(same_item($3));
}
| MACRO_CHAR
{
$$ = same_char($1);
}
- | '$' '{' token '}'
+ | '$' '{' TOKEN '}'
+ {
+ $$ = variable(same_item($3));
+ }
+ | '$' '(' TOKEN ')'
+ {
+ $$ = variable(same_item($3));
+ }
+ | '$' TOKEN
{
- $$ = variable($3);
+ $$ = variable(same_item($2));
}
| '-'
{
;
%%
#include <stdio.h>
+#include <ctype.h>
static int last_char, last_saved = 0;
static int column = 0, lineno = 1;
static same_t
*null,
*blank,
+ *cwd_line,
*newline;
extern char *malloc();
return ptr;
}
+#define same_singleton(s) ((s)->nexttoken == (s))
+
same_t *
same_search(list, token)
same_t
return head;
}
+
+same_t *
+same_merge(t1, t2)
+same_t
+ *t1,
+ *t2;
+{
+ if (same_singleton(t1) && same_singleton(t2)) {
+ int length = strlen(t1->string->string)+strlen(t2->string->string);
+ char *buffer = malloc(length+1);
+ same_t *value;
+
+ if (buffer == 0) {
+ yyerror("No space to merge strings in same_merge!");
+ exit(1);
+ }
+ strcpy(buffer, t1->string->string);
+ strcat(buffer, t2->string->string);
+ value = same_item(string_lookup(buffer));
+ free(buffer);
+ return value;
+ } else {
+ yyerror("Internal error - same_merge with non-singletons");
+ exit(1);
+ }
+}
+
+
void
same_free(list)
same_t *list;
{
same_t *token, *ptr;
+ if (list == 0) {
+ return;
+ }
+
token = list;
do {
ptr = token->nexttoken;
return tmp;
}
+void
+same_replace(old, new)
+same_t
+ *old,
+ *new;
+{
+ new->lasttoken->nexttoken = old->nexttoken;
+ old->nexttoken->lasttoken = new->lasttoken;
+ new->lasttoken = old->lasttoken;
+ /* rather than
+ * old->lasttoken->nexttoken = new
+ * we update in place (for the case where there isn't anything else)
+ */
+ *old = *new;
+}
+
+
same_t *
same_char(ch)
char ch;
return same_item(string_lookup(buffer));
}
-same_t *
-add_target(target)
+
+void
+add_target(target, actions)
same_t
- *target;
+ *target,
+ *actions;
{
same_t *ptr;
if ((ptr = same_search(targets, target)) == 0) {
targets = same_cat(targets, target);
- return target;
+ ptr = target;
} else {
- ptr->action_list = same_cat(ptr->action_list, target->action_list);
ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
- return ptr;
+ }
+ if (actions) {
+ if (ptr->action_list) {
+ same_free(ptr->action_list);
+ }
+ ptr->action_list = same_copy(actions);
}
}
+
same_t *
add_targets_actions(target, actions)
same_t
return 0;
}
do {
- target->action_list = same_cat(target->action_list,
- same_copy(actions));
ptr = same_unlink(target);
- add_target(target);
+ add_target(target, actions);
target = ptr;
} while (target);
if ((ptr = same_search(variables, variable)) != 0) {
same_free(ptr->value_list);
- (void) same_unlink(ptr);
+ variables = same_unlink(ptr);
same_free(ptr);
}
variable->value_list = value;
char *string = token->string->string;
same_t *tmp = same_unlink(token);
- if ((string[0] == '$') && (string[1] == '{')) {/* '}' Expand time */
+ if ((string[0] == '$') && (string[1] == '{')) { /* Expand time */
int len = strlen(string);
string[len-1] = 0;
return head;
}
+
+same_t *
+ws_merge(list)
+same_t *list;
+{
+ same_t *newlist = 0, *item;
+ int what = 0;
+
+ while (list) {
+ switch (what) {
+ case 0:
+ if (isspace(list->string->string[0])) {
+ ;
+ } else {
+ item = same_item(list->string);
+ what = 1;
+ }
+ break;
+ case 1:
+ if (isspace(list->string->string[0])) {
+ newlist = same_cat(newlist, item);
+ item = 0;
+ what = 0;
+ } else {
+ item = same_merge(item, same_item(list->string));
+ what = 1;
+ }
+ break;
+ }
+ list = same_unlink(list);
+ }
+ return same_cat(newlist, item);
+}
+
+
same_t *
variable(var_name)
same_t *var_name;
same_t *
-shell_variable(name)
-same_t *name;
+shell_variable(var_name)
+same_t *var_name;
{
- same_t *shell;
+ int length = strlen(var_name->string->string);
+ same_t *resolved;
+ char *newname;
- if ((shell = same_search(shell_variables, name)) == 0) {
- char buffer[100];
- sprintf(buffer, "Unknown shell variable %s.", name->string->string);
- yyerror(buffer);
+ if ((newname = malloc(length+1+2)) == 0) {
+ fprintf("Out of space for a variable name.\n");
exit(1);
}
- return same_copy(shell->shell_item);
+ newname[0] = '$';
+ newname[1] = '$';
+ strcpy(newname+2, var_name->string->string);
+ resolved = same_item(string_lookup(newname));
+ free(newname);
+
+ return resolved;
}
same_t *
*variable,
*list;
{
- shell_special = special;
+ variable->shell_item = special;
variable->value_list = list;
- shell_variables = variable;
- return same_copy(null);
+ return variable;
+}
+
+same_t *
+do_command(forlist, commands)
+same_t
+ *forlist,
+ *commands;
+{
+ same_t
+ *special,
+ *command_list = 0,
+ *new_commands,
+ *tmp,
+ *shell_item,
+ *value_list = forlist->value_list;
+ char
+ *tmpstr,
+ *variable_name = forlist->string->string;
+
+ special = forlist->shell_item;
+ if (same_unlink(forlist->shell_item) != 0) {
+ yyerror("Unexpected second item in special part of do_command");
+ exit(1);
+ }
+
+ while ((shell_item = value_list) != 0) {
+ value_list = same_unlink(shell_item);
+ /* Visit each item in commands. For each shell variable which
+ * matches ours, replace it with ours.
+ */
+ new_commands = same_copy(commands);
+ for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
+ tmpstr = tmp->string->string;
+ if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
+ if (strcmp(tmpstr+2, variable_name) == 0) {
+ same_replace(tmp, same_copy(shell_item));
+ }
+ }
+ }
+ visit_end();
+ command_list = same_cat(command_list, new_commands);
+ }
+ return same_cat(command_list, same_copy(newline));
}
Return(c,c);
case '\'':
case '"':
- {
+ if (bufptr != buffer) {
+ if (bufptr[-1] == '\\') {
+ bufptr[-1] = c;
+ }
+ break;
+ } else {
int newc;
ret_token(c);
Return(EOF, 0);
}
+#ifndef lint
+static char sccsid[] = "@(#)mkmake.y 4.1 (Berkeley) %G%";
+#endif /* not lint */
+
main()
{
#define YYDEBUG
null = same_item(string_lookup(""));
newline = same_item(string_lookup("\n"));
blank = same_item(string_lookup(" "));
+ cwd_line = same_cat(same_copy(newline),
+ same_cat(same_item(string_lookup("cd ${CWD}")),
+ same_copy(newline)));
yyparse();
do_dump();
+
+ return 0;
}
#if defined(YYDEBUG)
}
visit_end();
- printf("#targets...\n");
+ printf("\n\n#targets...\n");
for (visit(targets, same); !visited(same); visit_next(same)) {
- printf("%s :\t", same->string->string);
+ printf("\n%s:\t", same->string->string);
for (visit(same->depend_list, same2); !visited(same2);
visit_next(same2)) {
printf(same2->string->string);