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