mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2026-02-06 21:11:38 -05:00
518 lines
12 KiB
C
518 lines
12 KiB
C
/*
|
|
* The builtin Math object.
|
|
* Copyright (c) 1998 New Generation Software (NGS) Oy
|
|
*
|
|
* Author: Markku Rossi <mtr@ngs.fi>
|
|
*/
|
|
|
|
/*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
* MA 02111-1307, USA
|
|
*/
|
|
|
|
/*
|
|
* $Source: /tmp/cvsroot-15-2-2007/clamav-devel/libclamav/js/b_math.c,v $
|
|
* $Id: b_math.c,v 1.2 2006/10/28 11:27:44 njh Exp $
|
|
*/
|
|
#if HAVE_CONFIG_H
|
|
#include "clamav-config.h"
|
|
#endif
|
|
|
|
#ifdef CL_EXPERIMENTAL
|
|
|
|
#include "jsint.h"
|
|
#include "rentrant.h"
|
|
|
|
/*
|
|
* Types and definitions.
|
|
*/
|
|
|
|
#ifndef M_E
|
|
#define M_E 2.71828182845904523536028747135266250
|
|
#endif
|
|
|
|
#ifndef M_LN10
|
|
#define M_LN10 2.302585092994046
|
|
#endif
|
|
|
|
#ifndef M_LN2
|
|
#define M_LN2 0.693147180559945309417232121458176568
|
|
#endif
|
|
|
|
#ifndef M_LOG10E
|
|
#define M_LOG10E 0.434294481903251827651128918916605082
|
|
#endif
|
|
|
|
#ifndef M_LOG2E
|
|
#define M_LOG2E 1.44269504088896340735992468100189214
|
|
#endif
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846264338327950288
|
|
#endif
|
|
|
|
#ifndef M_SQRT1_2
|
|
#define M_SQRT1_2 0.707106781186547524400844362104849039
|
|
#endif
|
|
|
|
#ifndef M_SQRT2
|
|
#define M_SQRT2 1.41421356237309504880168872420969808
|
|
#endif
|
|
|
|
|
|
#define ONE_ARG() \
|
|
do { \
|
|
JSNode cvt; \
|
|
\
|
|
if (args->u.vinteger != 1) \
|
|
goto argument_error; \
|
|
\
|
|
js_vm_to_number (vm, &args[1], &cvt); \
|
|
if (cvt.type == JS_INTEGER) \
|
|
d = (double) cvt.u.vinteger; \
|
|
else if (cvt.type == JS_FLOAT) \
|
|
d = cvt.u.vfloat; \
|
|
else \
|
|
{ \
|
|
/* Must be NaN. */ \
|
|
result_return->type = JS_NAN; \
|
|
goto done; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define TWO_ARGS() \
|
|
do { \
|
|
JSNode cvt; \
|
|
\
|
|
if (args->u.vinteger != 2) \
|
|
goto argument_error; \
|
|
\
|
|
js_vm_to_number (vm, &args[1], &cvt); \
|
|
if (cvt.type == JS_INTEGER) \
|
|
d = (double) cvt.u.vinteger; \
|
|
else if (cvt.type == JS_FLOAT) \
|
|
d = cvt.u.vfloat; \
|
|
else \
|
|
{ \
|
|
/* Must be NaN. */ \
|
|
result_return->type = JS_NAN; \
|
|
goto done; \
|
|
} \
|
|
\
|
|
js_vm_to_number (vm, &args[2], &cvt); \
|
|
if (cvt.type == JS_INTEGER) \
|
|
d2 = (double) args[1].u.vinteger; \
|
|
else if (cvt.type == JS_FLOAT) \
|
|
d2 = cvt.u.vfloat; \
|
|
else \
|
|
{ \
|
|
/* Must be NaN. */ \
|
|
result_return->type = JS_NAN; \
|
|
goto done; \
|
|
} \
|
|
\
|
|
} while (0)
|
|
|
|
/* Class context. */
|
|
struct math_ctx_st
|
|
{
|
|
JSSymbol s_abs;
|
|
JSSymbol s_acos;
|
|
JSSymbol s_asin;
|
|
JSSymbol s_atan;
|
|
JSSymbol s_atan2;
|
|
JSSymbol s_ceil;
|
|
JSSymbol s_cos;
|
|
JSSymbol s_exp;
|
|
JSSymbol s_floor;
|
|
JSSymbol s_log;
|
|
JSSymbol s_max;
|
|
JSSymbol s_min;
|
|
JSSymbol s_pow;
|
|
JSSymbol s_random;
|
|
JSSymbol s_round;
|
|
JSSymbol s_seed;
|
|
JSSymbol s_sin;
|
|
JSSymbol s_sqrt;
|
|
JSSymbol s_tan;
|
|
|
|
JSSymbol s_E;
|
|
JSSymbol s_LN10;
|
|
JSSymbol s_LN2;
|
|
JSSymbol s_LOG10E;
|
|
JSSymbol s_LOG2E;
|
|
JSSymbol s_PI;
|
|
JSSymbol s_SQRT1_2;
|
|
JSSymbol s_SQRT2;
|
|
|
|
void *drand48_context;
|
|
};
|
|
|
|
typedef struct math_ctx_st MathCtx;
|
|
|
|
/*
|
|
* Static functions.
|
|
*/
|
|
|
|
/* Method proc. */
|
|
static int
|
|
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
|
|
void *instance_context, JSSymbol method, JSNode *result_return,
|
|
JSNode *args)
|
|
{
|
|
MathCtx *ctx = builtin_info->obj_context;
|
|
double d, d2;
|
|
int i;
|
|
|
|
/* The default return value. */
|
|
result_return->type = JS_FLOAT;
|
|
|
|
if (method == ctx->s_abs)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = fabs (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_acos)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = acos (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_asin)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = asin (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_atan)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = atan (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_atan2)
|
|
{
|
|
TWO_ARGS ();
|
|
result_return->u.vfloat = atan2 (d, d2);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_ceil)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = ceil (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_cos)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = cos (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_exp)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = exp (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_floor)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = floor (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_log)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = log (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_max || method == ctx->s_min)
|
|
{
|
|
JSNode cvt;
|
|
|
|
if (args->u.vinteger < 1)
|
|
goto argument_error;
|
|
|
|
/* Take the initial argument. */
|
|
js_vm_to_number (vm, &args[1], &cvt);
|
|
if (cvt.type == JS_NAN)
|
|
{
|
|
result_return->type = JS_NAN;
|
|
goto done;
|
|
}
|
|
if (cvt.type == JS_INTEGER)
|
|
d = (double) cvt.u.vinteger;
|
|
else
|
|
d = cvt.u.vfloat;
|
|
|
|
/* Handle the rest. */
|
|
for (i = 1; i < args->u.vinteger; i++)
|
|
{
|
|
js_vm_to_number (vm, &args[1], &cvt);
|
|
if (cvt.type == JS_NAN)
|
|
{
|
|
result_return->type = JS_NAN;
|
|
goto done;
|
|
}
|
|
if (cvt.type == JS_INTEGER)
|
|
d2 = (double) cvt.u.vinteger;
|
|
else
|
|
d2 = cvt.u.vfloat;
|
|
|
|
if (method == ctx->s_max)
|
|
{
|
|
if (d2 > d)
|
|
d = d2;
|
|
}
|
|
else
|
|
{
|
|
if (d2 < d)
|
|
d = d2;
|
|
}
|
|
}
|
|
|
|
result_return->type = JS_FLOAT;
|
|
result_return->u.vfloat = d;
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_pow)
|
|
{
|
|
TWO_ARGS ();
|
|
result_return->u.vfloat = pow (d, d2);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_random)
|
|
{
|
|
if (args->u.vinteger != 0)
|
|
goto argument_error;
|
|
|
|
/* js_srand48 (ctx->drand48_context, time (NULL)); */
|
|
js_drand48 (ctx->drand48_context, &result_return->u.vfloat);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_round)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->type = JS_INTEGER;
|
|
result_return->u.vinteger = (long) (d + 0.5);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_seed)
|
|
{
|
|
ONE_ARG ();
|
|
js_srand48 (ctx->drand48_context, (long) d);
|
|
result_return->type = JS_UNDEFINED;
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_sin)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = sin (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_sqrt)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = sqrt (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_tan)
|
|
{
|
|
ONE_ARG ();
|
|
result_return->u.vfloat = tan (d);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == vm->syms.s_toString)
|
|
{
|
|
js_vm_make_static_string (vm, result_return, "Math", 4);
|
|
}
|
|
/* ********************************************************************** */
|
|
else
|
|
return JS_PROPERTY_UNKNOWN;
|
|
|
|
done:
|
|
|
|
return JS_PROPERTY_FOUND;
|
|
|
|
|
|
/*
|
|
* Error handling.
|
|
*/
|
|
|
|
argument_error:
|
|
sprintf (vm->error, "Math.%s(): illegal amount of arguments",
|
|
js_vm_symname (vm, method));
|
|
js_vm_error (vm);
|
|
|
|
argument_type_error:
|
|
sprintf (vm->error, "Math.%s(): illegal argument",
|
|
js_vm_symname (vm, method));
|
|
js_vm_error (vm);
|
|
|
|
/* NOTREACHED. */
|
|
return 0;
|
|
}
|
|
|
|
/* Property proc. */
|
|
static int
|
|
property (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
|
|
void *instance_context, JSSymbol property, int set, JSNode *node)
|
|
{
|
|
MathCtx *ctx = builtin_info->obj_context;
|
|
|
|
/* The default result is float. */
|
|
node->type = JS_FLOAT;
|
|
|
|
if (property == ctx->s_E)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_E;
|
|
}
|
|
else if (property == ctx->s_LN10)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_LN10;
|
|
}
|
|
else if (property == ctx->s_LN2)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_LN2;
|
|
}
|
|
else if (property == ctx->s_LOG10E)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_LOG10E;
|
|
}
|
|
else if (property == ctx->s_LOG2E)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_LOG2E;
|
|
}
|
|
else if (property == ctx->s_PI)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_PI;
|
|
}
|
|
else if (property == ctx->s_SQRT1_2)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_SQRT1_2;
|
|
}
|
|
else if (property == ctx->s_SQRT2)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->u.vfloat = M_SQRT2;
|
|
}
|
|
else
|
|
{
|
|
if (!set)
|
|
node->type = JS_UNDEFINED;
|
|
|
|
return JS_PROPERTY_UNKNOWN;
|
|
}
|
|
|
|
return JS_PROPERTY_FOUND;
|
|
|
|
|
|
/*
|
|
* Error handling.
|
|
*/
|
|
|
|
immutable:
|
|
sprintf (vm->error, "Math.%s: immutable property",
|
|
js_vm_symname (vm, property));
|
|
js_vm_error (vm);
|
|
|
|
/* NOTREACHED. */
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Global functions.
|
|
*/
|
|
|
|
void
|
|
js_builtin_Math (JSVirtualMachine *vm)
|
|
{
|
|
JSBuiltinInfo *info;
|
|
MathCtx *ctx;
|
|
JSNode *n;
|
|
|
|
ctx = js_calloc (vm, 1, sizeof (*ctx));
|
|
|
|
ctx->s_abs = js_vm_intern (vm, "abs");
|
|
ctx->s_acos = js_vm_intern (vm, "acos");
|
|
ctx->s_asin = js_vm_intern (vm, "asin");
|
|
ctx->s_atan = js_vm_intern (vm, "atan");
|
|
ctx->s_atan2 = js_vm_intern (vm, "atan2");
|
|
ctx->s_ceil = js_vm_intern (vm, "ceil");
|
|
ctx->s_cos = js_vm_intern (vm, "cos");
|
|
ctx->s_exp = js_vm_intern (vm, "exp");
|
|
ctx->s_floor = js_vm_intern (vm, "floor");
|
|
ctx->s_log = js_vm_intern (vm, "log");
|
|
ctx->s_max = js_vm_intern (vm, "max");
|
|
ctx->s_min = js_vm_intern (vm, "min");
|
|
ctx->s_pow = js_vm_intern (vm, "pow");
|
|
ctx->s_random = js_vm_intern (vm, "random");
|
|
ctx->s_round = js_vm_intern (vm, "round");
|
|
ctx->s_seed = js_vm_intern (vm, "seed");
|
|
ctx->s_sin = js_vm_intern (vm, "sin");
|
|
ctx->s_sqrt = js_vm_intern (vm, "sqrt");
|
|
ctx->s_tan = js_vm_intern (vm, "tan");
|
|
|
|
ctx->s_E = js_vm_intern (vm, "E");
|
|
ctx->s_LN10 = js_vm_intern (vm, "LN10");
|
|
ctx->s_LN2 = js_vm_intern (vm, "LN2");
|
|
ctx->s_LOG10E = js_vm_intern (vm, "LOG10E");
|
|
ctx->s_LOG2E = js_vm_intern (vm, "LOG2E");
|
|
ctx->s_PI = js_vm_intern (vm, "PI");
|
|
ctx->s_SQRT1_2 = js_vm_intern (vm, "SQRT1_2");
|
|
ctx->s_SQRT2 = js_vm_intern (vm, "SQRT2");
|
|
|
|
ctx->drand48_context = js_drand48_create (vm);
|
|
|
|
/* Object information. */
|
|
|
|
info = js_vm_builtin_info_create (vm);
|
|
|
|
info->method_proc = method;
|
|
info->property_proc = property;
|
|
info->obj_context = ctx;
|
|
info->obj_context_delete = js_free;
|
|
|
|
/* Define it. */
|
|
n = &vm->globals[js_vm_intern (vm, "Math")];
|
|
js_vm_builtin_create (vm, n, info, NULL);
|
|
}
|
|
#endif /*CL_EXPERIMENTAL*/
|