1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-12 04:23:49 +03:00
Files
samba-mirror/source/lib/appweb/ejs/ejsProcs.c
Andrew Tridgell 57d7a585e8 r8483: switched our generated ejs rpc code over to the new OO interface. This
means we don't pollute the name space, and also makes for faster
startup times as we only create variables for the pipes that we use,
not all pipes
2007-10-10 13:23:08 -05:00

705 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));
mprCreatePropertyValue(obj, "NULL", mprCreatePtrVar(NULL));
#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
*/