#include "turmit.h" TURMIT_OP(mem_sz) { turmit_int *new; turmit_int new_sz, old_sz, new_blc, old_blc; old_sz = turmit->stack_sz; old_blc = (old_sz / TURMIT_STACK_GROW) + 1; new_sz = SPOP(turmit); new_sz %= TURMIT_STACK_MAX; new_sz = new_sz<2?2:new_sz; new_blc = (new_sz / TURMIT_STACK_GROW) + 1; if(new_blc != old_blc) { new = realloc(turmit->stack, sizeof(turmit_int) * (new_blc * TURMIT_STACK_GROW)); if(!new) { perror("Unable to reallocate memory for stack"); return; } turmit->stack = new; } turmit->stack_sz = new_sz; turmit->stack_cur %= new_sz; if(old_sz < new_sz) { bzero(turmit->stack + old_sz, sizeof(turmit_int) * (new_sz - old_sz)); } } TURMIT_OP(add) { turmit_int a = SPOP(turmit), b = SPOP(turmit); SPUSH(turmit, a+b); } TURMIT_OP(sub) { turmit_int a = SPOP(turmit), b = SPOP(turmit); if(turmit->flags & TURMIT_SIGNED) { fprintf(stderr, "Signed int not implemented\n"); } else { SPUSH(turmit, a>b?(turmit->int_max - a) + b:b - a); } } TURMIT_OP(bin_and) { turmit_int a = SPOP(turmit), b = SPOP(turmit); SPUSH(turmit, b & a); } TURMIT_OP(dup) { turmit_int a = SCUR(turmit); SPUSH(turmit, a); } TURMIT_OP(lshift) { turmit_int a,b; a = SPOP(turmit); b = SPOP(turmit); SPUSH(turmit, b << a); } TURMIT_OP(mod) { turmit_int a,b; a = SPOP(turmit); b = SPOP(turmit); a = !a?0:b%a; SPUSH(turmit, a); } TURMIT_OP(mul) { turmit_int a = SPOP(turmit), b = SPOP(turmit); SPUSH(turmit, a*b); } TURMIT_OP(div) { turmit_int a, b; a = SPOP(turmit); b = SPOP(turmit); SPUSH(turmit, a==0?0:b/a); } TURMIT_OP(bin_or) { turmit_int a = SPOP(turmit), b = SPOP(turmit); SPUSH(turmit, a | b); } TURMIT_OP(bin_xor) { turmit_int a = SPOP(turmit), b = SPOP(turmit); SPUSH(turmit, a ^ b); } TURMIT_OP(pop) { SPOP(turmit); } TURMIT_OP(swp) { turmit_int a, b; a = SPOP(turmit); b = SPOP(turmit); SPUSH(turmit, a); SPUSH(turmit, b); } TURMIT_OP(jmp) { turmit_int a; a = SPOP(turmit); TURMIT_JMP(turmit, a); } TURMIT_OP(jz) { turmit_int a, b; a = SPOP(turmit); b = SPOP(turmit); if(b == 0) { TURMIT_JMP(turmit, a); } } TURMIT_OP(jcmp) { turmit_int a, b, cnd, offset; offset = SPOP(turmit); cnd = SPOP(turmit); b = SPOP(turmit); a = SPOP(turmit); if(((cnd & 7) == 0 && a != b) || (cnd > 6) || ((cnd & 1) && a == b) || ((cnd & 7) > 2 && a < b) || ((cnd & 7) > 4 && a > b)) { TURMIT_JMP(turmit, offset); } } turmit_t *turmit_alloc(ssize_t stack_sz, ssize_t int_max, const char *expr, unsigned char flags) { turmit_t *res; res = malloc(sizeof(struct turmit_s)); if(!res) { perror("Unable to allocate memory for turmit"); return NULL; } return turmit_init(res, stack_sz, int_max, expr, flags); } turmit_t *turmit_init(turmit_t *turmit, ssize_t stack_sz, ssize_t int_max, const char *expr, unsigned char flags) { turmit->expr = strndup(expr, TURMIT_EXPR_MAX_SZ); turmit->flags = flags; turmit->int_max = int_max; turmit->op_expr = NULL; turmit->op_expr_sz = 0; turmit->op_cur = 0; turmit->op_end = 0; turmit->stack_sz = stack_sz; turmit->stack_cur = turmit->stack_sz - 1; turmit->err = 0; turmit->err_str = NULL; turmit->stack = malloc(sizeof(turmit_int) * ((turmit->stack_sz / TURMIT_STACK_GROW)+1) * TURMIT_STACK_GROW); if(!turmit->stack) { perror("Unable to allocate turmit's stack's memory"); return turmit; } bzero(turmit->stack, sizeof(turmit_int) * turmit->stack_sz); if(turmit->flags & TURMIT_AUTOCOMP) { turmit_compile(turmit); } return turmit; } turmit_t *turmit_copy(turmit_t *turmit) { turmit_t *res; turmit_int stack_blck; res = malloc(sizeof(turmit_t)); if(!res) { perror("Unable to allocate memory for copy"); return NULL; } memcpy(res, turmit, sizeof(turmit_t)); if(turmit->expr) { res->expr = strdup(turmit->expr); } if(turmit->stack) { stack_blck = (res->stack_sz / TURMIT_STACK_GROW) + 1; res->stack = malloc( sizeof(turmit_int) * stack_blck * TURMIT_STACK_GROW); memcpy(res->stack, turmit->stack, sizeof(turmit_int) * stack_blck * TURMIT_STACK_GROW); } if(turmit->op_expr) { res->op_expr = malloc(sizeof(turmit_op_t) * res->op_expr_sz); if(!res->op_expr) { perror("Unable to allocate memory for expression"); return res; } memcpy(res->op_expr, turmit->op_expr, sizeof(turmit_op_t) * res->op_expr_sz); } return res; } void turmit_clean(turmit_t *turmit) { if(turmit->stack) { free(turmit->stack); } if(turmit->err_str) { free(turmit->err_str); } if(turmit->expr) { free(turmit->expr); } if(turmit->op_expr) { free(turmit->op_expr); } } void turmit_free(turmit_t *turmit) { turmit_clean(turmit); free(turmit); } turmit_int turmit_exec(turmit_t *turmit, const turmit_int args[5]) { turmit_op_t *op; turmit->op_cur = 0; turmit->op_end = 0; while(!turmit->op_end && turmit->op_cur < turmit->op_expr_sz) { op = &(turmit->op_expr[turmit->op_cur]); switch(op->value) { case TURMIT_SYM_OP: op->op.op(turmit); break; case TURMIT_SYM_VAL: SPUSH(turmit, op->op.val); break; case TURMIT_SYM_VAR: SPUSH(turmit, args[op->op.var]); break; default: // Null sym encountered. This sould NOT append fprintf(stderr, "Warning NULL sym encountered\n"); turmit->op_cur = turmit->op_expr_sz; break; } //_turmit_stack_dump(turmit); turmit->op_cur++; } return SCUR(turmit); } int turmit_compile(turmit_t *turmit) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-braces" turmit_sym_t tsym[] = TURMIT_OP_LST; #pragma GCC diagnostic pop char *cur, *endptr; turmit_sym_t *isym; ssize_t opcur; turmit_op_t *pret; long int iret; int err; int i; turmit->op_expr_sz = 64; turmit->op_expr = malloc(sizeof(turmit_op_t) * turmit->op_expr_sz); bzero(turmit->op_expr, sizeof(turmit_op_t) * turmit->op_expr_sz); opcur = 0; cur = turmit->expr; while(*cur != '\0') { if(opcur >= turmit->op_expr_sz - 1) { //more space needed turmit->op_expr_sz += 64; pret = realloc(turmit->op_expr, sizeof(turmit_op_t) * turmit->op_expr_sz); if(!pret) { perror("Unable to allocate memory"); goto turmit_compile_err; } bzero(pret + opcur - 1, 64 * sizeof(turmit_op_t)); turmit->op_expr = pret; } //Checking for separators if(*cur == ' ' || *cur == '\t' || *cur == ' ') { cur++; continue; } //Checking for variables for(i=0; TURMIT_VAR_L[i] != '\0'; i++) { if(tolower(*cur) == TURMIT_VAR_L[i]) { turmit->op_expr[opcur].op.var = i; turmit->op_expr[opcur].value = TURMIT_SYM_VAR; opcur++; cur++; break; } } if(TURMIT_VAR_L[i] != '\0') { continue; } //Checking for values //hex if(strncasecmp("0x", cur, 2) == 0) { cur+= 2; errno = 0; iret = strtol(cur, &endptr, 16); err = errno; if(err || endptr == cur) { fprintf(stderr, "Invalid constant %s : %s\n", cur-2, strerror(err)); goto turmit_compile_err; } turmit->op_expr[opcur].op.val = iret; turmit->op_expr[opcur].value = TURMIT_SYM_VAL; opcur++; cur = endptr; continue; } //decimal if(*cur <= '9' && *cur >= '0') { iret = strtol(cur, &endptr, 10); err = errno; if(err || endptr == cur) { fprintf(stderr, "Invalid constant %s : %s\n", cur, strerror(err)); goto turmit_compile_err; } turmit->op_expr[opcur].op.val = iret; turmit->op_expr[opcur].value = TURMIT_SYM_VAL; opcur++; cur = endptr; continue; } //Checking for op isym = tsym; while(isym->str != NULL) { endptr = cur; if(strncasecmp(isym->str, cur, strlen(isym->str)) == 0) { endptr = cur+strlen(isym->str); } else if(isym->alias && strncmp(cur, isym->alias, strlen(isym->alias)) == 0) { endptr = cur+strlen(isym->alias); } if(cur != endptr) { cur = endptr; turmit->op_expr[opcur].op.op = isym->op_fun; turmit->op_expr[opcur].value = TURMIT_SYM_OP; opcur++; break; } isym++; } if(isym->str != NULL) { continue; } //unrecognized symbol :'( turmit->err = 1; if(turmit->err_str) { free(turmit->err_str); } turmit->err_str = malloc(sizeof(char) * 256); if(!turmit->err_str) { perror("Unable to allocate memory for error string"); return -1; } snprintf(turmit->err_str, 256, "Error compiling prog starting at : '%s'", cur); goto turmit_compile_err; } if(!opcur) { //empty expression turmit->op_expr_sz = 0; free(turmit->op_expr); turmit->op_expr = NULL; return 0; } turmit->op_expr_sz = opcur; pret = realloc(turmit->op_expr, sizeof(turmit_op_t) * turmit->op_expr_sz); if(!pret) { perror("Unable to shrink op_expr"); return 1; } else { turmit->op_expr = pret; } return 0; turmit_compile_err: free(turmit->op_expr); turmit->op_expr = NULL; turmit->op_expr_sz = 0; turmit->op_cur = 0; return 1; } void _turmit_stack_dump(turmit_t *turmit) { int i; fprintf(stderr, "Stack cur = %lu\n[", turmit->stack_cur); for(i=0; istack_sz; i++) { fprintf(stderr,"%llu, ", turmit->stack[i]); } fprintf(stderr, "]\n"); }