123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- #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; i<turmit->stack_sz; i++)
- {
- fprintf(stderr,"%llu, ", turmit->stack[i]);
- }
- fprintf(stderr, "]\n");
- }
|