Select Git revision
operators.c
-
Fredrik Hübinette (Hubbe) authored
Rev: README:1.1 Rev: bin/create_testsuite:1.3 Rev: bin/hilfe.lpc:1.2 Rev: bin/rsif:1.2 Rev: bin/uhttpd.lpc:1.2 Rev: doc/simulated/open:1.1 Rev: lib/master.lpc:1.2 Rev: lib/simulate.lpc:1.4 Rev: lib/testsuite.lpc:1.3 Rev: src/BUGS:1.3 Rev: src/Makefile.in:1.6 Rev: src/Makefile.in.src:1.2 Rev: src/README:1.2 Rev: src/add_efun.c:1.2 Rev: src/add_efun.h:1.2 Rev: src/array.c:1.4 Rev: src/array.h:1.2 Rev: src/backend.c:1.3 Rev: src/backend.h:1.2 Rev: src/builtin_efuns.c:1.2 Rev: src/builtin_efuns.h:1.2 Rev: src/call_out.c:1.5 Rev: src/call_out.h:1.2 Rev: src/callback.c:1.2 Rev: src/callback.h:1.2 Rev: src/config.h:1.6 Rev: src/configure.in:1.9 Rev: src/debug.c:1.4 Rev: src/debug.h:1.4 Rev: src/docode.c:1.4 Rev: src/docode.h:1.2 Rev: src/dynamic_buffer.c:1.3 Rev: src/dynamic_buffer.h:1.2 Rev: src/efun.h:1.2 Rev: src/error.c:1.2 Rev: src/error.h:1.2 Rev: src/fd_control.c:1.2 Rev: src/fd_control.h:1.2 Rev: src/fsort.c:1.2 Rev: src/fsort.h:1.2 Rev: src/global.h:1.2 Rev: src/hashtable.c:1.2 Rev: src/hashtable.h:1.2 Rev: src/interpret.c:1.5 Rev: src/interpret.h:1.2 Rev: src/language.y:1.3 Rev: src/las.c:1.3 Rev: src/las.h:1.3 Rev: src/lex.c:1.3 Rev: src/lex.h:1.2 Rev: src/list.c:1.3 Rev: src/list.h:1.2 Rev: src/lpc_signal.c:1.1 Rev: src/lpc_signal.h:1.1 Rev: src/lpc_types.c:1.3 Rev: src/lpc_types.h:1.2 Rev: src/machine.h.in:1.3 Rev: src/macros.h:1.4 Rev: src/main.c:1.8 Rev: src/main.h:1.2 Rev: src/mapping.c:1.4 Rev: src/mapping.h:1.2 Rev: src/memory.c:1.3 Rev: src/memory.h:1.2 Rev: src/module.c:1.2 Rev: src/module.h:1.2 Rev: src/modules/files/Makefile.in:1.3 Rev: src/modules/files/Makefile.in.src:1.2 Rev: src/modules/files/configure.in:1.5 Rev: src/modules/files/datagram.c:1.2 Rev: src/modules/files/efuns.c:1.4 Rev: src/modules/files/file.c:1.5 Rev: src/modules/files/file.h:1.3 Rev: src/modules/files/file_machine.h.in:1.3 Rev: src/modules/files/socket.c:1.6 Rev: src/modules/math/Makefile.in:1.4 Rev: src/modules/math/Makefile.in.src:1.3 Rev: src/modules/math/math.c:1.2 Rev: src/modules/regexp/Makefile.in:1.3 Rev: src/modules/regexp/Makefile.in.src:1.2 Rev: src/modules/regexp/glue.c:1.2 Rev: src/modules/regexp/regexp.h:1.2 Rev: src/modules/sprintf/Makefile.in:1.3 Rev: src/modules/sprintf/Makefile.in.src:1.2 Rev: src/modules/sprintf/sprintf.c:1.2 Rev: src/object.c:1.3 Rev: src/object.h:1.2 Rev: src/opcodes.c:1.6 Rev: src/opcodes.h:1.2 Rev: src/operators.c:1.3 Rev: src/operators.h:1.2 Rev: src/otable.h:1.2 Rev: src/port.c:1.9 Rev: src/port.h:1.4 Rev: src/program.h:1.2 Rev: src/rusage.c:1.3 Rev: src/rusage.h:1.2 Rev: src/stralloc.c:1.3 Rev: src/stralloc.h:1.3 Rev: src/stuff.c:1.2 Rev: src/stuff.h:1.2 Rev: src/svalue.c:1.4 Rev: src/svalue.h:1.2 Rev: src/todo:1.2 Rev: src/types.h:1.6 Rev: src/ualarm.c:1.2
Fredrik Hübinette (Hubbe) authoredRev: README:1.1 Rev: bin/create_testsuite:1.3 Rev: bin/hilfe.lpc:1.2 Rev: bin/rsif:1.2 Rev: bin/uhttpd.lpc:1.2 Rev: doc/simulated/open:1.1 Rev: lib/master.lpc:1.2 Rev: lib/simulate.lpc:1.4 Rev: lib/testsuite.lpc:1.3 Rev: src/BUGS:1.3 Rev: src/Makefile.in:1.6 Rev: src/Makefile.in.src:1.2 Rev: src/README:1.2 Rev: src/add_efun.c:1.2 Rev: src/add_efun.h:1.2 Rev: src/array.c:1.4 Rev: src/array.h:1.2 Rev: src/backend.c:1.3 Rev: src/backend.h:1.2 Rev: src/builtin_efuns.c:1.2 Rev: src/builtin_efuns.h:1.2 Rev: src/call_out.c:1.5 Rev: src/call_out.h:1.2 Rev: src/callback.c:1.2 Rev: src/callback.h:1.2 Rev: src/config.h:1.6 Rev: src/configure.in:1.9 Rev: src/debug.c:1.4 Rev: src/debug.h:1.4 Rev: src/docode.c:1.4 Rev: src/docode.h:1.2 Rev: src/dynamic_buffer.c:1.3 Rev: src/dynamic_buffer.h:1.2 Rev: src/efun.h:1.2 Rev: src/error.c:1.2 Rev: src/error.h:1.2 Rev: src/fd_control.c:1.2 Rev: src/fd_control.h:1.2 Rev: src/fsort.c:1.2 Rev: src/fsort.h:1.2 Rev: src/global.h:1.2 Rev: src/hashtable.c:1.2 Rev: src/hashtable.h:1.2 Rev: src/interpret.c:1.5 Rev: src/interpret.h:1.2 Rev: src/language.y:1.3 Rev: src/las.c:1.3 Rev: src/las.h:1.3 Rev: src/lex.c:1.3 Rev: src/lex.h:1.2 Rev: src/list.c:1.3 Rev: src/list.h:1.2 Rev: src/lpc_signal.c:1.1 Rev: src/lpc_signal.h:1.1 Rev: src/lpc_types.c:1.3 Rev: src/lpc_types.h:1.2 Rev: src/machine.h.in:1.3 Rev: src/macros.h:1.4 Rev: src/main.c:1.8 Rev: src/main.h:1.2 Rev: src/mapping.c:1.4 Rev: src/mapping.h:1.2 Rev: src/memory.c:1.3 Rev: src/memory.h:1.2 Rev: src/module.c:1.2 Rev: src/module.h:1.2 Rev: src/modules/files/Makefile.in:1.3 Rev: src/modules/files/Makefile.in.src:1.2 Rev: src/modules/files/configure.in:1.5 Rev: src/modules/files/datagram.c:1.2 Rev: src/modules/files/efuns.c:1.4 Rev: src/modules/files/file.c:1.5 Rev: src/modules/files/file.h:1.3 Rev: src/modules/files/file_machine.h.in:1.3 Rev: src/modules/files/socket.c:1.6 Rev: src/modules/math/Makefile.in:1.4 Rev: src/modules/math/Makefile.in.src:1.3 Rev: src/modules/math/math.c:1.2 Rev: src/modules/regexp/Makefile.in:1.3 Rev: src/modules/regexp/Makefile.in.src:1.2 Rev: src/modules/regexp/glue.c:1.2 Rev: src/modules/regexp/regexp.h:1.2 Rev: src/modules/sprintf/Makefile.in:1.3 Rev: src/modules/sprintf/Makefile.in.src:1.2 Rev: src/modules/sprintf/sprintf.c:1.2 Rev: src/object.c:1.3 Rev: src/object.h:1.2 Rev: src/opcodes.c:1.6 Rev: src/opcodes.h:1.2 Rev: src/operators.c:1.3 Rev: src/operators.h:1.2 Rev: src/otable.h:1.2 Rev: src/port.c:1.9 Rev: src/port.h:1.4 Rev: src/program.h:1.2 Rev: src/rusage.c:1.3 Rev: src/rusage.h:1.2 Rev: src/stralloc.c:1.3 Rev: src/stralloc.h:1.3 Rev: src/stuff.c:1.2 Rev: src/stuff.h:1.2 Rev: src/svalue.c:1.4 Rev: src/svalue.h:1.2 Rev: src/todo:1.2 Rev: src/types.h:1.6 Rev: src/ualarm.c:1.2
operators.c 10.66 KiB
/*\
||| This file a part of uLPC, and is copyright by Fredrik Hubinette
||| uLPC is distributed as GPL (General Public License)
||| See the files COPYING and DISCLAIMER for more information.
\*/
#include <math.h>
#include "global.h"
#include "interpret.h"
#include "svalue.h"
#include "list.h"
#include "mapping.h"
#include "array.h"
#include "stralloc.h"
#include "opcodes.h"
#include "operators.h"
#include "language.h"
#include "memory.h"
#include "error.h"
#define COMPARISON(ID,EXPR) \
void ID() \
{ \
int i=EXPR; \
pop_n_elems(2); \
sp->type=T_INT; \
sp->u.integer=i; \
sp++; \
}
COMPARISON(f_eq, is_eq(sp-2,sp-1))
COMPARISON(f_ne,!is_eq(sp-2,sp-1))
COMPARISON(f_lt, is_lt(sp-2,sp-1))
COMPARISON(f_le,!is_gt(sp-2,sp-1))
COMPARISON(f_gt, is_gt(sp-2,sp-1))
COMPARISON(f_ge,!is_lt(sp-2,sp-1))
void f_sum(INT32 args)
{
INT32 e,size;
TYPE_FIELD types;
types=0;
for(e=-args;e<0;e++) types|=1<<sp[e].type;
switch(types)
{
default:
if(args)
{
switch(sp[-args].type)
{
case T_OBJECT:
case T_PROGRAM:
case T_FUNCTION:
error("Bad argument 1 to summation\n");
}
}
error("Incompatible types to sum() or +\n");
return; /* compiler hint */
case BIT_STRING:
{
struct lpc_string *r;
char *buf;
if(args==1) return;
size=0;
for(e=-args;e<0;e++) size+=sp[e].u.string->len;
if(args==2)
{
r=add_shared_strings(sp[-2].u.string,sp[-1].u.string);
}else{
r=begin_shared_string(size);
buf=r->str;
for(e=-args;e<0;e++)
{
MEMCPY(buf,sp[e].u.string->str,sp[e].u.string->len);
buf+=sp[e].u.string->len;
}
r=end_shared_string(r);
}
for(e=-args;e<0;e++)
{
free_string(sp[e].u.string);
}
sp-=args;
push_string(r);
break;
}
case BIT_STRING | BIT_INT:
case BIT_STRING | BIT_FLOAT:
case BIT_STRING | BIT_FLOAT | BIT_INT:
{
struct lpc_string *r;
char *buf,*str;
size=0;
for(e=-args;e<0;e++)
{
switch(sp[e].type)
{
case T_STRING:
size+=sp[e].u.string->len;
break;
case T_INT:
size+=14;
break;
case T_FLOAT:
size+=22;
break;
}
}
str=buf=xalloc(size+1);
size=0;
for(e=-args;e<0;e++)
{
switch(sp[e].type)
{
case T_STRING:
MEMCPY(buf,sp[e].u.string->str,sp[e].u.string->len);
buf+=sp[e].u.string->len;
break;
case T_INT:
sprintf(buf,"%ld",(long)sp[e].u.integer);
buf+=strlen(buf);
break;
case T_FLOAT:
sprintf(buf,"%f",(double)sp[e].u.float_number);
buf+=strlen(buf);
break;
}
}
r=make_shared_binary_string(str,buf-str);
free(str);
pop_n_elems(args);
push_string(r);
break;
}
case BIT_INT:
size=0;
for(e=-args; e<0; e++) size+=sp[e].u.integer;
sp-=args-1;
sp[-1].u.integer=size;
break;
case BIT_FLOAT:
{
FLOAT_TYPE sum;
sum=0.0;
for(e=-args; e<0; e++) sum+=sp[e].u.float_number;
sp-=args-1;
sp[-1].u.float_number=sum;
break;
}
case BIT_ARRAY:
{
struct array *a;
a=add_arrays(sp-args,args);
pop_n_elems(args);
push_array(a);
break;
}
case BIT_MAPPING:
{
struct mapping *m;
m = add_mappings(sp - args, args);
pop_n_elems(args);
push_mapping(m);
break;
}
case BIT_LIST:
{
struct list *l;
l = add_lists(sp - args, args);
pop_n_elems(args);
push_list(l);
break;
}
}
}
void f_add() { f_sum(2); }
void f_subtract()
{
if (sp[-2].type != sp[-1].type )
error("Subtract on different types.\n");
switch(sp[-1].type)
{
case T_ARRAY:
{
struct array *a;
check_array_for_destruct(sp[-2].u.array);
check_array_for_destruct(sp[-1].u.array);
a = subtract_arrays(sp[-2].u.array, sp[-1].u.array);
pop_n_elems(2);
push_array(a);
return;
}
case T_MAPPING:
{
struct mapping *m;
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping,OP_SUB);
pop_n_elems(2);
push_mapping(m);
return;
}
case T_LIST:
{
struct list *l;
l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_SUB);
pop_n_elems(2);
push_list(l);
return;
}
case T_FLOAT:
sp--;
sp[-1].u.float_number -= sp[0].u.float_number;
return;
case T_INT:
sp--;
sp[-1].u.integer -= sp[0].u.integer;
return;
case T_STRING:
{
struct lpc_string *s,*ret;
sp--;
s=make_shared_string("");
ret=string_replace(sp[-1].u.string,sp[0].u.string,s);
free_string(sp[-1].u.string);
free_string(sp[0].u.string);
free_string(s);
sp[-1].u.string=ret;
return;
}
default:
error("Bad argument 1 to subtraction.\n");
}
}
void f_and()
{
if(sp[-1].type != sp[-2].type)
error("Bitwise and on different types.\n");
switch(sp[-2].type)
{
case T_INT:
sp--;
sp[-1].u.integer &= sp[0].u.integer;
break;
case T_MAPPING:
{
struct mapping *m;
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_AND);
pop_n_elems(2);
push_mapping(m);
return;
}
case T_LIST:
{
struct list *l;
l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_AND);
pop_n_elems(2);
push_list(l);
return;
}
case T_ARRAY:
{
struct array *a;
a=and_arrays(sp[-2].u.array, sp[-1].u.array);
pop_n_elems(2);
push_array(a);
return;
}
default:
error("Bitwise and on illegal type.\n");
}
}
void f_or()
{
if(sp[-1].type != sp[-2].type)
error("Bitwise or on different types.\n");
switch(sp[-2].type)
{
case T_INT:
sp--;
sp[-1].u.integer |= sp[0].u.integer;
break;
case T_MAPPING:
{
struct mapping *m;
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_OR);
pop_n_elems(2);
push_mapping(m);
return;
}
case T_LIST:
{
struct list *l;
l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_OR);
pop_n_elems(2);
push_list(l);
return;
}
case T_ARRAY:
{
struct array *a;
a=merge_array_without_order(sp[-2].u.array, sp[-1].u.array, OP_OR);
pop_n_elems(2);
push_array(a);
return;
}
default:
error("Bitwise or on illegal type.\n");
}
}
void f_xor()
{
if(sp[-1].type != sp[-2].type)
error("Bitwise xor on different types.\n");
switch(sp[-2].type)
{
case T_INT:
sp--;
sp[-1].u.integer ^= sp[0].u.integer;
break;
case T_MAPPING:
{
struct mapping *m;
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_XOR);
pop_n_elems(2);
push_mapping(m);
return;
}
case T_LIST:
{
struct list *l;
l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_XOR);
pop_n_elems(2);
push_list(l);
return;
}
case T_ARRAY:
{
struct array *a;
a=merge_array_without_order(sp[-2].u.array, sp[-1].u.array, OP_XOR);
pop_n_elems(2);
push_array(a);
return;
}
default:
error("Bitwise xor on illegal type.\n");
}
}
void f_lsh()
{
if(sp[-2].type != T_INT) error("Bad argument 1 to <<\n");
if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n");
sp--;
sp[-1].u.integer <<= sp[0].u.integer;
}
void f_rsh()
{
if(sp[-2].type != T_INT) error("Bad argument 1 to >>\n");
if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n");
sp--;
sp[-1].u.integer >>= sp[0].u.integer;
}
void f_multiply()
{
switch(sp[-2].type)
{
case T_ARRAY:
if(sp[-1].type!=T_STRING)
{
error("Bad argument 2 to multiply.\n");
}else{
struct lpc_string *ret;
sp--;
ret=implode(sp[-1].u.array,sp[0].u.string);
free_string(sp[0].u.string);
free_array(sp[-1].u.array);
sp[-1].type=T_STRING;
sp[-1].u.string=ret;
return;
}
case T_FLOAT:
if(sp[-1].type!=T_FLOAT) error("Bad argument 2 to multiply.\n");
sp--;
sp[-1].u.float_number *= sp[0].u.float_number;
return;
case T_INT:
if(sp[-1].type!=T_INT) error("Bad argument 2 to multiply.\n");
sp--;
sp[-1].u.integer *= sp[0].u.integer;
return;
default:
error("Bad argument 1 to multiply.\n");
}
}
void f_divide()
{
if(sp[-2].type!=sp[-1].type)
error("Division on different types.\n");
switch(sp[-2].type)
{
case T_STRING:
{
struct array *ret;
sp--;
ret=explode(sp[-1].u.string,sp[0].u.string);
free_string(sp[-1].u.string);
free_string(sp[0].u.string);
sp[-1].type=T_ARRAY;
sp[-1].u.array=ret;
return;
}
case T_FLOAT:
if(sp[-1].u.float_number == 0.0)
error("Division by zero.\n");
sp--;
sp[-1].u.float_number /= sp[0].u.float_number;
return;
case T_INT:
if (sp[-1].u.integer == 0)
error("Division by zero\n");
sp--;
sp[-1].u.integer /= sp[0].u.integer;
return;
default:
error("Bad argument 1 to divide.\n");
}
}
void f_mod()
{
if(sp[-2].type != sp[-1].type)
error("Modulo on different types.\n");
switch(sp[-1].type)
{
case T_FLOAT:
{
FLOAT_TYPE foo;
if(sp[-1].u.float_number == 0.0)
error("Modulo by zero.\n");
sp--;
foo=sp[-1].u.float_number / sp[0].u.float_number;
foo=sp[-1].u.float_number - sp[0].u.float_number * floor(foo);
sp[-1].u.float_number=foo;
return;
}
case T_INT:
if (sp[-1].u.integer == 0) error("Modulo by zero.\n");
sp--;
sp[-1].u.integer %= sp[0].u.integer;
return;
default:
error("Bad argument 1 to modulo.\n");
}
}
void f_not()
{
if(sp[-1].type==T_INT)
{
sp[-1].u.integer = !sp[-1].u.integer;
}else{
pop_stack();
sp->type=T_INT;
sp->u.integer=0;
sp++;
}
}
void f_compl()
{
if (sp[-1].type != T_INT) error("Bad argument to ~\n");
sp[-1].u.integer = ~ sp[-1].u.integer;
}
void f_negate()
{
switch(sp[-1].type)
{
case T_FLOAT:
sp[-1].u.float_number=-sp[-1].u.float_number;
return;
case T_INT:
sp[-1].u.integer = - sp[-1].u.integer;
return;
default:
error("Bad argument to unary minus\n");
}
}
void f_range()
{
INT32 from,to;
if(sp[-2].type != T_INT)
error("Bad argument 1 to [ .. ]\n");
if(sp[-1].type != T_INT)
error("Bad argument 2 to [ .. ]\n");
from=sp[-2].u.integer;
if(from<0) from=0;
to=sp[-1].u.integer;
if(to<from-1) to=from-1;
sp-=2;
switch(sp[-1].type)
{
case T_STRING:
{
struct lpc_string *s;
if(to>=sp[-1].u.string->len-1)
{
if(from==0) return;
to=sp[-1].u.string->len-1;
if(from>to+1) from=to+1;
}
s=make_shared_binary_string(sp[-1].u.string->str+from,to-from+1);
free_string(sp[-1].u.string);
sp[-1].u.string=s;
break;
}
case T_ARRAY:
{
struct array *a;
if(to>=sp[-1].u.array->size-1)
{
to=sp[-1].u.array->size-1;
if(from>to+1) from=to+1;
}
a=slice_array(sp[-1].u.array,from,to+1);
free_array(sp[-1].u.array);
sp[-1].u.array=a;
break;
}
default:
error("[ .. ] can only be done on strings and arrays.\n");
}
}