Release 4.1
[unix-history] / usr / src / usr.bin / tn3270 / tools / mkmake.y
index 080af67..67f7b81 100644 (file)
@@ -1,4 +1,24 @@
 %{
 %{
+
+/*
+ * 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,
 typedef struct string {
     int
        hashval,
@@ -51,7 +71,7 @@ typedef struct same {
 %token <intval> MACRO_CHAR NL WHITE_SPACE
 %token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
 %type <same> target target1 assignment assign1 actions action
 %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
 %type <same> for_statement maybe_at_minus tokens token
 %type <same> maybe_white_space
 %type <intval> white_space macro_char
@@ -68,8 +88,7 @@ line : NL
     | target_action
     ;
 
     | target_action
     ;
 
-assignment :
-    assign1 tokens NL
+assignment : assign1 tokens NL
     {
        assign($1, $2);
     }
     {
        assign($1, $2);
     }
@@ -79,7 +98,7 @@ assignment :
     }
     ;
 
     }
     ;
 
-assign1: tokens maybe_white_space '=' maybe_white_space
+assign1: token maybe_white_space '=' maybe_white_space
     ;
 
 target_action: target actions
     ;
 
 target_action: target actions
@@ -88,12 +107,11 @@ target_action: target actions
     }
     | target
     {
     }
     | 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);
     }
     {
        $$ = add_depends($1, $2);
     }
@@ -104,12 +122,15 @@ target :
     ;
 
 target1: tokens maybe_white_space ':' maybe_white_space
     ;
 
 target1: tokens maybe_white_space ':' maybe_white_space
+    {
+       $$ = ws_merge($1);
+    }
     ;
 
 actions: action
     | actions action
     {
     ;
 
 actions: action
     | actions action
     {
-       $$ = same_cat($1, $2);
+       $$ = same_cat(same_cat($1, same_copy(newline)), $2);
     }
     ;
 
     }
     ;
 
@@ -126,7 +147,7 @@ action:     white_space command_list NL
 for_statement: maybe_at_minus FOR white_space token
                in tokens semi_colon
     {
 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)));
     }
     ;
 
     }
     ;
 
@@ -143,21 +164,26 @@ semi_colon:       ';'
 command_list: list
     | '(' list maybe_white_space ')'
     {
 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 maybe_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 */
     ;
 
 maybe_at_minus: /* empty */
@@ -207,17 +233,25 @@ token: TOKEN
 
        $$ = same_item(string_lookup(buffer));
     }
 
        $$ = same_item(string_lookup(buffer));
     }
-    | '$' '$' token
+    | '$' '$' TOKEN
     {
     {
-       $$ = shell_variable($3);
+       $$ = shell_variable(same_item($3));
     }
     | MACRO_CHAR
     {
        $$ = same_char($1);
     }
     }
     | MACRO_CHAR
     {
        $$ = same_char($1);
     }
-    | '$' '{' token '}'
+    | '$' '{' TOKEN '}'
+    {
+       $$ = variable(same_item($3));
+    }
+    | '$' '(' TOKEN ')'
     {
     {
-       $$ = variable($3);
+       $$ = variable(same_item($3));
+    }
+    | '$' TOKEN
+    {
+       $$ = variable(same_item($2));
     }
     | '-'
     {
     }
     | '-'
     {
@@ -248,6 +282,7 @@ white_space : WHITE_SPACE
     ;
 %%
 #include <stdio.h>
     ;
 %%
 #include <stdio.h>
+#include <ctype.h>
 
 static int last_char, last_saved = 0;
 static int column = 0, lineno = 1;
 
 static int last_char, last_saved = 0;
 static int column = 0, lineno = 1;
@@ -266,6 +301,7 @@ static same_t
 static same_t
     *null,
     *blank,
 static same_t
     *null,
     *blank,
+    *cwd_line,
     *newline;
 
 extern char *malloc();
     *newline;
 
 extern char *malloc();
@@ -361,6 +397,8 @@ char *string;
     return ptr;
 }
 
     return ptr;
 }
 
+#define        same_singleton(s)       ((s)->nexttoken == (s))
+
 same_t *
 same_search(list, token)
 same_t
 same_t *
 same_search(list, token)
 same_t
@@ -439,12 +477,44 @@ same_t *same;
     return head;
 }
 
     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;
 
 void
 same_free(list)
 same_t *list;
 {
     same_t *token, *ptr;
 
+    if (list == 0) {
+       return;
+    }
+
     token = list;
     do {
        ptr = token->nexttoken;
     token = list;
     do {
        ptr = token->nexttoken;
@@ -473,6 +543,23 @@ same_t
     return tmp;
 }
 
     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;
 same_t *
 same_char(ch)
 char ch;
@@ -485,23 +572,30 @@ char ch;
     return same_item(string_lookup(buffer));
 }
 
     return same_item(string_lookup(buffer));
 }
 
-same_t *
-add_target(target)
+
+void
+add_target(target, actions)
 same_t
 same_t
-    *target;
+    *target,
+    *actions;
 {
     same_t *ptr;
 
     if ((ptr = same_search(targets, target)) == 0) {
        targets = same_cat(targets, target);
 {
     same_t *ptr;
 
     if ((ptr = same_search(targets, target)) == 0) {
        targets = same_cat(targets, target);
-       return target;
+       ptr = target;
     } else {
     } else {
-       ptr->action_list = same_cat(ptr->action_list, target->action_list);
        ptr->depend_list = same_cat(ptr->depend_list, target->depend_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
 same_t *
 add_targets_actions(target, actions)
 same_t
@@ -514,10 +608,8 @@ same_t
        return 0;
     }
     do {
        return 0;
     }
     do {
-       target->action_list = same_cat(target->action_list,
-                                               same_copy(actions));
        ptr = same_unlink(target);
        ptr = same_unlink(target);
-       add_target(target);
+       add_target(target, actions);
        target = ptr;
     } while (target);
 
        target = ptr;
     } while (target);
 
@@ -559,7 +651,7 @@ same_t
 
     if ((ptr = same_search(variables, variable)) != 0) {
        same_free(ptr->value_list);
 
     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;
        same_free(ptr);
     }
     variable->value_list = value;
@@ -595,7 +687,7 @@ int free;
        char *string = token->string->string;
        same_t *tmp = same_unlink(token);
 
        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;
            int len = strlen(string);
 
            string[len-1] = 0;
@@ -610,6 +702,41 @@ int        free;
     return head;
 }
 
     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 *
 variable(var_name)
 same_t *var_name;
@@ -672,7 +799,41 @@ same_t
     *forlist,
     *commands;
 {
     *forlist,
     *commands;
 {
-    return same_cat(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));
 }
 
 
 }
 
 
@@ -794,7 +955,12 @@ yylex()
            Return(c,c);
        case '\'':
        case '"':
            Return(c,c);
        case '\'':
        case '"':
-           {
+           if (bufptr != buffer) {
+               if (bufptr[-1] == '\\') {
+                   bufptr[-1] = c;
+               }
+               break;
+           } else {
                int newc;
 
                ret_token(c);
                int newc;
 
                ret_token(c);
@@ -834,6 +1000,10 @@ yylex()
     Return(EOF, 0);
 }
 
     Return(EOF, 0);
 }
 
+#ifndef lint
+static char sccsid[] = "@(#)mkmake.y   4.1 (Berkeley) %G%";
+#endif /* not lint */
+
 main()
 {
 #define        YYDEBUG
 main()
 {
 #define        YYDEBUG
@@ -842,10 +1012,15 @@ main()
     null = same_item(string_lookup(""));
     newline = same_item(string_lookup("\n"));
     blank = same_item(string_lookup(" "));
     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();
 
     yyparse();
 
     do_dump();
+
+    return 0;
 }
 
 #if    defined(YYDEBUG)
 }
 
 #if    defined(YYDEBUG)
@@ -885,9 +1060,9 @@ do_dump()
     }
     visit_end();
 
     }
     visit_end();
 
-    printf("#targets...\n");
+    printf("\n\n#targets...\n");
     for (visit(targets, same); !visited(same); visit_next(same)) {
     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);
        for (visit(same->depend_list, same2); !visited(same2);
                                                visit_next(same2)) {
            printf(same2->string->string);