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