xref: /original-bsd/usr.bin/tn3270/tools/mkmake.y (revision 9a77813a)
1 %{
2 
3 /*
4  * Copyright (c) 1988 Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by the University of California, Berkeley.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  *	@(#)mkmake.y	4.1 (Berkeley) 12/04/88
20  */
21 
22 typedef struct string {
23     int
24 	hashval,
25 	length;
26     char
27 	*string;
28     struct string
29 	*next;
30 } string_t;
31 
32 /*
33  * The deal with these is that they exist on various lists.
34  *
35  * First off, they are on a temporary list during the time they
36  * are in the active focus of the parser.
37  *
38  * Secondly, they live on one of three queues:
39  *	1.  Variables
40  *	2.  Targets
41  *	3.  Actions
42  * (and, we restrict any given one to live on one and only one such list)
43  *
44  * Also, they may live on the list of values for someone else's variable,
45  * or as someone's dependancy.
46  */
47 
48 typedef struct same {
49     string_t
50 	*string;			/* My name */
51     struct same
52 	*nexttoken,			/* Next pointer */
53 	*lasttoken,			/* Back pointer */
54 	*depend_list,			/* If target, dependancies */
55 	*action_list,			/* If target, actions */
56 	*value_list,			/* If variable, value list */
57 	*shell_item;			/* If a shell variable, current value */
58 } same_t;
59 
60 %}
61 
62 %union {
63     string_t *string;
64     same_t *same;
65     int	intval;
66     }
67 
68 %start makefile
69 %token <string> TOKEN QUOTED_STRING
70 %token <intval>	FOR IN DO DONE
71 %token <intval> MACRO_CHAR NL WHITE_SPACE
72 %token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
73 %type <same> target target1 assignment assign1 actions action
74 %type <same> command_list list list_element
75 %type <same> for_statement maybe_at_minus tokens token
76 %type <same> maybe_white_space
77 %type <intval> white_space macro_char
78 %%
79 
80 makefile : lines;
81 
82 lines : line
83     | lines line
84     ;
85 
86 line : NL
87     | assignment
88     | target_action
89     ;
90 
91 assignment : assign1 tokens NL
92     {
93 	assign($1, $2);
94     }
95     | assign1 NL
96     {
97 	assign($1, same_copy(null));
98     }
99     ;
100 
101 assign1: token maybe_white_space '=' maybe_white_space
102     ;
103 
104 target_action: target actions
105     {
106 	add_targets_actions($1, $2);
107     }
108     | target
109     {
110 	add_targets_actions($1, 0);
111     }
112     ;
113 
114 target : target1 tokens NL
115     {
116 	$$ = add_depends($1, $2);
117     }
118     | target1 NL
119     {
120 	$$ = add_depends($1, same_copy(null));
121     }
122     ;
123 
124 target1: tokens maybe_white_space ':' maybe_white_space
125     {
126 	$$ = ws_merge($1);
127     }
128     ;
129 
130 actions: action
131     | actions action
132     {
133 	$$ = same_cat(same_cat($1, same_copy(newline)), $2);
134     }
135     ;
136 
137 action:	white_space command_list NL
138     {
139 	$$ = $2;
140     }
141     | white_space for_statement do command_list semi_colon done NL
142     {
143 	$$ = do_command($2, $4);
144     }
145     ;
146 
147 for_statement: maybe_at_minus FOR white_space token
148 		in tokens semi_colon
149     {
150 	$$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
151     }
152     ;
153 
154 in:	white_space IN white_space
155 do:	white_space DO white_space
156     ;
157 
158 done:	white_space DONE
159     ;
160 
161 semi_colon:	';'
162     ;
163 
164 command_list: list
165     | '(' list maybe_white_space ')'
166     {
167 	$$ = same_cat($2, same_copy(cwd_line));
168     }
169     ;
170 
171 list: token
172     | list list_element
173     {
174 	$$ = same_cat($1, $2);
175     }
176     | list white_space list_element
177     {
178 	$$ = same_cat($1, same_cat(same_copy(blank), $3));
179     }
180     ;
181 
182 list_element: token
183     | semi_colon
184     {
185 	$$ = same_copy(newline);
186     }
187     ;
188 
189 maybe_at_minus: /* empty */
190     {
191 	$$ = same_copy(null);
192     }
193     | '@'
194     {
195 	char buffer[2];
196 
197 	buffer[0] = $1;
198 	buffer[1] = 0;
199 	$$ = same_item(string_lookup(buffer));
200     }
201     | '-'
202     {
203 	char buffer[2];
204 
205 	buffer[0] = $1;
206 	buffer[1] = 0;
207 	$$ = same_item(string_lookup(buffer));
208     }
209     ;
210 
211 tokens : token
212     | tokens maybe_white_space token
213     {
214 	$$ = same_cat($1, same_cat($2, $3));
215     }
216     ;
217 
218 token: TOKEN
219     {
220 	$$ = same_item($1);
221     }
222     | QUOTED_STRING
223     {
224 	$$ = same_item($1);
225     }
226     | '$' macro_char
227     {
228 	char buffer[3];
229 
230 	buffer[0] = '$';
231 	buffer[1] = $2;
232 	buffer[2] = 0;
233 
234 	$$ = same_item(string_lookup(buffer));
235     }
236     | '$' '$' TOKEN
237     {
238 	$$ = shell_variable(same_item($3));
239     }
240     | MACRO_CHAR
241     {
242 	$$ = same_char($1);
243     }
244     | '$' '{' TOKEN '}'
245     {
246 	$$ = variable(same_item($3));
247     }
248     | '$' '(' TOKEN ')'
249     {
250 	$$ = variable(same_item($3));
251     }
252     | '$' TOKEN
253     {
254 	$$ = variable(same_item($2));
255     }
256     | '-'
257     {
258 	$$ = same_char('-');
259     }
260     | '@'
261     {
262 	$$ = same_char('@');
263     }
264     ;
265 
266 macro_char: MACRO_CHAR
267     | '@'
268     ;
269 
270 maybe_white_space:
271     {
272 	$$ = same_copy(null);
273     }
274     | white_space
275     {
276 	$$ = same_char($1);
277     }
278     ;
279 
280 white_space : WHITE_SPACE
281     | white_space WHITE_SPACE
282     ;
283 %%
284 #include <stdio.h>
285 #include <ctype.h>
286 
287 static int last_char, last_saved = 0;
288 static int column = 0, lineno = 1;
289 
290 
291 static string_t
292     *strings = 0;
293 
294 static same_t
295     *shell_variables = 0,
296     *shell_special = 0,
297     *variables = 0,
298     *targets = 0,
299     *actions = 0;
300 
301 static same_t
302     *null,
303     *blank,
304     *cwd_line,
305     *newline;
306 
307 extern char *malloc();
308 
309 static unsigned int
310 	clock = -1;
311 
312 struct {
313     same_t *first;
314     int next;
315 } visit_stack[20];		/* 20 maximum */
316 
317 #define	visit(what,via) \
318 	(visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
319 #define	visited(via)	(visitcheck(via) || ((via) == 0) \
320 	|| (visit_stack[clock].next && (via == visit_stack[clock].first)))
321 #define	visit_next(via)	(visit_stack[clock].next = 1, (via) = (via)->nexttoken)
322 #define	visit_end()	(clock--)
323 
324 yyerror(s)
325 char *s;
326 {
327     fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
328     do_dump();
329 }
330 
331 int
332 visitcheck(same)
333 same_t *same;
334 {
335     if (same->string == 0) {
336 	yyerror("BUG - freed 'same' in use...");
337 	exit(1);
338     }
339     return 0;
340 }
341 
342 int
343 string_hashof(string, length)
344 char *string;
345 int length;
346 {
347     register int i = 0;
348 
349     while (length--) {
350 	i = (i<<3) + *string ^ ((i>>28)&0x7);
351     }
352     return i;
353 }
354 
355 int
356 string_same(s1, s2)
357 string_t
358     *s1, *s2;
359 {
360     if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
361 		&& (memcmp(s1->string, s2->string, s1->length) == 0)) {
362 	return 1;
363     } else {
364 	return 0;
365     }
366 }
367 
368 string_t *
369 string_lookup(string)
370 char *string;
371 {
372     string_t ours;
373     string_t *ptr;
374 
375     ours.length = strlen(string);
376     ours.hashval = string_hashof(string, ours.length);
377     ours.string = string;
378 
379     for (ptr = strings; ptr; ptr = ptr->next) {
380 	if (string_same(&ours, ptr)) {
381 	    return ptr;
382 	}
383     }
384     if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
385 	fprintf(stderr, "No space to add string *%s*!\n", string);
386 	exit(1);
387     }
388     ptr->hashval = ours.hashval;
389     ptr->length = ours.length;
390     if ((ptr->string = malloc(ours.length+1)) == 0) {
391 	fprintf(stderr, "No space to add literal *%s*!\n", string);
392 	exit(1);
393     }
394     memcpy(ptr->string, string, ours.length+1);
395     ptr->next = strings;
396     strings = ptr;
397     return ptr;
398 }
399 
400 #define	same_singleton(s)	((s)->nexttoken == (s))
401 
402 same_t *
403 same_search(list, token)
404 same_t
405     *list,
406     *token;
407 {
408     same_t *ptr;
409 
410     ptr = list;
411     for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
412 	string_t *string;
413 
414 	string = ptr->string;
415 	if (string_same(string, token->string)) {
416 	    visit_end();
417 	    return ptr;
418 	}
419     }
420     visit_end();
421     return 0;
422 }
423 
424 same_t *
425 same_cat(list, tokens)
426 same_t
427     *list,
428     *tokens;
429 {
430     same_t *last;
431 
432     if (tokens == 0) {
433 	return list;
434     }
435     if (list) {
436 	last = tokens->lasttoken;
437 	tokens->lasttoken = list->lasttoken;
438 	list->lasttoken = last;
439 	tokens->lasttoken->nexttoken = tokens;
440 	last->nexttoken = list;
441 	return list;
442     } else {
443 	return tokens;
444     }
445 }
446 
447 same_t *
448 same_item(string)
449 string_t *string;
450 {
451     same_t *ptr;
452 
453     if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) {
454 	fprintf(stderr, "No more space for tokens!\n");
455 	exit(1);
456     }
457     memset((char *)ptr, 0, sizeof *ptr);
458     ptr->nexttoken = ptr->lasttoken = ptr;
459     ptr->string = string;
460     return ptr;
461 }
462 
463 same_t *
464 same_copy(same)
465 same_t *same;
466 {
467     same_t *head, *copy;
468 
469     head = 0;
470     for (visit(same, copy); !visited(copy); visit_next(copy)) {
471 	same_t *ptr;
472 
473 	ptr = same_item(copy->string);
474 	head = same_cat(head, ptr);
475     }
476     visit_end();
477     return head;
478 }
479 
480 
481 same_t *
482 same_merge(t1, t2)
483 same_t
484     *t1,
485     *t2;
486 {
487     if (same_singleton(t1) && same_singleton(t2)) {
488 	int length = strlen(t1->string->string)+strlen(t2->string->string);
489 	char *buffer = malloc(length+1);
490 	same_t *value;
491 
492 	if (buffer == 0) {
493 	    yyerror("No space to merge strings in same_merge!");
494 	    exit(1);
495 	}
496 	strcpy(buffer, t1->string->string);
497 	strcat(buffer, t2->string->string);
498 	value = same_item(string_lookup(buffer));
499 	free(buffer);
500 	return value;
501     } else {
502 	yyerror("Internal error - same_merge with non-singletons");
503 	exit(1);
504     }
505 }
506 
507 
508 void
509 same_free(list)
510 same_t *list;
511 {
512     same_t *token, *ptr;
513 
514     if (list == 0) {
515 	return;
516     }
517 
518     token = list;
519     do {
520 	ptr = token->nexttoken;
521 	token->string = 0;
522 	(void) free((char *)token);
523 	token = ptr;
524     } while (token != list);
525 }
526 
527 same_t *
528 same_unlink(token)
529 same_t
530     *token;
531 {
532     same_t *tmp;
533 
534     if (token == 0) {
535 	return 0;
536     }
537     if ((tmp = token->nexttoken) == token) {
538 	tmp = 0;
539     }
540     token->lasttoken->nexttoken = token->nexttoken;
541     token->nexttoken->lasttoken = token->lasttoken;
542     token->nexttoken = token->lasttoken = token;
543     return tmp;
544 }
545 
546 void
547 same_replace(old, new)
548 same_t
549     *old,
550     *new;
551 {
552     new->lasttoken->nexttoken = old->nexttoken;
553     old->nexttoken->lasttoken = new->lasttoken;
554     new->lasttoken = old->lasttoken;
555     /* rather than
556      * old->lasttoken->nexttoken = new
557      * we update in place (for the case where there isn't anything else)
558      */
559     *old = *new;
560 }
561 
562 
563 same_t *
564 same_char(ch)
565 char ch;
566 {
567     char buffer[2];
568 
569     buffer[0] = ch;
570     buffer[1] = 0;
571 
572     return same_item(string_lookup(buffer));
573 }
574 
575 
576 void
577 add_target(target, actions)
578 same_t
579     *target,
580     *actions;
581 {
582     same_t *ptr;
583 
584     if ((ptr = same_search(targets, target)) == 0) {
585 	targets = same_cat(targets, target);
586 	ptr = target;
587     } else {
588 	ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
589     }
590     if (actions) {
591 	if (ptr->action_list) {
592 	    same_free(ptr->action_list);
593 	}
594 	ptr->action_list = same_copy(actions);
595     }
596 }
597 
598 
599 same_t *
600 add_targets_actions(target, actions)
601 same_t
602     *target,
603     *actions;
604 {
605     same_t *ptr;
606 
607     if (target == 0) {
608 	return 0;
609     }
610     do {
611 	ptr = same_unlink(target);
612 	add_target(target, actions);
613 	target = ptr;
614     } while (target);
615 
616     same_free(actions);
617     return 0;
618 }
619 
620 same_t *
621 add_depends(target, depends)
622 same_t
623     *target,
624     *depends;
625 {
626     same_t *original = target;
627 
628     depends = same_cat(depends, same_copy(blank));	/* Separator */
629 
630     for (visit(original, target); !visited(target); visit_next(target)) {
631 	target->depend_list = same_cat(target->depend_list, same_copy(depends));
632     }
633     visit_end();
634     same_free(depends);
635 
636     return original;
637 }
638 
639 
640 /*
641  * We know that variable is a singleton
642  */
643 
644 void
645 assign(variable, value)
646 same_t
647     *variable,
648     *value;
649 {
650     same_t *ptr;
651 
652     if ((ptr = same_search(variables, variable)) != 0) {
653 	same_free(ptr->value_list);
654 	variables = same_unlink(ptr);
655 	same_free(ptr);
656     }
657     variable->value_list = value;
658     variables = same_cat(variables, variable);
659 }
660 
661 same_t *
662 value_of(variable)
663 same_t *variable;
664 {
665     same_t *ptr = same_search(variables, variable);
666 
667     if (ptr == 0) {
668 	return same_copy(null);
669     } else {
670 	return same_copy(ptr->value_list);
671     }
672 }
673 
674 
675 same_t *
676 expand_variables(token, free)
677 same_t *token;
678 int	free;
679 {
680     same_t *head = 0;
681 
682     if (!free) {
683 	token = same_copy(token);		/* Get our private copy */
684     }
685 
686     while (token) {
687 	char *string = token->string->string;
688 	same_t *tmp = same_unlink(token);
689 
690 	if ((string[0] == '$') && (string[1] == '{')) {	/* Expand time */
691 	    int len = strlen(string);
692 
693 	    string[len-1] = 0;
694 	    head = same_cat(head, expand_variables(
695 			value_of(same_item(string_lookup(string+2))), 1));
696 	    string[len-1] = '}';
697 	} else {
698 	    head = same_cat(head, token);
699 	}
700 	token = tmp;
701     }
702     return head;
703 }
704 
705 
706 same_t *
707 ws_merge(list)
708 same_t *list;
709 {
710     same_t *newlist = 0, *item;
711     int what = 0;
712 
713     while (list) {
714 	switch (what) {
715 	case 0:
716 	    if (isspace(list->string->string[0])) {
717 		;
718 	    } else {
719 		item = same_item(list->string);
720 		what = 1;
721 	    }
722 	    break;
723 	case 1:
724 	    if (isspace(list->string->string[0])) {
725 		newlist = same_cat(newlist, item);
726 		item = 0;
727 		what = 0;
728 	    } else {
729 		item = same_merge(item, same_item(list->string));
730 		what = 1;
731 	    }
732 	    break;
733 	}
734 	list = same_unlink(list);
735     }
736     return same_cat(newlist, item);
737 }
738 
739 
740 same_t *
741 variable(var_name)
742 same_t *var_name;
743 {
744     int length = strlen(var_name->string->string);
745     same_t *resolved;
746     char *newname;
747 
748     if ((newname = malloc(length+1+3)) == 0) {
749 	fprintf("Out of space for a variable name.\n");
750 	exit(1);
751     }
752     newname[0] = '$';
753     newname[1] = '{';
754     strcpy(newname+2, var_name->string->string);
755     strcat(newname, "}");
756     resolved = same_item(string_lookup(newname));
757     free(newname);
758 
759     return resolved;
760 }
761 
762 
763 same_t *
764 shell_variable(var_name)
765 same_t *var_name;
766 {
767     int length = strlen(var_name->string->string);
768     same_t *resolved;
769     char *newname;
770 
771     if ((newname = malloc(length+1+2)) == 0) {
772 	fprintf("Out of space for a variable name.\n");
773 	exit(1);
774     }
775     newname[0] = '$';
776     newname[1] = '$';
777     strcpy(newname+2, var_name->string->string);
778     resolved = same_item(string_lookup(newname));
779     free(newname);
780 
781     return resolved;
782 }
783 
784 same_t *
785 for_statement(special, variable, list)
786 same_t
787     *special,
788     *variable,
789     *list;
790 {
791     variable->shell_item = special;
792     variable->value_list = list;
793     return variable;
794 }
795 
796 same_t *
797 do_command(forlist, commands)
798 same_t
799     *forlist,
800     *commands;
801 {
802     same_t
803 	*special,
804 	*command_list = 0,
805 	*new_commands,
806 	*tmp,
807 	*shell_item,
808 	*value_list = forlist->value_list;
809     char
810 	*tmpstr,
811 	*variable_name = forlist->string->string;
812 
813     special = forlist->shell_item;
814     if (same_unlink(forlist->shell_item) != 0) {
815 	yyerror("Unexpected second item in special part of do_command");
816 	exit(1);
817     }
818 
819     while ((shell_item = value_list) != 0) {
820 	value_list = same_unlink(shell_item);
821 	/* Visit each item in commands.  For each shell variable which
822 	 * matches ours, replace it with ours.
823 	 */
824 	new_commands = same_copy(commands);
825 	for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
826 	    tmpstr = tmp->string->string;
827 	    if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
828 		if (strcmp(tmpstr+2, variable_name) == 0) {
829 		    same_replace(tmp, same_copy(shell_item));
830 		}
831 	    }
832 	}
833 	visit_end();
834 	command_list = same_cat(command_list, new_commands);
835     }
836     return same_cat(command_list, same_copy(newline));
837 }
838 
839 
840 int
841 Getchar()
842 {
843     if (last_saved) {
844 	last_saved = 0;
845 	return last_char;
846     } else {
847 	int c;
848 	c = getchar();
849 	switch (c) {
850 	case '\n':
851 	    lineno++;
852 	    column = 0;
853 	    break;
854 	default:
855 	    column++;
856 	}
857 	return c;
858     }
859 }
860 
861 
862 int
863 token_type(string)
864 char *string;
865 {
866     switch (string[0]) {
867     case 'f':
868 	if (strcmp(string, "for") == 0) {
869 	    return FOR;
870 	}
871 	break;
872     case 'd':
873 	if (string[1] == 'o') {
874 	    if (strcmp(string, "do") == 0) {
875 		return DO;
876 	    } else if (strcmp(string, "done") == 0) {
877 		return DONE;
878 	    }
879 	}
880 	break;
881     case 'i':
882 	if (strcmp(string, "in") == 0) {
883 	    return IN;
884 	}
885 	break;
886     default:
887 	break;
888     }
889     return TOKEN;
890 }
891 
892 
893 yylex()
894 {
895 #define	ret_token(c)	if (bufptr != buffer) { \
896 			    save(c); \
897 			    *bufptr = 0; \
898 			    bufptr = buffer; \
899 			    yylval.string = string_lookup(buffer); \
900 			    return token_type(buffer); \
901 			}
902 #define	save(c)	{ last_char = c; last_saved = 1; }
903 #if	defined(YYDEBUG)
904 #define	Return(c)	if (yydebug) { \
905 			    printf("[%d]", c); \
906 			    fflush(stdout); \
907 			} \
908 			yyval.intval = c; \
909 			return c;
910 #else	/* defined(YYDEBUG) */
911 #define	Return(y,c)	{ yylval.intval = c; return y; }
912 #endif	/* defined(YYDEBUG) */
913 
914 
915     static char buffer[500], *bufptr = buffer;
916     static int eof_found = 0;
917     int c;
918 
919     if (eof_found != 0) {
920 	eof_found++;
921 	if (eof_found > 2) {
922 	    fprintf(stderr, "End of file ignored.\n");
923 	    exit(1);
924 	}
925 	Return(EOF,0);
926     }
927     while ((c = Getchar()) != EOF) {
928 	switch (c) {
929 	case '#':
930 	    ret_token(c);
931 	    while (((c = Getchar()) != EOF) && (c != '\n')) {
932 		;
933 	    }
934 	    save(c);
935 	    break;
936 	case '<':
937 	case '?':
938 	    ret_token(c);
939 	    Return(MACRO_CHAR, c);
940 	case '\t':
941 	case ' ':
942 	    ret_token(c);
943 	    Return(WHITE_SPACE, c);
944 	case '-':
945 	case '@':
946 	case ':':
947 	case ';':
948 	case '=':
949 	case '$':
950 	case '{':
951 	case '}':
952 	case '(':
953 	case ')':
954 	    ret_token(c);
955 	    Return(c,c);
956 	case '\'':
957 	case '"':
958 	    if (bufptr != buffer) {
959 		if (bufptr[-1] == '\\') {
960 		    bufptr[-1] = c;
961 		}
962 		break;
963 	    } else {
964 		int newc;
965 
966 		ret_token(c);
967 		*bufptr++ = c;
968 		while (((newc = Getchar()) != EOF) && (newc != c)) {
969 		    *bufptr++ = newc;
970 		}
971 		*bufptr++ = c;
972 		*bufptr = 0;
973 		bufptr = buffer;
974 		yylval.string = string_lookup(buffer);
975 		return QUOTED_STRING;
976 	    }
977 	case '\n':
978 	    if (bufptr != buffer) {
979 		if (bufptr[-1] == '\\') {
980 		    bufptr--;
981 		    if ((c = Getchar()) != '\t') {
982 			yyerror("continuation line doesn't begin with a tab");
983 			save(c);
984 		    }
985 		    ret_token(c);
986 		    Return(WHITE_SPACE, c);
987 		}
988 	    }
989 	    ret_token(c);
990 	    Return(NL, 0);
991 	default:
992 	    *bufptr++ = c;
993 	    break;
994 	}
995     }
996 
997     eof_found = 1;
998 
999     ret_token(' ');
1000     Return(EOF, 0);
1001 }
1002 
1003 #ifndef lint
1004 static char sccsid[] = "@(#)mkmake.y	4.1 (Berkeley) 12/04/88";
1005 #endif	/* not lint */
1006 
1007 main()
1008 {
1009 #define	YYDEBUG
1010     extern int yydebug;
1011 
1012     null = same_item(string_lookup(""));
1013     newline = same_item(string_lookup("\n"));
1014     blank = same_item(string_lookup(" "));
1015     cwd_line = same_cat(same_copy(newline),
1016 			same_cat(same_item(string_lookup("cd ${CWD}")),
1017 				 same_copy(newline)));
1018 
1019     yyparse();
1020 
1021     do_dump();
1022 
1023     return 0;
1024 }
1025 
1026 #if	defined(YYDEBUG)
1027 dump_same(same)
1028 same_t *same;
1029 {
1030     same_t *same2;
1031 
1032     for (visit(same, same2); !visited(same2); visit_next(same2)) {
1033 	printf(same2->string->string);
1034     }
1035     visit_end();
1036 }
1037 #endif	/* YYDEBUG */
1038 
1039 do_dump()
1040 {
1041     string_t *string;
1042     same_t *same, *same2;
1043 
1044     if (yydebug > 1) {
1045 	printf("strings...\n");
1046 	for (string = strings; string; string = string->next) {
1047 	    printf("\t%s\n", string->string);
1048 	}
1049     }
1050 
1051     printf("# variables...\n");
1052     for (visit(variables, same); !visited(same); visit_next(same)) {
1053 	printf("%s =\t", same->string->string);
1054 	for (visit(same->value_list, same2); !visited(same2);
1055 						visit_next(same2)) {
1056 	    printf(same2->string->string);
1057 	}
1058 	visit_end();
1059 	printf("\n");
1060     }
1061     visit_end();
1062 
1063     printf("\n\n#targets...\n");
1064     for (visit(targets, same); !visited(same); visit_next(same)) {
1065 	printf("\n%s:\t", same->string->string);
1066 	for (visit(same->depend_list, same2); !visited(same2);
1067 						visit_next(same2)) {
1068 	    printf(same2->string->string);
1069 	}
1070 	visit_end();
1071 	printf("\n\t");
1072 	for (visit(same->action_list, same2); !visited(same2);
1073 					    visit_next(same2)) {
1074 	    printf(same2->string->string);
1075 	    if (same2->string->string[0] == '\n') {
1076 		printf("\t");
1077 	    }
1078 	}
1079 	visit_end();
1080 	printf("\n");
1081     }
1082     visit_end();
1083 }
1084