/*********************************************************************************************** The Xastha Compiler Beta (Untested, unfinished & completely bleeding edge) Use at your own risk... (c)2005, Gathering of Gray lovepump@gatheringofgray.com Contributors: lovepump Afterburn This implements Xastha, a minimalist language imagined and designed by Enjoi. See http://www.snkenjoi.com/ for details. ************************************************************************************************/ #include #include #include #include #define MEMCHUNK 1024 /* Size of realloc */ #define _MEMCHUNK "1024" #define X_MAXRAND 10 #define ERRORFILE "xastha.errlog" #define NAME "xastha-0.15 BETA" FILE *logfile; char mess[1024]; int exit_error(const char *text) { char out[1100]; printf("Fatal Error: %s\n", text); sprintf(out, "Fatal Error: %s\n", text); fwrite(out, strlen(out), 1, logfile); close(logfile); exit(EXIT_FAILURE); } int warning(const char *text) { char out[1100]; printf("Warning: %s\n", text); sprintf(out, "Warning: %s\n", text); fwrite(out, strlen(out), 1, logfile); } int getnumber(const char* t, int* len) { char *x; int i, j; i = 0; while((t[i] >= '0' && t[i] <= '9') && i < 4) i++; if(i > 3 || i <= 0) return -1; x = (char *)malloc(i + 1); strncpy(x, t, i); x[i] = '\0'; *len = i; return atoi(x); } int range_random(const char *t, int* len) { int a, b, a_len, b_len; a = getnumber(t, &a_len); b = getnumber((t + a_len + 1), &b_len); if(a == -1 || b == -1) return -1; *len = a_len + b_len + 1; srand(time(NULL)); return (rand()%(b-a)+a); } void banner() { printf("\n----------------------------------------------------------------------\n"); printf("\nThe %s Compiler\nBrought to You by Gathering of Gray (c) 2004\n\n", NAME); printf("Implements Xastha, a langauge imagined & created by Enjoi.\n"); printf("\n----------------------------------------------------------------------\n\n"); } void usage() { printf("\n%s Compiler Usage:\n\n", NAME); printf("\t-s\t\tXastha Source Code file\n"); printf("\t-d\t\tDestination File (See -o for output type)\n"); printf("\t-o\t\tIs the Output type , c = C Source, a = ASM, b = Binary\n"); printf("\t-b\t\tEnables Bounds Checking\n"); } int main(int argc, char **argv) { if(argc < 2) { usage(); exit(0); } banner(); char command[1024], realbuf[33], tmp; char *inbuf, *inpos; char c[] = {0x25, 0x63, 0x00}; int ret, numlen, filesize, rand_iter, rands[X_MAXRAND], buf_size = 0; int in = 0; int bufp = 0; int d; int b_flag = 0; char *src_file; char *dst_file; char *out_type; FILE *infile, *outfile; while((d = getopt(argc, argv, "s:d:o:b")) != EOF) { switch(d) { case 's': src_file = optarg; break; case 'd': dst_file = optarg; break; case 'o': out_type = optarg; break; case 'b': b_flag = 1; break; case '?': printf("-s Source File\n-d Dest File\n-o Output Type(C, ASM, Binary\n-b Bound Checking\n"); exit(0); break; } } printf("\n\nSource File = %s\nDestination File = %s\nBounds Checking = %i\nOutput Type = %s\n\n", src_file, dst_file, b_flag, out_type ); /* Done Command line Parsing Here */ if((logfile = fopen(ERRORFILE, "w")) == NULL) { printf("Cannot stat logfile, exiting.\n"); exit(EXIT_FAILURE); } if((infile = fopen(src_file, "r")) == NULL) exit_error("Cannot open source"); fseek(infile, 0, SEEK_END); filesize = ftell(infile); rewind(infile); inbuf = (char *)malloc(filesize+1); ret = fread(inbuf, 1, filesize, infile); if(ret < filesize) { exit_error("File read error."); } inbuf[filesize] = '\0'; if((outfile = fopen("src_file.c", "w")) == NULL) exit_error("Cannot open target file"); buf_size = MEMCHUNK; sprintf(command, "main(){char *p, *buf, *tmp; buf=(char*)malloc(%s);p=buf;", _MEMCHUNK); fwrite(command, strlen(command), 1, outfile); logfile = fopen(ERRORFILE, "w"); inpos = inbuf; while(*inpos != '\0') { sprintf(command, "X"); /*printf("%c: ", *inpos);*/ switch(*inpos) { case('>'): if(b_flag == 1 && bufp >= (buf_size - 1)) { sprintf(command, "realloc(buf, %d);", (MEMCHUNK + buf_size)); buf_size += MEMCHUNK; } sprintf(command, "p++;"); bufp++; break; case('<'): if(b_flag == 1 && bufp <= 0) break; sprintf(command, "p--;"); bufp--; break; case('+'): sprintf(command, "(*p)++;"); break; case('-'): sprintf(command, "(*p)--;"); break; case('.'): sprintf(command, "printf(\"%s\", *p);", c); break; case(','): inpos++; sprintf(command, "*p = '%c';", *inpos); break; case('['): sprintf(command, "tmp = p; while(tmp != 0x00) {"); in++; break; case(']'): if(in > 0) { sprintf(command, "}"); in--; } break; case('^'): sprintf(command, "(*p)+=10;"); break; case('v'): sprintf(command, "(*p)-=10;"); break; case('/'): sprintf(command, "(*p)+=100;"); break; case('\\'): sprintf(command, "(*p)-=100;"); break; case('0'): sprintf(command, "(*p) = 0x00;"); break; case('('): inpos++; ret = getnumber(inpos, &numlen); if(ret < 0) { sprintf(mess, "No terminating bracket at %d", inpos-inbuf); exit_error(mess); } sprintf(command, "printf(\"%c\"); (*p) = 0x00;", ret); inpos+=numlen; break; case('{'): inpos++; rand_iter = 0; while(rand_iter < X_MAXRAND && (*inpos) != '}') { ret = range_random(inpos, &numlen); if(ret < 0) { sprintf(mess, "Range random error at %d", inpos-inbuf); exit_error(mess); } rands[rand_iter] = ret; inpos+=numlen; if((*inpos) == '|') inpos++; rand_iter++; } rand_iter--; srand(time(NULL)); ret = (rand()%(rand_iter+1)); sprintf(command, "(*p) = %d;", rands[ret]); inpos++; break; case('~'): sprintf(command, "memset(buf, 0, %d); p = buf;", buf_size); break; case('?'): srand(time(NULL)); ret = rand(); sprintf(command, "(*p) = %d;", ret); break; case('*'): sprintf(command, "*"); break; case('#'): inpos++; ret = getnumber(inpos, &numlen); if(ret < 0) { sprintf(mess, "Index Error at %d", inpos-inbuf); exit_error(mess); } if((ret+(inpos-inbuf)) >= buf_size && b_flag == 1) { sprintf(mess, "Index out of Range at %d", inpos-inbuf); exit_error(mess); } (*(inpos+ret))=*inpos; sprintf(command, "*"); break; case('\n'): sprintf(command, "X"); break; default: sprintf(command, "X"); sprintf(mess, "Bad syntax at: %d\n", inpos-inbuf); warning(mess); } if(command[0] == '*') break; inpos++; if(command[0] == 'X') continue; /*printf("%s\n", command);*/ fwrite(command, strlen(command), 1, outfile); fwrite("\n", 1, 1, outfile); } sprintf(command, "free(buf); exit(0);}\n"); fwrite(command, strlen(command), 1, outfile); fclose(infile); fclose(outfile); fclose(logfile); if (strcmp(out_type, "c") == 0) { printf("C Source Code: src_file.c\n\n"); } else if(strcmp(out_type, "b") == 0) { sprintf(command, "gcc src_file.c -o %s", dst_file); system(command); system("rm -rf src_file.c"); printf("Binary Executable: %s\n\n", dst_file); } else if(strcmp(out_type, "a") == 0) { sprintf(command, "gcc src_file.c -S -o %s.s", dst_file); system(command); system("rm -rf src_file.c"); printf("ASM Source: %s.s\n\n", dst_file); } }