|
|
@ -35,10 +35,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define OP_DEF(o) int op_##o(variable *r, variable *a, variable *b)
|
|
|
|
#define OP_DEF(o) int op_##o(variable **r, variable *a, variable *b)
|
|
|
|
#define OP_VAR(o) {0, OPERATOR, 0, {.p = (uint32_t)op_##o}}
|
|
|
|
#define OP_VAR(o) {0, OPERATOR, 0, 0, {.p = (uint32_t)op_##o}}
|
|
|
|
#define OP_NONE {0, OPERATOR, 0, {.p = 0x0BADCAFE}}
|
|
|
|
#define OP_NONE {0, OPERATOR, 0, 0, {.p = 0x0BADCAFE}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OP_DEF(idx);
|
|
|
|
OP_DEF(mul);
|
|
|
|
OP_DEF(mul);
|
|
|
|
OP_DEF(div);
|
|
|
|
OP_DEF(div);
|
|
|
|
OP_DEF(mod);
|
|
|
|
OP_DEF(mod);
|
|
|
@ -67,6 +68,7 @@ OP_DEF(set);
|
|
|
|
* priority, they will be evaluated from left-to-right by the parser.
|
|
|
|
* priority, they will be evaluated from left-to-right by the parser.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
variable opvars[] = {
|
|
|
|
variable opvars[] = {
|
|
|
|
|
|
|
|
OP_VAR(idx), OP_NONE,
|
|
|
|
OP_VAR(mul), OP_VAR(div), OP_VAR(mod), OP_NONE,
|
|
|
|
OP_VAR(mul), OP_VAR(div), OP_VAR(mod), OP_NONE,
|
|
|
|
OP_VAR(add), OP_VAR(sub), OP_VAR(shl), OP_VAR(shr),
|
|
|
|
OP_VAR(add), OP_VAR(sub), OP_VAR(shl), OP_VAR(shr),
|
|
|
|
OP_VAR(lte), OP_VAR(lt), OP_VAR(gte), OP_VAR(gt),
|
|
|
|
OP_VAR(lte), OP_VAR(lt), OP_VAR(gte), OP_VAR(gt),
|
|
|
@ -75,6 +77,7 @@ variable opvars[] = {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const char *opnames[] = {
|
|
|
|
const char *opnames[] = {
|
|
|
|
|
|
|
|
".", 0,
|
|
|
|
"*", "/", "%", 0,
|
|
|
|
"*", "/", "%", 0,
|
|
|
|
"+", "-", "<<", ">>",
|
|
|
|
"+", "-", "<<", ">>",
|
|
|
|
"<=", "<", ">=", ">",
|
|
|
|
"<=", "<", ">=", ">",
|
|
|
@ -97,103 +100,125 @@ variable *igetop(const char *name, int *retlen)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OP_DEF(idx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (a->array == 0)
|
|
|
|
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern void itryfree(variable *);
|
|
|
|
|
|
|
|
itryfree(*r);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int idx = b->value.f;
|
|
|
|
|
|
|
|
if (idx >= a->array) {
|
|
|
|
|
|
|
|
variable *newarray = calloc(idx + 1, sizeof(variable));
|
|
|
|
|
|
|
|
void *old = (void *)a->value.p;
|
|
|
|
|
|
|
|
a->value.p = (uint32_t)memcpy(newarray, (variable *)a->value.p,
|
|
|
|
|
|
|
|
a->array * sizeof(variable));
|
|
|
|
|
|
|
|
free(old);
|
|
|
|
|
|
|
|
a->array = idx + 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variable *array = (variable *)a->value.p;
|
|
|
|
|
|
|
|
*r = &array[idx];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
OP_DEF(mul)
|
|
|
|
OP_DEF(mul)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f * b->value.f;
|
|
|
|
(*r)->value.f = a->value.f * b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(div)
|
|
|
|
OP_DEF(div)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f / b->value.f;
|
|
|
|
(*r)->value.f = a->value.f / b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(mod)
|
|
|
|
OP_DEF(mod)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = (int)a->value.f % (int)b->value.f;
|
|
|
|
(*r)->value.f = (int)a->value.f % (int)b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(add)
|
|
|
|
OP_DEF(add)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f + b->value.f;
|
|
|
|
(*r)->value.f = a->value.f + b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(sub)
|
|
|
|
OP_DEF(sub)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f - b->value.f;
|
|
|
|
(*r)->value.f = a->value.f - b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(shl)
|
|
|
|
OP_DEF(shl)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = (int)a->value.f << (int)b->value.f;
|
|
|
|
(*r)->value.f = (int)a->value.f << (int)b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(shr)
|
|
|
|
OP_DEF(shr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = (int)a->value.f >> (int)b->value.f;
|
|
|
|
(*r)->value.f = (int)a->value.f >> (int)b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(lte)
|
|
|
|
OP_DEF(lte)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f <= b->value.f;
|
|
|
|
(*r)->value.f = a->value.f <= b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(lt)
|
|
|
|
OP_DEF(lt)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f < b->value.f;
|
|
|
|
(*r)->value.f = a->value.f < b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(gte)
|
|
|
|
OP_DEF(gte)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f >= b->value.f;
|
|
|
|
(*r)->value.f = a->value.f >= b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(gt)
|
|
|
|
OP_DEF(gt)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f > b->value.f;
|
|
|
|
(*r)->value.f = a->value.f > b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(eq)
|
|
|
|
OP_DEF(eq)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
if (a->type == NUMBER && b->type == NUMBER)
|
|
|
|
if (a->type == NUMBER && b->type == NUMBER)
|
|
|
|
r->value.f = a->value.f == b->value.f;
|
|
|
|
(*r)->value.f = a->value.f == b->value.f;
|
|
|
|
else if (a->type == STRING && b->type == STRING)
|
|
|
|
else if (a->type == STRING && b->type == STRING)
|
|
|
|
r->value.f = !strcmp((const char *)a->value.p, (const char *)b->value.p);
|
|
|
|
(*r)->value.f = !strcmp((const char *)a->value.p, (const char *)b->value.p);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
r->value.f = 0.0f; // *sshhh*
|
|
|
|
(*r)->value.f = 0.0f; // *sshhh*
|
|
|
|
//return seterror(EBADPARAM);
|
|
|
|
//return seterror(EBADPARAM);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -202,32 +227,32 @@ OP_DEF(ne)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f != b->value.f;
|
|
|
|
(*r)->value.f = a->value.f != b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(and)
|
|
|
|
OP_DEF(and)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = (int)a->value.f & (int)b->value.f;
|
|
|
|
(*r)->value.f = (int)a->value.f & (int)b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(xor)
|
|
|
|
OP_DEF(xor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = (int)a->value.f ^ (int)b->value.f;
|
|
|
|
(*r)->value.f = (int)a->value.f ^ (int)b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(or)
|
|
|
|
OP_DEF(or)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
if (a->type != NUMBER || b->type != NUMBER)
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = (int)a->value.f | (int)b->value.f;
|
|
|
|
(*r)->value.f = (int)a->value.f | (int)b->value.f;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OP_DEF(set)
|
|
|
|
OP_DEF(set)
|
|
|
@ -235,14 +260,14 @@ OP_DEF(set)
|
|
|
|
if (b->type == NUMBER) {
|
|
|
|
if (b->type == NUMBER) {
|
|
|
|
a->type = NUMBER;
|
|
|
|
a->type = NUMBER;
|
|
|
|
a->value.f = b->value.f;
|
|
|
|
a->value.f = b->value.f;
|
|
|
|
r->type = NUMBER;
|
|
|
|
(*r)->type = NUMBER;
|
|
|
|
r->value.f = a->value.f;
|
|
|
|
(*r)->value.f = a->value.f;
|
|
|
|
} else if (b->type == STRING) {
|
|
|
|
} else if (b->type == STRING) {
|
|
|
|
a->type = STRING;
|
|
|
|
a->type = STRING;
|
|
|
|
free((void *)a->value.p);
|
|
|
|
free((void *)a->value.p);
|
|
|
|
a->value.p = (uint32_t)strclone((char *)b->value.p);
|
|
|
|
a->value.p = (uint32_t)strclone((char *)b->value.p);
|
|
|
|
r->type = STRING;
|
|
|
|
(*r)->type = STRING;
|
|
|
|
r->value.p = (uint32_t)strclone((char *)a->value.p);
|
|
|
|
(*r)->value.p = (uint32_t)strclone((char *)a->value.p);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
return seterror(EBADPARAM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|