Install sccs headers and copyright notices.
[unix-history] / usr / src / usr.bin / tn3270 / tools / mkmake.y
index 0351df6..1e27b35 100644 (file)
@@ -1,4 +1,26 @@
 %{
 %{
+
+/*
+ *     Copyright (c) 1984-1987 by the Regents of the
+ *     University of California and by Gregory Glenn Minshall.
+ *
+ *     Permission to use, copy, modify, and distribute these
+ *     programs and their documentation for any purpose and
+ *     without fee is hereby granted, provided that this
+ *     copyright and permission appear on all copies and
+ *     supporting documentation, the name of the Regents of
+ *     the University of California not be used in advertising
+ *     or publicity pertaining to distribution of the programs
+ *     without specific prior permission, and notice be given in
+ *     supporting documentation that copying and distribution is
+ *     by permission of the Regents of the University of California
+ *     and by Gregory Glenn Minshall.  Neither the Regents of the
+ *     University of California nor Gregory Glenn Minshall make
+ *     representations about the suitability of this software
+ *     for any purpose.  It is provided "as is" without
+ *     express or implied warranty.
+ */
+
 typedef struct string {
     int
        hashval,
 typedef struct string {
     int
        hashval,
@@ -33,7 +55,8 @@ typedef struct same {
        *lasttoken,                     /* Back pointer */
        *depend_list,                   /* If target, dependancies */
        *action_list,                   /* If target, actions */
        *lasttoken,                     /* Back pointer */
        *depend_list,                   /* If target, dependancies */
        *action_list,                   /* If target, actions */
-       *value_list;                    /* If variable, value list */
+       *value_list,                    /* If variable, value list */
+       *shell_item;                    /* If a shell variable, current value */
 } same_t;
 
 %}
 } same_t;
 
 %}
@@ -46,73 +69,152 @@ typedef struct same {
 
 %start makefile
 %token <string> TOKEN QUOTED_STRING
 
 %start makefile
 %token <string> TOKEN QUOTED_STRING
-%token <intval> MACRO_CHAR BREAK_CHAR WHITE_SPACE NL END_OF_FILE
-%token <intval> ':' '=' '$' '{' '}'
-%type <same> target assignment actions action tokens token
-%type <intval> special_chars white_space macro_char
+%token <intval>        FOR IN DO DONE
+%token <intval> MACRO_CHAR NL WHITE_SPACE
+%token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
+%type <same> target target1 assignment assign1 actions action
+%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
 %%
 
 %%
 
-makefile : lines END_OF_FILE;
+makefile : lines;
 
 lines : line
     | lines line
     ;
 
 
 lines : line
     | lines line
     ;
 
-line : maybe_white_space NL
+line : NL
     | assignment
     | target_action
     ;
 
     | assignment
     | target_action
     ;
 
-assignment :
-    token maybe_white_space '=' maybe_white_space tokens maybe_white_space NL
+assignment : assign1 tokens NL
     {
     {
-       assign($1, $5);
+       assign($1, $2);
     }
     }
-    | token maybe_white_space '=' maybe_white_space NL
+    | assign1 NL
     {
        assign($1, same_copy(null));
     }
     ;
 
     {
        assign($1, same_copy(null));
     }
     ;
 
+assign1: token maybe_white_space '=' maybe_white_space
+    ;
+
 target_action: target actions
     {
        add_targets_actions($1, $2);
     }
     | target
     {
 target_action: target actions
     {
        add_targets_actions($1, $2);
     }
     | target
     {
-       add_targets_actions($1, same_copy(null));
+       add_targets_actions($1, 0);
     }
     ;
 
     }
     ;
 
-target :
-    tokens maybe_white_space ':' maybe_white_space tokens maybe_white_space NL
+target : target1 tokens NL
     {
     {
-       $$ = add_depends($1, $5);
+       $$ = add_depends($1, $2);
     }
     }
-    | tokens maybe_white_space ':' maybe_white_space NL
+    | target1 NL
     {
        $$ = add_depends($1, same_copy(null));
     }
     ;
 
     {
        $$ = add_depends($1, same_copy(null));
     }
     ;
 
+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);
     }
     ;
 
     }
     ;
 
-action:        white_space tokens NL
+action:        white_space command_list NL
     {
        $$ = $2;
     }
     {
        $$ = $2;
     }
+    | white_space for_statement do command_list semi_colon done NL
+    {
+       $$ = do_command($2, $4);
+    }
     ;
 
     ;
 
-tokens : token
-    | tokens token
+for_statement: maybe_at_minus FOR white_space token
+               in tokens semi_colon
+    {
+       $$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
+    }
+    ;
+
+in:    white_space IN white_space
+do:    white_space DO white_space
+    ;
+
+done:  white_space DONE
+    ;
+
+semi_colon:    ';'
+    ;
+
+command_list: list
+    | '(' list maybe_white_space ')'
+    {
+       $$ = same_cat($2, same_copy(cwd_line));
+    }
+    ;
+
+list: token
+    | list list_element
     {
        $$ = same_cat($1, $2);
     }
     {
        $$ = same_cat($1, $2);
     }
+    | list white_space list_element
+    {
+       $$ = same_cat($1, same_cat(same_copy(blank), $3));
+    }
+    ;
+
+list_element: token
+    | semi_colon
+    {
+       $$ = same_copy(newline);
+    }
+    ;
+
+maybe_at_minus: /* empty */
+    {
+       $$ = same_copy(null);
+    }
+    | '@'
+    {
+       char buffer[2];
+
+       buffer[0] = $1;
+       buffer[1] = 0;
+       $$ = same_item(string_lookup(buffer));
+    }
+    | '-'
+    {
+       char buffer[2];
+
+       buffer[0] = $1;
+       buffer[1] = 0;
+       $$ = same_item(string_lookup(buffer));
+    }
+    ;
+
+tokens : token
+    | tokens maybe_white_space token
+    {
+       $$ = same_cat($1, same_cat($2, $3));
+    }
     ;
 
 token: TOKEN
     ;
 
 token: TOKEN
@@ -133,39 +235,56 @@ token: TOKEN
 
        $$ = same_item(string_lookup(buffer));
     }
 
        $$ = same_item(string_lookup(buffer));
     }
-    | special_chars
+    | '$' '$' TOKEN
     {
     {
-       char buffer[2];
-
-       buffer[0] = $1;
-       buffer[1] = 0;
-
-       $$ = same_item(string_lookup(buffer));
+       $$ = shell_variable(same_item($3));
     }
     }
-    | '$' '{' token '}'
+    | MACRO_CHAR
     {
     {
-       $$ = variable($3);
+       $$ = same_char($1);
+    }
+    | '$' '{' TOKEN '}'
+    {
+       $$ = variable(same_item($3));
+    }
+    | '$' '(' TOKEN ')'
+    {
+       $$ = variable(same_item($3));
+    }
+    | '$' TOKEN
+    {
+       $$ = variable(same_item($2));
+    }
+    | '-'
+    {
+       $$ = same_char('-');
+    }
+    | '@'
+    {
+       $$ = same_char('@');
     }
     ;
 
 macro_char: MACRO_CHAR
     }
     ;
 
 macro_char: MACRO_CHAR
-    | '$'
+    | '@'
     ;
 
     ;
 
-special_chars : BREAK_CHAR
-    | MACRO_CHAR
+maybe_white_space:
+    {
+       $$ = same_copy(null);
+    }
     | white_space
     | white_space
+    {
+       $$ = same_char($1);
+    }
     ;
 
     ;
 
-maybe_white_space:
-    | white_space;
-
 white_space : WHITE_SPACE
     | white_space WHITE_SPACE
     ;
 white_space : WHITE_SPACE
     | 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;
@@ -173,7 +292,10 @@ static int column = 0, lineno = 1;
 
 static string_t
     *strings = 0;
 
 static string_t
     *strings = 0;
+
 static same_t
 static same_t
+    *shell_variables = 0,
+    *shell_special = 0,
     *variables = 0,
     *targets = 0,
     *actions = 0;
     *variables = 0,
     *targets = 0,
     *actions = 0;
@@ -181,6 +303,7 @@ static same_t
 static same_t
     *null,
     *blank,
 static same_t
     *null,
     *blank,
+    *cwd_line,
     *newline;
 
 extern char *malloc();
     *newline;
 
 extern char *malloc();
@@ -276,6 +399,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
@@ -306,6 +431,9 @@ same_t
 {
     same_t *last;
 
 {
     same_t *last;
 
+    if (tokens == 0) {
+       return list;
+    }
     if (list) {
        last = tokens->lasttoken;
        tokens->lasttoken = list->lasttoken;
     if (list) {
        last = tokens->lasttoken;
        tokens->lasttoken = list->lasttoken;
@@ -351,12 +479,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;
@@ -366,36 +526,78 @@ same_t *list;
     } while (token != list);
 }
 
     } while (token != list);
 }
 
-void
+same_t *
 same_unlink(token)
 same_t
     *token;
 {
 same_unlink(token)
 same_t
     *token;
 {
+    same_t *tmp;
+
     if (token == 0) {
     if (token == 0) {
-       return;
+       return 0;
+    }
+    if ((tmp = token->nexttoken) == token) {
+       tmp = 0;
     }
     token->lasttoken->nexttoken = token->nexttoken;
     token->nexttoken->lasttoken = token->lasttoken;
     token->nexttoken = token->lasttoken = token;
     }
     token->lasttoken->nexttoken = token->nexttoken;
     token->nexttoken->lasttoken = token->lasttoken;
     token->nexttoken = token->lasttoken = token;
+    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_t *
-add_target(target)
+same_char(ch)
+char ch;
+{
+    char buffer[2];
+
+    buffer[0] = ch;
+    buffer[1] = 0;
+
+    return same_item(string_lookup(buffer));
+}
+
+
+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
@@ -408,13 +610,8 @@ same_t
        return 0;
     }
     do {
        return 0;
     }
     do {
-       target->action_list = same_cat(target->action_list,
-                                               same_copy(actions));
-       if ((ptr = target->nexttoken) == target) {
-           ptr = 0;
-       }
-       same_unlink(target);
-       add_target(target);
+       ptr = same_unlink(target);
+       add_target(target, actions);
        target = ptr;
     } while (target);
 
        target = ptr;
     } while (target);
 
@@ -456,7 +653,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);
-       same_unlink(ptr);
+       variables = same_unlink(ptr);
        same_free(ptr);
     }
     variable->value_list = value;
        same_free(ptr);
     }
     variable->value_list = value;
@@ -476,6 +673,72 @@ same_t *variable;
     }
 }
 
     }
 }
 
+
+same_t *
+expand_variables(token, free)
+same_t *token;
+int    free;
+{
+    same_t *head = 0;
+
+    if (!free) {
+       token = same_copy(token);               /* Get our private copy */
+    }
+
+    while (token) {
+       char *string = token->string->string;
+       same_t *tmp = same_unlink(token);
+
+       if ((string[0] == '$') && (string[1] == '{')) { /* Expand time */
+           int len = strlen(string);
+
+           string[len-1] = 0;
+           head = same_cat(head, expand_variables(
+                       value_of(same_item(string_lookup(string+2))), 1));
+           string[len-1] = '}';
+       } else {
+           head = same_cat(head, token);
+       }
+       token = tmp;
+    }
+    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;
@@ -499,6 +762,83 @@ same_t *var_name;
 }
 
 
 }
 
 
+same_t *
+shell_variable(var_name)
+same_t *var_name;
+{
+    int length = strlen(var_name->string->string);
+    same_t *resolved;
+    char *newname;
+
+    if ((newname = malloc(length+1+2)) == 0) {
+       fprintf("Out of space for a variable name.\n");
+       exit(1);
+    }
+    newname[0] = '$';
+    newname[1] = '$';
+    strcpy(newname+2, var_name->string->string);
+    resolved = same_item(string_lookup(newname));
+    free(newname);
+
+    return resolved;
+}
+
+same_t *
+for_statement(special, variable, list)
+same_t
+    *special,
+    *variable,
+    *list;
+{
+    variable->shell_item = special;
+    variable->value_list = list;
+    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));
+}
+
+
 int
 Getchar()
 {
 int
 Getchar()
 {
@@ -521,6 +861,37 @@ Getchar()
 }
 
 
 }
 
 
+int
+token_type(string)
+char *string;
+{
+    switch (string[0]) {
+    case 'f':
+       if (strcmp(string, "for") == 0) {
+           return FOR;
+       }
+       break;
+    case 'd':
+       if (string[1] == 'o') {
+           if (strcmp(string, "do") == 0) {
+               return DO;
+           } else if (strcmp(string, "done") == 0) {
+               return DONE;
+           }
+       }
+       break;
+    case 'i':
+       if (strcmp(string, "in") == 0) {
+           return IN;
+       }
+       break;
+    default:
+       break;
+    }
+    return TOKEN;
+}
+
+
 yylex()
 {
 #define        ret_token(c)    if (bufptr != buffer) { \
 yylex()
 {
 #define        ret_token(c)    if (bufptr != buffer) { \
@@ -528,7 +899,7 @@ yylex()
                            *bufptr = 0; \
                            bufptr = buffer; \
                            yylval.string = string_lookup(buffer); \
                            *bufptr = 0; \
                            bufptr = buffer; \
                            yylval.string = string_lookup(buffer); \
-                           return TOKEN; \
+                           return token_type(buffer); \
                        }
 #define        save(c) { last_char = c; last_saved = 1; }
 #if    defined(YYDEBUG)
                        }
 #define        save(c) { last_char = c; last_saved = 1; }
 #if    defined(YYDEBUG)
@@ -553,7 +924,7 @@ yylex()
            fprintf(stderr, "End of file ignored.\n");
            exit(1);
        }
            fprintf(stderr, "End of file ignored.\n");
            exit(1);
        }
-       Return(END_OF_FILE,0);
+       Return(EOF,0);
     }
     while ((c = Getchar()) != EOF) {
        switch (c) {
     }
     while ((c = Getchar()) != EOF) {
        switch (c) {
@@ -564,31 +935,34 @@ yylex()
            }
            save(c);
            break;
            }
            save(c);
            break;
-       case '@':
        case '<':
        case '?':
            ret_token(c);
            Return(MACRO_CHAR, c);
        case '<':
        case '?':
            ret_token(c);
            Return(MACRO_CHAR, c);
-       case '-':
-       case '(':
-       case ')':
-       case ';':
-           ret_token(c);
-           Return(BREAK_CHAR, c);
        case '\t':
        case ' ':
            ret_token(c);
            Return(WHITE_SPACE, c);
        case '\t':
        case ' ':
            ret_token(c);
            Return(WHITE_SPACE, c);
+       case '-':
+       case '@':
        case ':':
        case ':':
+       case ';':
        case '=':
        case '$':
        case '{':
        case '}':
        case '=':
        case '$':
        case '{':
        case '}':
+       case '(':
+       case ')':
            ret_token(c);
            Return(c,c);
        case '\'':
        case '"':
            ret_token(c);
            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);
@@ -625,7 +999,7 @@ yylex()
     eof_found = 1;
 
     ret_token(' ');
     eof_found = 1;
 
     ret_token(' ');
-    Return(END_OF_FILE, 0);
+    Return(EOF, 0);
 }
 
 main()
 }
 
 main()
@@ -636,8 +1010,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();
 
 
-    return yyparse();
+    return 0;
 }
 
 #if    defined(YYDEBUG)
 }
 
 #if    defined(YYDEBUG)
@@ -651,6 +1032,7 @@ same_t *same;
     }
     visit_end();
 }
     }
     visit_end();
 }
+#endif /* YYDEBUG */
 
 do_dump()
 {
 
 do_dump()
 {
@@ -664,9 +1046,9 @@ do_dump()
        }
     }
 
        }
     }
 
-    printf("variables...\n");
+    printf("variables...\n");
     for (visit(variables, same); !visited(same); visit_next(same)) {
     for (visit(variables, same); !visited(same); visit_next(same)) {
-       printf("\t%s =\t", same->string->string);
+       printf("%s =\t", same->string->string);
        for (visit(same->value_list, same2); !visited(same2);
                                                visit_next(same2)) {
            printf(same2->string->string);
        for (visit(same->value_list, same2); !visited(same2);
                                                visit_next(same2)) {
            printf(same2->string->string);
@@ -676,20 +1058,20 @@ 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("\t%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);
        }
        visit_end();
        for (visit(same->depend_list, same2); !visited(same2);
                                                visit_next(same2)) {
            printf(same2->string->string);
        }
        visit_end();
-       printf("\n\t\t");
+       printf("\n\t");
        for (visit(same->action_list, same2); !visited(same2);
                                            visit_next(same2)) {
            printf(same2->string->string);
            if (same2->string->string[0] == '\n') {
        for (visit(same->action_list, same2); !visited(same2);
                                            visit_next(same2)) {
            printf(same2->string->string);
            if (same2->string->string[0] == '\n') {
-               printf("\t\t");
+               printf("\t");
            }
        }
        visit_end();
            }
        }
        visit_end();
@@ -697,4 +1079,3 @@ do_dump()
     }
     visit_end();
 }
     }
     visit_end();
 }
-#endif /* YYDEBUG */