#ifndef _TURMIT_H_ #define _TURMIT_H_ #include #include #include #include #include /**@Todo For the moment there is no way to track wether a variable is used * or not in result processing */ typedef unsigned long long int turmit_int; typedef struct turmit_op_s turmit_op_t; typedef struct turmit_s turmit_t; typedef struct turmit_sym_s turmit_sym_t; typedef void (*turmit_op_f)(turmit_t*); #define SCUR(t) (t->stack[t->stack_cur]) #define SDEC(t) (t->stack_cur = (t->stack_cur>0?t->stack_cur:t->stack_sz) -1) #define SINC(t) (t->stack_cur = (t->stack_cur + 1) % t->stack_sz) #define SPOP(t) (__SPOP(t)) #define SPUSH(t, v) (t->stack[SINC(t)] = v % t->int_max) #define TURMIT_EXPR_MAX_SZ 0xFFFFFFFF #define TURMIT_LAZY 0 #define TURMIT_AUTOCOMP 1 #define TURMIT_OK 0 #define TURMIT_ERROR -1 #define TURMIT_SYM_OP 1 #define TURMIT_SYM_VAL 2 #define TURMIT_SYM_VAR 3 #define TURMIT_VAR_L "xyrgb" #define TURMIT_OPSYM(NAME) {#NAME, NULL, turmit_op_##NAME} #define TURMIT_OPSYMALIAS(NAME, alias) {#NAME, alias, turmit_op_##NAME} // OPSYMALIAS has to be first ! #define TURMIT_OP_LST {\ TURMIT_OPSYMALIAS(add, "+"),\ TURMIT_OPSYMALIAS(sub, "-"),\ TURMIT_OPSYMALIAS(mul, "*"),\ TURMIT_OPSYMALIAS(div, "/"),\ TURMIT_OPSYMALIAS(mod, "%"),\ TURMIT_OPSYMALIAS(bin_or, "|"),\ TURMIT_OPSYMALIAS(bin_and, "&"),\ TURMIT_OPSYMALIAS(bin_xor, "^"),\ TURMIT_OPSYMALIAS(lshift, "<<"),\ TURMIT_OPSYM(mem_sz),\ TURMIT_OPSYM(dup),\ TURMIT_OPSYM(pop),\ TURMIT_OPSYM(swp),\ TURMIT_OPSYM(jmp),\ TURMIT_OPSYM(jz),\ TURMIT_OPSYM(jcmp),\ NULL,\ } struct turmit_sym_s { char *str; char *alias; turmit_op_f op_fun; }; union turmit_op_u { turmit_op_f op; turmit_int val; short var; /*!< interpreted % 5 */ }; struct turmit_op_s { union turmit_op_u op; /** 0 for NULL, 1 if operation pointer, 2 if value, 3 if variable */ short value; }; struct turmit_s { char *expr; unsigned char flags; ssize_t int_max; turmit_op_t *op_expr; ssize_t op_expr_sz; ssize_t op_cur; ssize_t stack_sz; turmit_int *stack; ssize_t stack_cur; /**@brief 0 if no error * @note only for compilation error for the moment */ char err; char *err_str; }; inline static turmit_int __SPOP(turmit_t *t) { turmit_int r = t->stack[t->stack_cur]; SDEC(t); return r; } #define TURMIT_OP(NAME) void turmit_op_##NAME (turmit_t *turmit) /**@brief Allocate memory and initialise a turmit * @param const char* The turmit expression * @param unsigned char One of TURMIT_LAZY or TURMIT_AUTOCOMP. * @return A pointer on the new turmit */ turmit_t *turmit_alloc(ssize_t stack_sz, ssize_t int_max, const char *expr, unsigned char flags); /**@brief Initialize a turmit * @param turmit_t* The turmit to initialize * @param const char* The turmit expression * @param unsigned char One of TURMIT_LAZY or TURMIT_AUTOCOMP. * @return The pointer on the turmit */ turmit_t *turmit_init(turmit_t *turmit, ssize_t stack_sz, ssize_t int_max, const char *expr, unsigned char flags); turmit_t *turmit_copy(turmit_t *turmit); void turmit_clean(turmit_t *turmit); /**@brief Free memory of a turmit * @param turmit the turmit to free */ void turmit_free(turmit_t *turmit); /**@brief Exec a turmit expr * @param turmit_t* Concerned turmit * @param turmit_int* Arguments ( see @ref TURMIT_VAL_L ) * @return Processed value */ turmit_int turmit_exec(turmit_t *turmit, const turmit_int args[5]); /**@brief Populate turmit_t.op_expr and set op_expr_sz * @return 0 if no errors */ int turmit_compile(turmit_t *turmit); void _turmit_stack_dump(turmit_t *turmit); TURMIT_OP(mem_sz); TURMIT_OP(add); TURMIT_OP(sub); TURMIT_OP(bin_and); TURMIT_OP(dup); TURMIT_OP(lshift); TURMIT_OP(mod); TURMIT_OP(mul); TURMIT_OP(div); TURMIT_OP(bin_or); TURMIT_OP(bin_xor); TURMIT_OP(pop); TURMIT_OP(swp); TURMIT_OP(jmp); TURMIT_OP(jz); TURMIT_OP(jcmp); #endif