All but end of file.
[unix-history] / usr / src / usr.bin / tn3270 / tools / mkmake.y
index eb8a765..3ad7d78 100644 (file)
@@ -9,66 +9,100 @@ typedef struct string {
        *next;
 } string_t;
 
        *next;
 } string_t;
 
+/*
+ * The deal with these is that they exist on various lists.
+ *
+ * First off, they are on a temporary list during the time they
+ * are in the active focus of the parser.
+ *
+ * Secondly, they live on one of three queues:
+ *     1.  Variables
+ *     2.  Targets
+ *     3.  Actions
+ * (and, we restrict any given one to live on one and only one such list)
+ *
+ * Also, they may live on the list of values for someone else's variable,
+ * or as someone's dependancy.
+ */
+
 typedef struct same {
 typedef struct same {
-    int
-       myname,
-       values,         /* If a variable, the values */
-       action;         /* If a target, the action number */
-    struct same
-       *moretokens,
-       *depends;
     string_t
     string_t
-       *string;
+       *string;                        /* My name */
+    struct same
+       *nexttoken,                     /* Next pointer */
+       *lasttoken,                     /* Back pointer */
+       *depend_list,                   /* If target, dependancies */
+       *action_list,                   /* If target, actions */
+       *value_list;                    /* If variable, value list */
 } same_t;
 
 } same_t;
 
-same_t
-    *add_depends(),
-    *assign(),
-    *token_cat(),
-    *token_item();
 %}
 
 %union {
     string_t *string;
     same_t *same;
 %}
 
 %union {
     string_t *string;
     same_t *same;
+    int        intval;
     }
 
     }
 
-%token <string> TOKEN
-%token END_OF_FILE NL
+%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 <same> target assignment actions action tokens token
+%type <intval> special_chars white_space macro_char
 %%
 %%
+
 makefile : lines END_OF_FILE;
 
 lines : line
     | lines line
     ;
 
 makefile : lines END_OF_FILE;
 
 lines : line
     | lines line
     ;
 
-line : NL
-    | target NL
-    | assignment NL
-    | actions NL
+line : maybe_white_space NL
+    | assignment
+    | target_action
     ;
 
     ;
 
-target : tokens ':' tokens
+assignment :
+    token maybe_white_space '=' maybe_white_space tokens maybe_white_space NL
+    {
+       assign($1, $5);
+    }
+    | token maybe_white_space '=' maybe_white_space NL
+    {
+       assign($1, same_copy(null));
+    }
+    ;
+
+target_action: target actions
+    {
+       add_targets_actions($1, $2);
+    }
+    | target
     {
     {
-       $$ = add_depends($1, $3);
+       add_targets_actions($1, same_copy(null));
     }
     ;
 
     }
     ;
 
-assignment : token '=' tokens
+target :
+    tokens maybe_white_space ':' maybe_white_space tokens maybe_white_space NL
     {
     {
-       $$ = assign($1, $3);
+       $$ = add_depends($1, $5);
+    }
+    | tokens maybe_white_space ':' maybe_white_space NL
+    {
+       $$ = add_depends($1, same_copy(null));
     }
     ;
 
 actions: action
     | actions action
     {
     }
     ;
 
 actions: action
     | actions action
     {
-       $$ = token_cat($1, $2);
+       $$ = same_cat($1, $2);
     }
     ;
 
     }
     ;
 
-action:        '\t' tokens
+action:        white_space tokens NL
     {
        $$ = $2;
     }
     {
        $$ = $2;
     }
@@ -77,14 +111,59 @@ action:    '\t' tokens
 tokens : token
     | tokens token
     {
 tokens : token
     | tokens token
     {
-       $$ = token_cat($1, $2);
+       $$ = same_cat($1, $2);
     }
     ;
     }
     ;
+
 token: TOKEN
     {
 token: TOKEN
     {
-       $$ = token_item($1);
+       $$ = same_item($1);
+    }
+    | QUOTED_STRING
+    {
+       $$ = same_item($1);
+    }
+    | '$' macro_char
+    {
+       char buffer[3];
+
+       buffer[0] = '$';
+       buffer[1] = $2;
+       buffer[2] = 0;
+
+       $$ = same_item(string_lookup(buffer));
+    }
+    | special_chars
+    {
+       char buffer[2];
+
+       buffer[0] = $1;
+       buffer[1] = 0;
+
+       $$ = same_item(string_lookup(buffer));
+    }
+    | '$' '{' token '}'
+    {
+       $$ = value_of($3);
     }
     ;
     }
     ;
+
+macro_char: MACRO_CHAR
+    | '$'
+    ;
+
+special_chars : BREAK_CHAR
+    | MACRO_CHAR
+    | white_space
+    ;
+
+maybe_white_space:
+    | white_space;
+
+white_space : WHITE_SPACE
+    | white_space WHITE_SPACE
+    ;
+
 %%
 #include <stdio.h>
 
 %%
 #include <stdio.h>
 
@@ -92,66 +171,155 @@ static int last_char, last_saved = 0;
 static int column = 0, lineno = 1;
 
 
 static int column = 0, lineno = 1;
 
 
-static string_t *strings = 0;
+static string_t
+    *strings = 0;
 static same_t
     *variables = 0,
     *targets = 0,
     *actions = 0;
 
 static same_t
     *variables = 0,
     *targets = 0,
     *actions = 0;
 
+static same_t
+    *null,
+    *blank,
+    *newline;
+
 extern char *malloc();
 
 extern char *malloc();
 
-main()
-{
-#define        YYDEBUG
-    extern int yydebug;
+static unsigned int
+       clock = -1;
 
 
-    return yyparse();
-}
+struct {
+    same_t *first;
+    int next;
+} visit_stack[20];             /* 20 maximum */
+
+#define        visit(what,via) \
+       (visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
+#define        visited(via)    (visitcheck(via) || ((via) == 0) \
+       || (visit_stack[clock].next && (via == visit_stack[clock].first)))
+#define        visit_next(via) (visit_stack[clock].next = 1, (via) = (via)->nexttoken)
+#define        visit_end()     (clock--)
 
 yyerror(s)
 char *s;
 {
 
 yyerror(s)
 char *s;
 {
-    fprintf(stderr, "line %d, column %d: %s\n", lineno, column, s);
+    fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
+    do_dump();
 }
 
 }
 
-same_t *
-add_depends(list1, list2)
-same_t
-    *list1,
-    *list2;
+int
+visitcheck(same)
+same_t *same;
 {
 {
+    if (same->string == 0) {
+       yyerror("BUG - freed 'same' in use...");
+       exit(1);
+    }
+    return 0;
 }
 
 }
 
-same_t *
-assign(variable, value)
-same_t
-    *variable,
-    *value;
+int
+string_hashof(string, length)
+char *string;
+int length;
 {
 {
+    register int i = 0;
+
+    while (length--) {
+       i = (i<<3) + *string ^ ((i>>28)&0x7);
+    }
+    return i;
 }
 
 }
 
+int
+string_same(s1, s2)
+string_t
+    *s1, *s2;
+{
+    if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
+               && (memcmp(s1->string, s2->string, s1->length) == 0)) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+string_t *
+string_lookup(string)
+char *string;
+{
+    string_t ours;
+    string_t *ptr;
+
+    ours.length = strlen(string);
+    ours.hashval = string_hashof(string, ours.length);
+    ours.string = string;
+
+    for (ptr = strings; ptr; ptr = ptr->next) {
+       if (string_same(&ours, ptr)) {
+           return ptr;
+       }
+    }
+    if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
+       fprintf(stderr, "No space to add string *%s*!\n", string);
+       exit(1);
+    }
+    ptr->hashval = ours.hashval;
+    ptr->length = ours.length;
+    if ((ptr->string = malloc(ours.length+1)) == 0) {
+       fprintf(stderr, "No space to add literal *%s*!\n", string);
+       exit(1);
+    }
+    memcpy(ptr->string, string, ours.length+1);
+    ptr->next = strings;
+    strings = ptr;
+    return ptr;
+}
 
 same_t *
 
 same_t *
-token_cat(tokens, token)
+same_search(list, token)
 same_t
 same_t
-    *tokens,
+    *list,
     *token;
 {
     same_t *ptr;
 
     *token;
 {
     same_t *ptr;
 
-    if (tokens->moretokens == 0) {
-       tokens->moretokens = token;
-    } else {
-       for (ptr = tokens; ptr->moretokens; ptr = ptr->moretokens) {
-           ;
+    ptr = list;
+    for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
+       string_t *string;
+
+       string = ptr->string;
+       if (string_same(string, token->string)) {
+           visit_end();
+           return ptr;
        }
        }
-       ptr->moretokens = token;
     }
     }
-    return tokens;
+    visit_end();
+    return 0;
 }
 
 same_t *
 }
 
 same_t *
-token_item(string)
+same_cat(list, tokens)
+same_t
+    *list,
+    *tokens;
+{
+    same_t *last;
+
+    if (list) {
+       last = tokens->lasttoken;
+       tokens->lasttoken = list->lasttoken;
+       list->lasttoken = last;
+       tokens->lasttoken->nexttoken = tokens;
+       last->nexttoken = list;
+       return list;
+    } else {
+       return tokens;
+    }
+}
+
+same_t *
+same_item(string)
 string_t *string;
 {
     same_t *ptr;
 string_t *string;
 {
     same_t *ptr;
@@ -160,12 +328,155 @@ string_t *string;
        fprintf(stderr, "No more space for tokens!\n");
        exit(1);
     }
        fprintf(stderr, "No more space for tokens!\n");
        exit(1);
     }
-
+    memset((char *)ptr, 0, sizeof *ptr);
+    ptr->nexttoken = ptr->lasttoken = ptr;
     ptr->string = string;
     ptr->string = string;
-    ptr->moretokens = 0;
     return ptr;
 }
 
     return ptr;
 }
 
+same_t *
+same_copy(same)
+same_t *same;
+{
+    same_t *head, *copy;
+
+    head = 0;
+    for (visit(same, copy); !visited(copy); visit_next(copy)) {
+       same_t *ptr;
+
+       ptr = same_item(copy->string);
+       head = same_cat(head, ptr);
+    }
+    visit_end();
+    return head;
+}
+
+void
+same_free(list)
+same_t *list;
+{
+    same_t *token, *ptr;
+
+    token = list;
+    do {
+       ptr = token->nexttoken;
+       token->string = 0;
+       (void) free((char *)token);
+       token = ptr;
+    } while (token != list);
+}
+
+void
+same_unlink(token)
+same_t
+    *token;
+{
+    if (token == 0) {
+       return;
+    }
+    token->lasttoken->nexttoken = token->nexttoken;
+    token->nexttoken->lasttoken = token->lasttoken;
+    token->nexttoken = token->lasttoken = token;
+}
+
+same_t *
+add_target(target)
+same_t
+    *target;
+{
+    same_t *ptr;
+
+    if ((ptr = same_search(targets, target)) == 0) {
+       targets = same_cat(targets, target);
+       return 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;
+    }
+}
+
+same_t *
+add_targets_actions(target, actions)
+same_t
+    *target,
+    *actions;
+{
+    same_t *ptr;
+
+    if (target == 0) {
+       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);
+       target = ptr;
+    } while (target);
+
+    same_free(actions);
+    return 0;
+}
+
+same_t *
+add_depends(target, depends)
+same_t
+    *target,
+    *depends;
+{
+    same_t *original = target;
+
+    depends = same_cat(depends, same_copy(blank));     /* Separator */
+
+    for (visit(original, target); !visited(target); visit_next(target)) {
+       target->depend_list = same_cat(target->depend_list, same_copy(depends));
+    }
+    visit_end();
+    same_free(depends);
+
+    return original;
+}
+
+
+/*
+ * We know that variable is a singleton
+ */
+
+void
+assign(variable, value)
+same_t
+    *variable,
+    *value;
+{
+    same_t *ptr;
+
+    if ((ptr = same_search(variables, variable)) != 0) {
+       same_free(ptr->value_list);
+       same_unlink(ptr);
+       same_free(ptr);
+    }
+    variable->value_list = value;
+    variables = same_cat(variables, variable);
+}
+
+same_t *
+value_of(variable)
+same_t *variable;
+{
+    same_t *ptr = same_search(variables, variable);
+
+    if (ptr == 0) {
+       return same_copy(null);
+    } else {
+       return same_copy(ptr->value_list);
+    }
+}
+
+
 int
 Getchar()
 {
 int
 Getchar()
 {
@@ -187,52 +498,6 @@ Getchar()
     }
 }
 
     }
 }
 
-int
-hashof(string, length)
-char *string;
-int length;
-{
-    register int i = 0;
-
-    while (length--) {
-       i = (i<<3) + *string ^ ((i>>28)&0x7);
-    }
-    return i;
-}
-
-string_t *
-lookup(string)
-char *string;
-{
-    int hashval;
-    int length = strlen(string);
-    string_t *ptr;
-
-    hashval = hashof(string, length);
-
-    for (ptr = strings; ptr; ptr = ptr->next) {
-       if ((ptr->hashval == hashval) && (ptr->length == length)) {
-           if (memcmp(string, ptr->string, length) == 0) {
-               return ptr;
-           }
-       }
-    }
-    if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
-       fprintf(stderr, "No space to add string *%s*!\n", string);
-       exit(1);
-    }
-    ptr->hashval = hashval;
-    ptr->length = length;
-    if ((ptr->string = malloc(length+1)) == 0) {
-       fprintf(stderr, "No space to add literal *%s*!\n", string);
-       exit(1);
-    }
-    memcpy(ptr->string, string, length+1);
-    ptr->next = strings;
-    strings = ptr;
-    return ptr;
-}
-
 
 yylex()
 {
 
 yylex()
 {
@@ -240,17 +505,23 @@ yylex()
                            save(c); \
                            *bufptr = 0; \
                            bufptr = buffer; \
                            save(c); \
                            *bufptr = 0; \
                            bufptr = buffer; \
-                           yylval.string = lookup(buffer); \
+                           yylval.string = string_lookup(buffer); \
                            return TOKEN; \
                        }
 #define        save(c) { last_char = c; last_saved = 1; }
                            return TOKEN; \
                        }
 #define        save(c) { last_char = c; last_saved = 1; }
+#if    defined(YYDEBUG)
 #define        Return(c)       if (yydebug) { \
                            printf("[%d]", c); \
                            fflush(stdout); \
                        } \
 #define        Return(c)       if (yydebug) { \
                            printf("[%d]", c); \
                            fflush(stdout); \
                        } \
+                       yyval.intval = c; \
                        return c;
                        return c;
+#else  /* defined(YYDEBUG) */
+#define        Return(y,c)     { yylval.intval = c; return y; }
+#endif /* defined(YYDEBUG) */
 
 
-    static char buffer[100], *bufptr = buffer;
+
+    static char buffer[500], *bufptr = buffer;
     static int eof_found = 0;
     int c;
 
     static int eof_found = 0;
     int c;
 
@@ -260,7 +531,7 @@ yylex()
            fprintf(stderr, "End of file ignored.\n");
            exit(1);
        }
            fprintf(stderr, "End of file ignored.\n");
            exit(1);
        }
-       Return(END_OF_FILE);
+       Return(END_OF_FILE,0);
     }
     while ((c = Getchar()) != EOF) {
        switch (c) {
     }
     while ((c = Getchar()) != EOF) {
        switch (c) {
@@ -271,28 +542,58 @@ yylex()
            }
            save(c);
            break;
            }
            save(c);
            break;
-       case ' ':
-           ret_token(' ');
-           break;
+       case '@':
+       case '<':
+       case '?':
+           ret_token(c);
+           Return(MACRO_CHAR, c);
+       case '-':
+       case '(':
+       case ')':
+       case ';':
+           ret_token(c);
+           Return(BREAK_CHAR, c);
        case '\t':
        case '\t':
+       case ' ':
            ret_token(c);
            ret_token(c);
-           if (column == 1) {
-               Return(c);
-           }
-           break;
+           Return(WHITE_SPACE, c);
        case ':':
        case '=':
        case ':':
        case '=':
+       case '$':
+       case '{':
+       case '}':
            ret_token(c);
            ret_token(c);
-           Return(c);
+           Return(c,c);
+       case '\'':
+       case '"':
+           {
+               int newc;
+
+               ret_token(c);
+               *bufptr++ = c;
+               while (((newc = Getchar()) != EOF) && (newc != c)) {
+                   *bufptr++ = newc;
+               }
+               *bufptr++ = c;
+               *bufptr = 0;
+               bufptr = buffer;
+               yylval.string = string_lookup(buffer);
+               return QUOTED_STRING;
+           }
        case '\n':
            if (bufptr != buffer) {
                if (bufptr[-1] == '\\') {
                    bufptr--;
        case '\n':
            if (bufptr != buffer) {
                if (bufptr[-1] == '\\') {
                    bufptr--;
-                   break;
+                   if ((c = Getchar()) != '\t') {
+                       yyerror("continuation line doesn't begin with a tab");
+                       save(c);
+                   }
+                   ret_token(c);
+                   Return(WHITE_SPACE, c);
                }
            }
            ret_token(c);
                }
            }
            ret_token(c);
-           Return(NL);
+           Return(NL, 0);
        default:
            *bufptr++ = c;
            break;
        default:
            *bufptr++ = c;
            break;
@@ -302,5 +603,76 @@ yylex()
     eof_found = 1;
 
     ret_token(' ');
     eof_found = 1;
 
     ret_token(' ');
-    Return(END_OF_FILE);
+    Return(END_OF_FILE, 0);
+}
+
+main()
+{
+#define        YYDEBUG
+    extern int yydebug;
+
+    null = same_item(string_lookup(""));
+    newline = same_item(string_lookup("\n"));
+    blank = same_item(string_lookup(" "));
+
+    return yyparse();
+}
+
+#if    defined(YYDEBUG)
+dump_same(same)
+same_t *same;
+{
+    same_t *same2;
+
+    for (visit(same, same2); !visited(same2); visit_next(same2)) {
+       printf(same2->string->string);
+    }
+    visit_end();
+}
+
+do_dump()
+{
+    string_t *string;
+    same_t *same, *same2;
+
+    if (yydebug > 1) {
+       printf("strings...\n");
+       for (string = strings; string; string = string->next) {
+           printf("\t%s\n", string->string);
+       }
+    }
+
+    printf("variables...\n");
+    for (visit(variables, same); !visited(same); visit_next(same)) {
+       printf("\t%s =\t", same->string->string);
+       for (visit(same->value_list, same2); !visited(same2);
+                                               visit_next(same2)) {
+           printf(same2->string->string);
+       }
+       visit_end();
+       printf("\n");
+    }
+    visit_end();
+
+    printf("targets...\n");
+    for (visit(targets, same); !visited(same); visit_next(same)) {
+       printf("\t%s :\t", same->string->string);
+       for (visit(same->depend_list, same2); !visited(same2);
+                                               visit_next(same2)) {
+           printf(same2->string->string);
+       }
+       visit_end();
+       printf("\n\t\t");
+       for (visit(same->action_list, same2); !visited(same2);
+                                           visit_next(same2)) {
+           printf(same2->string->string);
+           if (same2->string->string[0] == '\n') {
+               printf("\t\t");
+           }
+       }
+       visit_end();
+       printf("\n");
+    }
+    visit_end();
 }
 }
+#endif /* YYDEBUG */