baum

view baum.c @ 55:6279e5b14d9e

added error handling for fopen and malloc; code cleanups
author meillo@marmaro.de
date Sun, 16 Mar 2008 10:40:53 +0100
parents 6e46b106c334
children b7544f23673b 73de2151aebd
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.4"
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 if (node == NULL) {
48 perror("unable to allocate memory");
49 exit(10);
50 }
51 strcpy(node->name, name);
52 node->value = value;
53 node->right = 0;
54 node->down = 0;
55 return node;
56 }
60 struct Node* lastNode(struct Node* node) {
61 while (node->right != NULL) {
62 node = node->right;
63 }
64 return node;
65 }
67 struct Node* insertLast(struct Node* node, struct Node* insert) {
68 node = lastNode(node);
69 node->right = insert;
70 return insert;
71 }
73 struct Node* copyTree(struct Node* node) {
74 if (node == NULL) {
75 return NULL;
76 }
77 struct Node* tmp;
78 tmp = newNode(node->name, node->value);
79 tmp->down = copyTree(node->down);
80 tmp->right = copyTree(node->right);
81 return tmp;
82 }
85 /* delete */
86 void delete(struct Node* node) {
87 if (node == NULL) {
88 return;
89 }
90 delete(node->down);
91 delete(node->right);
92 free(node); node=0;
93 }
96 /* print */
97 void printNode(struct Node* node, int level) {
98 if (node == NULL) {
99 return;
100 }
101 while (level-- > 0) {
102 fprintf(stderr, "\t");
103 }
104 fprintf(stderr, "%s (%d|%c)\n", node->name, node->value, node->value);
105 }
107 void printTree(struct Node* root, int level) {
108 if (root == NULL) {
109 return;
110 }
111 printNode(root, level);
112 printTree(root->down, level+1);
113 printTree(root->right, level);
114 }
120 /* stack for read_input */
121 void push(struct Node* node) {
122 struct Stackitem* tmp;
123 struct Stackitem* new;
124 new = (struct Stackitem*) malloc(sizeof(struct Stackitem));
125 if (new == NULL) {
126 perror("unable to allocate memory");
127 exit(10);
128 }
129 new->node = node;
130 tmp = stack;
131 stack = new;
132 stack->next = tmp;
133 }
134 struct Node* pull() {
135 if (stack == NULL) {
136 return NULL;
137 }
138 struct Stackitem* tmp;
139 struct Node* node;
140 tmp = stack;
141 stack = stack->next;
142 node = tmp->node;
143 free(tmp); tmp=0;
144 return node;
145 }
149 /* read input */
150 void read_input(char* filename) {
151 int c;
152 int indent;
153 char name[256];
154 int value;
155 int last_indent;
156 struct Node* last_node;
157 struct Node* node;
158 FILE* file;
160 indent = 0;
161 strcpy(name, "");
162 value = 0;
163 last_indent = -1;
164 last_node = NULL;
165 file = fopen(filename, "r");
166 if (file == NULL) {
167 perror("unable to open file");
168 exit(10);
169 }
171 while ((c = getc(file)) != EOF) {
172 if (c == '#') { /* comment */
173 while ((c = getc(file)) != '\n') {
174 }
175 }
177 if (c == ' ' || c == '\t') { /* indent if at start of line */
178 if (strlen(name) == 0) {
179 indent++;
180 }
181 }
183 if (c == '\n') { /* end of line: create node */
184 if (strlen(name) > 0) {
185 /* create node */
186 node = newNode((char*) name, value);
187 if (indent > last_indent) { /* down */
188 /* if it goes more than one level down -> error */
189 if (indent > last_indent + 1) {
190 fprintf(stderr, "error: Indention over more than one level. Only indent by one!\n");
191 exit(5);
192 }
193 if (last_node == NULL) {
194 root = node;
195 last_node = root;
196 } else {
197 last_node->down = node;
198 }
199 push(last_node);
200 } else if (indent == last_indent) { /* right */
201 last_node->right = node;
202 } else if (indent < last_indent) { /* up */
203 /* handle if it goes more than one level up */
204 while (indent < last_indent) {
205 last_node = pull();
206 last_indent--;
207 }
208 last_node->right = node;
209 }
210 last_indent = indent;
211 last_node = node;
212 }
213 indent = 0;
214 strcpy(name, "");
215 value = 0;
216 }
218 if (c >= 'a' && c <= 'z') { /* name */
219 int i = 1;
220 name[0] = (char) c;
221 while ((c = getc(file)) != '(') {
222 name[i] = (char) c;
223 i++;
224 if (i > 255) {
225 fprintf(stderr, "error: node name too long, or no value given\n");
226 exit(6);
227 }
228 }
229 name[i] = '\0';
230 }
232 if (c == '(') { /* value */
233 fscanf(file, "%d)", &value);
234 }
236 }
238 /* clear stack */
239 while (stack != NULL) {
240 pull();
241 }
243 fclose(file);
244 }
248 /* main */
249 int main(int argc, char* argv[]) {
250 unsigned char shell_return = 0;
252 option_verbose = 0;
254 while (--argc > 0 && (*++argv)[0] == '-') {
255 if (strcmp(argv[0], "--version") == 0) {
256 printf("\
257 baum %s\n\
258 an esoteric programming language\n\
259 by markus schnalke and julian forster\n\
260 http://prog.marmaro.de/baum\n\
261 ", VERSION);
262 exit(0);
263 } else if (strcmp(argv[0], "--help") == 0) {
264 printf("\
265 baum --version print version information and exit\n\
266 baum --help print this output\n\
267 baum [-v] <file> (verbosly) run file\n\
268 ");
269 exit(0);
270 } else if (strcmp(argv[0], "-v") == 0) {
271 option_verbose = 1;
272 /*
273 } else if (strcmp(argv[0], "-W") == 0) {
274 / * TODO: catch if no value given * /
275 iDWarn = atoi((++argv)[0]);
276 argc--;
277 */
278 } else {
279 fprintf(stderr, "unknown option: %s\n", argv[0]);
280 exit(126);
281 }
282 }
284 if (argc != 1) {
285 fprintf(stderr, "%d source files given, please specify one.\n", argc);
286 exit(3);
287 }
289 read_input(argv[0]);
291 if (option_verbose) {
292 fprintf(stderr, "\n\ntree read from input:\n");
293 printTree(root, 1);
294 }
296 shell_return = action(root);
297 fflush(stdout);
299 if (option_verbose) {
300 fprintf(stderr, "\n\nmodified tree after execution:\n");
301 printTree(root, 1);
302 }
304 delete(root);
305 exit(shell_return);
306 }