* The deal with these is that they exist on various lists.
* First off, they are on a temporary list during the time they
* are in the active focus of the parser.
* Secondly, they live on one of three queues:
* (and, we restrict any given one to live on one and only one such list)
* Also, they may live on the list of values for someone else's variable,
* or as someone's dependancy.
*nexttoken, /* Next pointer */
*lasttoken, /* Back pointer */
*depend_list, /* If target, dependancies */
*action_list, /* If target, actions */
*value_list; /* If variable, value list */
%token <string> TOKEN QUOTED_STRING
%token <intval> MACRO_CHAR BREAK_CHAR WHITE_SPACE NL END_OF_FILE
%token <intval> ':' '=' '$' '{' '}'
%type <same> target assignment actions action tokens token
%type <intval> special_chars white_space macro_char
makefile : lines END_OF_FILE;
line : maybe_white_space NL
token maybe_white_space '=' maybe_white_space tokens maybe_white_space NL
| token maybe_white_space '=' maybe_white_space NL
assign($1, same_copy(null));
target_action: target actions
add_targets_actions($1, $2);
add_targets_actions($1, same_copy(null));
tokens maybe_white_space ':' maybe_white_space tokens maybe_white_space NL
$$ = add_depends($1, $5);
| tokens maybe_white_space ':' maybe_white_space NL
$$ = add_depends($1, same_copy(null));
action: white_space tokens NL
$$ = same_item(string_lookup(buffer));
$$ = same_item(string_lookup(buffer));
$$ = same_copy(value_of($3));
special_chars : BREAK_CHAR
white_space : WHITE_SPACE
| white_space WHITE_SPACE
static int last_char, last_saved = 0;
static int column = 0, lineno = 1;
} visit_stack[20]; /* 20 maximum */
#define visit(what,via) \
(visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
#define visited(via) (((via) == 0) \
|| (visit_stack[clock].next && (via == visit_stack[clock].first)))
#define visit_next(via) (visit_stack[clock].next = 1, (via) = (via)->nexttoken)
#define visit_end() (clock--)
fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
string_hashof(string, length)
i = (i<<3) + *string ^ ((i>>28)&0x7);
if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
&& (memcmp(s1->string, s2->string, s1->length) == 0)) {
ours.length = strlen(string);
ours.hashval = string_hashof(string, ours.length);
for (ptr = strings; ptr; ptr = ptr->next) {
if (string_same(&ours, ptr)) {
if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
fprintf(stderr, "No space to add string *%s*!\n", string);
ptr->hashval = ours.hashval;
ptr->length = ours.length;
if ((ptr->string = malloc(ours.length+1)) == 0) {
fprintf(stderr, "No space to add literal *%s*!\n", string);
memcpy(ptr->string, string, ours.length+1);
for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
if (string_same(string, token->string)) {
last = tokens->lasttoken;
tokens->lasttoken = list->lasttoken;
tokens->lasttoken->nexttoken = tokens;
if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) {
fprintf(stderr, "No more space for tokens!\n");
memset((char *)ptr, 0, sizeof *ptr);
ptr->nexttoken = ptr->lasttoken = ptr;
for (visit(same, copy); !visited(copy); visit_next(copy)) {
ptr = same_item(copy->string);
head = same_cat(head, ptr);
(void) free((char *)token);
token->lasttoken->nexttoken = token->nexttoken;
token->nexttoken->lasttoken = token->lasttoken;
token->nexttoken = token->lasttoken = token;
(void) free((char *) token);
if ((ptr = same_search(targets, target)) == 0) {
targets = same_cat(targets, target);
ptr->action_list = same_cat(ptr->action_list, target->action_list);
ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
add_targets_actions(target, actions)
same_t *ptr, *original = target;
target->action_list = same_cat(target->action_list,
} while (target != original);
add_depends(target, depends)
same_t *original = target;
depends = same_cat(depends, same_copy(blank)); /* Separator */
for (visit(original, target); !visited(target); visit_next(target)) {
target->depend_list = same_cat(target->depend_list, same_copy(depends));
* We know that variable is a singleton
if ((ptr = same_search(variables, variable)) != 0) {
same_free(ptr->value_list);
variable->value_list = value;
variables = same_cat(variables, variable);
same_t *ptr = same_search(variables, variable);
return same_copy(ptr->value_list);
#define ret_token(c) if (bufptr != buffer) { \
yylval.string = string_lookup(buffer); \
#define save(c) { last_char = c; last_saved = 1; }
#define Return(c) if (yydebug) { \
#else /* defined(YYDEBUG) */
#define Return(y,c) { yylval.intval = c; return y; }
#endif /* defined(YYDEBUG) */
static char buffer[500], *bufptr = buffer;
static int eof_found = 0;
fprintf(stderr, "End of file ignored.\n");
while ((c = Getchar()) != EOF) {
while (((c = Getchar()) != EOF) && (c != '\n')) {
while (((newc = Getchar()) != EOF) && (newc != c)) {
yylval.string = string_lookup(buffer);
if (bufptr[-1] == '\\') {
if ((c = Getchar()) != '\t') {
yyerror("continuation line doesn't begin with a tab");
null = same_item(string_lookup(""));
newline = same_item(string_lookup("\n"));
blank = same_item(string_lookup(" "));
for (string = strings; string; string = string->next) {
printf("\t%s\n", string->string);
printf("variables...\n");
for (visit(variables, same); !visited(same); visit_next(same)) {
printf("\t%s =\t", same->string->string);
for (visit(same->value_list, same2); !visited(same2);
printf(same2->string->string);
for (visit(targets, same); !visited(same); visit_next(same)) {
printf("\t%s :\t", same->string->string);
for (visit(same->depend_list, same2); !visited(same2);
printf(same2->string->string);
for (visit(same->action_list, same2); !visited(same2);
printf(same2->string->string);
if (same2->string->string[0] == '\n') {