1c10df855Sminshall %{
27f36b3ebSminshall
3df35f3bcSbostic /*-
4*e50d1fc5Sbostic * Copyright (c) 1988, 1993
5*e50d1fc5Sbostic * The Regents of the University of California. All rights reserved.
67f36b3ebSminshall *
7df35f3bcSbostic * %sccs.include.redist.c%
87f36b3ebSminshall */
97f36b3ebSminshall
10df35f3bcSbostic #ifndef lint
11*e50d1fc5Sbostic static char sccsid[] = "@(#)mkmake.y 8.1 (Berkeley) 06/06/93";
12df35f3bcSbostic #endif /* not lint */
13df35f3bcSbostic
14c10df855Sminshall typedef struct string {
15c10df855Sminshall int
16c10df855Sminshall hashval,
17c10df855Sminshall length;
18c10df855Sminshall char
19c10df855Sminshall *string;
20c10df855Sminshall struct string
21c10df855Sminshall *next;
22c10df855Sminshall } string_t;
23c10df855Sminshall
2484402bf5Sminshall /*
2584402bf5Sminshall * The deal with these is that they exist on various lists.
2684402bf5Sminshall *
2784402bf5Sminshall * First off, they are on a temporary list during the time they
2884402bf5Sminshall * are in the active focus of the parser.
2984402bf5Sminshall *
3084402bf5Sminshall * Secondly, they live on one of three queues:
3184402bf5Sminshall * 1. Variables
3284402bf5Sminshall * 2. Targets
3384402bf5Sminshall * 3. Actions
3484402bf5Sminshall * (and, we restrict any given one to live on one and only one such list)
3584402bf5Sminshall *
3684402bf5Sminshall * Also, they may live on the list of values for someone else's variable,
3784402bf5Sminshall * or as someone's dependancy.
3884402bf5Sminshall */
3984402bf5Sminshall
40c10df855Sminshall typedef struct same {
41c10df855Sminshall string_t
4284402bf5Sminshall *string; /* My name */
4384402bf5Sminshall struct same
4484402bf5Sminshall *nexttoken, /* Next pointer */
4584402bf5Sminshall *lasttoken, /* Back pointer */
4684402bf5Sminshall *depend_list, /* If target, dependancies */
4784402bf5Sminshall *action_list, /* If target, actions */
48bbfe3fc0Sminshall *value_list, /* If variable, value list */
49bbfe3fc0Sminshall *shell_item; /* If a shell variable, current value */
50c10df855Sminshall } same_t;
51c10df855Sminshall
52c10df855Sminshall %}
53c10df855Sminshall
54c10df855Sminshall %union {
55c10df855Sminshall string_t *string;
56c10df855Sminshall same_t *same;
5784402bf5Sminshall int intval;
58c10df855Sminshall }
59c10df855Sminshall
604788ac1fSminshall %start makefile
6184402bf5Sminshall %token <string> TOKEN QUOTED_STRING
62bbfe3fc0Sminshall %token <intval> FOR IN DO DONE
63bbfe3fc0Sminshall %token <intval> MACRO_CHAR NL WHITE_SPACE
64bbfe3fc0Sminshall %token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
65d70f92ebSminshall %type <same> target target1 assignment assign1 actions action
66f53f6b88Sminshall %type <same> command_list list list_element
67bc7371f7Sminshall %type <same> for_statement maybe_at_minus tokens token
68d70f92ebSminshall %type <same> maybe_white_space
69bbfe3fc0Sminshall %type <intval> white_space macro_char
70c10df855Sminshall %%
7184402bf5Sminshall
72bbfe3fc0Sminshall makefile : lines;
73c10df855Sminshall
74c10df855Sminshall lines : line
75c10df855Sminshall | lines line
76c10df855Sminshall ;
77c10df855Sminshall
78bbfe3fc0Sminshall line : NL
7984402bf5Sminshall | assignment
8084402bf5Sminshall | target_action
81c10df855Sminshall ;
82c10df855Sminshall
83f53f6b88Sminshall assignment : assign1 tokens NL
84c10df855Sminshall {
85bbfe3fc0Sminshall assign($1, $2);
8684402bf5Sminshall }
87bbfe3fc0Sminshall | assign1 NL
8884402bf5Sminshall {
89953a4c02Sminshall assign($1, same_copy(null));
90c10df855Sminshall }
91c10df855Sminshall ;
92c10df855Sminshall
934ffc2a5cSminshall assign1: token maybe_white_space '=' maybe_white_space
94bbfe3fc0Sminshall ;
95bbfe3fc0Sminshall
9684402bf5Sminshall target_action: target actions
97c10df855Sminshall {
9884402bf5Sminshall add_targets_actions($1, $2);
9984402bf5Sminshall }
10084402bf5Sminshall | target
10184402bf5Sminshall {
102bc7371f7Sminshall add_targets_actions($1, 0);
10384402bf5Sminshall }
10484402bf5Sminshall ;
10584402bf5Sminshall
106f53f6b88Sminshall target : target1 tokens NL
10784402bf5Sminshall {
108d70f92ebSminshall $$ = add_depends($1, $2);
10984402bf5Sminshall }
110d70f92ebSminshall | target1 NL
111d70f92ebSminshall {
112d70f92ebSminshall $$ = add_depends($1, same_copy(null));
113d70f92ebSminshall }
114d70f92ebSminshall ;
115d70f92ebSminshall
116d70f92ebSminshall target1: tokens maybe_white_space ':' maybe_white_space
117bc7371f7Sminshall {
118bc7371f7Sminshall $$ = ws_merge($1);
119bc7371f7Sminshall }
120c10df855Sminshall ;
121c10df855Sminshall
122c10df855Sminshall actions: action
123c10df855Sminshall | actions action
124c10df855Sminshall {
125f53f6b88Sminshall $$ = same_cat(same_cat($1, same_copy(newline)), $2);
126c10df855Sminshall }
127c10df855Sminshall ;
128c10df855Sminshall
129bbfe3fc0Sminshall action: white_space command_list NL
130c10df855Sminshall {
131c10df855Sminshall $$ = $2;
132c10df855Sminshall }
133bbfe3fc0Sminshall | white_space for_statement do command_list semi_colon done NL
1347fe218f1Sminshall {
135486c8420Sminshall $$ = do_command($2, $4);
1367fe218f1Sminshall }
137c10df855Sminshall ;
138c10df855Sminshall
139d70f92ebSminshall for_statement: maybe_at_minus FOR white_space token
140bc7371f7Sminshall in tokens semi_colon
1417fe218f1Sminshall {
142e334f66eSminshall $$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
143bbfe3fc0Sminshall }
144bbfe3fc0Sminshall ;
145bbfe3fc0Sminshall
146d70f92ebSminshall in: white_space IN white_space
147bbfe3fc0Sminshall do: white_space DO white_space
148bbfe3fc0Sminshall ;
149bbfe3fc0Sminshall
150bbfe3fc0Sminshall done: white_space DONE
151bbfe3fc0Sminshall ;
152bbfe3fc0Sminshall
153d70f92ebSminshall semi_colon: ';'
154bbfe3fc0Sminshall ;
155bbfe3fc0Sminshall
156bbfe3fc0Sminshall command_list: list
157bbfe3fc0Sminshall | '(' list maybe_white_space ')'
158bbfe3fc0Sminshall {
1594ffc2a5cSminshall $$ = same_cat($2, same_copy(cwd_line));
160bbfe3fc0Sminshall }
161bbfe3fc0Sminshall ;
162bbfe3fc0Sminshall
163f53f6b88Sminshall list: token
164f53f6b88Sminshall | list list_element
165bbfe3fc0Sminshall {
166f53f6b88Sminshall $$ = same_cat($1, $2);
167f53f6b88Sminshall }
168f53f6b88Sminshall | list white_space list_element
169f53f6b88Sminshall {
170f53f6b88Sminshall $$ = same_cat($1, same_cat(same_copy(blank), $3));
171bbfe3fc0Sminshall }
172bbfe3fc0Sminshall ;
173bbfe3fc0Sminshall
174f53f6b88Sminshall list_element: token
175f53f6b88Sminshall | semi_colon
176f53f6b88Sminshall {
177f53f6b88Sminshall $$ = same_copy(newline);
178f53f6b88Sminshall }
1797fe218f1Sminshall ;
1807fe218f1Sminshall
1817fe218f1Sminshall maybe_at_minus: /* empty */
1827fe218f1Sminshall {
1837fe218f1Sminshall $$ = same_copy(null);
1847fe218f1Sminshall }
1857fe218f1Sminshall | '@'
1867fe218f1Sminshall {
1877fe218f1Sminshall char buffer[2];
1887fe218f1Sminshall
1897fe218f1Sminshall buffer[0] = $1;
1907fe218f1Sminshall buffer[1] = 0;
1917fe218f1Sminshall $$ = same_item(string_lookup(buffer));
1927fe218f1Sminshall }
1937fe218f1Sminshall | '-'
1947fe218f1Sminshall {
1957fe218f1Sminshall char buffer[2];
1967fe218f1Sminshall
1977fe218f1Sminshall buffer[0] = $1;
1987fe218f1Sminshall buffer[1] = 0;
1997fe218f1Sminshall $$ = same_item(string_lookup(buffer));
2007fe218f1Sminshall }
2017fe218f1Sminshall ;
202bbfe3fc0Sminshall
203c10df855Sminshall tokens : token
204d70f92ebSminshall | tokens maybe_white_space token
205c10df855Sminshall {
206d70f92ebSminshall $$ = same_cat($1, same_cat($2, $3));
207c10df855Sminshall }
208c10df855Sminshall ;
20984402bf5Sminshall
210d70f92ebSminshall token: TOKEN
211c10df855Sminshall {
21284402bf5Sminshall $$ = same_item($1);
21384402bf5Sminshall }
21484402bf5Sminshall | QUOTED_STRING
21584402bf5Sminshall {
21684402bf5Sminshall $$ = same_item($1);
21784402bf5Sminshall }
21884402bf5Sminshall | '$' macro_char
21984402bf5Sminshall {
22084402bf5Sminshall char buffer[3];
22184402bf5Sminshall
22284402bf5Sminshall buffer[0] = '$';
22384402bf5Sminshall buffer[1] = $2;
22484402bf5Sminshall buffer[2] = 0;
22584402bf5Sminshall
22684402bf5Sminshall $$ = same_item(string_lookup(buffer));
22784402bf5Sminshall }
228bc7371f7Sminshall | '$' '$' TOKEN
22984402bf5Sminshall {
230bc7371f7Sminshall $$ = shell_variable(same_item($3));
23184402bf5Sminshall }
232bbfe3fc0Sminshall | MACRO_CHAR
233bbfe3fc0Sminshall {
234bbfe3fc0Sminshall $$ = same_char($1);
235bbfe3fc0Sminshall }
236bc7371f7Sminshall | '$' '{' TOKEN '}'
23784402bf5Sminshall {
238bc7371f7Sminshall $$ = variable(same_item($3));
239bc7371f7Sminshall }
240bc7371f7Sminshall | '$' '(' TOKEN ')'
241bc7371f7Sminshall {
242bc7371f7Sminshall $$ = variable(same_item($3));
243bc7371f7Sminshall }
244bc7371f7Sminshall | '$' TOKEN
245bc7371f7Sminshall {
246bc7371f7Sminshall $$ = variable(same_item($2));
247c10df855Sminshall }
2487fe218f1Sminshall | '-'
2497fe218f1Sminshall {
2507fe218f1Sminshall $$ = same_char('-');
2517fe218f1Sminshall }
2527fe218f1Sminshall | '@'
2537fe218f1Sminshall {
2547fe218f1Sminshall $$ = same_char('@');
2557fe218f1Sminshall }
256c10df855Sminshall ;
25784402bf5Sminshall
25884402bf5Sminshall macro_char: MACRO_CHAR
259bbfe3fc0Sminshall | '@'
26084402bf5Sminshall ;
26184402bf5Sminshall
26284402bf5Sminshall maybe_white_space:
263d70f92ebSminshall {
264d70f92ebSminshall $$ = same_copy(null);
265d70f92ebSminshall }
266d70f92ebSminshall | white_space
267d70f92ebSminshall {
268d70f92ebSminshall $$ = same_char($1);
269d70f92ebSminshall }
270d70f92ebSminshall ;
27184402bf5Sminshall
27284402bf5Sminshall white_space : WHITE_SPACE
27384402bf5Sminshall | white_space WHITE_SPACE
27484402bf5Sminshall ;
275c10df855Sminshall %%
276c10df855Sminshall #include <stdio.h>
277bc7371f7Sminshall #include <ctype.h>
278c10df855Sminshall
279c10df855Sminshall static int last_char, last_saved = 0;
280c10df855Sminshall static int column = 0, lineno = 1;
281c10df855Sminshall
282c10df855Sminshall
28384402bf5Sminshall static string_t
28484402bf5Sminshall *strings = 0;
285bbfe3fc0Sminshall
286c10df855Sminshall static same_t
287bbfe3fc0Sminshall *shell_variables = 0,
288bbfe3fc0Sminshall *shell_special = 0,
289ff189d06Sminshall *variables = 0,
290ff189d06Sminshall *targets = 0,
291ff189d06Sminshall *actions = 0;
29284402bf5Sminshall
29384402bf5Sminshall static same_t
294953a4c02Sminshall *null,
295953a4c02Sminshall *blank,
2964ffc2a5cSminshall *cwd_line,
297953a4c02Sminshall *newline;
298c10df855Sminshall
299c10df855Sminshall extern char *malloc();
300c10df855Sminshall
301953a4c02Sminshall static unsigned int
302953a4c02Sminshall clock = -1;
303953a4c02Sminshall
304953a4c02Sminshall struct {
305953a4c02Sminshall same_t *first;
306953a4c02Sminshall int next;
307953a4c02Sminshall } visit_stack[20]; /* 20 maximum */
308953a4c02Sminshall
309953a4c02Sminshall #define visit(what,via) \
310953a4c02Sminshall (visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
3114788ac1fSminshall #define visited(via) (visitcheck(via) || ((via) == 0) \
312ff189d06Sminshall || (visit_stack[clock].next && (via == visit_stack[clock].first)))
313953a4c02Sminshall #define visit_next(via) (visit_stack[clock].next = 1, (via) = (via)->nexttoken)
314953a4c02Sminshall #define visit_end() (clock--)
315953a4c02Sminshall
yyerror(s)316c10df855Sminshall yyerror(s)
317c10df855Sminshall char *s;
318c10df855Sminshall {
31984402bf5Sminshall fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
32084402bf5Sminshall do_dump();
321c10df855Sminshall }
322c10df855Sminshall
32384402bf5Sminshall int
visitcheck(same)3244788ac1fSminshall visitcheck(same)
3254788ac1fSminshall same_t *same;
3264788ac1fSminshall {
3274788ac1fSminshall if (same->string == 0) {
3284788ac1fSminshall yyerror("BUG - freed 'same' in use...");
3294788ac1fSminshall exit(1);
3304788ac1fSminshall }
3314788ac1fSminshall return 0;
3324788ac1fSminshall }
3334788ac1fSminshall
3344788ac1fSminshall int
string_hashof(string,length)33584402bf5Sminshall string_hashof(string, length)
33684402bf5Sminshall char *string;
33784402bf5Sminshall int length;
338c10df855Sminshall {
33984402bf5Sminshall register int i = 0;
34084402bf5Sminshall
34184402bf5Sminshall while (length--) {
34284402bf5Sminshall i = (i<<3) + *string ^ ((i>>28)&0x7);
34384402bf5Sminshall }
34484402bf5Sminshall return i;
345c10df855Sminshall }
346c10df855Sminshall
34784402bf5Sminshall int
string_same(s1,s2)34884402bf5Sminshall string_same(s1, s2)
34984402bf5Sminshall string_t
35084402bf5Sminshall *s1, *s2;
351c10df855Sminshall {
35284402bf5Sminshall if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
35384402bf5Sminshall && (memcmp(s1->string, s2->string, s1->length) == 0)) {
35484402bf5Sminshall return 1;
35584402bf5Sminshall } else {
35684402bf5Sminshall return 0;
35784402bf5Sminshall }
358c10df855Sminshall }
359c10df855Sminshall
36084402bf5Sminshall string_t *
string_lookup(string)36184402bf5Sminshall string_lookup(string)
36284402bf5Sminshall char *string;
36384402bf5Sminshall {
36484402bf5Sminshall string_t ours;
36584402bf5Sminshall string_t *ptr;
36684402bf5Sminshall
36784402bf5Sminshall ours.length = strlen(string);
36884402bf5Sminshall ours.hashval = string_hashof(string, ours.length);
36984402bf5Sminshall ours.string = string;
37084402bf5Sminshall
37184402bf5Sminshall for (ptr = strings; ptr; ptr = ptr->next) {
37284402bf5Sminshall if (string_same(&ours, ptr)) {
37384402bf5Sminshall return ptr;
37484402bf5Sminshall }
37584402bf5Sminshall }
37684402bf5Sminshall if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
37784402bf5Sminshall fprintf(stderr, "No space to add string *%s*!\n", string);
37884402bf5Sminshall exit(1);
37984402bf5Sminshall }
38084402bf5Sminshall ptr->hashval = ours.hashval;
38184402bf5Sminshall ptr->length = ours.length;
38284402bf5Sminshall if ((ptr->string = malloc(ours.length+1)) == 0) {
38384402bf5Sminshall fprintf(stderr, "No space to add literal *%s*!\n", string);
38484402bf5Sminshall exit(1);
38584402bf5Sminshall }
38684402bf5Sminshall memcpy(ptr->string, string, ours.length+1);
38784402bf5Sminshall ptr->next = strings;
38884402bf5Sminshall strings = ptr;
38984402bf5Sminshall return ptr;
39084402bf5Sminshall }
391c10df855Sminshall
392bc7371f7Sminshall #define same_singleton(s) ((s)->nexttoken == (s))
393bc7371f7Sminshall
394c10df855Sminshall same_t *
same_search(list,token)39584402bf5Sminshall same_search(list, token)
396c10df855Sminshall same_t
39784402bf5Sminshall *list,
398c10df855Sminshall *token;
399c10df855Sminshall {
400c10df855Sminshall same_t *ptr;
401c10df855Sminshall
402953a4c02Sminshall ptr = list;
403953a4c02Sminshall for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
40484402bf5Sminshall string_t *string;
40584402bf5Sminshall
40684402bf5Sminshall string = ptr->string;
40784402bf5Sminshall if (string_same(string, token->string)) {
408953a4c02Sminshall visit_end();
40984402bf5Sminshall return ptr;
410c10df855Sminshall }
411c10df855Sminshall }
412953a4c02Sminshall visit_end();
41384402bf5Sminshall return 0;
414c10df855Sminshall }
415c10df855Sminshall
416c10df855Sminshall same_t *
same_cat(list,tokens)41784402bf5Sminshall same_cat(list, tokens)
41884402bf5Sminshall same_t
41984402bf5Sminshall *list,
42084402bf5Sminshall *tokens;
42184402bf5Sminshall {
42284402bf5Sminshall same_t *last;
42384402bf5Sminshall
424bbfe3fc0Sminshall if (tokens == 0) {
425bbfe3fc0Sminshall return list;
426bbfe3fc0Sminshall }
427ff189d06Sminshall if (list) {
42884402bf5Sminshall last = tokens->lasttoken;
42984402bf5Sminshall tokens->lasttoken = list->lasttoken;
43084402bf5Sminshall list->lasttoken = last;
43184402bf5Sminshall tokens->lasttoken->nexttoken = tokens;
432953a4c02Sminshall last->nexttoken = list;
43384402bf5Sminshall return list;
434ff189d06Sminshall } else {
435ff189d06Sminshall return tokens;
436ff189d06Sminshall }
43784402bf5Sminshall }
43884402bf5Sminshall
43984402bf5Sminshall same_t *
same_item(string)44084402bf5Sminshall same_item(string)
441c10df855Sminshall string_t *string;
442c10df855Sminshall {
443c10df855Sminshall same_t *ptr;
444c10df855Sminshall
445c10df855Sminshall if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) {
446c10df855Sminshall fprintf(stderr, "No more space for tokens!\n");
447c10df855Sminshall exit(1);
448c10df855Sminshall }
44984402bf5Sminshall memset((char *)ptr, 0, sizeof *ptr);
450953a4c02Sminshall ptr->nexttoken = ptr->lasttoken = ptr;
451c10df855Sminshall ptr->string = string;
452c10df855Sminshall return ptr;
453c10df855Sminshall }
454c10df855Sminshall
45584402bf5Sminshall same_t *
same_copy(same)45684402bf5Sminshall same_copy(same)
45784402bf5Sminshall same_t *same;
45884402bf5Sminshall {
459953a4c02Sminshall same_t *head, *copy;
46084402bf5Sminshall
461ff189d06Sminshall head = 0;
462ff189d06Sminshall for (visit(same, copy); !visited(copy); visit_next(copy)) {
46384402bf5Sminshall same_t *ptr;
46484402bf5Sminshall
465953a4c02Sminshall ptr = same_item(copy->string);
466ff189d06Sminshall head = same_cat(head, ptr);
46784402bf5Sminshall }
468ff189d06Sminshall visit_end();
46984402bf5Sminshall return head;
47084402bf5Sminshall }
47184402bf5Sminshall
472bc7371f7Sminshall
473bc7371f7Sminshall same_t *
same_merge(t1,t2)474bc7371f7Sminshall same_merge(t1, t2)
475bc7371f7Sminshall same_t
476bc7371f7Sminshall *t1,
477bc7371f7Sminshall *t2;
478bc7371f7Sminshall {
479bc7371f7Sminshall if (same_singleton(t1) && same_singleton(t2)) {
480bc7371f7Sminshall int length = strlen(t1->string->string)+strlen(t2->string->string);
481bc7371f7Sminshall char *buffer = malloc(length+1);
482bc7371f7Sminshall same_t *value;
483bc7371f7Sminshall
484bc7371f7Sminshall if (buffer == 0) {
485bc7371f7Sminshall yyerror("No space to merge strings in same_merge!");
486bc7371f7Sminshall exit(1);
487bc7371f7Sminshall }
488bc7371f7Sminshall strcpy(buffer, t1->string->string);
489bc7371f7Sminshall strcat(buffer, t2->string->string);
490bc7371f7Sminshall value = same_item(string_lookup(buffer));
491bc7371f7Sminshall free(buffer);
492bc7371f7Sminshall return value;
493bc7371f7Sminshall } else {
494bc7371f7Sminshall yyerror("Internal error - same_merge with non-singletons");
495bc7371f7Sminshall exit(1);
496bc7371f7Sminshall }
497bc7371f7Sminshall }
498bc7371f7Sminshall
499bc7371f7Sminshall
50084402bf5Sminshall void
same_free(list)501953a4c02Sminshall same_free(list)
502953a4c02Sminshall same_t *list;
50384402bf5Sminshall {
504953a4c02Sminshall same_t *token, *ptr;
50584402bf5Sminshall
506bc7371f7Sminshall if (list == 0) {
507bc7371f7Sminshall return;
508bc7371f7Sminshall }
509bc7371f7Sminshall
510953a4c02Sminshall token = list;
511953a4c02Sminshall do {
51284402bf5Sminshall ptr = token->nexttoken;
5134788ac1fSminshall token->string = 0;
51484402bf5Sminshall (void) free((char *)token);
51584402bf5Sminshall token = ptr;
516953a4c02Sminshall } while (token != list);
51784402bf5Sminshall }
51884402bf5Sminshall
5197fe218f1Sminshall same_t *
same_unlink(token)520953a4c02Sminshall same_unlink(token)
52184402bf5Sminshall same_t
522953a4c02Sminshall *token;
52384402bf5Sminshall {
5247fe218f1Sminshall same_t *tmp;
5257fe218f1Sminshall
526ff189d06Sminshall if (token == 0) {
5277fe218f1Sminshall return 0;
5287fe218f1Sminshall }
5297fe218f1Sminshall if ((tmp = token->nexttoken) == token) {
5307fe218f1Sminshall tmp = 0;
531ff189d06Sminshall }
53284402bf5Sminshall token->lasttoken->nexttoken = token->nexttoken;
53384402bf5Sminshall token->nexttoken->lasttoken = token->lasttoken;
534ff189d06Sminshall token->nexttoken = token->lasttoken = token;
5357fe218f1Sminshall return tmp;
5367fe218f1Sminshall }
5377fe218f1Sminshall
5384ffc2a5cSminshall void
same_replace(old,new)5394ffc2a5cSminshall same_replace(old, new)
5404ffc2a5cSminshall same_t
5414ffc2a5cSminshall *old,
5424ffc2a5cSminshall *new;
5434ffc2a5cSminshall {
5444ffc2a5cSminshall new->lasttoken->nexttoken = old->nexttoken;
5454ffc2a5cSminshall old->nexttoken->lasttoken = new->lasttoken;
5464ffc2a5cSminshall new->lasttoken = old->lasttoken;
5474ffc2a5cSminshall /* rather than
5484ffc2a5cSminshall * old->lasttoken->nexttoken = new
5494ffc2a5cSminshall * we update in place (for the case where there isn't anything else)
5504ffc2a5cSminshall */
5514ffc2a5cSminshall *old = *new;
5524ffc2a5cSminshall }
5534ffc2a5cSminshall
5544ffc2a5cSminshall
5557fe218f1Sminshall same_t *
same_char(ch)5567fe218f1Sminshall same_char(ch)
5577fe218f1Sminshall char ch;
5587fe218f1Sminshall {
5597fe218f1Sminshall char buffer[2];
5607fe218f1Sminshall
5617fe218f1Sminshall buffer[0] = ch;
5627fe218f1Sminshall buffer[1] = 0;
5637fe218f1Sminshall
5647fe218f1Sminshall return same_item(string_lookup(buffer));
56584402bf5Sminshall }
56684402bf5Sminshall
5674ffc2a5cSminshall
568bc7371f7Sminshall void
add_target(target,actions)569bc7371f7Sminshall add_target(target, actions)
57084402bf5Sminshall same_t
571bc7371f7Sminshall *target,
572bc7371f7Sminshall *actions;
57384402bf5Sminshall {
57484402bf5Sminshall same_t *ptr;
57584402bf5Sminshall
576953a4c02Sminshall if ((ptr = same_search(targets, target)) == 0) {
577ff189d06Sminshall targets = same_cat(targets, target);
578bc7371f7Sminshall ptr = target;
57984402bf5Sminshall } else {
580ff189d06Sminshall ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
581bc7371f7Sminshall }
582bc7371f7Sminshall if (actions) {
583bc7371f7Sminshall if (ptr->action_list) {
584bc7371f7Sminshall same_free(ptr->action_list);
585bc7371f7Sminshall }
586bc7371f7Sminshall ptr->action_list = same_copy(actions);
58784402bf5Sminshall }
58884402bf5Sminshall }
58984402bf5Sminshall
5904ffc2a5cSminshall
59184402bf5Sminshall same_t *
add_targets_actions(target,actions)59284402bf5Sminshall add_targets_actions(target, actions)
59384402bf5Sminshall same_t
59484402bf5Sminshall *target,
59584402bf5Sminshall *actions;
59684402bf5Sminshall {
5974788ac1fSminshall same_t *ptr;
59884402bf5Sminshall
599ff189d06Sminshall if (target == 0) {
600ff189d06Sminshall return 0;
60184402bf5Sminshall }
602ff189d06Sminshall do {
6037fe218f1Sminshall ptr = same_unlink(target);
604bc7371f7Sminshall add_target(target, actions);
605ff189d06Sminshall target = ptr;
6064788ac1fSminshall } while (target);
607ff189d06Sminshall
608ff189d06Sminshall same_free(actions);
60984402bf5Sminshall return 0;
61084402bf5Sminshall }
61184402bf5Sminshall
61284402bf5Sminshall same_t *
add_depends(target,depends)61384402bf5Sminshall add_depends(target, depends)
61484402bf5Sminshall same_t
61584402bf5Sminshall *target,
61684402bf5Sminshall *depends;
61784402bf5Sminshall {
61884402bf5Sminshall same_t *original = target;
61984402bf5Sminshall
620ff189d06Sminshall depends = same_cat(depends, same_copy(blank)); /* Separator */
62184402bf5Sminshall
622953a4c02Sminshall for (visit(original, target); !visited(target); visit_next(target)) {
623ff189d06Sminshall target->depend_list = same_cat(target->depend_list, same_copy(depends));
624953a4c02Sminshall }
625953a4c02Sminshall visit_end();
626ff189d06Sminshall same_free(depends);
627953a4c02Sminshall
62884402bf5Sminshall return original;
62984402bf5Sminshall }
63084402bf5Sminshall
63184402bf5Sminshall
63284402bf5Sminshall /*
63384402bf5Sminshall * We know that variable is a singleton
63484402bf5Sminshall */
63584402bf5Sminshall
63684402bf5Sminshall void
assign(variable,value)63784402bf5Sminshall assign(variable, value)
63884402bf5Sminshall same_t
63984402bf5Sminshall *variable,
64084402bf5Sminshall *value;
64184402bf5Sminshall {
64284402bf5Sminshall same_t *ptr;
64384402bf5Sminshall
644953a4c02Sminshall if ((ptr = same_search(variables, variable)) != 0) {
64584402bf5Sminshall same_free(ptr->value_list);
646bc7371f7Sminshall variables = same_unlink(ptr);
647ff189d06Sminshall same_free(ptr);
64884402bf5Sminshall }
64984402bf5Sminshall variable->value_list = value;
650ff189d06Sminshall variables = same_cat(variables, variable);
65184402bf5Sminshall }
65284402bf5Sminshall
65384402bf5Sminshall same_t *
value_of(variable)65484402bf5Sminshall value_of(variable)
65584402bf5Sminshall same_t *variable;
65684402bf5Sminshall {
657953a4c02Sminshall same_t *ptr = same_search(variables, variable);
65884402bf5Sminshall
65984402bf5Sminshall if (ptr == 0) {
660ff189d06Sminshall return same_copy(null);
66184402bf5Sminshall } else {
662ff189d06Sminshall return same_copy(ptr->value_list);
66384402bf5Sminshall }
66484402bf5Sminshall }
66584402bf5Sminshall
6667fe218f1Sminshall
6677fe218f1Sminshall same_t *
expand_variables(token,free)6687fe218f1Sminshall expand_variables(token, free)
6697fe218f1Sminshall same_t *token;
6707fe218f1Sminshall int free;
6717fe218f1Sminshall {
6727fe218f1Sminshall same_t *head = 0;
6737fe218f1Sminshall
6747fe218f1Sminshall if (!free) {
6757fe218f1Sminshall token = same_copy(token); /* Get our private copy */
6767fe218f1Sminshall }
6777fe218f1Sminshall
6787fe218f1Sminshall while (token) {
6797fe218f1Sminshall char *string = token->string->string;
6807fe218f1Sminshall same_t *tmp = same_unlink(token);
6817fe218f1Sminshall
682e334f66eSminshall if ((string[0] == '$') && (string[1] == '{')) { /* Expand time */
6837fe218f1Sminshall int len = strlen(string);
6847fe218f1Sminshall
6857fe218f1Sminshall string[len-1] = 0;
6867fe218f1Sminshall head = same_cat(head, expand_variables(
6877fe218f1Sminshall value_of(same_item(string_lookup(string+2))), 1));
6887fe218f1Sminshall string[len-1] = '}';
689e334f66eSminshall } else {
6907fe218f1Sminshall head = same_cat(head, token);
6917fe218f1Sminshall }
6927fe218f1Sminshall token = tmp;
6937fe218f1Sminshall }
6947fe218f1Sminshall return head;
6957fe218f1Sminshall }
6967fe218f1Sminshall
697bc7371f7Sminshall
698bc7371f7Sminshall same_t *
ws_merge(list)699bc7371f7Sminshall ws_merge(list)
700bc7371f7Sminshall same_t *list;
701bc7371f7Sminshall {
702bc7371f7Sminshall same_t *newlist = 0, *item;
703bc7371f7Sminshall int what = 0;
704bc7371f7Sminshall
705bc7371f7Sminshall while (list) {
706bc7371f7Sminshall switch (what) {
707bc7371f7Sminshall case 0:
708bc7371f7Sminshall if (isspace(list->string->string[0])) {
709bc7371f7Sminshall ;
710bc7371f7Sminshall } else {
711bc7371f7Sminshall item = same_item(list->string);
712bc7371f7Sminshall what = 1;
713bc7371f7Sminshall }
714bc7371f7Sminshall break;
715bc7371f7Sminshall case 1:
716bc7371f7Sminshall if (isspace(list->string->string[0])) {
717bc7371f7Sminshall newlist = same_cat(newlist, item);
718bc7371f7Sminshall item = 0;
719bc7371f7Sminshall what = 0;
720bc7371f7Sminshall } else {
721bc7371f7Sminshall item = same_merge(item, same_item(list->string));
722bc7371f7Sminshall what = 1;
723bc7371f7Sminshall }
724bc7371f7Sminshall break;
725bc7371f7Sminshall }
726bc7371f7Sminshall list = same_unlink(list);
727bc7371f7Sminshall }
728bc7371f7Sminshall return same_cat(newlist, item);
729bc7371f7Sminshall }
730bc7371f7Sminshall
731bc7371f7Sminshall
732c4695814Sminshall same_t *
variable(var_name)733c4695814Sminshall variable(var_name)
734c4695814Sminshall same_t *var_name;
735c4695814Sminshall {
736c4695814Sminshall int length = strlen(var_name->string->string);
737c4695814Sminshall same_t *resolved;
738c4695814Sminshall char *newname;
739c4695814Sminshall
740c4695814Sminshall if ((newname = malloc(length+1+3)) == 0) {
741c4695814Sminshall fprintf("Out of space for a variable name.\n");
742c4695814Sminshall exit(1);
743c4695814Sminshall }
744c4695814Sminshall newname[0] = '$';
745c4695814Sminshall newname[1] = '{';
746c4695814Sminshall strcpy(newname+2, var_name->string->string);
747c4695814Sminshall strcat(newname, "}");
748c4695814Sminshall resolved = same_item(string_lookup(newname));
749c4695814Sminshall free(newname);
750c4695814Sminshall
751c4695814Sminshall return resolved;
752c4695814Sminshall }
753c4695814Sminshall
754bbfe3fc0Sminshall
7557fe218f1Sminshall same_t *
shell_variable(var_name)756486c8420Sminshall shell_variable(var_name)
757486c8420Sminshall same_t *var_name;
758bbfe3fc0Sminshall {
759486c8420Sminshall int length = strlen(var_name->string->string);
760486c8420Sminshall same_t *resolved;
761486c8420Sminshall char *newname;
762bbfe3fc0Sminshall
763486c8420Sminshall if ((newname = malloc(length+1+2)) == 0) {
764486c8420Sminshall fprintf("Out of space for a variable name.\n");
765bbfe3fc0Sminshall exit(1);
766bbfe3fc0Sminshall }
767486c8420Sminshall newname[0] = '$';
768486c8420Sminshall newname[1] = '$';
769486c8420Sminshall strcpy(newname+2, var_name->string->string);
770486c8420Sminshall resolved = same_item(string_lookup(newname));
771486c8420Sminshall free(newname);
772486c8420Sminshall
773486c8420Sminshall return resolved;
774bbfe3fc0Sminshall }
775bbfe3fc0Sminshall
776bbfe3fc0Sminshall same_t *
for_statement(special,variable,list)777bbfe3fc0Sminshall for_statement(special, variable, list)
7787fe218f1Sminshall same_t
7797fe218f1Sminshall *special,
7807fe218f1Sminshall *variable,
781bbfe3fc0Sminshall *list;
7827fe218f1Sminshall {
783486c8420Sminshall variable->shell_item = special;
784bbfe3fc0Sminshall variable->value_list = list;
785486c8420Sminshall return variable;
786486c8420Sminshall }
787486c8420Sminshall
788486c8420Sminshall same_t *
do_command(forlist,commands)789486c8420Sminshall do_command(forlist, commands)
790486c8420Sminshall same_t
791486c8420Sminshall *forlist,
792486c8420Sminshall *commands;
793486c8420Sminshall {
7944ffc2a5cSminshall same_t
7954ffc2a5cSminshall *special,
7964ffc2a5cSminshall *command_list = 0,
7974ffc2a5cSminshall *new_commands,
7984ffc2a5cSminshall *tmp,
7994ffc2a5cSminshall *shell_item,
8004ffc2a5cSminshall *value_list = forlist->value_list;
8014ffc2a5cSminshall char
8024ffc2a5cSminshall *tmpstr,
8034ffc2a5cSminshall *variable_name = forlist->string->string;
8044ffc2a5cSminshall
8054ffc2a5cSminshall special = forlist->shell_item;
8064ffc2a5cSminshall if (same_unlink(forlist->shell_item) != 0) {
8074ffc2a5cSminshall yyerror("Unexpected second item in special part of do_command");
8084ffc2a5cSminshall exit(1);
8094ffc2a5cSminshall }
8104ffc2a5cSminshall
8114ffc2a5cSminshall while ((shell_item = value_list) != 0) {
8124ffc2a5cSminshall value_list = same_unlink(shell_item);
8134ffc2a5cSminshall /* Visit each item in commands. For each shell variable which
8144ffc2a5cSminshall * matches ours, replace it with ours.
8154ffc2a5cSminshall */
8164ffc2a5cSminshall new_commands = same_copy(commands);
8174ffc2a5cSminshall for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
8184ffc2a5cSminshall tmpstr = tmp->string->string;
8194ffc2a5cSminshall if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
8204ffc2a5cSminshall if (strcmp(tmpstr+2, variable_name) == 0) {
8214ffc2a5cSminshall same_replace(tmp, same_copy(shell_item));
8224ffc2a5cSminshall }
8234ffc2a5cSminshall }
8244ffc2a5cSminshall }
8254ffc2a5cSminshall visit_end();
8264ffc2a5cSminshall command_list = same_cat(command_list, new_commands);
8274ffc2a5cSminshall }
8284ffc2a5cSminshall return same_cat(command_list, same_copy(newline));
8297fe218f1Sminshall }
8307fe218f1Sminshall
83184402bf5Sminshall
832c10df855Sminshall int
Getchar()833c10df855Sminshall Getchar()
834c10df855Sminshall {
835c10df855Sminshall if (last_saved) {
836c10df855Sminshall last_saved = 0;
837c10df855Sminshall return last_char;
838c10df855Sminshall } else {
839c10df855Sminshall int c;
840c10df855Sminshall c = getchar();
841c10df855Sminshall switch (c) {
842c10df855Sminshall case '\n':
843c10df855Sminshall lineno++;
844c10df855Sminshall column = 0;
845c10df855Sminshall break;
846c10df855Sminshall default:
847c10df855Sminshall column++;
848c10df855Sminshall }
849c10df855Sminshall return c;
850c10df855Sminshall }
851c10df855Sminshall }
852c10df855Sminshall
853c10df855Sminshall
8547fe218f1Sminshall int
token_type(string)8557fe218f1Sminshall token_type(string)
8567fe218f1Sminshall char *string;
8577fe218f1Sminshall {
8587fe218f1Sminshall switch (string[0]) {
8597fe218f1Sminshall case 'f':
8607fe218f1Sminshall if (strcmp(string, "for") == 0) {
8617fe218f1Sminshall return FOR;
8627fe218f1Sminshall }
8637fe218f1Sminshall break;
8647fe218f1Sminshall case 'd':
8657fe218f1Sminshall if (string[1] == 'o') {
8667fe218f1Sminshall if (strcmp(string, "do") == 0) {
8677fe218f1Sminshall return DO;
8687fe218f1Sminshall } else if (strcmp(string, "done") == 0) {
8697fe218f1Sminshall return DONE;
8707fe218f1Sminshall }
8717fe218f1Sminshall }
8727fe218f1Sminshall break;
8737fe218f1Sminshall case 'i':
8747fe218f1Sminshall if (strcmp(string, "in") == 0) {
8757fe218f1Sminshall return IN;
8767fe218f1Sminshall }
8777fe218f1Sminshall break;
8787fe218f1Sminshall default:
8797fe218f1Sminshall break;
8807fe218f1Sminshall }
8817fe218f1Sminshall return TOKEN;
8827fe218f1Sminshall }
8837fe218f1Sminshall
8847fe218f1Sminshall
yylex()885c10df855Sminshall yylex()
886c10df855Sminshall {
887c10df855Sminshall #define ret_token(c) if (bufptr != buffer) { \
888c10df855Sminshall save(c); \
889c10df855Sminshall *bufptr = 0; \
890c10df855Sminshall bufptr = buffer; \
89184402bf5Sminshall yylval.string = string_lookup(buffer); \
8927fe218f1Sminshall return token_type(buffer); \
893c10df855Sminshall }
894c10df855Sminshall #define save(c) { last_char = c; last_saved = 1; }
89584402bf5Sminshall #if defined(YYDEBUG)
896c10df855Sminshall #define Return(c) if (yydebug) { \
897c10df855Sminshall printf("[%d]", c); \
898c10df855Sminshall fflush(stdout); \
899c10df855Sminshall } \
90084402bf5Sminshall yyval.intval = c; \
901c10df855Sminshall return c;
90284402bf5Sminshall #else /* defined(YYDEBUG) */
90384402bf5Sminshall #define Return(y,c) { yylval.intval = c; return y; }
90484402bf5Sminshall #endif /* defined(YYDEBUG) */
905c10df855Sminshall
90684402bf5Sminshall
90784402bf5Sminshall static char buffer[500], *bufptr = buffer;
908c10df855Sminshall static int eof_found = 0;
909c10df855Sminshall int c;
910c10df855Sminshall
911c10df855Sminshall if (eof_found != 0) {
912c10df855Sminshall eof_found++;
913c10df855Sminshall if (eof_found > 2) {
914c10df855Sminshall fprintf(stderr, "End of file ignored.\n");
915c10df855Sminshall exit(1);
916c10df855Sminshall }
917bbfe3fc0Sminshall Return(EOF,0);
918c10df855Sminshall }
919c10df855Sminshall while ((c = Getchar()) != EOF) {
920c10df855Sminshall switch (c) {
921c10df855Sminshall case '#':
922c10df855Sminshall ret_token(c);
923c10df855Sminshall while (((c = Getchar()) != EOF) && (c != '\n')) {
924c10df855Sminshall ;
925c10df855Sminshall }
926c10df855Sminshall save(c);
927c10df855Sminshall break;
92884402bf5Sminshall case '<':
92984402bf5Sminshall case '?':
930c10df855Sminshall ret_token(c);
93184402bf5Sminshall Return(MACRO_CHAR, c);
93284402bf5Sminshall case '\t':
93384402bf5Sminshall case ' ':
93484402bf5Sminshall ret_token(c);
93584402bf5Sminshall Return(WHITE_SPACE, c);
9367fe218f1Sminshall case '-':
9377fe218f1Sminshall case '@':
938c10df855Sminshall case ':':
9397fe218f1Sminshall case ';':
940c10df855Sminshall case '=':
94184402bf5Sminshall case '$':
94284402bf5Sminshall case '{':
94384402bf5Sminshall case '}':
9447fe218f1Sminshall case '(':
9457fe218f1Sminshall case ')':
946c10df855Sminshall ret_token(c);
94784402bf5Sminshall Return(c,c);
94884402bf5Sminshall case '\'':
94984402bf5Sminshall case '"':
950e023e216Sminshall if (bufptr != buffer) {
951e023e216Sminshall if (bufptr[-1] == '\\') {
952e023e216Sminshall bufptr[-1] = c;
953e023e216Sminshall }
954e023e216Sminshall break;
955e023e216Sminshall } else {
95684402bf5Sminshall int newc;
95784402bf5Sminshall
95884402bf5Sminshall ret_token(c);
95984402bf5Sminshall *bufptr++ = c;
96084402bf5Sminshall while (((newc = Getchar()) != EOF) && (newc != c)) {
96184402bf5Sminshall *bufptr++ = newc;
96284402bf5Sminshall }
96384402bf5Sminshall *bufptr++ = c;
96484402bf5Sminshall *bufptr = 0;
96584402bf5Sminshall bufptr = buffer;
96684402bf5Sminshall yylval.string = string_lookup(buffer);
96784402bf5Sminshall return QUOTED_STRING;
96884402bf5Sminshall }
969c10df855Sminshall case '\n':
970c10df855Sminshall if (bufptr != buffer) {
971c10df855Sminshall if (bufptr[-1] == '\\') {
972c10df855Sminshall bufptr--;
97384402bf5Sminshall if ((c = Getchar()) != '\t') {
97484402bf5Sminshall yyerror("continuation line doesn't begin with a tab");
97584402bf5Sminshall save(c);
97684402bf5Sminshall }
97784402bf5Sminshall ret_token(c);
97884402bf5Sminshall Return(WHITE_SPACE, c);
979c10df855Sminshall }
980c10df855Sminshall }
981c10df855Sminshall ret_token(c);
98284402bf5Sminshall Return(NL, 0);
983c10df855Sminshall default:
984c10df855Sminshall *bufptr++ = c;
985c10df855Sminshall break;
986c10df855Sminshall }
987c10df855Sminshall }
988c10df855Sminshall
989c10df855Sminshall eof_found = 1;
990c10df855Sminshall
991c10df855Sminshall ret_token(' ');
992bbfe3fc0Sminshall Return(EOF, 0);
993c10df855Sminshall }
99484402bf5Sminshall
main()99584402bf5Sminshall main()
99684402bf5Sminshall {
99784402bf5Sminshall #define YYDEBUG
99884402bf5Sminshall extern int yydebug;
99984402bf5Sminshall
1000953a4c02Sminshall null = same_item(string_lookup(""));
1001953a4c02Sminshall newline = same_item(string_lookup("\n"));
1002953a4c02Sminshall blank = same_item(string_lookup(" "));
10034ffc2a5cSminshall cwd_line = same_cat(same_copy(newline),
10044ffc2a5cSminshall same_cat(same_item(string_lookup("cd ${CWD}")),
10054ffc2a5cSminshall same_copy(newline)));
100684402bf5Sminshall
1007d70f92ebSminshall yyparse();
1008d70f92ebSminshall
1009d70f92ebSminshall do_dump();
10104ffc2a5cSminshall
10114ffc2a5cSminshall return 0;
101284402bf5Sminshall }
101384402bf5Sminshall
101484402bf5Sminshall #if defined(YYDEBUG)
dump_same(same)10154788ac1fSminshall dump_same(same)
10164788ac1fSminshall same_t *same;
10174788ac1fSminshall {
10184788ac1fSminshall same_t *same2;
10194788ac1fSminshall
10204788ac1fSminshall for (visit(same, same2); !visited(same2); visit_next(same2)) {
10214788ac1fSminshall printf(same2->string->string);
10224788ac1fSminshall }
10234788ac1fSminshall visit_end();
10244788ac1fSminshall }
1025d70f92ebSminshall #endif /* YYDEBUG */
10264788ac1fSminshall
do_dump()102784402bf5Sminshall do_dump()
102884402bf5Sminshall {
102984402bf5Sminshall string_t *string;
103084402bf5Sminshall same_t *same, *same2;
103184402bf5Sminshall
103284402bf5Sminshall if (yydebug > 1) {
103384402bf5Sminshall printf("strings...\n");
103484402bf5Sminshall for (string = strings; string; string = string->next) {
103584402bf5Sminshall printf("\t%s\n", string->string);
103684402bf5Sminshall }
103784402bf5Sminshall }
103884402bf5Sminshall
1039d70f92ebSminshall printf("# variables...\n");
1040ff189d06Sminshall for (visit(variables, same); !visited(same); visit_next(same)) {
1041d70f92ebSminshall printf("%s =\t", same->string->string);
1042953a4c02Sminshall for (visit(same->value_list, same2); !visited(same2);
1043953a4c02Sminshall visit_next(same2)) {
1044bc7371f7Sminshall printf(same2->string->string);
104584402bf5Sminshall }
1046953a4c02Sminshall visit_end();
104784402bf5Sminshall printf("\n");
104884402bf5Sminshall }
1049ff189d06Sminshall visit_end();
105084402bf5Sminshall
1051f53f6b88Sminshall printf("\n\n#targets...\n");
1052ff189d06Sminshall for (visit(targets, same); !visited(same); visit_next(same)) {
1053f53f6b88Sminshall printf("\n%s:\t", same->string->string);
1054953a4c02Sminshall for (visit(same->depend_list, same2); !visited(same2);
1055953a4c02Sminshall visit_next(same2)) {
105684402bf5Sminshall printf(same2->string->string);
105784402bf5Sminshall }
1058953a4c02Sminshall visit_end();
1059d70f92ebSminshall printf("\n\t");
1060953a4c02Sminshall for (visit(same->action_list, same2); !visited(same2);
1061953a4c02Sminshall visit_next(same2)) {
106284402bf5Sminshall printf(same2->string->string);
106384402bf5Sminshall if (same2->string->string[0] == '\n') {
1064d70f92ebSminshall printf("\t");
106584402bf5Sminshall }
106684402bf5Sminshall }
1067953a4c02Sminshall visit_end();
106884402bf5Sminshall printf("\n");
106984402bf5Sminshall }
1070ff189d06Sminshall visit_end();
107184402bf5Sminshall }
1072