rev |
line source |
meillo@0
|
1 /*
|
meillo@0
|
2 * baum - an esoteric programming language
|
meillo@0
|
3 *
|
meillo@0
|
4 * (c) markus schnalke <meillo@marmaro.de>
|
meillo@0
|
5 * and julian forster
|
meillo@0
|
6 *
|
meillo@0
|
7 */
|
meillo@0
|
8
|
meillo@0
|
9
|
meillo@0
|
10 #include <stdio.h>
|
meillo@0
|
11 #include <stdlib.h>
|
meillo@1
|
12 #include <string.h>
|
meillo@0
|
13
|
meillo@1
|
14 #include "baum.h"
|
meillo@0
|
15
|
meillo@54
|
16 #define VERSION "0.4"
|
meillo@13
|
17
|
meillo@30
|
18
|
meillo@33
|
19 void printNode(struct Node* node, int level);
|
meillo@33
|
20 void printTree(struct Node* root, int level);
|
meillo@26
|
21 struct Node* lastNode(struct Node* node);
|
meillo@26
|
22 void delete(struct Node* node);
|
meillo@26
|
23
|
meillo@26
|
24
|
meillo@41
|
25 struct Stackitem {
|
meillo@41
|
26 struct Node* node;
|
meillo@41
|
27 struct Stackitem* next;
|
meillo@41
|
28 };
|
meillo@41
|
29
|
meillo@41
|
30
|
meillo@41
|
31
|
meillo@41
|
32 struct Node* root = 0;
|
meillo@41
|
33 struct Stackitem* stack = NULL;
|
meillo@41
|
34
|
meillo@26
|
35
|
meillo@1
|
36 void logit(char* text) {
|
meillo@13
|
37 if (option_verbose) {
|
meillo@13
|
38 fprintf(stderr, "[%s]\n", text);
|
meillo@13
|
39 }
|
meillo@1
|
40 }
|
meillo@1
|
41
|
meillo@1
|
42
|
meillo@1
|
43 /* new */
|
meillo@3
|
44 struct Node* newNode(char* name, unsigned char value) {
|
meillo@0
|
45 struct Node* node;
|
meillo@0
|
46 node = (struct Node*) malloc(sizeof(struct Node));
|
meillo@55
|
47 if (node == NULL) {
|
meillo@55
|
48 perror("unable to allocate memory");
|
meillo@55
|
49 exit(10);
|
meillo@55
|
50 }
|
meillo@9
|
51 strcpy(node->name, name);
|
meillo@3
|
52 node->value = value;
|
meillo@0
|
53 node->right = 0;
|
meillo@0
|
54 node->down = 0;
|
meillo@0
|
55 return node;
|
meillo@0
|
56 }
|
meillo@0
|
57
|
meillo@0
|
58
|
meillo@3
|
59
|
meillo@3
|
60 struct Node* lastNode(struct Node* node) {
|
meillo@3
|
61 while (node->right != NULL) {
|
meillo@3
|
62 node = node->right;
|
meillo@3
|
63 }
|
meillo@3
|
64 return node;
|
meillo@3
|
65 }
|
meillo@3
|
66
|
meillo@15
|
67 struct Node* insertLast(struct Node* node, struct Node* insert) {
|
meillo@3
|
68 node = lastNode(node);
|
meillo@3
|
69 node->right = insert;
|
meillo@15
|
70 return insert;
|
meillo@3
|
71 }
|
meillo@3
|
72
|
meillo@46
|
73 struct Node* copyTree(struct Node* node) {
|
meillo@46
|
74 if (node == NULL) {
|
meillo@46
|
75 return NULL;
|
meillo@46
|
76 }
|
meillo@46
|
77 struct Node* tmp;
|
meillo@46
|
78 tmp = newNode(node->name, node->value);
|
meillo@46
|
79 tmp->down = copyTree(node->down);
|
meillo@46
|
80 tmp->right = copyTree(node->right);
|
meillo@46
|
81 return tmp;
|
meillo@46
|
82 }
|
meillo@46
|
83
|
meillo@26
|
84
|
meillo@1
|
85 /* delete */
|
meillo@1
|
86 void delete(struct Node* node) {
|
meillo@26
|
87 if (node == NULL) {
|
meillo@26
|
88 return;
|
meillo@0
|
89 }
|
meillo@33
|
90 delete(node->down);
|
meillo@33
|
91 delete(node->right);
|
meillo@26
|
92 free(node); node=0;
|
meillo@0
|
93 }
|
meillo@0
|
94
|
meillo@1
|
95
|
meillo@1
|
96 /* print */
|
meillo@33
|
97 void printNode(struct Node* node, int level) {
|
meillo@55
|
98 if (node == NULL) {
|
meillo@55
|
99 return;
|
meillo@5
|
100 }
|
meillo@55
|
101 while (level-- > 0) {
|
meillo@55
|
102 fprintf(stderr, "\t");
|
meillo@55
|
103 }
|
meillo@55
|
104 fprintf(stderr, "%s (%d|%c)\n", node->name, node->value, node->value);
|
meillo@0
|
105 }
|
meillo@0
|
106
|
meillo@33
|
107 void printTree(struct Node* root, int level) {
|
meillo@26
|
108 if (root == NULL) {
|
meillo@26
|
109 return;
|
meillo@26
|
110 }
|
meillo@33
|
111 printNode(root, level);
|
meillo@33
|
112 printTree(root->down, level+1);
|
meillo@33
|
113 printTree(root->right, level);
|
meillo@0
|
114 }
|
meillo@0
|
115
|
meillo@0
|
116
|
meillo@1
|
117
|
meillo@1
|
118
|
meillo@3
|
119
|
meillo@30
|
120 /* stack for read_input */
|
meillo@9
|
121 void push(struct Node* node) {
|
meillo@10
|
122 struct Stackitem* tmp;
|
meillo@10
|
123 struct Stackitem* new;
|
meillo@10
|
124 new = (struct Stackitem*) malloc(sizeof(struct Stackitem));
|
meillo@55
|
125 if (new == NULL) {
|
meillo@55
|
126 perror("unable to allocate memory");
|
meillo@55
|
127 exit(10);
|
meillo@55
|
128 }
|
meillo@9
|
129 new->node = node;
|
meillo@10
|
130 tmp = stack;
|
meillo@10
|
131 stack = new;
|
meillo@10
|
132 stack->next = tmp;
|
meillo@9
|
133 }
|
meillo@9
|
134 struct Node* pull() {
|
meillo@10
|
135 if (stack == NULL) {
|
meillo@9
|
136 return NULL;
|
meillo@9
|
137 }
|
meillo@10
|
138 struct Stackitem* tmp;
|
meillo@9
|
139 struct Node* node;
|
meillo@10
|
140 tmp = stack;
|
meillo@10
|
141 stack = stack->next;
|
meillo@9
|
142 node = tmp->node;
|
meillo@9
|
143 free(tmp); tmp=0;
|
meillo@9
|
144 return node;
|
meillo@9
|
145 }
|
meillo@3
|
146
|
meillo@1
|
147
|
meillo@1
|
148
|
meillo@6
|
149 /* read input */
|
meillo@12
|
150 void read_input(char* filename) {
|
meillo@7
|
151 int c;
|
meillo@8
|
152 int indent;
|
meillo@7
|
153 char name[256];
|
meillo@6
|
154 int value;
|
meillo@9
|
155 int last_indent;
|
meillo@9
|
156 struct Node* last_node;
|
meillo@9
|
157 struct Node* node;
|
meillo@12
|
158 FILE* file;
|
meillo@6
|
159
|
meillo@8
|
160 indent = 0;
|
meillo@8
|
161 strcpy(name, "");
|
meillo@8
|
162 value = 0;
|
meillo@9
|
163 last_indent = -1;
|
meillo@34
|
164 last_node = NULL;
|
meillo@12
|
165 file = fopen(filename, "r");
|
meillo@55
|
166 if (file == NULL) {
|
meillo@55
|
167 perror("unable to open file");
|
meillo@55
|
168 exit(10);
|
meillo@55
|
169 }
|
meillo@6
|
170
|
meillo@12
|
171 while ((c = getc(file)) != EOF) {
|
meillo@55
|
172 if (c == '#') { /* comment */
|
meillo@12
|
173 while ((c = getc(file)) != '\n') {
|
meillo@7
|
174 }
|
meillo@7
|
175 }
|
meillo@7
|
176
|
meillo@8
|
177 if (c == ' ' || c == '\t') { /* indent if at start of line */
|
meillo@8
|
178 if (strlen(name) == 0) {
|
meillo@8
|
179 indent++;
|
meillo@8
|
180 }
|
meillo@7
|
181 }
|
meillo@6
|
182
|
meillo@8
|
183 if (c == '\n') { /* end of line: create node */
|
meillo@7
|
184 if (strlen(name) > 0) {
|
meillo@8
|
185 /* create node */
|
meillo@9
|
186 node = newNode((char*) name, value);
|
meillo@9
|
187 if (indent > last_indent) { /* down */
|
meillo@30
|
188 /* if it goes more than one level down -> error */
|
meillo@33
|
189 if (indent > last_indent + 1) {
|
meillo@30
|
190 fprintf(stderr, "error: Indention over more than one level. Only indent by one!\n");
|
meillo@31
|
191 exit(5);
|
meillo@30
|
192 }
|
meillo@34
|
193 if (last_node == NULL) {
|
meillo@34
|
194 root = node;
|
meillo@34
|
195 last_node = root;
|
meillo@34
|
196 } else {
|
meillo@34
|
197 last_node->down = node;
|
meillo@34
|
198 }
|
meillo@9
|
199 push(last_node);
|
meillo@9
|
200 } else if (indent == last_indent) { /* right */
|
meillo@9
|
201 last_node->right = node;
|
meillo@9
|
202 } else if (indent < last_indent) { /* up */
|
meillo@30
|
203 /* handle if it goes more than one level up */
|
meillo@30
|
204 while (indent < last_indent) {
|
meillo@30
|
205 last_node = pull();
|
meillo@30
|
206 last_indent--;
|
meillo@30
|
207 }
|
meillo@9
|
208 last_node->right = node;
|
meillo@9
|
209 }
|
meillo@9
|
210 last_indent = indent;
|
meillo@9
|
211 last_node = node;
|
meillo@6
|
212 }
|
meillo@6
|
213 indent = 0;
|
meillo@6
|
214 strcpy(name, "");
|
meillo@6
|
215 value = 0;
|
meillo@6
|
216 }
|
meillo@7
|
217
|
meillo@8
|
218 if (c >= 'a' && c <= 'z') { /* name */
|
meillo@7
|
219 int i = 1;
|
meillo@7
|
220 name[0] = (char) c;
|
meillo@12
|
221 while ((c = getc(file)) != '(') {
|
meillo@7
|
222 name[i] = (char) c;
|
meillo@7
|
223 i++;
|
meillo@8
|
224 if (i > 255) {
|
meillo@33
|
225 fprintf(stderr, "error: node name too long, or no value given\n");
|
meillo@33
|
226 exit(6);
|
meillo@8
|
227 }
|
meillo@7
|
228 }
|
meillo@7
|
229 name[i] = '\0';
|
meillo@7
|
230 }
|
meillo@7
|
231
|
meillo@8
|
232 if (c == '(') { /* value */
|
meillo@12
|
233 fscanf(file, "%d)", &value);
|
meillo@7
|
234 }
|
meillo@7
|
235
|
meillo@6
|
236 }
|
meillo@7
|
237
|
meillo@30
|
238 /* clear stack */
|
meillo@27
|
239 while (stack != NULL) {
|
meillo@27
|
240 pull();
|
meillo@27
|
241 }
|
meillo@27
|
242
|
meillo@12
|
243 fclose(file);
|
meillo@26
|
244 }
|
meillo@12
|
245
|
meillo@26
|
246
|
meillo@6
|
247
|
meillo@1
|
248 /* main */
|
meillo@0
|
249 int main(int argc, char* argv[]) {
|
meillo@7
|
250 unsigned char shell_return = 0;
|
meillo@38
|
251
|
meillo@38
|
252 option_verbose = 0;
|
meillo@9
|
253
|
meillo@13
|
254 while (--argc > 0 && (*++argv)[0] == '-') {
|
meillo@13
|
255 if (strcmp(argv[0], "--version") == 0) {
|
meillo@61
|
256 printf("baum %s\n"
|
meillo@61
|
257 "an esoteric programming language\n"
|
meillo@61
|
258 "by markus schnalke and julian forster\n"
|
meillo@61
|
259 "http://prog.marmaro.de/baum\n", VERSION);
|
meillo@13
|
260 exit(0);
|
meillo@13
|
261 } else if (strcmp(argv[0], "--help") == 0) {
|
meillo@61
|
262 printf("baum --version print version information and exit\n"
|
meillo@61
|
263 "baum --help print this output\n"
|
meillo@61
|
264 "baum [-v] <file> (verbosly) run file\n");
|
meillo@13
|
265 exit(0);
|
meillo@13
|
266 } else if (strcmp(argv[0], "-v") == 0) {
|
meillo@13
|
267 option_verbose = 1;
|
meillo@13
|
268 /*
|
meillo@13
|
269 } else if (strcmp(argv[0], "-W") == 0) {
|
meillo@13
|
270 / * TODO: catch if no value given * /
|
meillo@13
|
271 iDWarn = atoi((++argv)[0]);
|
meillo@13
|
272 argc--;
|
meillo@13
|
273 */
|
meillo@13
|
274 } else {
|
meillo@13
|
275 fprintf(stderr, "unknown option: %s\n", argv[0]);
|
meillo@42
|
276 exit(126);
|
meillo@13
|
277 }
|
meillo@13
|
278 }
|
meillo@13
|
279
|
meillo@13
|
280 if (argc != 1) {
|
meillo@13
|
281 fprintf(stderr, "%d source files given, please specify one.\n", argc);
|
meillo@13
|
282 exit(3);
|
meillo@13
|
283 }
|
meillo@13
|
284
|
meillo@13
|
285 read_input(argv[0]);
|
meillo@13
|
286
|
meillo@13
|
287 if (option_verbose) {
|
meillo@53
|
288 fprintf(stderr, "\n\ntree read from input:\n");
|
meillo@53
|
289 printTree(root, 1);
|
meillo@13
|
290 }
|
meillo@1
|
291
|
meillo@5
|
292 shell_return = action(root);
|
meillo@34
|
293 fflush(stdout);
|
meillo@1
|
294
|
meillo@13
|
295 if (option_verbose) {
|
meillo@53
|
296 fprintf(stderr, "\n\nmodified tree after execution:\n");
|
meillo@53
|
297 printTree(root, 1);
|
meillo@13
|
298 }
|
meillo@13
|
299
|
meillo@9
|
300 delete(root);
|
meillo@5
|
301 exit(shell_return);
|
meillo@0
|
302 }
|