Last active
February 24, 2020 21:28
-
-
Save Johann150/70d6f90531ca06af3965057b81bc3517 to your computer and use it in GitHub Desktop.
https://esolangs.org/wiki/BTree implementation in C89 aka C90 aka ANSI C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<stdio.h> | |
#include<stdlib.h> | |
#include<ctype.h> | |
#include<math.h> | |
#include<string.h> | |
#include<stdint.h> | |
void skip_whitespace(FILE* f){ | |
char c; | |
while(!feof(f)&&isspace(c=getc(f))); | |
if(!feof(f)){ | |
/* this will always take one character too much, so put it back */ | |
ungetc(c,f); | |
} | |
} | |
/* returns the number of nodes read */ | |
int parse(FILE* f,char*** p_tree){ | |
int nodes=0; | |
char** tree=NULL; | |
while(!feof(f)){ | |
{/* scope the 'new' variable */ | |
char** new=realloc(tree,(++nodes)*sizeof(char*)); | |
if(NULL==new){ | |
perror("allocating new node"); | |
goto parse_error; | |
}else{ | |
tree=new; | |
} | |
} | |
tree[nodes-1]=calloc(1,sizeof(char)); | |
/* error checks */ | |
if(NULL==tree[nodes-1]){ | |
perror("allocating new buffer"); | |
goto parse_error; | |
} | |
int i=1; | |
int again=1; | |
while(again){ | |
skip_whitespace(f);/* ignore whitespace */ | |
if(feof(f)) break; | |
/* assume this is just a normal node */ | |
again=0; | |
tree[nodes-1][i-1]=getc(f); | |
/* check assumption and make corretions if needed */ | |
switch(tree[nodes-1][i-1]){ | |
case '{': | |
/* skip comment */ | |
while(!feof(f)&&getc(f)!='}'); | |
again=1;/* did not read a node yet */ | |
break; | |
case ';':{ | |
void* new=realloc(tree[nodes-1],++i*sizeof(char)); | |
if(NULL==new){ | |
perror("scanning node"); | |
goto parse_error; | |
}else{ | |
/* reallocation was successfull */ | |
tree[nodes-1]=new; | |
skip_whitespace(f);/* ignore whitespace */ | |
if(feof(stdin)){ | |
fputs("unexpected EOF\n",stderr); | |
goto parse_error; | |
} | |
tree[nodes-1][i-2]=getc(f);/* index i-1 to adjust for the reallocation */ | |
again=1;/* semicolon means there is more coming */ | |
} | |
break; | |
} | |
default: | |
i++; | |
break; | |
} | |
} | |
skip_whitespace(f);/* so we do not have to allocate an unnecessary node */ | |
} | |
*p_tree=tree; | |
return nodes; | |
parse_error:/* do some cleanup before returning */ | |
free(tree);/* the tree scanned this far is unusable, so trash it */ | |
return 0; | |
} | |
typedef struct{ | |
int_fast8_t* val; | |
unsigned cap,len; | |
} deque; | |
int resize(deque* d,unsigned size){ | |
if(size==d->cap) return 1; | |
int_fast8_t* new=realloc(d->val,size*sizeof(int_fast8_t)); | |
if(NULL==new&&size>0){ | |
perror("allocating deque"); | |
return 0; | |
}else{ | |
d->val=new; | |
d->cap=size; | |
return 1; | |
} | |
} | |
void run(char** n,int size){ | |
int_fast8_t A=0,B=0; | |
deque d; | |
d.val=NULL; | |
d.cap=0; | |
d.len=0; | |
resize(&d,8); | |
int current=0; | |
while(current<size&¤t>=0){ | |
int i; | |
for(i=0;i<strlen(n[current]);i++){ | |
switch(n[current][i]){ | |
case '0':/* Set A to 0. */ | |
A=0; | |
break; | |
case '-':/* Set A to -1. */ | |
A=-1; | |
break; | |
case '+':/* Set A to +1. */ | |
A=1; | |
break; | |
case '^':{/* Exchange the content of A and B. */ | |
int_fast8_t temp=B; | |
B=A; | |
A=temp; | |
break; | |
} | |
case 'a':/* Insert the content of A at the end of the deque. */ | |
d.val[d.len++]=A; | |
if(d.len==d.cap&&!resize(&d,d.cap+8)){ | |
/* deque is full, but resizing failed */ | |
return; | |
} | |
break; | |
case 'A':/* Remove the element at the start of the deque and put it in B, or 0 if the deque is empty. */ | |
if(0==d.len){ | |
B=0; | |
}else{ | |
B=d.val[0]; | |
/* remove first element, other elements have to be shuffled up */ | |
memmove(d.val,d.val+1,--d.len); | |
} | |
break; | |
case 'b':/* Insert the content of A at the start of the deque. */ | |
memmove(d.val+1,d.val,d.len++);/* move all elements of deque one element up */ | |
d.val[0]=A;/* insert A accumulator */ | |
break; | |
case 'B':/* Remove the element at the end of the deque and put it in B, or 0 if the deque is empty. */ | |
if(0==d.len){ | |
B=0; | |
}else{ | |
B=d.val[--d.len]; | |
} | |
break; | |
case '&':/* Set A to the minimum of A and B (ternary AND). */ | |
if(B<A) | |
A=B; | |
break; | |
case '|':/* Set A to the maximum of A and B (ternary OR). */ | |
if(B>A) | |
A=B; | |
break; | |
case '=':/* Set A to 1 if A and B are equal, else -1. */ | |
if(A==B){ | |
A=1; | |
}else{ | |
A=-1; | |
} | |
break; | |
case '!':/* Multiply A by -1 (ternary NOT). */ | |
A*=-1; | |
break; | |
case 'i':{/* Input a ternary number (-, 0 or +) and put it in A. */ | |
char c; | |
do{ | |
c=getchar(); | |
}while(c!='-'&&c!='+'&&c!='0'); | |
switch(c){ | |
case '0': | |
A=0; | |
break; | |
case '-': | |
A=-1; | |
break; | |
case '+': | |
A=1; | |
break; | |
} | |
break; | |
} | |
case 'o':/* Output the content of A (-, 0 or +). */ | |
if(A==0){ | |
printf("0"); | |
}else if(A<0){ | |
printf("-"); | |
}else{/* A<0 */ | |
printf("+"); | |
} | |
break; | |
} | |
} | |
/* select next node */ | |
if(A==0){ | |
/* parent */ | |
current=(current-1)>>1;/* same as integer division by 2 */ | |
}else{ | |
current=(current+1)*2-(-1==A);/* select left if A==-1, else select right */ | |
} | |
} | |
} | |
int main(int argc,char** argv){ | |
if(argc<2){ | |
fputs("missing file argument\n",stderr); | |
return EXIT_FAILURE; | |
}else{ | |
FILE* f=fopen(argv[1],"r"); | |
if(NULL==f){ | |
perror("opening file"); | |
return EXIT_FAILURE; | |
}else{ | |
char** n=NULL; | |
int nodes=parse(f,&n); | |
run(n,nodes); | |
} | |
} | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.PHONY: all run | |
all: BTree | |
run: all truth.btr | |
./BTree truth.btr | |
BTree: BTree.c | |
gcc BTree.c -lm -o BTree -ggdb -ansi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ BTree truth machine } | |
{ "-" is 0 and "+" is 1 } | |
;i;aA | |
o ;^;o;^- | |
. . 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment