diff daoyu.c @ 7618:9643375f9afa

<Kaynato> mv Mcd6MMB5 daoyu.c
author HackBot
date Fri, 29 Apr 2016 01:09:47 +0000
parents df13af30c730
children 49eadf845bb9
line wrap: on
line diff
--- 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