Mercurial > repo
comparison src/daoyu.c @ 7767:5aac3c341f92
<FireFly> ` mv daoyu.c src/
author | HackBot |
---|---|
date | Wed, 04 May 2016 21:53:39 +0000 |
parents | daoyu.c@8f18f8a9c3ba |
children |
comparison
equal
deleted
inserted
replaced
7766:783c27aa7d62 | 7767:5aac3c341f92 |
---|---|
1 /* | |
2 * This program is free software: you can redistribute it and/or modify | |
3 * it under the terms of the GNU General Public License as published by | |
4 * the Free Software Foundation, either version 3 of the License, or | |
5 * (at your option) any later version. | |
6 * | |
7 * This program is distributed in the hope that it will be useful, | |
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 * GNU General Public License for more details. | |
11 * | |
12 * You should have received a copy of the GNU General Public License | |
13 * aint with this program. If not, see <http://www.gnu.org/licenses/>. | |
14 */ | |
15 | |
16 /* | |
17 * DaoLanguage / Daoyu Compiler and Interpreter. | |
18 * Kaynato - 2016 | |
19 * See splash() for details. | |
20 */ | |
21 | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 | |
26 #define BITS_IN_BYTE 8 | |
27 #define BITS_IN_CELL (sizeof(unsigned int) * 8) | |
28 #define INPUT_DELIMITER '@' | |
29 | |
30 typedef struct PATH | |
31 { | |
32 struct PATH* owner; /* OWNER PROGRAM */ | |
33 struct PATH* child; /* CHILD PROGRAM */ | |
34 unsigned int* prg_data; /* DATA */ | |
35 unsigned int prg_allocbits; /* OPEN DATA BITS*/ | |
36 unsigned int prg_index; /* INSTRUCTION POINTER*/ | |
37 unsigned char prg_level; /* OPERATING LEVEL */ | |
38 unsigned int sel_length; /* LENGTH OF SELECTION*/ | |
39 unsigned int sel_index; /* INDEX OF SELECTION*/ | |
40 unsigned int prg_floor; /* FLOOR OF PATH */ | |
41 unsigned int prg_start; /* START OF RUNNING */ | |
42 } Pathstrx; | |
43 | |
44 typedef Pathstrx* Path; | |
45 | |
46 static void interpret(char*); | |
47 | |
48 static void swaps(Path), later(Path), merge(Path), sifts(Path), delev(Path), equal(Path), halve(Path); | |
49 static void uplev(Path), reads(Path), dealc(Path), split(Path), polar(Path), doalc(Path), input(Path), execs(Path, Path); | |
50 | |
51 char getInput(); | |
52 char algn(Path); | |
53 char getChar(unsigned char); | |
54 char* bin(unsigned int); | |
55 char* str_dup(char *s); | |
56 char* l_to_str(unsigned int, unsigned char, unsigned char); | |
57 static void skip(); | |
58 static void write_by_bit_index(Path, unsigned int, unsigned int, unsigned int); | |
59 unsigned char getNybble(char); | |
60 unsigned int read_by_bit_index(Path, unsigned int, unsigned int); | |
61 unsigned int mask(int); | |
62 unsigned int ptwo_round(unsigned int); | |
63 | |
64 static unsigned char command = 0; | |
65 static int doloop = 1; | |
66 | |
67 typedef void(*PathFunc)(Path); | |
68 | |
69 static PathFunc functions[16] = \ | |
70 {NULL, swaps, later, merge, \ | |
71 sifts, NULL , delev, equal, \ | |
72 halve, uplev, reads, dealc, \ | |
73 split, polar, doalc, input}; | |
74 | |
75 const struct PATH NEW_PATH = { NULL, NULL, NULL, 1, 0, 0, 1, 0, 0, 0 }; | |
76 | |
77 static Path P_RUNNING = NULL, | |
78 P_WRITTEN = NULL; | |
79 | |
80 static const char* symbols = ".!/)%#>=(<:S[*$;"; | |
81 | |
82 static char* inputptr = NULL; | |
83 | |
84 /* Run argv[0] as code. Input separated by '!' and once empty reads the null character. */ | |
85 int main(int argc, char * argv[]) | |
86 { | |
87 char* i = argv[1]; | |
88 | |
89 /* No argument(s)? */ | |
90 if (argc < 2) | |
91 return 0; | |
92 | |
93 /* Seek input until it either points to delimiter or NUL */ | |
94 while (*i && *i != INPUT_DELIMITER) i++; | |
95 | |
96 /* If it is the input delimiter then put the inputptr there*/ | |
97 if (*i == INPUT_DELIMITER) | |
98 inputptr = ++i; | |
99 | |
100 interpret(argv[1]); | |
101 return 0; | |
102 } | |
103 | |
104 #define rc(r,c) case c: return r; | |
105 | |
106 unsigned char getNybble(char ch) | |
107 { | |
108 switch (ch) | |
109 { | |
110 rc(0x0, '.') rc(0x1, '!') rc(0x2, '/') rc(0x3, ']': case ')') | |
111 rc(0x4, '%') rc(0x5, '#') rc(0x6, '>') rc(0x7, '=') | |
112 rc(0x8, '(') rc(0x9, '<') rc(0xA, ':') rc(0xB, 'S') | |
113 rc(0xC, '[') rc(0xD, '*') rc(0xE, '$') rc(0xF, ';') | |
114 default: return 0x0; | |
115 } | |
116 } | |
117 | |
118 void interpret(char* input) | |
119 { | |
120 unsigned int length = 0; /* How many bytes in input */ | |
121 | |
122 /* Initialize path */ | |
123 struct PATH newpath = NEW_PATH; | |
124 Path dao = &newpath; | |
125 | |
126 /* Seek end of program input */ | |
127 while (input[length] && input[length] != INPUT_DELIMITER) length++; | |
128 | |
129 /* Terminate empty program */ | |
130 if (length == 0) return; | |
131 | |
132 /* Get necessary byte number from nybbles */ | |
133 length = ptwo_round((length+1) / 2); | |
134 | |
135 /* Set bit length of path */ | |
136 (dao->prg_allocbits) = length * 8; | |
137 | |
138 /* Prevent zero-sized allocation */ | |
139 if (length % sizeof(unsigned int) != 0) | |
140 length = sizeof(unsigned int); | |
141 | |
142 /* Allocate bytes for data array */ | |
143 if (((dao->prg_data) = calloc(length, 1)) == NULL) | |
144 { | |
145 printf("Error allocating %d bytes: ", length); | |
146 perror(""); | |
147 abort(); | |
148 } | |
149 | |
150 /* Copy over data */ | |
151 for (length = 0; input[length] && input[length] != INPUT_DELIMITER; length++) | |
152 { | |
153 int hex = getNybble(input[length]); | |
154 write_by_bit_index(dao, 4*length, 4, hex); | |
155 } | |
156 | |
157 P_RUNNING = dao; /* For the sake of levlim */ | |
158 | |
159 /***************************************************** EXECUTE ******************************************************/ | |
160 execs(dao, NULL); | |
161 free((dao->prg_data)); | |
162 (dao -> prg_data) = NULL; | |
163 /********************************************************************************************************************/ | |
164 | |
165 } | |
166 | |
167 unsigned int ptwo_round(unsigned int x) | |
168 { | |
169 unsigned int rounded = x; /* Initialize bytes_alloc with the file_size value. */ | |
170 unsigned int shift = 0; /* Shift for first one of file size for rounding */ | |
171 | |
172 while ((rounded >> 1) != 0) /* Determine leftmost '1' bit of file size. */ | |
173 { /* */ | |
174 rounded >>= 1; /* Shift right until the next shift zeroes it. */ | |
175 shift++; /* Keep track of shifts. */ | |
176 } /* */ | |
177 rounded <<= shift; /* Unshift. */ | |
178 if (x != rounded) /* If not a power of two, round up. */ | |
179 rounded <<= 1; | |
180 | |
181 return rounded; | |
182 } | |
183 | |
184 char getInput() | |
185 { | |
186 /* if null return zero */ | |
187 if (!inputptr) | |
188 return 0; | |
189 | |
190 /* If not zero then return-advance */ | |
191 if (*inputptr) | |
192 return *inputptr++; | |
193 | |
194 inputptr = NULL; | |
195 return 0; | |
196 } | |
197 | |
198 /*** | |
199 * oooooooooooo ooooooooooooo .oooooo. | |
200 * `888' `8 8' 888 `8 d8P' `Y8b | |
201 * 888 888 888 | |
202 * 888oooo8 888 888 | |
203 * 888 " 888 888 | |
204 * 888 o 888 `88b ooo | |
205 * o888ooooood8 o888o `Y8bood8P' | |
206 * | |
207 */ | |
208 | |
209 #define roc(o,v,c) case o:c=v; return &c; | |
210 | |
211 char *str_dup (char *s) { | |
212 char *d = malloc (strlen (s) + 1); /*Allocate memory */ | |
213 if (d != NULL) strcpy (d,s); /*Copy string if okay */ | |
214 return d; /*Return new memory */ | |
215 } | |
216 | |
217 char* bin(unsigned int val) { return l_to_str(val, 32, 2); } | |
218 | |
219 char getChar(unsigned char ch) | |
220 { | |
221 if (ch > 0xF) return '?'; | |
222 return symbols[ch]; | |
223 } | |
224 | |
225 char* l_to_str(unsigned int val, unsigned char len, unsigned char radix) | |
226 { | |
227 static char buf[32] = { '0' }; | |
228 int i = 33; | |
229 for (; val && i; --i, val /= radix) | |
230 buf[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"[val % radix]; | |
231 for (; i; i--) | |
232 buf[i] = '0'; | |
233 return &buf[2 + (32 - len)]; | |
234 } | |
235 | |
236 /*** | |
237 * .oooooo..o oooooo oooo ooo ooooo oooooooooo. .oooooo. ooooo .oooooo..o | |
238 * d8P' `Y8 `888. .8' `88. .888' `888' `Y8b d8P' `Y8b `888' d8P' `Y8 | |
239 * Y88bo. `888. .8' 888b d'888 888 888 888 888 888 Y88bo. | |
240 * `"Y8888o. `888.8' 8 Y88. .P 888 888oooo888' 888 888 888 `"Y8888o. | |
241 * `"Y88b `888' 8 `888' 888 888 `88b 888 888 888 `"Y88b | |
242 * oo .d8P 888 8 Y 888 888 .88P `88b d88' 888 o oo .d8P | |
243 * 8""88888P' o888o o8o o888o o888bood8P' `Y8bood8P' o888ooooood8 8""88888P' | |
244 * | |
245 */ | |
246 | |
247 #define levlim(l) if (PR_LEV >= l) return; | |
248 #define P_LEN (path -> sel_length) | |
249 #define P_IND (path -> sel_index) | |
250 #define P_ALC (path -> prg_allocbits) | |
251 #define P_LEV (path -> prg_level) | |
252 #define P_PIND (path -> prg_index) | |
253 #define P_DATA (path -> prg_data) | |
254 #define P_OWNER (path -> owner) | |
255 #define P_CHILD (path -> child) | |
256 #define PR_START (P_RUNNING -> prg_start) | |
257 #define PR_LEV (P_RUNNING -> prg_level) | |
258 | |
259 static void swaps(Path path) | |
260 { | |
261 unsigned int i = 0; | |
262 unsigned int report = 0; | |
263 levlim(1) | |
264 if (P_LEN == 1) return; | |
265 if (P_LEN <= BITS_IN_CELL) | |
266 { | |
267 unsigned int half_len = P_LEN / 2; | |
268 write_by_bit_index(path, P_IND, P_LEN, read_by_bit_index(path, P_IND, half_len) | (read_by_bit_index(path, P_IND + half_len, half_len) << half_len)); | |
269 return; | |
270 } | |
271 while (i < ((P_LEN / BITS_IN_CELL) / 2)) | |
272 { | |
273 report = P_DATA[(P_IND / BITS_IN_CELL) + i]; | |
274 P_DATA[(P_IND / BITS_IN_CELL) + i] = P_DATA[(P_IND / BITS_IN_CELL) + ((P_LEN / BITS_IN_CELL) / 2) + i]; | |
275 P_DATA[(P_IND / BITS_IN_CELL) + ((P_LEN / BITS_IN_CELL) / 2) + i++] = report; | |
276 } | |
277 } | |
278 | |
279 static void later(Path path) | |
280 { | |
281 if (algn(path) || (PR_LEV >= 4)) | |
282 P_IND += P_LEN; | |
283 else | |
284 merge(path); | |
285 } | |
286 | |
287 static void merge(Path path) | |
288 { | |
289 levlim(7) | |
290 if (P_LEN < P_ALC) | |
291 { | |
292 if (!algn(path)) | |
293 P_IND -= P_LEN; | |
294 P_LEN <<= 1; | |
295 return; | |
296 } | |
297 if (P_OWNER == NULL) | |
298 return; | |
299 P_WRITTEN = P_OWNER; | |
300 (P_WRITTEN->sel_length) = 1; | |
301 (P_WRITTEN->sel_index) = 1; | |
302 } | |
303 | |
304 static void sifts(Path path) | |
305 { | |
306 unsigned int write = P_IND; | |
307 unsigned int read = 0; | |
308 levlim(5) | |
309 while(write<P_ALC) | |
310 { | |
311 if (write+read<P_ALC) | |
312 while(!read_by_bit_index(path, write+read, 4)) | |
313 read += 4; | |
314 if(read) | |
315 write_by_bit_index(path, write, 4, (write+read<P_ALC)?read_by_bit_index(path, write+read, 4):0); | |
316 write += 4; | |
317 read += 4; | |
318 } | |
319 } | |
320 | |
321 static void execs(Path path, Path caller) | |
322 { | |
323 unsigned int tempNum1 = 0; /* Expedite calculation */ | |
324 levlim(8) /* Level operation checking */ | |
325 P_RUNNING = path; /* Set running */ | |
326 | |
327 if (P_CHILD == NULL) /* If there is no child */ | |
328 { | |
329 if ((P_CHILD = (calloc(1, sizeof(struct PATH)))) == NULL) /* Allocate memory space */ | |
330 { /* Cover error case */ | |
331 printf("FATAL ERROR: Unable to allocate memory."); | |
332 return; | |
333 } | |
334 memcpy(P_CHILD, &NEW_PATH, sizeof(struct PATH)); /* Copy over initialization data */ | |
335 path->child->owner = path; /* Set owner of this new Path */ | |
336 path->child->prg_floor = (path->prg_floor) + 1; /* Set floor of this new Path */ | |
337 path->child->prg_data = calloc(1, sizeof(unsigned int)); /* Set data of this new Path */ | |
338 } | |
339 | |
340 P_WRITTEN = P_CHILD; /* Set this as written on */ | |
341 P_PIND = (P_IND / 4); /* Set program pointer. Rounds down.x */ | |
342 PR_START = P_PIND; /* Track start position */ | |
343 | |
344 for (; doloop && P_PIND < (P_ALC / 4) && path != NULL && P_WRITTEN != NULL ; P_PIND++) /* Execution Loop */ | |
345 { | |
346 tempNum1 = (P_RUNNING->prg_index); | |
347 command = ((P_RUNNING->prg_data)[(tempNum1 * 4) / BITS_IN_CELL] >> (BITS_IN_CELL - ((tempNum1 * 4) % BITS_IN_CELL) - 4)) & mask(4); /* Calculate command */ | |
348 | |
349 if (command == 5) | |
350 execs(P_WRITTEN, path); | |
351 else if (command != 0) | |
352 functions[command](P_WRITTEN); | |
353 } | |
354 if (caller == NULL) | |
355 { | |
356 free(P_CHILD); | |
357 P_CHILD = NULL; | |
358 return; | |
359 } | |
360 if (!doloop) | |
361 { | |
362 free(P_CHILD); | |
363 P_CHILD = NULL; | |
364 doloop = 1; | |
365 } | |
366 P_RUNNING = caller; | |
367 P_WRITTEN = caller->child; | |
368 return; | |
369 } | |
370 | |
371 static void delev(Path path) | |
372 { | |
373 if (PR_LEV > 0) PR_LEV--; | |
374 } | |
375 | |
376 static void equal(Path path) | |
377 { | |
378 levlim(5) | |
379 if (read_by_bit_index(path, P_IND, 1) ^ read_by_bit_index(path, P_IND + P_LEN - 1, 1)) | |
380 skip(); | |
381 } | |
382 | |
383 static void halve(Path path) | |
384 { | |
385 levlim(7) | |
386 if (P_LEN > 1) | |
387 { | |
388 P_LEN /= 2; | |
389 return; | |
390 } | |
391 if (P_CHILD == NULL) | |
392 return; | |
393 P_WRITTEN = P_CHILD; | |
394 (P_WRITTEN->sel_length) = (P_WRITTEN->prg_allocbits); | |
395 } | |
396 | |
397 static void uplev(Path path) | |
398 { | |
399 levlim(9) | |
400 PR_LEV++; | |
401 (P_RUNNING->prg_index) = PR_START - 1; | |
402 } | |
403 | |
404 static void reads(Path path) | |
405 { | |
406 int pos = P_IND; | |
407 levlim(6) | |
408 if (P_LEN < 8) | |
409 { | |
410 char* out = bin(read_by_bit_index(path, pos, P_LEN)); | |
411 printf("%s", &out[strlen(out) - P_LEN]); | |
412 return; | |
413 } | |
414 for (; pos < (P_IND + P_LEN); pos += 8) | |
415 putchar(read_by_bit_index(path, pos, 8)); | |
416 } | |
417 | |
418 static void dealc(Path path) | |
419 { | |
420 levlim(2) | |
421 if (P_ALC == 1) | |
422 { | |
423 int report = read_by_bit_index(path, 0, 1); | |
424 if ((P_RUNNING->owner) != NULL) | |
425 { | |
426 unsigned int ownind = ((P_RUNNING->owner)->prg_index); | |
427 write_by_bit_index(P_RUNNING->owner, (ownind) * 4, 4, report); | |
428 } | |
429 free(P_DATA); | |
430 P_DATA = NULL; | |
431 doloop = 0; | |
432 return; | |
433 } | |
434 P_ALC >>= 1; | |
435 if (P_ALC <= 8) | |
436 realloc(P_DATA, 1); | |
437 else | |
438 realloc(P_DATA, P_ALC / 8); | |
439 if (P_LEN > 1) | |
440 halve(path); | |
441 if ((P_IND + P_LEN) > P_ALC) | |
442 P_IND -= P_ALC; | |
443 } | |
444 | |
445 static void split(Path path) | |
446 { | |
447 if (PR_LEV < 1) | |
448 { | |
449 unsigned int len = P_LEN; | |
450 if (len == 1) | |
451 { | |
452 if (P_CHILD == NULL) | |
453 return; | |
454 P_WRITTEN = P_CHILD; | |
455 (P_WRITTEN->sel_length) = (P_WRITTEN->prg_allocbits); | |
456 split(P_WRITTEN); | |
457 halve(P_WRITTEN); | |
458 return; | |
459 } | |
460 if (len <= BITS_IN_CELL) | |
461 { | |
462 write_by_bit_index(path, P_IND, len >> 1, mask(len)); | |
463 write_by_bit_index(path, P_IND + (len >> 1), len >> 1, ~mask(len)); | |
464 } | |
465 else | |
466 { | |
467 unsigned int leftIndex = (P_IND / BITS_IN_CELL); | |
468 unsigned int rightIndex = leftIndex + (len / BITS_IN_CELL) - 1; | |
469 while (leftIndex < rightIndex) | |
470 { | |
471 P_DATA[leftIndex++] = 0xFFFFFFFF; | |
472 P_DATA[rightIndex--] = 0; | |
473 } | |
474 } | |
475 } | |
476 halve(path); | |
477 } | |
478 | |
479 static void polar(Path path) | |
480 { | |
481 levlim(3) | |
482 if (!(read_by_bit_index(path, P_IND, 1) && !read_by_bit_index(path, P_IND + P_LEN - 1, 1))) | |
483 skip(); | |
484 } | |
485 | |
486 static void doalc(Path path) | |
487 { | |
488 unsigned int new_cell_count = 0; | |
489 unsigned int* new_data_pointer = NULL; | |
490 levlim(1) | |
491 P_ALC <<= 1; | |
492 | |
493 if (P_ALC <= BITS_IN_CELL) | |
494 new_cell_count = BITS_IN_CELL / BITS_IN_BYTE; | |
495 else | |
496 new_cell_count = P_ALC / BITS_IN_BYTE; | |
497 | |
498 new_cell_count /= sizeof(unsigned int); | |
499 | |
500 if ((new_data_pointer = calloc(new_cell_count, sizeof(unsigned int))) == NULL) | |
501 { | |
502 printf("Error allocating %d bytes: ", new_cell_count * sizeof(unsigned int)); | |
503 perror(""); | |
504 abort(); | |
505 } | |
506 | |
507 if (new_cell_count > 1) | |
508 memcpy(new_data_pointer, P_DATA, new_cell_count * sizeof(unsigned int) / 2); | |
509 else | |
510 memcpy(new_data_pointer, P_DATA, sizeof(unsigned int)); | |
511 | |
512 P_DATA = new_data_pointer; | |
513 | |
514 merge(path); | |
515 } | |
516 | |
517 static void input(Path path) | |
518 { | |
519 int i = P_IND; | |
520 levlim(6) | |
521 if (P_LEN < 8) | |
522 { | |
523 write_by_bit_index(path, P_IND, P_LEN, getInput()); | |
524 return; | |
525 } | |
526 for (; i < (P_IND + P_LEN); i += 8) | |
527 write_by_bit_index(path, i, 8, getInput()); | |
528 } | |
529 | |
530 /*** | |
531 * oooooooooooo ooooooooooooo .oooooo. | |
532 * `888' `8 8' 888 `8 d8P' `Y8b | |
533 * 888 888 888 | |
534 * 888oooo8 888 888 | |
535 * 888 " 888 888 | |
536 * 888 o 888 `88b ooo | |
537 * o888ooooood8 o888o `Y8bood8P' | |
538 */ | |
539 | |
540 char algn(Path path) | |
541 { | |
542 return P_IND % (P_LEN << 1) == 0; | |
543 } | |
544 | |
545 unsigned int mask(int length) | |
546 { | |
547 if (length < BITS_IN_CELL) return ((int)1 << length) - 1; | |
548 else return 0xFFFFFFFF; | |
549 } | |
550 | |
551 unsigned int read_by_bit_index(Path path, unsigned int i, unsigned int len) | |
552 { | |
553 return (P_DATA[i / BITS_IN_CELL] >> (BITS_IN_CELL - (i % BITS_IN_CELL) - len)) & mask(len); | |
554 } | |
555 | |
556 static void write_by_bit_index(Path path, unsigned int i, unsigned int len, unsigned int write) | |
557 { | |
558 int shift = BITS_IN_CELL - (i % BITS_IN_CELL) - len; | |
559 if (len > BITS_IN_CELL) abort(); | |
560 P_DATA[i / BITS_IN_CELL] &= ~(mask(len) << shift); | |
561 P_DATA[i / BITS_IN_CELL] |= ((write & mask(len)) << shift); | |
562 } | |
563 | |
564 static void skip() | |
565 { | |
566 if (P_RUNNING == NULL) return; | |
567 (P_RUNNING->prg_index)++; | |
568 } |