main
  1#include <stdint.h>
  2#include <stdio.h>
  3#include <dlfcn.h>
  4#include <stdlib.h>
  5#include <unistd.h>
  6#include "./common.h"
  7
  8char controls[NUM_CHILDREN] = { 'w', 'a', 's', 'd' };
  9
 10typedef struct _NodeListElem {
 11	struct _NodeListElem *prev;
 12	Node *node;
 13} NodeListElem;
 14
 15void _iterate_nodes( NodeListElem *prev, Node *p, Node *n, void (*f)( Node *parent, Node *current, void* ctx), void *ctx ) {
 16
 17	NodeListElem start = {
 18		.prev = prev,
 19		.node = n
 20	};
 21
 22	if( 0 == n ) return;
 23
 24	/* Ensure we are not recursing back into a previous node on the same branch */
 25	for( NodeListElem *e = prev; e->prev != 0; e = e->prev ) {
 26		if( e->node == n ) {
 27			return;
 28		}
 29	}
 30
 31	f( p, n, ctx );
 32
 33	_iterate_nodes( &start, n, n->children[0], f, ctx );
 34	_iterate_nodes( &start, n, n->children[1], f, ctx );
 35	_iterate_nodes( &start, n, n->children[2], f, ctx );
 36	_iterate_nodes( &start, n, n->children[3], f, ctx );
 37}
 38
 39void iterate_nodes( Node *p, Node *n, void (*f)( Node *parent, Node *current, void* ctx), void *ctx ) {
 40	NodeListElem start = {
 41		.prev = 0,
 42		.node = p
 43	};
 44
 45	_iterate_nodes( &start, p, n, f, ctx );
 46}
 47
 48
 49void print_as_current( Node *n ) {
 50	printf("%s\n", n->name);
 51
 52	for( size_t i = 0; i < NUM_CHILDREN; ++i ) {
 53		if( n->children[i] ) {
 54			printf("[%c] %s\n", controls[i], n->children[i]->name);
 55		}
 56	}
 57}
 58
 59void execute_node( Node *n ) {
 60	system( n->cmd );
 61}
 62
 63void gen_forward_declaration( Node *parent, Node *current, void *ctx ) {
 64	FILE *f = ctx;
 65
 66	if( current->seen_decl ) {
 67		return;
 68	}
 69
 70	fprintf( f, "Node %s;\n", current->name );
 71	current->seen_decl = 1;
 72}
 73
 74
 75void gen_node_macro( Node *parent, Node *current, void *ctx ) {
 76	FILE *f = ctx;
 77
 78	if( current->seen_def ) {
 79		return;
 80	}
 81
 82	fprintf( f, "NODE( %s, ", current->name );
 83
 84	if( current->cmd ) {
 85		fprintf( f, "\"%s\", ", current->cmd );
 86	} else {
 87		fprintf( f, "0, ");
 88	}
 89
 90	fprintf( f, "{ " );
 91
 92	for( size_t i = 0; i < NUM_CHILDREN; ++i ) {
 93		if( current->children[i] ) {
 94			fprintf( f, "&%s, ", current->children[i]->name );
 95		} else {
 96			fprintf( f, "0, " );
 97		}
 98	}
 99
100	current->seen_def = 1;
101	fprintf( f, "}" );
102	fprintf( f, " );\n" );
103}
104
105void generate_code( Node *root, FILE *f ) {
106	fprintf( f, "#include \"./common.h\"\n\n" );
107
108	iterate_nodes( (void*)&root, root, gen_forward_declaration, f );
109	fprintf( f, "\n\n" );
110	iterate_nodes( (void*)&root, root, gen_node_macro, f );
111	fprintf( f, "\n\n" );
112
113	fprintf( f, "Node *root = &%s;", root->name );
114}
115
116int main(void) {
117	Node *root;
118	Node *current;
119
120	system("gcc -shared -ffreestanding data.c -o data.so");
121
122	void *data_so = dlopen( "./data.so", RTLD_NOW );
123	if( !data_so ) return 1;
124
125	void *sym = dlsym( data_so, "root" );
126	if( !sym ) return 2;
127
128	root = *(Node**)sym;
129
130	current = root;
131	char in;
132
133	print_as_current( current );
134
135	while( (in = getchar()) ) {
136		if( in == 'c' ) { /* codegen */
137			FILE *f = fopen( "./gen.c", "w" );
138			if( !f ) return 3;
139			generate_code( root, f );
140			fclose( f );
141			goto end;
142		}
143
144		for( size_t i = 0; i < NUM_CHILDREN; ++i ) {
145			if( in == controls[i] ) {
146				if( current->children[i] ) {
147					current = current->children[i];
148					execute_node( current );
149				} else {
150					/* Ignore direction that is not present on the current node */
151					break;
152				}
153			}
154		}
155
156		bool has_child = 0;
157		for( size_t i = 0; i < NUM_CHILDREN; ++i ) {
158			if( current->children[i] ) {
159				has_child = 1;
160				break;
161			}
162		}
163
164		if( !has_child ) {
165			break;
166		}
167		print_as_current( current );
168	}
169
170end:
171	dlclose(data_so);
172
173	return 0;
174}