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