diff --git a/Makefile b/Makefile index 8bca3c1..b4a7bfc 100644 --- a/Makefile +++ b/Makefile @@ -7,13 +7,17 @@ CFLAGS = -Wall -Wextra -Werror -pedantic \ -Wno-discarded-qualifiers \ -I. -fsigned-char -fno-builtin -ggdb -all: - $(CC) $(CFLAGS) -c shelpers.c - $(CC) $(CFLAGS) -c parser.c - $(CC) $(CFLAGS) -c builtins.c - $(CC) $(CFLAGS) -c stack.c - $(CC) $(CFLAGS) -c ops.c - $(CC) $(CFLAGS) -c variable.c - $(AR) r libinterp.a *.o - @rm -f *.o - #$(CC) $(CFLAGS) shell.c *.o -o shell +FILES = $(wildcard *.c) +OUTFILES = $(patsubst %.c, %.o, $(FILES)) + +all: $(OUTFILES) + @#$(CC) $(CFLAGS) *.o -o shell + @$(AR) r libinterp.a *.o + +clean: + @echo " CLEAN" + @rm -f *.o shell libinterp.a + +%.o: %.c + @echo " CC " $< + @$(CC) $(CFLAGS) -c $< -o $@ diff --git a/builtins.c b/builtins.c index b2295c5..7dba1aa 100644 --- a/builtins.c +++ b/builtins.c @@ -3,9 +3,7 @@ #include "shelpers.h" #include - -extern char *str_func; -extern char *str_undef; +#include int ifunc_set(interpreter *it); int ifunc_label(interpreter *it); @@ -42,11 +40,10 @@ int ifunc_set(interpreter *it) if (n == 0) return -1; + if (n->valtype == STRING) + free((void *)n->value.p); n->valtype = v->valtype; - n->value = v->value; - if (n->svalue != 0 && n->svalue != str_func && n->svalue != str_undef) - free(n->svalue); - n->svalue = strclone(v->svalue); + n->value.p = v->value.p; return 0; } @@ -58,15 +55,14 @@ int ifunc_label(interpreter *it) return -1; n->valtype = FUNC; - n->value = it->lnidx; - n->svalue = str_func; + n->value.p = it->lnidx; iskip(it); return 0; } int ifunc_if(interpreter *it) { - int v = igetarg_integer(it, 0); + int v = igetarg(it, 0)->value.p; if (v == 0) iskip(it); void *tmp = ipop(it); @@ -94,7 +90,7 @@ int ifunc_do(interpreter *it) int ifunc_while(interpreter *it) { - int c = igetarg_integer(it, 0); + int c = igetarg(it, 0)->value.p; ipop(it); int nidx = (int)ipop(it); if (c != 0) { @@ -108,26 +104,21 @@ int ifunc_while(interpreter *it) void iret(interpreter *it, variable *v) { switch (v->valtype) { - case INTEGER: - inew_integer(it, "RET", INT(v)); - break; - case FLOAT: - inew_float(it, "RET", FLOAT(v)); + case NUMBER: + inew_number(it, "RET", v->value.f); break; case STRING: - inew_string(it, "RET", v->svalue); + inew_string(it, "RET", (char *)v->value.p); break; default: return; break; } if (it->ret != 0) { + if (it->ret->valtype == STRING && it->ret->value.p != 0) + free((void *)it->ret->value.p); it->ret->valtype = v->valtype; - it->ret->value = v->value; - char *s = it->ret->svalue; - if (s != 0 && s != str_undef) - free(s); - it->ret->svalue = strclone(v->svalue); + it->ret->value.p = v->value.p; it->ret = 0; } } diff --git a/old/parser.c b/old/parser.c deleted file mode 100644 index 5e94e79..0000000 --- a/old/parser.c +++ /dev/null @@ -1,225 +0,0 @@ -#include - -#include -#include - -static const char *interpreter_operators = "=("; - -bool strcmp(const char *a, const char *b) -{ - int i = 0; - for (; a[i] == b[i] && a[i] != '\0'; i++); - return a[i] == b[i]; -} - -bool strncmp(const char *a, const char *b, int count) -{ - int i = 0; - for (; a[i] == b[i] && i < count; i++); - return i == count; -} - -uint8_t isalpha(char c) -{ - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); -} - -uint8_t isnum(char c) -{ - return (c >= '0' && c <= '9'); -} - -uint8_t isname(char c) -{ - return isalpha(c) || isnum(c); -} - -uint8_t isspace(char c) -{ - return (c == ' ' || c == '\t' || c == '\n'); -} - -uint8_t isoper(char c) -{ - for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) { - if (c == interpreter_operators[i]) - return 1; - } - - return 0; -} - -void interpreter_init(interpreter *interp) -{ - interp->status = READY; - interp->vcount = 0; - interp->vars = (variable *)calloc(32, sizeof(variable)); - interp->names = (char **)calloc(32, sizeof(char *)); - interp->stack = (stack_t *)calloc(64, sizeof(stack_t)); -} - -void interpreter_define_value(interpreter *interp, const char *name, int32_t value) -{ - interp->names[interp->vcount] = (char *)name; - interp->vars[interp->vcount].nameidx = interp->vcount; - interp->vars[interp->vcount].type = VALUE; - interp->vars[interp->vcount].value = (uint32_t)value; - interp->vcount++; -} - -void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr) -{ - interp->names[interp->vcount] = (char *)name; - interp->vars[interp->vcount].nameidx = interp->vcount; - interp->vars[interp->vcount].type = CFUNCTION; - interp->vars[interp->vcount].value = (uint32_t)addr; - interp->vcount++; -} - -int32_t interpreter_get_value(interpreter *interp, const char *name) -{ - for (uint16_t i = 0; i < interp->vcount; i++) { - if (!strcmp(interp->names[i], name)) - return (int32_t)interp->vars[i].value; - } - - return 0; -} - -/** - * doline section - */ - -bool namencmp(const char *name, const char *s) -{ - uint16_t i; - for (i = 0; name[i] == s[i] && s[i] != '\0'; i++); - return (name[i] == '\0' && !isname(s[i])); -} - -uint16_t spacecount(const char *s) -{ - uint16_t i; - for (i = 0; isspace(s[i]); i++); - return i; -} - -char *copystr(const char *s, char end) -{ - uint16_t len = 0; - while (s[len++] != end); - char *buf = (char *)malloc(len); - for (uint16_t i = 0; i < len; i++) - buf[i] = s[i]; - return buf; -} - -char *copysubstr(const char *s, int end) -{ - char *buf = (char *)malloc(end); - for (uint16_t i = 0; i < end; i++) - buf[i] = s[i]; - return buf; -} - -variable *interpreter_getvar(interpreter *interp, const char *line) -{ - for (uint16_t i = 0; i < interp->vcount; i++) { - if (namencmp(interp->names[i], line)) - return &interp->vars[i]; - } - - return 0; -} - -int interpreter_doline(interpreter *interp, const char *line) -{ - variable *bits[16]; - uint16_t offset = 0, boffset = 0; - - // check for var/func set or usage - int end; -getvar: - for (end = 0; isname(line[end]); end++); - variable *var = interpreter_getvar(interp, line); - - if (var != 0) { - bits[boffset++] = var; - } else { - // defining new variable - interpreter_define_value(interp, copysubstr(line, end), 0); - goto getvar; // try again - } - - // skip whitespace/name - offset += end; - offset += spacecount(line + offset); - - if (boffset == 0 && line[offset] != '=') - return -1; // variable not found - - // find operator - if (line[offset] == '\0') { - // print value - return -99; - } else if (line[offset] == '=') { - // assignment/expression - offset++; - offset += spacecount(line + offset); - bits[0]->value = (uint32_t)copystr(line + offset, '\0'); - } else if (line[offset] == '(') { - // function call - offset++; - if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION) - return -2; - offset += spacecount(line + offset); - - // collect arg offsets - uint16_t offsets[8]; - uint8_t ooffset = 0; - while (line[offset] != ')' && line[offset] != '\0') { - offsets[ooffset] = offset; - offset += spacecount(line + offset); - - uint8_t isvn = 1; - do { - if (line[offset] == ' ' || line[offset] == '\t') { - offset += spacecount(line + offset); - isvn = 0; - } - - if (line[offset] == ',') { - offset++; - ooffset++; - break; - } else if (line[offset] == ')') { - ooffset++; - break; - } else if (isvn == 0) { - return -3; - } - } while (++offset); - } - - // populate stack - for (uint8_t i = 0; i < ooffset; i++) { - uint16_t j; - for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' && - line[j] != ',' && line[j] != ')'; j++); - j -= offsets[i]; - - variable *var = interpreter_getvar(interp, line + offsets[i]); - if (var != 0) - interp->stack[i] = copystr((char *)var->value, '\0'); - else - interp->stack[i] = copysubstr(line + offsets[i], j); - } - - ((func_t)bits[0]->value)(interp->stack); - } else { - return -2; // invalid operation - } - - return 0; -} - diff --git a/old/parser.h b/old/parser.h deleted file mode 100644 index c6a2b17..0000000 --- a/old/parser.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PARSER_H_ -#define PARSER_H_ - -#include - -typedef void *stack_t; - -typedef struct { - uint16_t status; - uint16_t vcount; - variable *vars; - char **names; - stack_t *stack; -} interpreter; - -enum status { - READY = 0 -}; - -typedef void (*func_t)(stack_t *); - -void interpreter_init(interpreter *); - -void interpreter_define_value(interpreter *, const char *, int32_t); -void interpreter_define_cfunc(interpreter *, const char *, func_t); - -int32_t interpreter_get_value(interpreter *, const char *); - -int interpreter_doline(interpreter *, const char *); - -#endif // PARSER_H_ diff --git a/old/variable.h b/old/variable.h deleted file mode 100644 index fd84a6e..0000000 --- a/old/variable.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef TOKEN_H_ -#define TOKEN_H_ - -#include - -typedef struct { - uint16_t nameidx; - uint8_t type; - uint8_t info; - uint32_t value; -} variable; - -#define INFO_ARGS(x) ((x) & 0x07) -#define INFO_RET (1 << 3) - -enum vartype { - VALUE = 0, - VARIABLE, - OPERATOR, - FUNCTION, - CFUNCTION -}; - -#endif // TOKEN_H_ diff --git a/ops.c b/ops.c index 34e7986..cb07093 100644 --- a/ops.c +++ b/ops.c @@ -32,136 +32,81 @@ operation_t iopfuncs[IOPS_COUNT] = { void iop_add(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) + INT(b); - } else { - itofloat(a); - itofloat(b); - FLOAT(r) = FLOAT(a) + FLOAT(b); - } + r->value.f = a->value.f + b->value.f; } void iop_sub(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) - INT(b); - } else { - itofloat(a); - itofloat(b); - FLOAT(r) = FLOAT(a) - FLOAT(b); - } + r->value.f = a->value.f - b->value.f; } void iop_mult(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) * INT(b); - } else { - itofloat(a); - itofloat(b); - FLOAT(r) = FLOAT(a) * FLOAT(b); - } + r->value.f = a->value.f * b->value.f; } void iop_div(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) / INT(b); - } else { - itofloat(a); - itofloat(b); - FLOAT(r) = FLOAT(a) / FLOAT(b); - } + r->value.f = a->value.f / b->value.f; } void iop_and(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) & INT(b); - } + r->value.f = (float)((int)a->value.f & (int)b->value.f); } void iop_or(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) | INT(b); - } + r->value.f = (float)((int)a->value.f | (int)b->value.f); } void iop_xor(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) ^ INT(b); - } + r->value.f = (float)((int)a->value.f ^ (int)b->value.f); } void iop_shr(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) >> INT(b); - } + r->value.f = (float)((int)a->value.f >> (int)b->value.f); } void iop_shl(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) { - INT(r) = INT(a) << INT(b); - } + r->value.f = (float)((int)a->value.f << (int)b->value.f); } void iop_eq(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) == INT(b); - else - INT(r) = FLOAT(a) == FLOAT(b); + r->value.f = a->value.f == b->value.f; } void iop_lt(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) < INT(b); - else - INT(r) = FLOAT(a) < FLOAT(b); + r->value.f = a->value.f < b->value.f; } void iop_gt(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) > INT(b); - else - INT(r) = FLOAT(a) > FLOAT(b); + r->value.f = a->value.f > b->value.f; } void iop_lte(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) <= INT(b); - else - INT(r) = FLOAT(a) <= FLOAT(b); + r->value.f = a->value.f <= b->value.f; } void iop_gte(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) >= INT(b); - else - INT(r) = FLOAT(a) >= FLOAT(b); + r->value.f = a->value.f >= b->value.f; } void iop_ne(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) != INT(b); - else - INT(r) = FLOAT(a) != FLOAT(b); + r->value.f = a->value.f != b->value.f; } void iop_mod(variable *r, variable *a, variable *b) { - if (a->valtype == INTEGER && b->valtype == INTEGER) - INT(r) = INT(a) % INT(b); - else - INT(r) = 0; + r->value.f = (float)((int)a->value.f % (int)b->value.f); } diff --git a/parser.c b/parser.c index 5608998..3311d5c 100644 --- a/parser.c +++ b/parser.c @@ -17,9 +17,6 @@ extern int atoi(const char *); extern float strtof(const char *, char **); -char *str_func = "(func)"; -char *str_undef = "(undefined)"; - void iinit(interpreter *interp) { interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable)); @@ -39,14 +36,30 @@ void iend(interpreter *it) { for (unsigned int i = 0; i < MAX_VARS; i++) { if (it->vars[i].used == 1) { - //char *s = it->vars[i].svalue; - //if (s != 0 && s != str_undef && s != str_func) - // free(s); + if (it->vars[i].valtype == STRING || + it->vars[i].valtype == EXPR) + free((void *)it->vars[i].value.p); free(it->vnames[i]); } } - for (unsigned int i = 0; i < MAX_LINES; i++) + for (unsigned int i = 0; i < MAX_LINES; i++) { + if (it->lines[i] != 0) { + for (unsigned int j = 0; (int32_t)it->lines[i][j] > 0; j++) { + switch (it->lines[i][j]->valtype) { + case STRING: + case EXPR: + free((void *)it->lines[i][j]->value.p); + free(it->lines[i][j]); + break; + case NUMBER: + if (!it->lines[i][j]->used) + free(it->lines[i][j]); + break; + } + } + } free(it->lines[i]); + } free(it->vars); free(it->vnames); free(it->stack); @@ -63,14 +76,9 @@ variable *interpreter_get_variable(interpreter *interp, const char *name) { for (uint32_t i = 0; i < MAX_VARS; i++) { if (!interp->vars[i].used) { - variable *v = &interp->vars[i]; + variable *v = make_vars(&interp->vars[i], 0); v->used = 1; - v->fromc = 0; - v->valtype = STRING; - v->value = 0; - v->svalue = str_undef; - char *s = strclone(name); - interp->vnames[i] = s; + interp->vnames[i] = strclone(name); return v; } else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) { return &interp->vars[i]; @@ -85,51 +93,40 @@ char *interpreter_get_name(interpreter *interp, variable *v) if (v == &interp->vars[i]) return interp->vnames[i]; } - return str_undef; + return "(undefined)"; } -variable *inew_string(interpreter *interp, const char *name, char *value) +variable *inew_string(interpreter *interp, const char *name, const char *value) { variable *v = interpreter_get_variable(interp, name); if (v != 0) { v->valtype = STRING; - INT(v) = 0; - v->svalue = strclone(value); - } - return v; -} - -variable *inew_integer(interpreter *interp, const char *name, int32_t value) -{ - variable *v = interpreter_get_variable(interp, name); - if (v != 0) { - v->valtype = INTEGER; - INT(v) = value; - isetstr(v); + if (v->value.p != 0) + free((void *)v->value.p); + v->value.p = (uint32_t)strclone(value); } return v; } -variable *inew_float(interpreter *interp, const char *name, float value) +variable *inew_number(interpreter *interp, const char *name, float value) { variable *v = interpreter_get_variable(interp, name); if (v != 0) { - v->valtype = FLOAT; - FLOAT(v) = value; - fsetstr(v); + v->valtype = NUMBER; + v->value.f = value; } return v; } -void inew_cfunc(interpreter *interp, const char *name, func_t func) +variable *inew_cfunc(interpreter *interp, const char *name, func_t func) { variable *v = interpreter_get_variable(interp, name); if (v != 0) { v->fromc = 1; v->valtype = FUNC; - v->value = (uint32_t)func; - v->svalue = str_func; + v->value.p = (uint32_t)func; } + return v; } variable *make_var(interpreter *interp, const char *line, uint32_t *next) @@ -142,7 +139,10 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next) return 0; // TODO string breakdown *next = end + 1; - return vmake(0, STRING, strnclone(line + 1, end - 1)); + char *str = strnclone(line + 1, end - 1); + variable *v = make_vars(0, str); + free(str); + return v; } end++; } @@ -152,8 +152,10 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next) if (eot(line[end])) return 0; *next = end + 1; - return vmake(0, EXPR, strnclone(line + 1, end)); - //return idoexpr(interp, line + 1); + char *expr = strnclone(line + 1, end); + variable *v = make_vare(0, expr); + free(expr); + return v; } else if (isalpha(line[0])) { // variable/func uint32_t end = 1; for (; isalnum(line[end]); end++); @@ -186,9 +188,9 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next) copy[end] = '\0'; variable *v; if (dec) - v = vmakef(strtof(copy, 0)); + v = make_varn(0, strtof(copy, 0)); else - v = vmake(0, INTEGER, (void *)atoi(copy)); + v = make_varn(0, (float)atoi(copy)); free(copy); *next = end; return v; @@ -246,7 +248,7 @@ int idoline(interpreter *interp, const char *line) goto fail; } - if (ops[0]->fromc && ops[0]->value == 0) { + if (ops[0]->fromc && ops[0]->value.p == 0) { fret = -3; goto fail; } @@ -256,14 +258,14 @@ int idoline(interpreter *interp, const char *line) loop: for (uint8_t i = 0; i < IUP_COUNT; i++) { - if (interp->lines[interp->lnidx][0]->value + if (interp->lines[interp->lnidx][0]->value.p == (uint32_t)indent_up[i]) { interp->indent++; goto cont; } } for (uint8_t i = 0; i < IDOWN_COUNT; i++) { - if (interp->lines[interp->lnidx][0]->value + if (interp->lines[interp->lnidx][0]->value.p == (uint32_t)indent_down[i]) { if (--interp->indent < 0) { fret = -6; @@ -290,7 +292,7 @@ cont: ooffset = 1; for (; ops[ooffset] != 0 && ops[ooffset] != (void *)-1; ooffset++) { if (ops[ooffset]->valtype == EXPR) { - char *expr = strclone(ops[ooffset]->svalue); + char *expr = strclone((char *)ops[ooffset]->value.p); variable *r = idoexpr(interp, expr); ops[ooffset] = r; free(expr); @@ -304,7 +306,7 @@ cont: for (uint32_t i = ooffset; --i > 0;) ipush(interp, ops[i]); - int ret = ((func_t)ops[0]->value)(interp); + int ret = ((func_t)ops[0]->value.p)(interp); if (ret != 0) return ret; ipopm(interp, ooffset - 1); @@ -314,13 +316,10 @@ cont: snprintf(an, 6, "arg%d", (int)(i - 1)); switch (ops[i]->valtype) { case STRING: - inew_string(interp, an, ops[i]->svalue); + inew_string(interp, an, (char *)ops[i]->value.p); break; - case INTEGER: - inew_integer(interp, an, INT(ops[i])); - break; - case FLOAT: - inew_float(interp, an, FLOAT(ops[i])); + case NUMBER: + inew_number(interp, an, ops[i]->value.f); break; default: break; @@ -328,7 +327,7 @@ cont: } ipush(interp, (void *)(interp->lnidx)); - interp->lnidx = ops[0]->value; + interp->lnidx = ops[0]->value.p; interp->indent++; } @@ -339,7 +338,8 @@ cont: for (uint32_t i = 1; i < ooffset; i++) { if (ops[i] != interp->lines[oldLnidx][i]) { - free(ops[i]->svalue); + if (ops[i]->valtype == STRING || ops[i]->valtype == EXPR) + free((void *)ops[i]->value.p); free(ops[i]); } } @@ -431,20 +431,15 @@ variable *idoexpr(interpreter *interp, const char *line) // step 2 - do operations variable *result = (variable *)calloc(1, sizeof(variable)); result->valtype = ((variable *)ops[0])->valtype; - result->value = ((variable *)ops[0])->value; + result->value.p = ((variable *)ops[0])->value.p; for (uint32_t i = 1; i < ooffset; i += 2) iopfuncs[(uint32_t)ops[i] - 1](result, result, ops[i + 1]); - if (result->valtype == INTEGER) - isetstr(result); - else - fsetstr(result); - for (uint32_t i = 0; i < ooffset; i += 2) { - if (!((variable *)ops[i])->used) { - char *s = ((variable *)ops[i])->svalue; - if (s != 0 && s != str_undef) - free(s); + variable *v = (variable *)ops[i]; + if (!v->used) { + if (v->valtype == STRING || v->valtype == EXPR) + free((void *)v->value.p); free(ops[i]); } } diff --git a/parser.h b/parser.h index 24c2c89..1b821cd 100644 --- a/parser.h +++ b/parser.h @@ -26,10 +26,9 @@ void iend(interpreter *it); void iskip(interpreter *it); -variable *inew_string(interpreter *, const char *, char *); -variable *inew_integer(interpreter *, const char *, int32_t); -variable *inew_float(interpreter *, const char *, float); -void inew_cfunc(interpreter *, const char *, func_t); +variable *inew_string(interpreter *, const char *, const char *); +variable *inew_number(interpreter *, const char *, float); +variable *inew_cfunc(interpreter *, const char *, func_t); int idoline(interpreter *, const char *); variable *idoexpr(interpreter *interp, const char *line); diff --git a/shell.c b/shell.c deleted file mode 100644 index c5460e7..0000000 --- a/shell.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include - -#include "stack.h" - -#include -#include -//#include -#include - -extern int rand(void); - -int s_put(interpreter *it) -{ - char *s = igetarg_string(it, 0); - printf("%s", s); - return 0; -} - -int s_type(interpreter *it) -{ - variable *v = (variable *)it->stack[0]; - switch (v->valtype) { - case STRING: - puts("string"); - break; - case INTEGER: - puts("integer"); - break; - case FLOAT: - puts("float"); - break; - case FUNC: - puts("func"); - break; - default: - puts("unknown"); - break; - } - return 0; -} - -int input(interpreter *it) -{ - variable *v = igetarg(it, 0); - v->valtype = STRING; - v->svalue = malloc(128); - unsigned int unused; - getline(&v->svalue, &unused, stdin); - *strchr(v->svalue, '\n') = '\0'; - return 0; -} - -int concat(interpreter *it) -{ - variable *v = igetarg(it, 0); - char *s = igetarg_string(it, 1); - char *new = malloc(strlen(v->svalue) + strlen(s) + 1); - strcpy(new, v->svalue); - strcpy(new + strlen(v->svalue), s); - new[strlen(v->svalue) + strlen(s)] = 0; - v->svalue = new; - return 0; -} - -int script_rand(interpreter *it) -{ - static variable v; - v.valtype = INTEGER; - unsigned int mod = igetarg_integer(it, 0); - unsigned int val = rand(); - INT(&v) = val % mod; - isetstr(&v); - iret(it, &v); - return 0; -} - -int line(interpreter *it) -{ - (void)it; - return 0; -} - -int main(int argc, char **argv) -{ - interpreter interp; - - if (argc != 2) { - printf("Usage: %s file\n", argv[0]); - return -1; - } - - FILE *fp = fopen(argv[1], "r"); - if (fp == 0) { - printf("Could not open file: %s\n", argv[1]); - return -1; - } - - iinit(&interp); - inew_cfunc(&interp, "print", s_put); - inew_cfunc(&interp, "tp", s_type); - inew_cfunc(&interp, "gets", input); - inew_cfunc(&interp, "concat", concat); - inew_cfunc(&interp, "rand", script_rand); - inew_cfunc(&interp, "line", line); - - - char *line = 0; - unsigned int size; - int result; - while (getline(&line, &size, fp) != -1) { - *strchr(line, '\n') = '\0'; - result = idoline(&interp, line); - if (result != 0) - printf("Error: %d\n", result); - } - - fclose(fp); - iend(&interp); - return 0; -} diff --git a/stack.c b/stack.c index d970bc2..8ada8ea 100644 --- a/stack.c +++ b/stack.c @@ -20,27 +20,19 @@ variable *igetarg(interpreter *interp, uint32_t index) return interp->stack[interp->stidx - index - 1]; } -char *igetarg_string(interpreter *interp, uint32_t index) +const char *igetarg_string(interpreter *interp, uint32_t index) { if (index >= interp->stidx) return 0; variable *v = igetarg(interp, index); - return v->svalue; + return (const char *)v->value.p; } -int igetarg_integer(interpreter *interp, uint32_t index) +float igetarg_number(interpreter *interp, uint32_t index) { if (index >= interp->stidx) return 0; variable *v = igetarg(interp, index); - return INT(itoint(v)); -} - -float igetarg_float(interpreter *interp, uint32_t index) -{ - if (index >= interp->stidx) - return 0; - variable *v = igetarg(interp, index); - return FLOAT(itofloat(v)); + return v->value.f; } diff --git a/stack.h b/stack.h index d5a7f96..18821a1 100644 --- a/stack.h +++ b/stack.h @@ -6,10 +6,11 @@ void ipush(interpreter *it, void *v); void *ipop(interpreter *it); void ipopm(interpreter *it, uint32_t count); + variable *igetarg(interpreter *interp, uint32_t index); -char *igetarg_string(interpreter *interp, uint32_t index); -int igetarg_integer(interpreter *interp, uint32_t index); -float igetarg_float(interpreter *interp, uint32_t index); +const char *igetarg_string(interpreter *interp, uint32_t index); +float igetarg_number(interpreter *interp, uint32_t index); +#define igetarg_integer(i, x) (int)igetarg_number(i, x) #endif // STACK_H_ diff --git a/variable.c b/variable.c index 8b7dc12..c170f79 100644 --- a/variable.c +++ b/variable.c @@ -4,12 +4,10 @@ #include #include #include +#include extern int atoi(const char *); -extern char *str_undef; -extern char *str_func; - char *fixstring(char *s) { char *n = malloc(strlen(s) + 1); @@ -27,105 +25,47 @@ char *fixstring(char *s) return n; } -variable *vmake(uint8_t fromc, uint8_t valtype, void *value) +variable *make_varn(variable *v, float value) { - variable *v = (variable *)malloc(sizeof(variable)); + if (v == 0) + v = (variable *)malloc(sizeof(variable)); v->used = 0; - v->fromc = fromc; - v->valtype = valtype; - v->value = 0; - v->svalue = 0; - switch (valtype) { - case STRING: - v->svalue = fixstring(value); - free(value); - break; - case INTEGER: - INT(v) = (int32_t)value; - isetstr(v); - break; - case FUNC: - v->value = (uint32_t)value; - v->svalue = str_func; - break; - case EXPR: - v->svalue = value; - break; - } + v->fromc = 0; + v->valtype = NUMBER; + v->value.f = value; return v; } -variable *vmakef(float value) +variable *make_vars(variable *v, const char *value) { - variable *v = (variable *)malloc(sizeof(variable)); + if (v == 0) + v = (variable *)malloc(sizeof(variable)); v->used = 0; v->fromc = 0; - v->valtype = FLOAT; - FLOAT(v) = value; - fsetstr(v); + v->valtype = STRING; + v->value.p = (value != 0) ? (uint32_t)fixstring(value) : 0; return v; } -void fsetstr(variable *f) +variable *make_varf(variable *v, uint8_t fromc, uint32_t func) { - if (f->svalue == 0 || f->svalue == str_undef) - f->svalue = (char *)malloc(32); - snprintf(f->svalue, 32, "%f", FLOAT(f)); -} - -void isetstr(variable *i) -{ - if (i->svalue == 0 || i->svalue == str_undef) - i->svalue = (char *)malloc(32); - snprintf(i->svalue, 32, "%d", (int)INT(i)); -} - -variable *itostring(variable *v) -{ - switch (v->valtype) { - case INTEGER: - v->valtype = STRING; - isetstr(v); - break; - case FLOAT: - v->valtype = STRING; - fsetstr(v); - break; - } - return v; -} - -variable *itoint(variable *v) -{ - switch (v->valtype) { - case STRING: - v->valtype = INTEGER; - INT(v) = atoi(v->svalue); - isetstr(v); - break; - case FLOAT: - v->valtype = INTEGER; - INT(v) = (int32_t)FLOAT(v); - isetstr(v); - break; - } + if (v == 0) + v = (variable *)malloc(sizeof(variable)); + v->used = 0; + v->fromc = fromc; + v->valtype = FUNC; + v->value.p = func; return v; } -variable *itofloat(variable *v) +variable *make_vare(variable *v, const char *expr) { - switch (v->valtype) { - case STRING: - v->valtype = FLOAT; - FLOAT(v) = strtof(v->svalue, 0); - fsetstr(v); - break; - case INTEGER: - v->valtype = FLOAT; - FLOAT(v) = (float)INT(v); - fsetstr(v); - break; - } + if (v == 0) + v = (variable *)malloc(sizeof(variable)); + v->used = 0; + v->fromc = 0; + v->valtype = EXPR; + v->value.p = (uint32_t)strclone(expr); return v; } diff --git a/variable.h b/variable.h index beb8be3..b4a7c72 100644 --- a/variable.h +++ b/variable.h @@ -3,33 +3,26 @@ #include -#define INT(v) (*((int32_t *)&(v)->value)) -#define FLOAT(v) (*((float *)&(v)->value)) - typedef struct { uint8_t used :1; uint8_t fromc :1; uint8_t valtype :4; - uint32_t value; - char *svalue; + union { + float f; + uint32_t p; + } value; } variable; enum valtype { STRING = 0, - INTEGER, - FLOAT, + NUMBER, FUNC, EXPR }; -variable *vmake(uint8_t fromc, uint8_t valtype, void *value); -variable *vmakef(float value); - -void isetstr(variable *i); -void fsetstr(variable *f); - -variable *itostring(variable *v); -variable *itoint(variable *v); -variable *itofloat(variable *v); +variable *make_varn(variable *v, float value); +variable *make_vars(variable *v, const char *s); +variable *make_varf(variable *v, uint8_t fromc, uint32_t func); +variable *make_vare(variable *v, const char *e); #endif // VARIABLE_H_