1
0
mirror of https://github.com/samba-team/samba.git synced 2025-06-29 04:49:44 +03:00
Andrew Tridgell adbb1612c1 r8399: move the ejs and esp code closer to the directory layout used by the
upstream sources. This makes it much easier to keep it up to date.

I will separate out the mpr code into lib/appweb/mpr next
(This used to be commit 52db7a052baeb0f11361ed69b71cb790039e3cc9)
2007-10-10 13:22:39 -05:00

704 lines
17 KiB
C

/*
* @file ejsProc.c
* @brief EJS support functions
*/
/********************************* Copyright **********************************/
/*
* @copy default.g
*
* Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
* Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http://www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http://www.mbedthis.com
*
* @end
*/
/********************************** Includes **********************************/
#include "ejsInternal.h"
#if BLD_FEATURE_EJS
/****************************** Forward Declarations **************************/
/*
* Object constructors
*/
static int objectConsProc(EjsHandle eid, int argc, MprVar **argv);
static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv);
static int booleanConsProc(EjsHandle eid, int argc, MprVar **agv);
static int numberConsProc(EjsHandle eid, int argc, MprVar **argv);
static int stringConsProc(EjsHandle eid, int argc, MprVar **argv);
/*
* Core functions
*/
static int toStringProc(EjsHandle eid, int argc, MprVar **argv);
static int valueOfProc(EjsHandle eid, int argc, MprVar **argv);
/*
* Triggers
*/
static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op,
MprProperties *parentProperties, MprVar *prop, MprVar *newValue,
bool copyRef);
/******************************************************************************/
/*
* Routine to create the base common to all object types
*/
MprVar ejsCreateObj(const char *name, int hashSize)
{
MprVar o;
o = mprCreateObjVar(name, hashSize);
if (o.type == MPR_TYPE_UNDEFINED) {
mprAssert(0);
return o;
}
mprCreatePropertyValue(&o, "toString",
mprCreateCFunctionVar(toStringProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(&o, "valueOf",
mprCreateCFunctionVar(valueOfProc, 0, MPR_VAR_SCRIPT_HANDLE));
return o;
}
/******************************************************************************/
/*
* Routine to destroy a variable
*/
bool ejsDestroyVar(MprVar *obj)
{
return mprDestroyVar(obj);
}
/******************************************************************************/
/*
* Routine to create the base array type
*/
MprVar ejsCreateArray(const char *name, int size)
{
MprVar obj, *lp, undef;
char idx[16];
int i;
/* Sanity limit for size of hash table */
obj = ejsCreateObj(name, max(size, 503));
if (obj.type == MPR_TYPE_UNDEFINED) {
mprAssert(0);
return obj;
}
undef = mprCreateUndefinedVar();
for (i = 0; i < size; i++) {
mprItoa(i, idx, sizeof(idx));
mprCreateProperty(&obj, idx, &undef);
}
lp = mprCreatePropertyValue(&obj, "length", mprCreateIntegerVar(size));
mprAssert(lp);
mprSetVarReadonly(lp, 1);
mprAddVarTrigger(lp, lengthTrigger);
return obj;
}
/******************************************************************************/
/******************************** Constructors ********************************/
/******************************************************************************/
/*
* Object constructor. Nothing really done here. For future expansion.
*/
static int objectConsProc(EjsHandle eid, int argc, MprVar **argv)
{
#if XX_UNUSED_XX
MprVar *obj;
Ejs *ep;
if((ep = ejsPtr(eid)) == NULL) {
return -1;
}
obj = mprGetProperty(ep->local, "this", 0);
mprAssert(obj);
#endif
return 0;
}
/******************************************************************************/
/*
* Array constructor
*/
static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv)
{
MprVar *obj, *lp, undef;
Ejs *ep;
char idx[16];
int i, max;
objectConsProc(eid, argc, argv);
if((ep = ejsPtr(eid)) == NULL) {
return -1;
}
obj = mprGetProperty(ep->local, "this", 0);
mprAssert(obj);
if (argc == 1 && mprVarIsNumber(argv[0]->type)) {
/*
* x = new Array(size);
*/
undef = mprCreateUndefinedVar();
max = (int) mprVarToInteger(argv[0]);
for (i = 0; i < max; i++) {
mprItoa(i, idx, sizeof(idx));
mprCreateProperty(obj, idx, &undef);
}
} else {
/*
* x = new Array(element0, element1, ..., elementN):
*/
max = argc;
for (i = 0; i < max; i++) {
mprItoa(i, idx, sizeof(idx));
mprCreateProperty(obj, idx, argv[i]);
}
}
lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max));
mprAssert(lp);
mprSetVarReadonly(lp, 1);
mprAddVarTrigger(lp, lengthTrigger);
return 0;
}
/******************************************************************************/
/*
* Boolean constructor
*/
static int booleanConsProc(EjsHandle eid, int argc, MprVar **argv)
{
objectConsProc(eid, argc, argv);
return 0;
}
/******************************************************************************/
#if FUTURE
/*
* Date constructor
*/
static int dateConsProc(EjsHandle eid, int argc, MprVar **argv)
{
objectConsProc(eid, argc, argv);
return 0;
}
#endif
/******************************************************************************/
/*
* Number constructor
*/
static int numberConsProc(EjsHandle eid, int argc, MprVar **argv)
{
objectConsProc(eid, argc, argv);
return 0;
}
/******************************************************************************/
/*
* String constructor
*/
static int stringConsProc(EjsHandle eid, int argc, MprVar **argv)
{
objectConsProc(eid, argc, argv);
return 0;
}
/******************************************************************************/
/********************************** Functions *********************************/
/******************************************************************************/
static int toStringProc(EjsHandle eid, int argc, MprVar **argv)
{
MprVar *obj;
Ejs *ep;
char *buf;
int radix;
if (argc == 0) {
radix = 10;
} else if (argc == 1) {
radix = (int) mprVarToInteger(argv[0]);
} else {
mprAssert(0);
return -1;
}
if((ep = ejsPtr(eid)) == NULL) {
return -1;
}
obj = mprGetProperty(ep->local, "this", 0);
mprAssert(obj);
mprVarToString(&buf, MPR_MAX_STRING, 0, obj);
mprCopyVarValue(&ep->result, mprCreateStringVar(buf, 0), MPR_SHALLOW_COPY);
mprFree(buf);
return 0;
}
/******************************************************************************/
static int valueOfProc(EjsHandle eid, int argc, MprVar **argv)
{
MprVar *obj;
Ejs *ep;
if (argc != 0) {
mprAssert(0);
return -1;
}
if((ep = ejsPtr(eid)) == NULL) {
return -1;
}
obj = mprGetProperty(ep->local, "this", 0);
mprAssert(obj);
switch (obj->type) {
default:
case MPR_TYPE_UNDEFINED:
case MPR_TYPE_NULL:
case MPR_TYPE_CFUNCTION:
case MPR_TYPE_OBJECT:
case MPR_TYPE_FUNCTION:
case MPR_TYPE_STRING_CFUNCTION:
case MPR_TYPE_PTR:
mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY);
break;
case MPR_TYPE_STRING:
mprCopyVarValue(&ep->result, mprCreateIntegerVar(atoi(obj->string)), 0);
break;
case MPR_TYPE_BOOL:
case MPR_TYPE_INT:
#if BLD_FEATURE_INT64
case MPR_TYPE_INT64:
#endif
#if BLD_FEATURE_FLOATING_POINT
case MPR_TYPE_FLOAT:
#endif
mprCopyVar(&ep->result, obj, 0);
break;
}
return 0;
}
/******************************************************************************/
/*
* Var access trigger on the Array.length property. Return the count of
* enumerable properties (don't count functions).
*/
static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op,
MprProperties *parentProperties, MprVar *prop, MprVar *newValue,
bool copyRef)
{
switch (op) {
case MPR_VAR_READ:
/*
* Subtract one for the length property
* FUTURE -- need an API to access parentProperties
* FUTURE -- contradiction to be read-only yet allow USE_NEW_VALUE.
* API needs finer control.
*/
*newValue = mprCreateIntegerVar(parentProperties->numDataItems - 1);
return MPR_TRIGGER_USE_NEW_VALUE;
case MPR_VAR_WRITE:
return MPR_TRIGGER_ABORT;
case MPR_VAR_CREATE_PROPERTY:
case MPR_VAR_DELETE_PROPERTY:
case MPR_VAR_DELETE:
default:
break;
}
return MPR_TRIGGER_PROCEED;
}
/******************************************************************************/
/**************************** Extension Functions *****************************/
/******************************************************************************/
/*
* Assert
*/
static int assertProc(EjsHandle eid, int argc, MprVar **argv)
{
bool b;
if (argc < 1) {
ejsSetErrorMsg(eid, "usage: assert(condition)\n");
return -1;
}
b = mprVarToBool(argv[0]);
if (b == 0) {
ejsSetErrorMsg(eid, "Assertion failure\n");
return -1;
}
ejsSetReturnValue(eid, mprCreateBoolVar(b));
return 0;
}
/******************************************************************************/
/*
* Exit
*/
static int exitProc(EjsHandle eid, int argc, MprVar **argv)
{
int status;
if (argc < 1) {
ejsSetErrorMsg(eid, "usage: exit(status)\n");
return -1;
}
status = (int) mprVarToInteger(argv[0]);
ejsSetExitStatus(eid, status);
ejsSetReturnValue(eid, mprCreateStringVar("", 0));
return 0;
}
/******************************************************************************/
static void printVar(MprVar *vp, int recurseCount, int indent)
{
MprVar *np;
char *buf;
int i;
if (recurseCount > 5) {
write(1, "Skipping - recursion too deep\n", 29);
return;
}
for (i = 0; i < indent; i++) {
write(1, " ", 2);
}
if (vp->type == MPR_TYPE_OBJECT) {
if (vp->name) {
write(1, vp->name, strlen(vp->name));
} else {
write(1, "unknown", 7);
}
write(1, ": {\n", 4);
np = mprGetFirstProperty(vp, MPR_ENUM_DATA);
while (np) {
if (strcmp(np->name, "local") == 0 ||
strcmp(np->name, "global") == 0 ||
strcmp(np->name, "this") == 0) {
np = mprGetNextProperty(vp, np, MPR_ENUM_DATA);
continue;
}
printVar(np, recurseCount + 1, indent + 1);
np = mprGetNextProperty(vp, np, MPR_ENUM_DATA);
if (np) {
write(1, ",\n", 2);
}
}
write(1, "\n", 1);
for (i = 0; i < indent; i++) {
write(1, " ", 2);
}
write(1, "}", 1);
} else {
if (vp->name) {
write(1, vp->name, strlen(vp->name));
} else {
write(1, "unknown", 7);
}
write(1, ": ", 2);
/* FUTURE -- other types ? */
mprVarToString(&buf, MPR_MAX_STRING, 0, vp);
if (vp->type == MPR_TYPE_STRING) {
write(1, "\"", 1);
}
write(1, buf, strlen(buf));
if (vp->type == MPR_TYPE_STRING) {
write(1, "\"", 1);
}
mprFree(buf);
}
}
/******************************************************************************/
/*
* Print the args to stdout
*/
static int printVarsProc(EjsHandle eid, int argc, MprVar **argv)
{
MprVar *vp;
char *buf;
int i;
for (i = 0; i < argc; i++) {
vp = argv[i];
switch (vp->type) {
case MPR_TYPE_OBJECT:
printVar(vp, 0, 0);
break;
default:
mprVarToString(&buf, MPR_MAX_STRING, 0, vp);
write(1, buf, strlen(buf));
mprFree(buf);
break;
}
}
write(1, "\n", 1);
ejsSetReturnValue(eid, mprCreateStringVar("", 0));
return 0;
}
/******************************************************************************/
/*
* Print the args to stdout
*/
static int printProc(EjsHandle eid, int argc, MprVar **argv)
{
char *buf;
int i;
for (i = 0; i < argc; i++) {
mprVarToString(&buf, MPR_MAX_STRING, 0, argv[i]);
write(1, buf, strlen(buf));
mprFree(buf);
}
return 0;
}
/******************************************************************************/
/*
* println
*/
static int printlnProc(EjsHandle eid, int argc, MprVar **argv)
{
printProc(eid, argc, argv);
write(1, "\n", 1);
return 0;
}
/******************************************************************************/
/*
* Trace
*/
static int traceProc(EjsHandle eid, int argc, char **argv)
{
if (argc == 1) {
mprLog(0, "%s", argv[0]);
} else if (argc == 2) {
mprLog(atoi(argv[0]), "%s", argv[1]);
} else {
ejsSetErrorMsg(eid, "Usage: trace([level], message)");
return -1;
}
ejsSetReturnString(eid, "");
return 0;
}
/******************************************************************************/
/*
* Return the object reference count
*/
static int refCountProc(EjsHandle eid, int argc, MprVar **argv)
{
MprVar *vp;
int count;
vp = argv[0];
if (vp->type == MPR_TYPE_OBJECT) {
count = mprGetVarRefCount(vp);
ejsSetReturnValue(eid, mprCreateIntegerVar(count));
} else {
ejsSetReturnValue(eid, mprCreateIntegerVar(0));
}
return 0;
}
/******************************************************************************/
/*
* Evaluate a sub-script. It is evaluated in the same variable scope as
* the calling script / function.
*/
static int evalScriptProc(EjsHandle eid, int argc, MprVar **argv)
{
MprVar *arg;
char *emsg;
int i;
ejsSetReturnValue(eid, mprCreateUndefinedVar());
for (i = 0; i < argc; i++) {
arg = argv[i];
if (arg->type != MPR_TYPE_STRING) {
continue;
}
if (ejsEvalScript(eid, arg->string, 0, &emsg) < 0) {
ejsSetErrorMsg(eid, "%s", emsg);
mprFree(emsg);
return -1;
}
}
/*
* Return with the value of the last expression
*/
return 0;
}
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
/*
* Define the standard properties and functions inherited by all script engines.
*/
int ejsDefineStandardProperties(MprVar *obj)
{
#if BLD_FEATURE_FLOATING_POINT
double d = 0.0;
/* FUTURE - this generates warnings on some systems. This is okay. */
mprCreatePropertyValue(obj, "NaN", mprCreateFloatVar(0.0 / d));
d = MAX_FLOAT;
mprCreatePropertyValue(obj, "Infinity", mprCreateFloatVar(d * d));
#endif
mprCreatePropertyValue(obj, "null", mprCreateNullVar());
mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar());
mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1));
mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0));
#if BLD_FEATURE_LEGACY_API
/*
* DEPRECATED: 2.0.
* So that ESP/ASP can ignore "language=javascript" statements
*/
mprCreatePropertyValue(obj, "javascript", mprCreateIntegerVar(0));
#endif
/*
* Extension functions
*/
mprCreatePropertyValue(obj, "assert",
mprCreateCFunctionVar(assertProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "eval",
mprCreateCFunctionVar(evalScriptProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "exit",
mprCreateCFunctionVar(exitProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "refCount",
mprCreateCFunctionVar(refCountProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "print",
mprCreateCFunctionVar(printProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "println",
mprCreateCFunctionVar(printlnProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "printVars",
mprCreateCFunctionVar(printVarsProc,0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "trace",
mprCreateStringCFunctionVar(traceProc, 0, MPR_VAR_SCRIPT_HANDLE));
/*
* Constructors
*/
mprCreatePropertyValue(obj, "Array",
mprCreateCFunctionVar(arrayConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "Boolean",
mprCreateCFunctionVar(booleanConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "Object",
mprCreateCFunctionVar(objectConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "Number",
mprCreateCFunctionVar(numberConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
mprCreatePropertyValue(obj, "String",
mprCreateCFunctionVar(stringConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
/* mprCreatePropertyValue(obj, "Date",
* mprCreateCFunctionVar(dateConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
* mprCreatePropertyValue(obj, "Regexp",
* mprCreateCFunctionVar(regexpConsProc, 0, MPR_VAR_SCRIPT_HANDLE));
*/
/*
* Can we use on var x = "string text";
*/
return 0;
}
/******************************************************************************/
#else
void ejsProcsDummy() {}
/******************************************************************************/
#endif /* BLD_FEATURE_EJS */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/