xref: /csrg-svn/usr.bin/tn3270/tools/mkmake.y (revision 62362)
131644Sminshall %{
231896Sminshall 
348763Sbostic /*-
4*62362Sbostic  * Copyright (c) 1988, 1993
5*62362Sbostic  *	The Regents of the University of California.  All rights reserved.
631896Sminshall  *
748763Sbostic  * %sccs.include.redist.c%
831896Sminshall  */
931896Sminshall 
1048763Sbostic #ifndef lint
11*62362Sbostic static char sccsid[] = "@(#)mkmake.y	8.1 (Berkeley) 06/06/93";
1248763Sbostic #endif /* not lint */
1348763Sbostic 
1431644Sminshall typedef struct string {
1531644Sminshall     int
1631644Sminshall 	hashval,
1731644Sminshall 	length;
1831644Sminshall     char
1931644Sminshall 	*string;
2031644Sminshall     struct string
2131644Sminshall 	*next;
2231644Sminshall } string_t;
2331644Sminshall 
2431654Sminshall /*
2531654Sminshall  * The deal with these is that they exist on various lists.
2631654Sminshall  *
2731654Sminshall  * First off, they are on a temporary list during the time they
2831654Sminshall  * are in the active focus of the parser.
2931654Sminshall  *
3031654Sminshall  * Secondly, they live on one of three queues:
3131654Sminshall  *	1.  Variables
3231654Sminshall  *	2.  Targets
3331654Sminshall  *	3.  Actions
3431654Sminshall  * (and, we restrict any given one to live on one and only one such list)
3531654Sminshall  *
3631654Sminshall  * Also, they may live on the list of values for someone else's variable,
3731654Sminshall  * or as someone's dependancy.
3831654Sminshall  */
3931654Sminshall 
4031644Sminshall typedef struct same {
4131654Sminshall     string_t
4231654Sminshall 	*string;			/* My name */
4331644Sminshall     struct same
4431654Sminshall 	*nexttoken,			/* Next pointer */
4531654Sminshall 	*lasttoken,			/* Back pointer */
4631654Sminshall 	*depend_list,			/* If target, dependancies */
4731654Sminshall 	*action_list,			/* If target, actions */
4831690Sminshall 	*value_list,			/* If variable, value list */
4931690Sminshall 	*shell_item;			/* If a shell variable, current value */
5031644Sminshall } same_t;
5131644Sminshall 
5231644Sminshall %}
5331644Sminshall 
5431644Sminshall %union {
5531644Sminshall     string_t *string;
5631644Sminshall     same_t *same;
5731654Sminshall     int	intval;
5831644Sminshall     }
5931644Sminshall 
6031670Sminshall %start makefile
6131690Sminshall %token <string> TOKEN QUOTED_STRING
6231684Sminshall %token <intval>	FOR IN DO DONE
6331690Sminshall %token <intval> MACRO_CHAR NL WHITE_SPACE
6431690Sminshall %token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
6531692Sminshall %type <same> target target1 assignment assign1 actions action
6631728Sminshall %type <same> command_list list list_element
6731717Sminshall %type <same> for_statement maybe_at_minus tokens token
6831692Sminshall %type <same> maybe_white_space
6931690Sminshall %type <intval> white_space macro_char
7031644Sminshall %%
7131654Sminshall 
7231690Sminshall makefile : lines;
7331644Sminshall 
7431644Sminshall lines : line
7531644Sminshall     | lines line
7631644Sminshall     ;
7731644Sminshall 
7831690Sminshall line : NL
7931654Sminshall     | assignment
8031654Sminshall     | target_action
8131644Sminshall     ;
8231644Sminshall 
8331728Sminshall assignment : assign1 tokens NL
8431644Sminshall     {
8531690Sminshall 	assign($1, $2);
8631644Sminshall     }
8731690Sminshall     | assign1 NL
8831654Sminshall     {
8931668Sminshall 	assign($1, same_copy(null));
9031654Sminshall     }
9131644Sminshall     ;
9231644Sminshall 
9331711Sminshall assign1: token maybe_white_space '=' maybe_white_space
9431690Sminshall     ;
9531690Sminshall 
9631654Sminshall target_action: target actions
9731644Sminshall     {
9831654Sminshall 	add_targets_actions($1, $2);
9931644Sminshall     }
10031654Sminshall     | target
10131654Sminshall     {
10231717Sminshall 	add_targets_actions($1, 0);
10331654Sminshall     }
10431644Sminshall     ;
10531644Sminshall 
10631728Sminshall target : target1 tokens NL
10731654Sminshall     {
10831692Sminshall 	$$ = add_depends($1, $2);
10931654Sminshall     }
11031692Sminshall     | target1 NL
11131692Sminshall     {
11231692Sminshall 	$$ = add_depends($1, same_copy(null));
11331692Sminshall     }
11431654Sminshall     ;
11531654Sminshall 
11631692Sminshall target1: tokens maybe_white_space ':' maybe_white_space
11731717Sminshall     {
11831717Sminshall 	$$ = ws_merge($1);
11931717Sminshall     }
12031692Sminshall     ;
12131692Sminshall 
12231644Sminshall actions: action
12331644Sminshall     | actions action
12431644Sminshall     {
12531728Sminshall 	$$ = same_cat(same_cat($1, same_copy(newline)), $2);
12631644Sminshall     }
12731644Sminshall     ;
12831644Sminshall 
12931690Sminshall action:	white_space command_list NL
13031644Sminshall     {
13131644Sminshall 	$$ = $2;
13231644Sminshall     }
13331690Sminshall     | white_space for_statement do command_list semi_colon done NL
13431684Sminshall     {
13531693Sminshall 	$$ = do_command($2, $4);
13631684Sminshall     }
13731644Sminshall     ;
13831644Sminshall 
13931692Sminshall for_statement: maybe_at_minus FOR white_space token
14031717Sminshall 		in tokens semi_colon
14131684Sminshall     {
14231754Sminshall 	$$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
14331684Sminshall     }
14431684Sminshall     ;
14531684Sminshall 
14631692Sminshall in:	white_space IN white_space
14731690Sminshall do:	white_space DO white_space
14831690Sminshall     ;
14931690Sminshall 
15031690Sminshall done:	white_space DONE
15131690Sminshall     ;
15231690Sminshall 
15331692Sminshall semi_colon:	';'
15431690Sminshall     ;
15531690Sminshall 
15631690Sminshall command_list: list
15731690Sminshall     | '(' list maybe_white_space ')'
15831690Sminshall     {
15931711Sminshall 	$$ = same_cat($2, same_copy(cwd_line));
16031690Sminshall     }
16131690Sminshall     ;
16231690Sminshall 
16331728Sminshall list: token
16431728Sminshall     | list list_element
16531690Sminshall     {
16631728Sminshall 	$$ = same_cat($1, $2);
16731690Sminshall     }
16831728Sminshall     | list white_space list_element
16931728Sminshall     {
17031728Sminshall 	$$ = same_cat($1, same_cat(same_copy(blank), $3));
17131728Sminshall     }
17231690Sminshall     ;
17331690Sminshall 
17431728Sminshall list_element: token
17531728Sminshall     | semi_colon
17631728Sminshall     {
17731728Sminshall 	$$ = same_copy(newline);
17831728Sminshall     }
17931690Sminshall     ;
18031690Sminshall 
18131684Sminshall maybe_at_minus: /* empty */
18231684Sminshall     {
18331684Sminshall 	$$ = same_copy(null);
18431684Sminshall     }
18531684Sminshall     | '@'
18631684Sminshall     {
18731684Sminshall 	char buffer[2];
18831684Sminshall 
18931684Sminshall 	buffer[0] = $1;
19031684Sminshall 	buffer[1] = 0;
19131684Sminshall 	$$ = same_item(string_lookup(buffer));
19231684Sminshall     }
19331684Sminshall     | '-'
19431684Sminshall     {
19531684Sminshall 	char buffer[2];
19631684Sminshall 
19731684Sminshall 	buffer[0] = $1;
19831684Sminshall 	buffer[1] = 0;
19931684Sminshall 	$$ = same_item(string_lookup(buffer));
20031684Sminshall     }
20131684Sminshall     ;
20231690Sminshall 
20331644Sminshall tokens : token
20431692Sminshall     | tokens maybe_white_space token
20531644Sminshall     {
20631692Sminshall 	$$ = same_cat($1, same_cat($2, $3));
20731644Sminshall     }
20831644Sminshall     ;
20931654Sminshall 
21031692Sminshall token: TOKEN
21131644Sminshall     {
21231654Sminshall 	$$ = same_item($1);
21331644Sminshall     }
21431654Sminshall     | QUOTED_STRING
21531654Sminshall     {
21631654Sminshall 	$$ = same_item($1);
21731654Sminshall     }
21831654Sminshall     | '$' macro_char
21931654Sminshall     {
22031654Sminshall 	char buffer[3];
22131654Sminshall 
22231654Sminshall 	buffer[0] = '$';
22331654Sminshall 	buffer[1] = $2;
22431654Sminshall 	buffer[2] = 0;
22531654Sminshall 
22631654Sminshall 	$$ = same_item(string_lookup(buffer));
22731654Sminshall     }
22831717Sminshall     | '$' '$' TOKEN
22931654Sminshall     {
23031717Sminshall 	$$ = shell_variable(same_item($3));
23131654Sminshall     }
23231690Sminshall     | MACRO_CHAR
23331654Sminshall     {
23431690Sminshall 	$$ = same_char($1);
23531690Sminshall     }
23631717Sminshall     | '$' '{' TOKEN '}'
23731690Sminshall     {
23831717Sminshall 	$$ = variable(same_item($3));
23931654Sminshall     }
24031717Sminshall     | '$' '(' TOKEN ')'
24131717Sminshall     {
24231717Sminshall 	$$ = variable(same_item($3));
24331717Sminshall     }
24431717Sminshall     | '$' TOKEN
24531717Sminshall     {
24631717Sminshall 	$$ = variable(same_item($2));
24731717Sminshall     }
24831684Sminshall     | '-'
24931684Sminshall     {
25031684Sminshall 	$$ = same_char('-');
25131684Sminshall     }
25231684Sminshall     | '@'
25331684Sminshall     {
25431684Sminshall 	$$ = same_char('@');
25531684Sminshall     }
25631644Sminshall     ;
25731654Sminshall 
25831654Sminshall macro_char: MACRO_CHAR
25931690Sminshall     | '@'
26031654Sminshall     ;
26131654Sminshall 
26231654Sminshall maybe_white_space:
26331692Sminshall     {
26431692Sminshall 	$$ = same_copy(null);
26531692Sminshall     }
26631692Sminshall     | white_space
26731692Sminshall     {
26831692Sminshall 	$$ = same_char($1);
26931692Sminshall     }
27031692Sminshall     ;
27131654Sminshall 
27231654Sminshall white_space : WHITE_SPACE
27331654Sminshall     | white_space WHITE_SPACE
27431654Sminshall     ;
27531644Sminshall %%
27631644Sminshall #include <stdio.h>
27731717Sminshall #include <ctype.h>
27831644Sminshall 
27931644Sminshall static int last_char, last_saved = 0;
28031644Sminshall static int column = 0, lineno = 1;
28131644Sminshall 
28231644Sminshall 
28331654Sminshall static string_t
28431654Sminshall     *strings = 0;
28531690Sminshall 
28631644Sminshall static same_t
28731690Sminshall     *shell_variables = 0,
28831690Sminshall     *shell_special = 0,
28931669Sminshall     *variables = 0,
29031669Sminshall     *targets = 0,
29131669Sminshall     *actions = 0;
29231644Sminshall 
29331654Sminshall static same_t
29431668Sminshall     *null,
29531668Sminshall     *blank,
29631711Sminshall     *cwd_line,
29731668Sminshall     *newline;
29831654Sminshall 
29931644Sminshall extern char *malloc();
30031644Sminshall 
30131668Sminshall static unsigned int
30231668Sminshall 	clock = -1;
30331668Sminshall 
30431668Sminshall struct {
30531668Sminshall     same_t *first;
30631668Sminshall     int next;
30731668Sminshall } visit_stack[20];		/* 20 maximum */
30831668Sminshall 
30931668Sminshall #define	visit(what,via) \
31031668Sminshall 	(visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
31131670Sminshall #define	visited(via)	(visitcheck(via) || ((via) == 0) \
31231669Sminshall 	|| (visit_stack[clock].next && (via == visit_stack[clock].first)))
31331668Sminshall #define	visit_next(via)	(visit_stack[clock].next = 1, (via) = (via)->nexttoken)
31431668Sminshall #define	visit_end()	(clock--)
31531668Sminshall 
yyerror(s)31631654Sminshall yyerror(s)
31731654Sminshall char *s;
31831644Sminshall {
31931654Sminshall     fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
32031654Sminshall     do_dump();
32131654Sminshall }
32231644Sminshall 
32331654Sminshall int
visitcheck(same)32431670Sminshall visitcheck(same)
32531670Sminshall same_t *same;
32631670Sminshall {
32731670Sminshall     if (same->string == 0) {
32831670Sminshall 	yyerror("BUG - freed 'same' in use...");
32931670Sminshall 	exit(1);
33031670Sminshall     }
33131670Sminshall     return 0;
33231670Sminshall }
33331670Sminshall 
33431670Sminshall int
string_hashof(string,length)33531654Sminshall string_hashof(string, length)
33631654Sminshall char *string;
33731654Sminshall int length;
33831654Sminshall {
33931654Sminshall     register int i = 0;
34031654Sminshall 
34131654Sminshall     while (length--) {
34231654Sminshall 	i = (i<<3) + *string ^ ((i>>28)&0x7);
34331654Sminshall     }
34431654Sminshall     return i;
34531644Sminshall }
34631644Sminshall 
34731654Sminshall int
string_same(s1,s2)34831654Sminshall string_same(s1, s2)
34931654Sminshall string_t
35031654Sminshall     *s1, *s2;
35131644Sminshall {
35231654Sminshall     if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
35331654Sminshall 		&& (memcmp(s1->string, s2->string, s1->length) == 0)) {
35431654Sminshall 	return 1;
35531654Sminshall     } else {
35631654Sminshall 	return 0;
35731654Sminshall     }
35831644Sminshall }
35931644Sminshall 
36031654Sminshall string_t *
string_lookup(string)36131654Sminshall string_lookup(string)
36231654Sminshall char *string;
36331644Sminshall {
36431654Sminshall     string_t ours;
36531654Sminshall     string_t *ptr;
36631654Sminshall 
36731654Sminshall     ours.length = strlen(string);
36831654Sminshall     ours.hashval = string_hashof(string, ours.length);
36931654Sminshall     ours.string = string;
37031654Sminshall 
37131654Sminshall     for (ptr = strings; ptr; ptr = ptr->next) {
37231654Sminshall 	if (string_same(&ours, ptr)) {
37331654Sminshall 	    return ptr;
37431654Sminshall 	}
37531654Sminshall     }
37631654Sminshall     if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
37731654Sminshall 	fprintf(stderr, "No space to add string *%s*!\n", string);
37831654Sminshall 	exit(1);
37931654Sminshall     }
38031654Sminshall     ptr->hashval = ours.hashval;
38131654Sminshall     ptr->length = ours.length;
38231654Sminshall     if ((ptr->string = malloc(ours.length+1)) == 0) {
38331654Sminshall 	fprintf(stderr, "No space to add literal *%s*!\n", string);
38431654Sminshall 	exit(1);
38531654Sminshall     }
38631654Sminshall     memcpy(ptr->string, string, ours.length+1);
38731654Sminshall     ptr->next = strings;
38831654Sminshall     strings = ptr;
38931654Sminshall     return ptr;
39031644Sminshall }
39131644Sminshall 
39231717Sminshall #define	same_singleton(s)	((s)->nexttoken == (s))
39331717Sminshall 
39431644Sminshall same_t *
same_search(list,token)39531654Sminshall same_search(list, token)
39631644Sminshall same_t
39731654Sminshall     *list,
39831654Sminshall     *token;
39931644Sminshall {
40031654Sminshall     same_t *ptr;
40131654Sminshall 
40231668Sminshall     ptr = list;
40331668Sminshall     for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
40431654Sminshall 	string_t *string;
40531654Sminshall 
40631654Sminshall 	string = ptr->string;
40731654Sminshall 	if (string_same(string, token->string)) {
40831668Sminshall 	    visit_end();
40931654Sminshall 	    return ptr;
41031654Sminshall 	}
41131654Sminshall     }
41231668Sminshall     visit_end();
41331654Sminshall     return 0;
41431644Sminshall }
41531644Sminshall 
41631644Sminshall same_t *
same_cat(list,tokens)41731654Sminshall same_cat(list, tokens)
41831644Sminshall same_t
41931654Sminshall     *list,
42031654Sminshall     *tokens;
42131644Sminshall {
42231654Sminshall     same_t *last;
42331644Sminshall 
42431690Sminshall     if (tokens == 0) {
42531690Sminshall 	return list;
42631690Sminshall     }
42731669Sminshall     if (list) {
42831669Sminshall 	last = tokens->lasttoken;
42931669Sminshall 	tokens->lasttoken = list->lasttoken;
43031669Sminshall 	list->lasttoken = last;
43131669Sminshall 	tokens->lasttoken->nexttoken = tokens;
43231669Sminshall 	last->nexttoken = list;
43331669Sminshall 	return list;
43431669Sminshall     } else {
43531669Sminshall 	return tokens;
43631669Sminshall     }
43731644Sminshall }
43831644Sminshall 
43931644Sminshall same_t *
same_item(string)44031654Sminshall same_item(string)
44131644Sminshall string_t *string;
44231644Sminshall {
44331644Sminshall     same_t *ptr;
44431644Sminshall 
44531644Sminshall     if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) {
44631644Sminshall 	fprintf(stderr, "No more space for tokens!\n");
44731644Sminshall 	exit(1);
44831644Sminshall     }
44931654Sminshall     memset((char *)ptr, 0, sizeof *ptr);
45031668Sminshall     ptr->nexttoken = ptr->lasttoken = ptr;
45131644Sminshall     ptr->string = string;
45231644Sminshall     return ptr;
45331644Sminshall }
45431644Sminshall 
45531654Sminshall same_t *
same_copy(same)45631654Sminshall same_copy(same)
45731654Sminshall same_t *same;
45831654Sminshall {
45931668Sminshall     same_t *head, *copy;
46031654Sminshall 
46131669Sminshall     head = 0;
46231669Sminshall     for (visit(same, copy); !visited(copy); visit_next(copy)) {
46331654Sminshall 	same_t *ptr;
46431654Sminshall 
46531668Sminshall 	ptr = same_item(copy->string);
46631669Sminshall 	head = same_cat(head, ptr);
46731654Sminshall     }
46831669Sminshall     visit_end();
46931654Sminshall     return head;
47031654Sminshall }
47131654Sminshall 
47231717Sminshall 
47331717Sminshall same_t *
same_merge(t1,t2)47431717Sminshall same_merge(t1, t2)
47531717Sminshall same_t
47631717Sminshall     *t1,
47731717Sminshall     *t2;
47831717Sminshall {
47931717Sminshall     if (same_singleton(t1) && same_singleton(t2)) {
48031717Sminshall 	int length = strlen(t1->string->string)+strlen(t2->string->string);
48131717Sminshall 	char *buffer = malloc(length+1);
48231717Sminshall 	same_t *value;
48331717Sminshall 
48431717Sminshall 	if (buffer == 0) {
48531717Sminshall 	    yyerror("No space to merge strings in same_merge!");
48631717Sminshall 	    exit(1);
48731717Sminshall 	}
48831717Sminshall 	strcpy(buffer, t1->string->string);
48931717Sminshall 	strcat(buffer, t2->string->string);
49031717Sminshall 	value = same_item(string_lookup(buffer));
49131717Sminshall 	free(buffer);
49231717Sminshall 	return value;
49331717Sminshall     } else {
49431717Sminshall 	yyerror("Internal error - same_merge with non-singletons");
49531717Sminshall 	exit(1);
49631717Sminshall     }
49731717Sminshall }
49831717Sminshall 
49931717Sminshall 
50031654Sminshall void
same_free(list)50131668Sminshall same_free(list)
50231668Sminshall same_t *list;
50331654Sminshall {
50431668Sminshall     same_t *token, *ptr;
50531654Sminshall 
50631717Sminshall     if (list == 0) {
50731717Sminshall 	return;
50831717Sminshall     }
50931717Sminshall 
51031668Sminshall     token = list;
51131668Sminshall     do {
51231654Sminshall 	ptr = token->nexttoken;
51331670Sminshall 	token->string = 0;
51431654Sminshall 	(void) free((char *)token);
51531654Sminshall 	token = ptr;
51631668Sminshall     } while (token != list);
51731654Sminshall }
51831654Sminshall 
51931684Sminshall same_t *
same_unlink(token)52031668Sminshall same_unlink(token)
52131654Sminshall same_t
52231668Sminshall     *token;
52331654Sminshall {
52431684Sminshall     same_t *tmp;
52531684Sminshall 
52631669Sminshall     if (token == 0) {
52731684Sminshall 	return 0;
52831669Sminshall     }
52931684Sminshall     if ((tmp = token->nexttoken) == token) {
53031684Sminshall 	tmp = 0;
53131684Sminshall     }
53231668Sminshall     token->lasttoken->nexttoken = token->nexttoken;
53331668Sminshall     token->nexttoken->lasttoken = token->lasttoken;
53431669Sminshall     token->nexttoken = token->lasttoken = token;
53531684Sminshall     return tmp;
53631654Sminshall }
53731654Sminshall 
53831711Sminshall void
same_replace(old,new)53931711Sminshall same_replace(old, new)
54031711Sminshall same_t
54131711Sminshall     *old,
54231711Sminshall     *new;
54331711Sminshall {
54431711Sminshall     new->lasttoken->nexttoken = old->nexttoken;
54531711Sminshall     old->nexttoken->lasttoken = new->lasttoken;
54631711Sminshall     new->lasttoken = old->lasttoken;
54731711Sminshall     /* rather than
54831711Sminshall      * old->lasttoken->nexttoken = new
54931711Sminshall      * we update in place (for the case where there isn't anything else)
55031711Sminshall      */
55131711Sminshall     *old = *new;
55231711Sminshall }
55331711Sminshall 
55431711Sminshall 
55531654Sminshall same_t *
same_char(ch)55631684Sminshall same_char(ch)
55731684Sminshall char ch;
55831684Sminshall {
55931684Sminshall     char buffer[2];
56031684Sminshall 
56131684Sminshall     buffer[0] = ch;
56231684Sminshall     buffer[1] = 0;
56331684Sminshall 
56431684Sminshall     return same_item(string_lookup(buffer));
56531684Sminshall }
56631684Sminshall 
56731711Sminshall 
56831717Sminshall void
add_target(target,actions)56931717Sminshall add_target(target, actions)
57031654Sminshall same_t
57131717Sminshall     *target,
57231717Sminshall     *actions;
57331654Sminshall {
57431654Sminshall     same_t *ptr;
57531654Sminshall 
57631668Sminshall     if ((ptr = same_search(targets, target)) == 0) {
57731669Sminshall 	targets = same_cat(targets, target);
57831717Sminshall 	ptr = target;
57931654Sminshall     } else {
58031669Sminshall 	ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
58131654Sminshall     }
58231717Sminshall     if (actions) {
58331717Sminshall 	if (ptr->action_list) {
58431717Sminshall 	    same_free(ptr->action_list);
58531717Sminshall 	}
58631717Sminshall 	ptr->action_list = same_copy(actions);
58731717Sminshall     }
58831654Sminshall }
58931654Sminshall 
59031711Sminshall 
59131654Sminshall same_t *
add_targets_actions(target,actions)59231654Sminshall add_targets_actions(target, actions)
59331654Sminshall same_t
59431654Sminshall     *target,
59531654Sminshall     *actions;
59631654Sminshall {
59731670Sminshall     same_t *ptr;
59831654Sminshall 
59931669Sminshall     if (target == 0) {
60031669Sminshall 	return 0;
60131654Sminshall     }
60231669Sminshall     do {
60331684Sminshall 	ptr = same_unlink(target);
60431717Sminshall 	add_target(target, actions);
60531669Sminshall 	target = ptr;
60631670Sminshall     } while (target);
60731669Sminshall 
60831669Sminshall     same_free(actions);
60931654Sminshall     return 0;
61031654Sminshall }
61131654Sminshall 
61231654Sminshall same_t *
add_depends(target,depends)61331654Sminshall add_depends(target, depends)
61431654Sminshall same_t
61531654Sminshall     *target,
61631654Sminshall     *depends;
61731654Sminshall {
61831654Sminshall     same_t *original = target;
61931654Sminshall 
62031669Sminshall     depends = same_cat(depends, same_copy(blank));	/* Separator */
62131654Sminshall 
62231668Sminshall     for (visit(original, target); !visited(target); visit_next(target)) {
62331669Sminshall 	target->depend_list = same_cat(target->depend_list, same_copy(depends));
62431654Sminshall     }
62531668Sminshall     visit_end();
62631669Sminshall     same_free(depends);
62731668Sminshall 
62831654Sminshall     return original;
62931654Sminshall }
63031654Sminshall 
63131654Sminshall 
63231654Sminshall /*
63331654Sminshall  * We know that variable is a singleton
63431654Sminshall  */
63531654Sminshall 
63631654Sminshall void
assign(variable,value)63731654Sminshall assign(variable, value)
63831654Sminshall same_t
63931654Sminshall     *variable,
64031654Sminshall     *value;
64131654Sminshall {
64231654Sminshall     same_t *ptr;
64331654Sminshall 
64431668Sminshall     if ((ptr = same_search(variables, variable)) != 0) {
64531654Sminshall 	same_free(ptr->value_list);
64631717Sminshall 	variables = same_unlink(ptr);
64731669Sminshall 	same_free(ptr);
64831654Sminshall     }
64931654Sminshall     variable->value_list = value;
65031669Sminshall     variables = same_cat(variables, variable);
65131654Sminshall }
65231654Sminshall 
65331654Sminshall same_t *
value_of(variable)65431654Sminshall value_of(variable)
65531654Sminshall same_t *variable;
65631654Sminshall {
65731668Sminshall     same_t *ptr = same_search(variables, variable);
65831654Sminshall 
65931654Sminshall     if (ptr == 0) {
66031669Sminshall 	return same_copy(null);
66131654Sminshall     } else {
66231669Sminshall 	return same_copy(ptr->value_list);
66331654Sminshall     }
66431654Sminshall }
66531654Sminshall 
66631684Sminshall 
66731683Sminshall same_t *
expand_variables(token,free)66831684Sminshall expand_variables(token, free)
66931684Sminshall same_t *token;
67031684Sminshall int	free;
67131684Sminshall {
67231684Sminshall     same_t *head = 0;
67331684Sminshall 
67431684Sminshall     if (!free) {
67531684Sminshall 	token = same_copy(token);		/* Get our private copy */
67631684Sminshall     }
67731684Sminshall 
67831684Sminshall     while (token) {
67931684Sminshall 	char *string = token->string->string;
68031684Sminshall 	same_t *tmp = same_unlink(token);
68131684Sminshall 
68231754Sminshall 	if ((string[0] == '$') && (string[1] == '{')) {	/* Expand time */
68331684Sminshall 	    int len = strlen(string);
68431684Sminshall 
68531684Sminshall 	    string[len-1] = 0;
68631684Sminshall 	    head = same_cat(head, expand_variables(
68731684Sminshall 			value_of(same_item(string_lookup(string+2))), 1));
68831684Sminshall 	    string[len-1] = '}';
68931754Sminshall 	} else {
69031684Sminshall 	    head = same_cat(head, token);
69131684Sminshall 	}
69231684Sminshall 	token = tmp;
69331684Sminshall     }
69431684Sminshall     return head;
69531684Sminshall }
69631684Sminshall 
69731717Sminshall 
69831684Sminshall same_t *
ws_merge(list)69931717Sminshall ws_merge(list)
70031717Sminshall same_t *list;
70131717Sminshall {
70231717Sminshall     same_t *newlist = 0, *item;
70331717Sminshall     int what = 0;
70431717Sminshall 
70531717Sminshall     while (list) {
70631717Sminshall 	switch (what) {
70731717Sminshall 	case 0:
70831717Sminshall 	    if (isspace(list->string->string[0])) {
70931717Sminshall 		;
71031717Sminshall 	    } else {
71131717Sminshall 		item = same_item(list->string);
71231717Sminshall 		what = 1;
71331717Sminshall 	    }
71431717Sminshall 	    break;
71531717Sminshall 	case 1:
71631717Sminshall 	    if (isspace(list->string->string[0])) {
71731717Sminshall 		newlist = same_cat(newlist, item);
71831717Sminshall 		item = 0;
71931717Sminshall 		what = 0;
72031717Sminshall 	    } else {
72131717Sminshall 		item = same_merge(item, same_item(list->string));
72231717Sminshall 		what = 1;
72331717Sminshall 	    }
72431717Sminshall 	    break;
72531717Sminshall 	}
72631717Sminshall 	list = same_unlink(list);
72731717Sminshall     }
72831717Sminshall     return same_cat(newlist, item);
72931717Sminshall }
73031717Sminshall 
73131717Sminshall 
73231717Sminshall same_t *
variable(var_name)73331683Sminshall variable(var_name)
73431683Sminshall same_t *var_name;
73531683Sminshall {
73631683Sminshall     int length = strlen(var_name->string->string);
73731683Sminshall     same_t *resolved;
73831683Sminshall     char *newname;
73931654Sminshall 
74031683Sminshall     if ((newname = malloc(length+1+3)) == 0) {
74131683Sminshall 	fprintf("Out of space for a variable name.\n");
74231683Sminshall 	exit(1);
74331683Sminshall     }
74431683Sminshall     newname[0] = '$';
74531683Sminshall     newname[1] = '{';
74631683Sminshall     strcpy(newname+2, var_name->string->string);
74731683Sminshall     strcat(newname, "}");
74831683Sminshall     resolved = same_item(string_lookup(newname));
74931683Sminshall     free(newname);
75031683Sminshall 
75131683Sminshall     return resolved;
75231683Sminshall }
75331683Sminshall 
75431690Sminshall 
75531684Sminshall same_t *
shell_variable(var_name)75631693Sminshall shell_variable(var_name)
75731693Sminshall same_t *var_name;
75831690Sminshall {
75931693Sminshall     int length = strlen(var_name->string->string);
76031693Sminshall     same_t *resolved;
76131693Sminshall     char *newname;
76231690Sminshall 
76331693Sminshall     if ((newname = malloc(length+1+2)) == 0) {
76431693Sminshall 	fprintf("Out of space for a variable name.\n");
76531690Sminshall 	exit(1);
76631690Sminshall     }
76731693Sminshall     newname[0] = '$';
76831693Sminshall     newname[1] = '$';
76931693Sminshall     strcpy(newname+2, var_name->string->string);
77031693Sminshall     resolved = same_item(string_lookup(newname));
77131693Sminshall     free(newname);
77231693Sminshall 
77331693Sminshall     return resolved;
77431690Sminshall }
77531690Sminshall 
77631690Sminshall same_t *
for_statement(special,variable,list)77731690Sminshall for_statement(special, variable, list)
77831684Sminshall same_t
77931684Sminshall     *special,
78031684Sminshall     *variable,
78131690Sminshall     *list;
78231684Sminshall {
78331693Sminshall     variable->shell_item = special;
78431690Sminshall     variable->value_list = list;
78531693Sminshall     return variable;
78631684Sminshall }
78731683Sminshall 
78831693Sminshall same_t *
do_command(forlist,commands)78931693Sminshall do_command(forlist, commands)
79031693Sminshall same_t
79131693Sminshall     *forlist,
79231693Sminshall     *commands;
79331693Sminshall {
79431711Sminshall     same_t
79531711Sminshall 	*special,
79631711Sminshall 	*command_list = 0,
79731711Sminshall 	*new_commands,
79831711Sminshall 	*tmp,
79931711Sminshall 	*shell_item,
80031711Sminshall 	*value_list = forlist->value_list;
80131711Sminshall     char
80231711Sminshall 	*tmpstr,
80331711Sminshall 	*variable_name = forlist->string->string;
80431711Sminshall 
80531711Sminshall     special = forlist->shell_item;
80631711Sminshall     if (same_unlink(forlist->shell_item) != 0) {
80731711Sminshall 	yyerror("Unexpected second item in special part of do_command");
80831711Sminshall 	exit(1);
80931711Sminshall     }
81031711Sminshall 
81131711Sminshall     while ((shell_item = value_list) != 0) {
81231711Sminshall 	value_list = same_unlink(shell_item);
81331711Sminshall 	/* Visit each item in commands.  For each shell variable which
81431711Sminshall 	 * matches ours, replace it with ours.
81531711Sminshall 	 */
81631711Sminshall 	new_commands = same_copy(commands);
81731711Sminshall 	for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
81831711Sminshall 	    tmpstr = tmp->string->string;
81931711Sminshall 	    if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
82031711Sminshall 		if (strcmp(tmpstr+2, variable_name) == 0) {
82131711Sminshall 		    same_replace(tmp, same_copy(shell_item));
82231711Sminshall 		}
82331711Sminshall 	    }
82431711Sminshall 	}
82531711Sminshall 	visit_end();
82631711Sminshall 	command_list = same_cat(command_list, new_commands);
82731711Sminshall     }
82831711Sminshall     return same_cat(command_list, same_copy(newline));
82931693Sminshall }
83031684Sminshall 
83131693Sminshall 
83231644Sminshall int
Getchar()83331644Sminshall Getchar()
83431644Sminshall {
83531644Sminshall     if (last_saved) {
83631644Sminshall 	last_saved = 0;
83731644Sminshall 	return last_char;
83831644Sminshall     } else {
83931644Sminshall 	int c;
84031644Sminshall 	c = getchar();
84131644Sminshall 	switch (c) {
84231644Sminshall 	case '\n':
84331644Sminshall 	    lineno++;
84431644Sminshall 	    column = 0;
84531644Sminshall 	    break;
84631644Sminshall 	default:
84731644Sminshall 	    column++;
84831644Sminshall 	}
84931644Sminshall 	return c;
85031644Sminshall     }
85131644Sminshall }
85231644Sminshall 
85331644Sminshall 
85431684Sminshall int
token_type(string)85531684Sminshall token_type(string)
85631684Sminshall char *string;
85731684Sminshall {
85831684Sminshall     switch (string[0]) {
85931684Sminshall     case 'f':
86031684Sminshall 	if (strcmp(string, "for") == 0) {
86131684Sminshall 	    return FOR;
86231684Sminshall 	}
86331684Sminshall 	break;
86431684Sminshall     case 'd':
86531684Sminshall 	if (string[1] == 'o') {
86631684Sminshall 	    if (strcmp(string, "do") == 0) {
86731684Sminshall 		return DO;
86831684Sminshall 	    } else if (strcmp(string, "done") == 0) {
86931684Sminshall 		return DONE;
87031684Sminshall 	    }
87131684Sminshall 	}
87231684Sminshall 	break;
87331684Sminshall     case 'i':
87431684Sminshall 	if (strcmp(string, "in") == 0) {
87531684Sminshall 	    return IN;
87631684Sminshall 	}
87731684Sminshall 	break;
87831684Sminshall     default:
87931684Sminshall 	break;
88031684Sminshall     }
88131684Sminshall     return TOKEN;
88231684Sminshall }
88331684Sminshall 
88431684Sminshall 
yylex()88531644Sminshall yylex()
88631644Sminshall {
88731644Sminshall #define	ret_token(c)	if (bufptr != buffer) { \
88831644Sminshall 			    save(c); \
88931644Sminshall 			    *bufptr = 0; \
89031644Sminshall 			    bufptr = buffer; \
89131654Sminshall 			    yylval.string = string_lookup(buffer); \
89231684Sminshall 			    return token_type(buffer); \
89331644Sminshall 			}
89431644Sminshall #define	save(c)	{ last_char = c; last_saved = 1; }
89531654Sminshall #if	defined(YYDEBUG)
89631644Sminshall #define	Return(c)	if (yydebug) { \
89731644Sminshall 			    printf("[%d]", c); \
89831644Sminshall 			    fflush(stdout); \
89931644Sminshall 			} \
90031654Sminshall 			yyval.intval = c; \
90131644Sminshall 			return c;
90231654Sminshall #else	/* defined(YYDEBUG) */
90331654Sminshall #define	Return(y,c)	{ yylval.intval = c; return y; }
90431654Sminshall #endif	/* defined(YYDEBUG) */
90531644Sminshall 
90631654Sminshall 
90731654Sminshall     static char buffer[500], *bufptr = buffer;
90831644Sminshall     static int eof_found = 0;
90931644Sminshall     int c;
91031644Sminshall 
91131644Sminshall     if (eof_found != 0) {
91231644Sminshall 	eof_found++;
91331644Sminshall 	if (eof_found > 2) {
91431644Sminshall 	    fprintf(stderr, "End of file ignored.\n");
91531644Sminshall 	    exit(1);
91631644Sminshall 	}
91731690Sminshall 	Return(EOF,0);
91831644Sminshall     }
91931644Sminshall     while ((c = Getchar()) != EOF) {
92031644Sminshall 	switch (c) {
92131644Sminshall 	case '#':
92231644Sminshall 	    ret_token(c);
92331644Sminshall 	    while (((c = Getchar()) != EOF) && (c != '\n')) {
92431644Sminshall 		;
92531644Sminshall 	    }
92631644Sminshall 	    save(c);
92731644Sminshall 	    break;
92831654Sminshall 	case '<':
92931654Sminshall 	case '?':
93031654Sminshall 	    ret_token(c);
93131654Sminshall 	    Return(MACRO_CHAR, c);
93231654Sminshall 	case '\t':
93331644Sminshall 	case ' ':
93431644Sminshall 	    ret_token(c);
93531654Sminshall 	    Return(WHITE_SPACE, c);
93631684Sminshall 	case '-':
93731684Sminshall 	case '@':
93831644Sminshall 	case ':':
93931684Sminshall 	case ';':
94031644Sminshall 	case '=':
94131654Sminshall 	case '$':
94231654Sminshall 	case '{':
94331654Sminshall 	case '}':
94431684Sminshall 	case '(':
94531684Sminshall 	case ')':
94631644Sminshall 	    ret_token(c);
94731654Sminshall 	    Return(c,c);
94831654Sminshall 	case '\'':
94931654Sminshall 	case '"':
95031764Sminshall 	    if (bufptr != buffer) {
95131764Sminshall 		if (bufptr[-1] == '\\') {
95231764Sminshall 		    bufptr[-1] = c;
95331764Sminshall 		}
95431764Sminshall 		break;
95531764Sminshall 	    } else {
95631654Sminshall 		int newc;
95731654Sminshall 
95831654Sminshall 		ret_token(c);
95931654Sminshall 		*bufptr++ = c;
96031654Sminshall 		while (((newc = Getchar()) != EOF) && (newc != c)) {
96131654Sminshall 		    *bufptr++ = newc;
96231654Sminshall 		}
96331654Sminshall 		*bufptr++ = c;
96431654Sminshall 		*bufptr = 0;
96531654Sminshall 		bufptr = buffer;
96631654Sminshall 		yylval.string = string_lookup(buffer);
96731654Sminshall 		return QUOTED_STRING;
96831654Sminshall 	    }
96931644Sminshall 	case '\n':
97031644Sminshall 	    if (bufptr != buffer) {
97131644Sminshall 		if (bufptr[-1] == '\\') {
97231644Sminshall 		    bufptr--;
97331654Sminshall 		    if ((c = Getchar()) != '\t') {
97431654Sminshall 			yyerror("continuation line doesn't begin with a tab");
97531654Sminshall 			save(c);
97631654Sminshall 		    }
97731654Sminshall 		    ret_token(c);
97831654Sminshall 		    Return(WHITE_SPACE, c);
97931644Sminshall 		}
98031644Sminshall 	    }
98131644Sminshall 	    ret_token(c);
98231654Sminshall 	    Return(NL, 0);
98331644Sminshall 	default:
98431644Sminshall 	    *bufptr++ = c;
98531644Sminshall 	    break;
98631644Sminshall 	}
98731644Sminshall     }
98831644Sminshall 
98931644Sminshall     eof_found = 1;
99031644Sminshall 
99131644Sminshall     ret_token(' ');
99231690Sminshall     Return(EOF, 0);
99331644Sminshall }
99431654Sminshall 
main()99531654Sminshall main()
99631654Sminshall {
99731654Sminshall #define	YYDEBUG
99831654Sminshall     extern int yydebug;
99931654Sminshall 
100031668Sminshall     null = same_item(string_lookup(""));
100131668Sminshall     newline = same_item(string_lookup("\n"));
100231668Sminshall     blank = same_item(string_lookup(" "));
100331711Sminshall     cwd_line = same_cat(same_copy(newline),
100431711Sminshall 			same_cat(same_item(string_lookup("cd ${CWD}")),
100531711Sminshall 				 same_copy(newline)));
100631654Sminshall 
100731692Sminshall     yyparse();
100831692Sminshall 
100931692Sminshall     do_dump();
101031711Sminshall 
101131711Sminshall     return 0;
101231654Sminshall }
101331654Sminshall 
101431654Sminshall #if	defined(YYDEBUG)
dump_same(same)101531670Sminshall dump_same(same)
101631670Sminshall same_t *same;
101731670Sminshall {
101831670Sminshall     same_t *same2;
101931670Sminshall 
102031670Sminshall     for (visit(same, same2); !visited(same2); visit_next(same2)) {
102131670Sminshall 	printf(same2->string->string);
102231670Sminshall     }
102331670Sminshall     visit_end();
102431670Sminshall }
102531692Sminshall #endif	/* YYDEBUG */
102631670Sminshall 
do_dump()102731654Sminshall do_dump()
102831654Sminshall {
102931654Sminshall     string_t *string;
103031654Sminshall     same_t *same, *same2;
103131654Sminshall 
103231654Sminshall     if (yydebug > 1) {
103331654Sminshall 	printf("strings...\n");
103431654Sminshall 	for (string = strings; string; string = string->next) {
103531654Sminshall 	    printf("\t%s\n", string->string);
103631654Sminshall 	}
103731654Sminshall     }
103831654Sminshall 
103931692Sminshall     printf("# variables...\n");
104031669Sminshall     for (visit(variables, same); !visited(same); visit_next(same)) {
104131692Sminshall 	printf("%s =\t", same->string->string);
104231668Sminshall 	for (visit(same->value_list, same2); !visited(same2);
104331668Sminshall 						visit_next(same2)) {
104431717Sminshall 	    printf(same2->string->string);
104531654Sminshall 	}
104631668Sminshall 	visit_end();
104731654Sminshall 	printf("\n");
104831654Sminshall     }
104931669Sminshall     visit_end();
105031654Sminshall 
105131728Sminshall     printf("\n\n#targets...\n");
105231669Sminshall     for (visit(targets, same); !visited(same); visit_next(same)) {
105331728Sminshall 	printf("\n%s:\t", same->string->string);
105431668Sminshall 	for (visit(same->depend_list, same2); !visited(same2);
105531668Sminshall 						visit_next(same2)) {
105631654Sminshall 	    printf(same2->string->string);
105731654Sminshall 	}
105831668Sminshall 	visit_end();
105931692Sminshall 	printf("\n\t");
106031669Sminshall 	for (visit(same->action_list, same2); !visited(same2);
106131669Sminshall 					    visit_next(same2)) {
106231669Sminshall 	    printf(same2->string->string);
106331669Sminshall 	    if (same2->string->string[0] == '\n') {
106431692Sminshall 		printf("\t");
106531654Sminshall 	    }
106631654Sminshall 	}
106731669Sminshall 	visit_end();
106831669Sminshall 	printf("\n");
106931654Sminshall     }
107031669Sminshall     visit_end();
107131654Sminshall }
1072