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 }