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}