Mercurial > repo
changeset 7618:9643375f9afa
<Kaynato> mv Mcd6MMB5 daoyu.c
author | HackBot |
---|---|
date | Fri, 29 Apr 2016 01:09:47 +0000 |
parents | f36d749de05d |
children | fc0dee1dcb96 |
files | Mcd6MMB5 daoyu.c |
diffstat | 2 files changed, 566 insertions(+), 609 deletions(-) [+] |
line wrap: on
line diff
--- a/Mcd6MMB5 Fri Apr 29 01:09:35 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,569 +0,0 @@ -/* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* -* DaoLanguage / Daoyu Compiler and Interpreter. -* Kaynato - 2016 -* See splash() for details. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#define DEFAULT_INTERPRET_CELL_LENGTH 32 -#define BITS_IN_BYTE 8 -#define BITS_IN_CELL (sizeof(unsigned long) * 8) -#define BYTE_MASK 0xff -#define INPUT_DELIMITER '@' - -typedef struct PATH -{ - struct PATH* owner; /* OWNER PROGRAM */ - struct PATH* child; /* CHILD PROGRAM */ - unsigned long* prg_data; /* DATA */ - unsigned long prg_allocbits; /* OPEN DATA BITS*/ - unsigned long prg_index; /* INSTRUCTION POINTER*/ - unsigned char prg_level; /* OPERATING LEVEL */ - unsigned long sel_length; /* LENGTH OF SELECTION*/ - unsigned long sel_index; /* INDEX OF SELECTION*/ - unsigned int prg_floor; /* FLOOR OF PATH */ - unsigned long prg_start; /* START OF RUNNING */ -} Pathstrx; - -typedef Pathstrx* Path; - -static void interpret(char*); - -static void swaps(Path), later(Path), merge(Path), sifts(Path), delev(Path), equal(Path), halve(Path); -static void uplev(Path), reads(Path), dealc(Path), split(Path), polar(Path), doalc(Path), input(Path), execs(Path, Path); - -char getInput(); -char algn(Path); -char getChar(unsigned char); -char* bin(unsigned long); -char* str_dup(char *s); -char* l_to_str(unsigned long, unsigned char, unsigned char); -static void skip(); -static void write_by_bit_index(Path, unsigned long, unsigned long, unsigned long); -unsigned char getNybble(char); -unsigned long read_by_bit_index(Path, unsigned long, unsigned long); -unsigned long mask(int); -unsigned long ptwo_round(unsigned long); - -static unsigned char command = 0; -static int doloop = 1; - -typedef void(*PathFunc)(Path); - -static PathFunc functions[16] = \ - {NULL, swaps, later, merge, \ - sifts, NULL , delev, equal, \ - halve, uplev, reads, dealc, \ - split, polar, doalc, input}; - -const struct PATH NEW_PATH = { NULL, NULL, NULL, 1, 0, 0, 1, 0, 0, 0 }; - -static Path P_RUNNING = NULL, - P_WRITTEN = NULL; - -static const char* symbols = ".!/)%#>=(<:S[*$;"; - -static char* inputptr = NULL; - -/* Run argv[0] as code. Input separated by '!' and once empty reads the null character. */ -int main(int argc, char * argv[]) -{ - char* i = argv[1]; - - /* No argument(s)? */ - if (argc < 2) - return 0; - - /* Seek input until it either points to delimiter or NUL */ - while (*i && *i != INPUT_DELIMITER) i++; - - /* If it is the input delimiter then put the inputptr there*/ - if (*i == INPUT_DELIMITER) - inputptr = ++i; - - interpret(argv[1]); - return 0; -} - -#define rc(r,c) case c: return r; - -unsigned char getNybble(char ch) -{ - switch (ch) - { - rc(0x0, '.') rc(0x1, '!') rc(0x2, '/') rc(0x3, ']': case ')') - rc(0x4, '%') rc(0x5, '#') rc(0x6, '>') rc(0x7, '=') - rc(0x8, '(') rc(0x9, '<') rc(0xA, ':') rc(0xB, 'S') - rc(0xC, '[') rc(0xD, '*') rc(0xE, '$') rc(0xF, ';') - default: return 0x0; - } -} - -void interpret(char* input) -{ - unsigned long length = 0; /* How many bytes in input */ - - /* Initialize path */ - struct PATH newpath = NEW_PATH; - Path dao = &newpath; - - /* Seek end of program input */ - while (input[length] && input[length] != INPUT_DELIMITER) length++; - - /* Terminate empty program */ - if (length == 0) return; - - /* Get necessary byte number from nybbles */ - length = ptwo_round((length+1) / 2); - - /* Set bit length of path */ - (dao->prg_allocbits) = length * 8; - - /* Prevent zero-sized allocation */ - if (length % sizeof(unsigned long) != 0) - length = sizeof(unsigned long); - - /* Allocate bytes for data array */ - if (((dao->prg_data) = calloc(length, 1)) == NULL) - { - printf("Error allocating %d bytes: ", length); - perror(""); - abort(); - } - - /* Copy over data */ - for (length = 0; input[length] && input[length] != INPUT_DELIMITER; length++) - { - int hex = getNybble(input[length]); - write_by_bit_index(dao, 4*length, 4, hex); - } - - P_RUNNING = dao; /* For the sake of levlim */ - - /***************************************************** EXECUTE ******************************************************/ - execs(dao, NULL); - free((dao->prg_data)); - (dao -> prg_data) = NULL; - /********************************************************************************************************************/ - -} - -unsigned long ptwo_round(unsigned long x) -{ - unsigned long rounded = x; /* Initialize bytes_alloc with the file_size value. */ - unsigned long shift = 0; /* Shift for first one of file size for rounding */ - - while ((rounded >> 1) != 0) /* Determine leftmost '1' bit of file size. */ - { /* */ - rounded >>= 1; /* Shift right until the next shift zeroes it. */ - shift++; /* Keep track of shifts. */ - } /* */ - rounded <<= shift; /* Unshift. */ - if (x != rounded) /* If not a power of two, round up. */ - rounded <<= 1; - - return rounded; -} - -char getInput() -{ - /* if null return zero */ - if (!inputptr) - return 0; - - /* If not zero then return-advance */ - if (*inputptr) - return *inputptr++; - - inputptr = NULL; - return 0; -} - -/*** - * oooooooooooo ooooooooooooo .oooooo. - * `888' `8 8' 888 `8 d8P' `Y8b - * 888 888 888 - * 888oooo8 888 888 - * 888 " 888 888 - * 888 o 888 `88b ooo - * o888ooooood8 o888o `Y8bood8P' - * - */ - -#define roc(o,v,c) case o:c=v; return &c; - -char *str_dup (char *s) { - char *d = malloc (strlen (s) + 1); /*Allocate memory */ - if (d != NULL) strcpy (d,s); /*Copy string if okay */ - return d; /*Return new memory */ -} - -char* bin(unsigned long val) { return l_to_str(val, 32, 2); } - -char getChar(unsigned char ch) -{ - if (ch > 0xF) return '?'; - return symbols[ch]; -} - -char* l_to_str(unsigned long val, unsigned char len, unsigned char radix) -{ - static char buf[32] = { '0' }; - int i = 33; - for (; val && i; --i, val /= radix) - buf[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"[val % radix]; - for (; i; i--) - buf[i] = '0'; - return &buf[2 + (32 - len)]; -} - -/*** - * .oooooo..o oooooo oooo ooo ooooo oooooooooo. .oooooo. ooooo .oooooo..o - * d8P' `Y8 `888. .8' `88. .888' `888' `Y8b d8P' `Y8b `888' d8P' `Y8 - * Y88bo. `888. .8' 888b d'888 888 888 888 888 888 Y88bo. - * `"Y8888o. `888.8' 8 Y88. .P 888 888oooo888' 888 888 888 `"Y8888o. - * `"Y88b `888' 8 `888' 888 888 `88b 888 888 888 `"Y88b - * oo .d8P 888 8 Y 888 888 .88P `88b d88' 888 o oo .d8P - * 8""88888P' o888o o8o o888o o888bood8P' `Y8bood8P' o888ooooood8 8""88888P' - * - */ - -#define levlim(l) if (PR_LEV >= l) return; -#define P_LEN (path -> sel_length) -#define P_IND (path -> sel_index) -#define P_ALC (path -> prg_allocbits) -#define P_LEV (path -> prg_level) -#define P_PIND (path -> prg_index) -#define P_DATA (path -> prg_data) -#define P_OWNER (path -> owner) -#define P_CHILD (path -> child) -#define PR_START (P_RUNNING -> prg_start) -#define PR_LEV (P_RUNNING -> prg_level) - -static void swaps(Path path) -{ - unsigned int i = 0; - unsigned long report = 0; - levlim(1) - if (P_LEN == 1) return; - if (P_LEN <= BITS_IN_CELL) - { - unsigned long half_len = P_LEN / 2; - 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)); - return; - } - while (i < ((P_LEN / BITS_IN_CELL) / 2)) - { - report = P_DATA[(P_IND / BITS_IN_CELL) + i]; - P_DATA[(P_IND / BITS_IN_CELL) + i] = P_DATA[(P_IND / BITS_IN_CELL) + ((P_LEN / BITS_IN_CELL) / 2) + i]; - P_DATA[(P_IND / BITS_IN_CELL) + ((P_LEN / BITS_IN_CELL) / 2) + i++] = report; - } -} - -static void later(Path path) -{ - if (algn(path) || (PR_LEV >= 4)) P_IND += P_LEN; - else merge(path); -} - -static void merge(Path path) -{ - levlim(7) - if (P_LEN < P_ALC) - { - if (!algn(path)) - P_IND -= P_LEN; - P_LEN <<= 1; - return; - } - if (P_OWNER == NULL) - return; - P_WRITTEN = P_OWNER; - (P_WRITTEN->sel_length) = 1; - (P_WRITTEN->sel_index) = 1; -} - -static void sifts(Path path) -{ - unsigned long write = P_IND; - unsigned long read = 0; - levlim(5) - while(write<P_ALC) - { - while(!read_by_bit_index(path, write+read, 4)) - read += 4; - if(read) - write_by_bit_index(path, write, 4, (write+read<P_ALC)?read_by_bit_index(path, write+read, 4):0); - write += 4; - read += 4; - } -} - -static void execs(Path path, Path caller) -{ - /***************************************************************EXECUTION LOOP***************************************************************/ - unsigned long tempNum1 = 0; /* Expedite calculation */ - levlim(8) /* Level operation checking */ - P_RUNNING = path; /* Set running */ - - if (P_CHILD == NULL) /* If there is no child */ - { - if ((P_CHILD = (calloc(1, sizeof(struct PATH)))) == NULL) /* Allocate memory space */ - { /* Cover error case */ - printf("FATAL ERROR: Unable to allocate memory."); - return; - } - memcpy(P_CHILD, &NEW_PATH, sizeof(struct PATH)); /* Copy over initialization data */ - (*(*path).child).owner = path; /* Set owner of this new Path */ - (*(*path).child).prg_floor = (path->prg_floor) + 1; /* Set floor of this new Path */ - (*(*path).child).prg_data = calloc(1, sizeof(unsigned long)); /* Set data of this new Path */ - } - - P_WRITTEN = P_CHILD; /* Set this as written on */ - P_PIND = (P_IND / 4); /* Set program pointer. Rounds down.x */ - PR_START = P_PIND; /* Track start position */ - - for (; doloop && P_PIND < (P_ALC / 4) && path != NULL && P_WRITTEN != NULL ; P_PIND++) /* Execution Loop */ - { - tempNum1 = (P_RUNNING->prg_index); - command = ((P_RUNNING->prg_data)[(tempNum1 * 4) / 32] >> (32 - ((tempNum1 * 4) % 32) - 4)) & mask(4); /* Calculate command */ - - if (command == 5) - execs(P_WRITTEN, path); - else if (command != 0) - functions[command](P_WRITTEN); - } - if (caller == NULL) - { - free(P_CHILD); - P_CHILD = NULL; - return; - } - if (!doloop) - { - free(P_CHILD); - P_CHILD = NULL; - doloop = 1; - } - P_RUNNING = caller; - P_WRITTEN = caller->child; - return; -} - -static void delev(Path path) -{ - if (PR_LEV > 0) PR_LEV--; -} - -static void equal(Path path) -{ - levlim(5) - if (read_by_bit_index(path, P_IND, 1) ^ read_by_bit_index(path, P_IND + P_LEN - 1, 1)) - skip(); -} - -static void halve(Path path) -{ - levlim(7) - if (P_LEN > 1) - { - P_LEN /= 2; - return; - } - if (P_CHILD == NULL) - return; - P_WRITTEN = P_CHILD; - (P_WRITTEN->sel_length) = (P_WRITTEN->prg_allocbits); -} - -static void uplev(Path path) -{ - levlim(9) - PR_LEV++; - (P_RUNNING->prg_index) = PR_START - 1; -} - -static void reads(Path path) -{ - long pos = P_IND; - levlim(6) - if (P_LEN < 8) - { - char* out = bin(read_by_bit_index(path, pos, P_LEN)); - printf("%s", &out[strlen(out) - P_LEN]); - return; - } - for (; pos < (P_IND + P_LEN); pos += 8) - putchar(read_by_bit_index(path, pos, 8)); -} - -static void dealc(Path path) -{ - levlim(2) - if (P_ALC == 1) - { - int report = read_by_bit_index(path, 0, 1); - if ((P_RUNNING->owner) != NULL) - { - unsigned long ownind = ((P_RUNNING->owner)->prg_index); - write_by_bit_index(P_RUNNING->owner, (ownind) * 4, 4, report); - } - free(P_DATA); - P_DATA = NULL; - doloop = 0; - return; - } - P_ALC >>= 1; - if (P_ALC <= 8) - realloc(P_DATA, 1); - else - realloc(P_DATA, P_ALC / 8); - if (P_LEN > 1) - halve(path); - if ((P_IND + P_LEN) > P_ALC) - P_IND -= P_ALC; -} - -static void split(Path path) -{ - if (PR_LEV < 1) - { - unsigned int len = P_LEN; - if (len == 1) - { - if (P_CHILD == NULL) - return; - P_WRITTEN = P_CHILD; - (P_WRITTEN->sel_length) = (P_WRITTEN->prg_allocbits); - split(P_WRITTEN); - halve(P_WRITTEN); - return; - } - if (len <= BITS_IN_CELL) - { - write_by_bit_index(path, P_IND, len >> 1, mask(len)); - write_by_bit_index(path, P_IND + (len >> 1), len >> 1, ~mask(len)); - } - else - { - unsigned int leftIndex = (P_IND / BITS_IN_CELL); - unsigned int rightIndex = leftIndex + (len / BITS_IN_CELL) - 1; - while (leftIndex < rightIndex) - { - P_DATA[leftIndex++] = 0xFFFFFFFF; - P_DATA[rightIndex--] = 0; - } - } - } - halve(path); -} - -static void polar(Path path) -{ - levlim(3) - if (!(read_by_bit_index(path, P_IND, 1) && !read_by_bit_index(path, P_IND + P_LEN - 1, 1))) - skip(); -} - -static void doalc(Path path) -{ - unsigned long new_cell_count = 0; - unsigned long* new_data_pointer = NULL; - levlim(1) - P_ALC <<= 1; - - if (P_ALC <= BITS_IN_CELL) - new_cell_count = BITS_IN_CELL / BITS_IN_BYTE; - else - new_cell_count = P_ALC / BITS_IN_BYTE; - - new_cell_count /= sizeof(unsigned long); - - if ((new_data_pointer = calloc(new_cell_count, sizeof(unsigned long))) == NULL) - { - printf("Error allocating %d bytes: ", new_cell_count * sizeof(unsigned long)); - perror(""); - abort(); - } - - if (new_cell_count > 1) - memcpy(new_data_pointer, P_DATA, new_cell_count * sizeof(unsigned long) / 2); - else - memcpy(new_data_pointer, P_DATA, sizeof(unsigned long)); - - P_DATA = new_data_pointer; - - merge(path); -} - -static void input(Path path) -{ - int i = P_IND; - levlim(6) - if (P_LEN < 8) - { - write_by_bit_index(path, P_IND, P_LEN, getInput()); - return; - } - for (; i < (P_IND + P_LEN); i += 8) - write_by_bit_index(path, i, 8, getInput()); -} - -/*** - * oooooooooooo ooooooooooooo .oooooo. - * `888' `8 8' 888 `8 d8P' `Y8b - * 888 888 888 - * 888oooo8 888 888 - * 888 " 888 888 - * 888 o 888 `88b ooo - * o888ooooood8 o888o `Y8bood8P' - */ - -char algn(Path path) -{ - return P_IND % (P_LEN << 1) == 0; -} - -unsigned long mask(int length) -{ - if (length < BITS_IN_CELL) return ((int)1 << length) - 1; - else return 0xFFFFFFFF; -} - -unsigned long read_by_bit_index(Path path, unsigned long i, unsigned long len) -{ - return (P_DATA[i / BITS_IN_CELL] >> (BITS_IN_CELL - (i % BITS_IN_CELL) - len)) & mask(len); -} - -static void write_by_bit_index(Path path, unsigned long i, unsigned long len, unsigned long write) -{ - int shift = BITS_IN_CELL - (i % BITS_IN_CELL) - len; - if (len > BITS_IN_CELL) abort(); - P_DATA[i / BITS_IN_CELL] &= ~(mask(len) << shift); - P_DATA[i / BITS_IN_CELL] |= ((write & mask(len)) << shift); -} - -static void skip() -{ - if (P_RUNNING == NULL) return; - (P_RUNNING->prg_index)++; -} \ No newline at end of file
--- a/daoyu.c Fri Apr 29 01:09:35 2016 +0000 +++ b/daoyu.c Fri Apr 29 01:09:47 2016 +0000 @@ -1,43 +1,569 @@ -/*COMPACT_DAOYU_INTERPRETER-KAYNATO_2016*/ +/* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* +* DaoLanguage / Daoyu Compiler and Interpreter. +* Kaynato - 2016 +* See splash() for details. +*/ + #include <stdio.h> #include <stdlib.h> #include <string.h> -#define r return -#define B (S*8) -#define R(c) Y(c)r -#define Q(i,j,k) Y(!(i=calloc(j,k))){printf("CANNOT ALLOCATE %d BYTES: ",j*k);perror("");abort();} -#define M(l) Y(V>=l)r; -#define T typedef -#define H while -#define D p->d -#define A p->a -#define O p->n -#define Y if -#define U p->c -#define N p->l -#define J p->g -#define P p->o -#define K C->b -#define V C->e -T unsigned long L;T void v;T struct ___{struct ___*o;struct ___*c;L* d;L a;L g;L e;L l;L n;L f;L b;}__;T __*_; -#undef T -v b(_),h(_),t(_),u(_),e(_),f(_),g(_),k(_),l(_),n(_),o(_),i(_),j(_),a(_),q(_,_),T(),W(_,L,L,L),(*F[16])(_)={0,b, -h,t,u,0,e,f,g,k,l,n,o,i,j,a};char X(),Z(_),*I;L G(_,L,L),s(L),m=1,x=0,y,z=0,S=sizeof(L);const __ w={0,0,0,1,0 -,0,1,0,0,0};_ C=0,E=0;int main(int argc,char*argv[]){__ i=w;_ p=&i;I=argv[1];R(argc<2)0;H(I[x]&&I[x]-64)x++;R(! -x++)0;y=x/2;H(y/2){y/=2;z++;}y<<=z;x=x/2-y?y*2:y;A=x*8;Y(x%S)x=S;Q(p->d,x,1)x=0;H(I[x]&&I[x]-64){y=I[x];W(p,4*x -++,4,y-33?y-47?y-93?y-41?y-37?y-35?y-62?y-61?y-40?y-60?y-58?y-83?y-91?y-42?y-36?y-59?0:15:14:13:12:11:10:9:8:7: -6:5:4:3:3:2:1);}H(*I&&*I-64)I++;I=*I-64?0:I+1;q(C=p,0);free(D);r 0;}v b(_ p){x=0;M(1)R(N<2);Y(N<=B){y=N/2;W(p,O -,N,G(p,O,y)|(G(p,O+y,y)<<y));r;}H(x<N/B/2){D[x+O/B]=D[x+O/B+N/B/2];D[x+O/B+N/B/2]=D[x+O/B];x++;}}v h(_ p){Y(Z(p -)||V>3){O+=N;r;}t(p);}v t(_ p){M(7)Y(N<A){Y(!Z(p))O-=N;N*=2;r;}R(!P);E=P;E->n=E->l=1;}v u(_ p){x=O;y=0;M(5);H(x -<A){H(!G(p,x+y,4))y+=4;Y(y)W(p,x,4,(x+y<A)?G(p,x+y,4):0);x+=4;y+=4;}}v q(_ p,_ i){y=0;M(8)C=p;Y(!U){Y(!(U=calloc -(1,sizeof(__)))){printf("MEMORY_OVERFLOW\n");r;}memcpy(U,&w,sizeof(__));p->c->o=p;p->c->f=p->f+1;p->c->d=calloc -(1,S);}E=U;J=O/4;K=J;H(m&&J<A/4&&p&&E){y=C->g;z=(C->d[y*4/32]>>(32-((y*4)%32)-4))&s(4);Y(z==5)q(E,p);else Y(z)F -[z](E);J++;}Y(!i){free(U);U=0;r;}Y(!m){free(U);U=0;m=1;}C=i;E=i->c;}v e(_ p){Y(V)V--;}v f(_ p){M(5)Y(G(p,O,1)^G -(p,O+N-1,1))T();}v g(_ p){M(7)Y(N>1){N/=2;r;}R(!U);E=U;E->l=E->a;}v k(_ p){M(9)V++;C->g=K-1;}v l(_ p){M(6)y=O;H -(y<O+N){putchar(G(p,y,8));y+=8;}}v n(_ p){M(2)Y(A==1){Y(!C->o)W(C->o,C->o->g*4,4,G(p,0,1));free(D);m=D=0;r;}A/= -2;realloc(D,A<9?1:A/8);Y(N>1)g(p);Y(O+N>A)O-=A;}v o(_ p){Y(V<1){x=N;Y(x==1){R(!U);E=U;E->l=E->a;o(E);g(E);r;}Y( -x>B){y=O/B;z=y-1+x/B;H(y<z){D[y++]=0xFFFFFFFF;D[z--]=0;}}else{W(p,O,x/2,s(x));W(p,O+(x/2),x/2,~s(x));}}g(p);} v -i(_ p){M(3)Y(!(G(p,O,1)&&!G(p,O+N-1,1)))T();}v j(_ p){L*i=0;M(1)z=0;A*=2;z=(A>B?A:B)/8/S;Q(i,z,S)memcpy(i,D,z>1 -?z*S/2:S);D=i;t(p);}v a(_ p){z=O;M(6);Y(N<8){W(p,O,N,X());r;}H(z<(O+N)){W(p,z,8,X());z+=8;}}char X(){r I&&*I?*I -++:(I=0);}char Z(_ p){r!(O%(N*2));}L s(L i){R(i<B)((int)1<<i)-1;r 0xFFFFFFFF;}L G(_ p,L i,L j){r(D[i/B]>>(B-j-i -%B))&s(j);}v W(_ p,L i,L j,L k){R(j>B);z=B-j-i%B;D[i/B]&=~(s(j)<<z);D[i/B]|=(k&s(j))<<z;}v T(){R(!C);C->g++;} \ No newline at end of file +#include <ctype.h> + +#define DEFAULT_INTERPRET_CELL_LENGTH 32 +#define BITS_IN_BYTE 8 +#define BITS_IN_CELL (sizeof(unsigned long) * 8) +#define BYTE_MASK 0xff +#define INPUT_DELIMITER '@' + +typedef struct PATH +{ + struct PATH* owner; /* OWNER PROGRAM */ + struct PATH* child; /* CHILD PROGRAM */ + unsigned long* prg_data; /* DATA */ + unsigned long prg_allocbits; /* OPEN DATA BITS*/ + unsigned long prg_index; /* INSTRUCTION POINTER*/ + unsigned char prg_level; /* OPERATING LEVEL */ + unsigned long sel_length; /* LENGTH OF SELECTION*/ + unsigned long sel_index; /* INDEX OF SELECTION*/ + unsigned int prg_floor; /* FLOOR OF PATH */ + unsigned long prg_start; /* START OF RUNNING */ +} Pathstrx; + +typedef Pathstrx* Path; + +static void interpret(char*); + +static void swaps(Path), later(Path), merge(Path), sifts(Path), delev(Path), equal(Path), halve(Path); +static void uplev(Path), reads(Path), dealc(Path), split(Path), polar(Path), doalc(Path), input(Path), execs(Path, Path); + +char getInput(); +char algn(Path); +char getChar(unsigned char); +char* bin(unsigned long); +char* str_dup(char *s); +char* l_to_str(unsigned long, unsigned char, unsigned char); +static void skip(); +static void write_by_bit_index(Path, unsigned long, unsigned long, unsigned long); +unsigned char getNybble(char); +unsigned long read_by_bit_index(Path, unsigned long, unsigned long); +unsigned long mask(int); +unsigned long ptwo_round(unsigned long); + +static unsigned char command = 0; +static int doloop = 1; + +typedef void(*PathFunc)(Path); + +static PathFunc functions[16] = \ + {NULL, swaps, later, merge, \ + sifts, NULL , delev, equal, \ + halve, uplev, reads, dealc, \ + split, polar, doalc, input}; + +const struct PATH NEW_PATH = { NULL, NULL, NULL, 1, 0, 0, 1, 0, 0, 0 }; + +static Path P_RUNNING = NULL, + P_WRITTEN = NULL; + +static const char* symbols = ".!/)%#>=(<:S[*$;"; + +static char* inputptr = NULL; + +/* Run argv[0] as code. Input separated by '!' and once empty reads the null character. */ +int main(int argc, char * argv[]) +{ + char* i = argv[1]; + + /* No argument(s)? */ + if (argc < 2) + return 0; + + /* Seek input until it either points to delimiter or NUL */ + while (*i && *i != INPUT_DELIMITER) i++; + + /* If it is the input delimiter then put the inputptr there*/ + if (*i == INPUT_DELIMITER) + inputptr = ++i; + + interpret(argv[1]); + return 0; +} + +#define rc(r,c) case c: return r; + +unsigned char getNybble(char ch) +{ + switch (ch) + { + rc(0x0, '.') rc(0x1, '!') rc(0x2, '/') rc(0x3, ']': case ')') + rc(0x4, '%') rc(0x5, '#') rc(0x6, '>') rc(0x7, '=') + rc(0x8, '(') rc(0x9, '<') rc(0xA, ':') rc(0xB, 'S') + rc(0xC, '[') rc(0xD, '*') rc(0xE, '$') rc(0xF, ';') + default: return 0x0; + } +} + +void interpret(char* input) +{ + unsigned long length = 0; /* How many bytes in input */ + + /* Initialize path */ + struct PATH newpath = NEW_PATH; + Path dao = &newpath; + + /* Seek end of program input */ + while (input[length] && input[length] != INPUT_DELIMITER) length++; + + /* Terminate empty program */ + if (length == 0) return; + + /* Get necessary byte number from nybbles */ + length = ptwo_round((length+1) / 2); + + /* Set bit length of path */ + (dao->prg_allocbits) = length * 8; + + /* Prevent zero-sized allocation */ + if (length % sizeof(unsigned long) != 0) + length = sizeof(unsigned long); + + /* Allocate bytes for data array */ + if (((dao->prg_data) = calloc(length, 1)) == NULL) + { + printf("Error allocating %d bytes: ", length); + perror(""); + abort(); + } + + /* Copy over data */ + for (length = 0; input[length] && input[length] != INPUT_DELIMITER; length++) + { + int hex = getNybble(input[length]); + write_by_bit_index(dao, 4*length, 4, hex); + } + + P_RUNNING = dao; /* For the sake of levlim */ + + /***************************************************** EXECUTE ******************************************************/ + execs(dao, NULL); + free((dao->prg_data)); + (dao -> prg_data) = NULL; + /********************************************************************************************************************/ + +} + +unsigned long ptwo_round(unsigned long x) +{ + unsigned long rounded = x; /* Initialize bytes_alloc with the file_size value. */ + unsigned long shift = 0; /* Shift for first one of file size for rounding */ + + while ((rounded >> 1) != 0) /* Determine leftmost '1' bit of file size. */ + { /* */ + rounded >>= 1; /* Shift right until the next shift zeroes it. */ + shift++; /* Keep track of shifts. */ + } /* */ + rounded <<= shift; /* Unshift. */ + if (x != rounded) /* If not a power of two, round up. */ + rounded <<= 1; + + return rounded; +} + +char getInput() +{ + /* if null return zero */ + if (!inputptr) + return 0; + + /* If not zero then return-advance */ + if (*inputptr) + return *inputptr++; + + inputptr = NULL; + return 0; +} + +/*** + * oooooooooooo ooooooooooooo .oooooo. + * `888' `8 8' 888 `8 d8P' `Y8b + * 888 888 888 + * 888oooo8 888 888 + * 888 " 888 888 + * 888 o 888 `88b ooo + * o888ooooood8 o888o `Y8bood8P' + * + */ + +#define roc(o,v,c) case o:c=v; return &c; + +char *str_dup (char *s) { + char *d = malloc (strlen (s) + 1); /*Allocate memory */ + if (d != NULL) strcpy (d,s); /*Copy string if okay */ + return d; /*Return new memory */ +} + +char* bin(unsigned long val) { return l_to_str(val, 32, 2); } + +char getChar(unsigned char ch) +{ + if (ch > 0xF) return '?'; + return symbols[ch]; +} + +char* l_to_str(unsigned long val, unsigned char len, unsigned char radix) +{ + static char buf[32] = { '0' }; + int i = 33; + for (; val && i; --i, val /= radix) + buf[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"[val % radix]; + for (; i; i--) + buf[i] = '0'; + return &buf[2 + (32 - len)]; +} + +/*** + * .oooooo..o oooooo oooo ooo ooooo oooooooooo. .oooooo. ooooo .oooooo..o + * d8P' `Y8 `888. .8' `88. .888' `888' `Y8b d8P' `Y8b `888' d8P' `Y8 + * Y88bo. `888. .8' 888b d'888 888 888 888 888 888 Y88bo. + * `"Y8888o. `888.8' 8 Y88. .P 888 888oooo888' 888 888 888 `"Y8888o. + * `"Y88b `888' 8 `888' 888 888 `88b 888 888 888 `"Y88b + * oo .d8P 888 8 Y 888 888 .88P `88b d88' 888 o oo .d8P + * 8""88888P' o888o o8o o888o o888bood8P' `Y8bood8P' o888ooooood8 8""88888P' + * + */ + +#define levlim(l) if (PR_LEV >= l) return; +#define P_LEN (path -> sel_length) +#define P_IND (path -> sel_index) +#define P_ALC (path -> prg_allocbits) +#define P_LEV (path -> prg_level) +#define P_PIND (path -> prg_index) +#define P_DATA (path -> prg_data) +#define P_OWNER (path -> owner) +#define P_CHILD (path -> child) +#define PR_START (P_RUNNING -> prg_start) +#define PR_LEV (P_RUNNING -> prg_level) + +static void swaps(Path path) +{ + unsigned int i = 0; + unsigned long report = 0; + levlim(1) + if (P_LEN == 1) return; + if (P_LEN <= BITS_IN_CELL) + { + unsigned long half_len = P_LEN / 2; + 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)); + return; + } + while (i < ((P_LEN / BITS_IN_CELL) / 2)) + { + report = P_DATA[(P_IND / BITS_IN_CELL) + i]; + P_DATA[(P_IND / BITS_IN_CELL) + i] = P_DATA[(P_IND / BITS_IN_CELL) + ((P_LEN / BITS_IN_CELL) / 2) + i]; + P_DATA[(P_IND / BITS_IN_CELL) + ((P_LEN / BITS_IN_CELL) / 2) + i++] = report; + } +} + +static void later(Path path) +{ + if (algn(path) || (PR_LEV >= 4)) P_IND += P_LEN; + else merge(path); +} + +static void merge(Path path) +{ + levlim(7) + if (P_LEN < P_ALC) + { + if (!algn(path)) + P_IND -= P_LEN; + P_LEN <<= 1; + return; + } + if (P_OWNER == NULL) + return; + P_WRITTEN = P_OWNER; + (P_WRITTEN->sel_length) = 1; + (P_WRITTEN->sel_index) = 1; +} + +static void sifts(Path path) +{ + unsigned long write = P_IND; + unsigned long read = 0; + levlim(5) + while(write<P_ALC) + { + while(!read_by_bit_index(path, write+read, 4)) + read += 4; + if(read) + write_by_bit_index(path, write, 4, (write+read<P_ALC)?read_by_bit_index(path, write+read, 4):0); + write += 4; + read += 4; + } +} + +static void execs(Path path, Path caller) +{ + /***************************************************************EXECUTION LOOP***************************************************************/ + unsigned long tempNum1 = 0; /* Expedite calculation */ + levlim(8) /* Level operation checking */ + P_RUNNING = path; /* Set running */ + + if (P_CHILD == NULL) /* If there is no child */ + { + if ((P_CHILD = (calloc(1, sizeof(struct PATH)))) == NULL) /* Allocate memory space */ + { /* Cover error case */ + printf("FATAL ERROR: Unable to allocate memory."); + return; + } + memcpy(P_CHILD, &NEW_PATH, sizeof(struct PATH)); /* Copy over initialization data */ + (*(*path).child).owner = path; /* Set owner of this new Path */ + (*(*path).child).prg_floor = (path->prg_floor) + 1; /* Set floor of this new Path */ + (*(*path).child).prg_data = calloc(1, sizeof(unsigned long)); /* Set data of this new Path */ + } + + P_WRITTEN = P_CHILD; /* Set this as written on */ + P_PIND = (P_IND / 4); /* Set program pointer. Rounds down.x */ + PR_START = P_PIND; /* Track start position */ + + for (; doloop && P_PIND < (P_ALC / 4) && path != NULL && P_WRITTEN != NULL ; P_PIND++) /* Execution Loop */ + { + tempNum1 = (P_RUNNING->prg_index); + command = ((P_RUNNING->prg_data)[(tempNum1 * 4) / 32] >> (32 - ((tempNum1 * 4) % 32) - 4)) & mask(4); /* Calculate command */ + + if (command == 5) + execs(P_WRITTEN, path); + else if (command != 0) + functions[command](P_WRITTEN); + } + if (caller == NULL) + { + free(P_CHILD); + P_CHILD = NULL; + return; + } + if (!doloop) + { + free(P_CHILD); + P_CHILD = NULL; + doloop = 1; + } + P_RUNNING = caller; + P_WRITTEN = caller->child; + return; +} + +static void delev(Path path) +{ + if (PR_LEV > 0) PR_LEV--; +} + +static void equal(Path path) +{ + levlim(5) + if (read_by_bit_index(path, P_IND, 1) ^ read_by_bit_index(path, P_IND + P_LEN - 1, 1)) + skip(); +} + +static void halve(Path path) +{ + levlim(7) + if (P_LEN > 1) + { + P_LEN /= 2; + return; + } + if (P_CHILD == NULL) + return; + P_WRITTEN = P_CHILD; + (P_WRITTEN->sel_length) = (P_WRITTEN->prg_allocbits); +} + +static void uplev(Path path) +{ + levlim(9) + PR_LEV++; + (P_RUNNING->prg_index) = PR_START - 1; +} + +static void reads(Path path) +{ + long pos = P_IND; + levlim(6) + if (P_LEN < 8) + { + char* out = bin(read_by_bit_index(path, pos, P_LEN)); + printf("%s", &out[strlen(out) - P_LEN]); + return; + } + for (; pos < (P_IND + P_LEN); pos += 8) + putchar(read_by_bit_index(path, pos, 8)); +} + +static void dealc(Path path) +{ + levlim(2) + if (P_ALC == 1) + { + int report = read_by_bit_index(path, 0, 1); + if ((P_RUNNING->owner) != NULL) + { + unsigned long ownind = ((P_RUNNING->owner)->prg_index); + write_by_bit_index(P_RUNNING->owner, (ownind) * 4, 4, report); + } + free(P_DATA); + P_DATA = NULL; + doloop = 0; + return; + } + P_ALC >>= 1; + if (P_ALC <= 8) + realloc(P_DATA, 1); + else + realloc(P_DATA, P_ALC / 8); + if (P_LEN > 1) + halve(path); + if ((P_IND + P_LEN) > P_ALC) + P_IND -= P_ALC; +} + +static void split(Path path) +{ + if (PR_LEV < 1) + { + unsigned int len = P_LEN; + if (len == 1) + { + if (P_CHILD == NULL) + return; + P_WRITTEN = P_CHILD; + (P_WRITTEN->sel_length) = (P_WRITTEN->prg_allocbits); + split(P_WRITTEN); + halve(P_WRITTEN); + return; + } + if (len <= BITS_IN_CELL) + { + write_by_bit_index(path, P_IND, len >> 1, mask(len)); + write_by_bit_index(path, P_IND + (len >> 1), len >> 1, ~mask(len)); + } + else + { + unsigned int leftIndex = (P_IND / BITS_IN_CELL); + unsigned int rightIndex = leftIndex + (len / BITS_IN_CELL) - 1; + while (leftIndex < rightIndex) + { + P_DATA[leftIndex++] = 0xFFFFFFFF; + P_DATA[rightIndex--] = 0; + } + } + } + halve(path); +} + +static void polar(Path path) +{ + levlim(3) + if (!(read_by_bit_index(path, P_IND, 1) && !read_by_bit_index(path, P_IND + P_LEN - 1, 1))) + skip(); +} + +static void doalc(Path path) +{ + unsigned long new_cell_count = 0; + unsigned long* new_data_pointer = NULL; + levlim(1) + P_ALC <<= 1; + + if (P_ALC <= BITS_IN_CELL) + new_cell_count = BITS_IN_CELL / BITS_IN_BYTE; + else + new_cell_count = P_ALC / BITS_IN_BYTE; + + new_cell_count /= sizeof(unsigned long); + + if ((new_data_pointer = calloc(new_cell_count, sizeof(unsigned long))) == NULL) + { + printf("Error allocating %d bytes: ", new_cell_count * sizeof(unsigned long)); + perror(""); + abort(); + } + + if (new_cell_count > 1) + memcpy(new_data_pointer, P_DATA, new_cell_count * sizeof(unsigned long) / 2); + else + memcpy(new_data_pointer, P_DATA, sizeof(unsigned long)); + + P_DATA = new_data_pointer; + + merge(path); +} + +static void input(Path path) +{ + int i = P_IND; + levlim(6) + if (P_LEN < 8) + { + write_by_bit_index(path, P_IND, P_LEN, getInput()); + return; + } + for (; i < (P_IND + P_LEN); i += 8) + write_by_bit_index(path, i, 8, getInput()); +} + +/*** + * oooooooooooo ooooooooooooo .oooooo. + * `888' `8 8' 888 `8 d8P' `Y8b + * 888 888 888 + * 888oooo8 888 888 + * 888 " 888 888 + * 888 o 888 `88b ooo + * o888ooooood8 o888o `Y8bood8P' + */ + +char algn(Path path) +{ + return P_IND % (P_LEN << 1) == 0; +} + +unsigned long mask(int length) +{ + if (length < BITS_IN_CELL) return ((int)1 << length) - 1; + else return 0xFFFFFFFF; +} + +unsigned long read_by_bit_index(Path path, unsigned long i, unsigned long len) +{ + return (P_DATA[i / BITS_IN_CELL] >> (BITS_IN_CELL - (i % BITS_IN_CELL) - len)) & mask(len); +} + +static void write_by_bit_index(Path path, unsigned long i, unsigned long len, unsigned long write) +{ + int shift = BITS_IN_CELL - (i % BITS_IN_CELL) - len; + if (len > BITS_IN_CELL) abort(); + P_DATA[i / BITS_IN_CELL] &= ~(mask(len) << shift); + P_DATA[i / BITS_IN_CELL] |= ((write & mask(len)) << shift); +} + +static void skip() +{ + if (P_RUNNING == NULL) return; + (P_RUNNING->prg_index)++; +} \ No newline at end of file