summaryrefslogtreecommitdiff
path: root/source4/lib/appweb/ejs-2.0/ejs/classes
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/ejs/classes')
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/.ignore1
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/Makefile21
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c167
-rwxr-xr-xsource4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c197
-rwxr-xr-xsource4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c140
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c588
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c144
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c381
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c1327
9 files changed, 2966 insertions, 0 deletions
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/.ignore b/source4/lib/appweb/ejs-2.0/ejs/classes/.ignore
new file mode 100644
index 0000000000..fb5a29031e
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/.ignore
@@ -0,0 +1 @@
+.updated
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/Makefile b/source4/lib/appweb/ejs-2.0/ejs/classes/Makefile
new file mode 100644
index 0000000000..ce12bb3829
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile to build the EJS Classes
+#
+# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+#
+
+COMPILE := *.c
+EXPORT_OBJECTS := yes
+MAKE_IFLAGS := -I.. -I../../mpr -I../../exml
+
+include make.dep
+
+compileExtra: .updated
+
+.updated: $(FILES)
+ @touch .updated
+
+## Local variables:
+## tab-width: 4
+## End:
+## vim: tw=78 sw=4 ts=4
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c
new file mode 100644
index 0000000000..feb64b1aa8
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c
@@ -0,0 +1,167 @@
+/*
+ * @file ejsArray.c
+ * @brief Array class
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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 "ejs.h"
+
+#if BLD_FEATURE_EJS
+
+/************************************ Code ************************************/
+
+int ejsDefineArrayClass(Ejs *ep)
+{
+ if (ejsDefineClass(ep, "Array", "Object", ejsArrayConstructor) == 0) {
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Routine to create the base array type
+ */
+
+EjsVar *ejsCreateArrayInternal(EJS_LOC_DEC(ep, loc), int size)
+{
+ EjsProperty *pp;
+ EjsVar *obj, *vp;
+
+ /* MOB -- need to supply hash size -- max(size, 503)); */
+
+ obj = ejsCreateSimpleObjInternal(EJS_LOC_PASS(ep, loc), "Array");
+ if (obj == 0) {
+ mprAssert(0);
+ return obj;
+ }
+ obj->isArray = 1;
+
+ /* MOB -- call constructor here and replace this code */
+
+ pp = ejsSetPropertyToInteger(ep, obj, "length", size);
+ ejsMakePropertyEnumerable(pp, 0);
+
+ vp = ejsGetVarPtr(pp);
+ vp->isArrayLength = 1;
+
+ return obj;
+}
+
+/******************************************************************************/
+
+EjsVar *ejsAddArrayElt(Ejs *ep, EjsVar *op, EjsVar *element,
+ EjsCopyDepth copyDepth)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+ char idx[16];
+ int length;
+
+ mprAssert(op->isArray);
+
+ length = ejsGetPropertyAsInteger(ep, op, "length");
+
+ mprItoa(idx, sizeof(idx), length);
+ pp = ejsCreateProperty(ep, op, idx);
+ vp = ejsGetVarPtr(pp);
+
+ ejsWriteVar(ep, vp, element, copyDepth);
+
+ ejsSetPropertyToInteger(ep, op, "length", length + 1);
+
+ return vp;
+}
+
+/******************************************************************************/
+/*
+ * Constructor
+ */
+
+int ejsArrayConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+ char idx[16];
+ int i, max;
+
+ thisObj->isArray = 1;
+ max = 0;
+
+ if (argc > 0) {
+ if (argc == 1 && ejsVarIsNumber(argv[0])) {
+ /*
+ * x = new Array(size);
+ */
+ max = (int) ejsVarToInteger(argv[0]);
+
+ } else {
+ /*
+ * x = new Array(element0, element1, ..., elementN):
+ */
+ max = argc;
+ for (i = 0; i < max; i++) {
+ mprItoa(idx, sizeof(idx), i);
+ pp = ejsCreateSimpleProperty(ep, thisObj, idx);
+ vp = ejsGetVarPtr(pp);
+ ejsWriteVar(ep, vp, argv[i], EJS_SHALLOW_COPY);
+ }
+ }
+ }
+
+ pp = ejsCreateSimpleProperty(ep, thisObj, "length");
+ ejsMakePropertyEnumerable(pp, 0);
+ vp = ejsGetVarPtr(pp);
+ ejsWriteVarAsInteger(ep, vp, max);
+ vp->isArrayLength = 1;
+
+ return 0;
+}
+
+/******************************************************************************/
+
+#else
+void ejsArrayDummy() {}
+
+/******************************************************************************/
+#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
+ */
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c
new file mode 100755
index 0000000000..096316a822
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c
@@ -0,0 +1,197 @@
+/*
+ * @file ejsStndClasses.c
+ * @brief EJS support methods
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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 "ejs.h"
+
+#if BLD_FEATURE_EJS && 0
+
+/******************************************************************************/
+/*
+ * Date constructor
+
+ *
+ * Date();
+ * Date(milliseconds);
+ * Date(dateString);
+ * Date(year, month, date);
+ * Date(year, month, date, hour, minute, second);
+ */
+
+int ejsDateConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ return 0;
+}
+
+/******************************************************************************/
+
+static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ const char *fileName;
+ XmlState *parser;
+ Exml *xp;
+ MprFile *file;
+
+ if (argc != 1 || !ejsVarIsString(argv[0])) {
+ ejsError(ep, EJS_ARG_ERROR, "Bad args. Usage: load(fileName);");
+ return -1;
+ }
+ fileName = argv[0]->string;
+
+ /* FUTURE -- not romable
+ Need rom code in MPR not MprServices
+ */
+ file = mprOpen(ep, fileName, O_RDONLY, 0664);
+ if (file == 0) {
+ ejsError(ep, EJS_IO_ERROR, "Can't open: %s", fileName);
+ return -1;
+ }
+
+ xp = initParser(ep, thisObj, fileName);
+ parser = exmlGetParseArg(xp);
+
+ exmlSetInputStream(xp, readFileData, (void*) file);
+
+ if (exmlParse(xp) < 0) {
+ if (! ejsGotException(ep)) {
+ ejsError(ep, EJS_IO_ERROR, "Can't parse XML file: %s\nDetails %s",
+ fileName, exmlGetErrorMsg(xp));
+ }
+ termParser(xp);
+ mprClose(file);
+ return -1;
+ }
+
+ ejsSetReturnValue(ep, parser->nodeStack[0].obj);
+
+ termParser(xp);
+ mprClose(file);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+int ejsDefineDateClass(Ejs *ep)
+{
+ EjsVar *dateClass;
+
+ dateClass = ejsDefineClass(ep, "Date", "Object", ejsDateConstructor);
+ if (dateClass == 0) {
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+
+ ejsDefineCMethod(ep, dateClass, "getDate", xxxProc, EJS_NO_LOCAL);
+
+ /* Returns "Friday" or 4 ? */
+ ejsDefineCMethod(ep, dateClass, "getDay", xxxProc, EJS_NO_LOCAL);
+
+ ejsDefineCMethod(ep, dateClass, "getMonth", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getFullYear", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getYear", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getHours", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getMinutes", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getSeconds", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getMilliseconds", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getTime", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "getTimeZoneOffset", xxxProc, EJS_NO_LOCAL);
+
+ ejsDefineCMethod(ep, dateClass, "parse", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setDate", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setMonth", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setFullYear", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setYear", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setMinutes", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setSeconds", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setMilliseconds", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "setTime", xxxProc, EJS_NO_LOCAL);
+
+ ejsDefineCMethod(ep, dateClass, "toString", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "toGMTString", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "toUTCString", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "toLocaleString", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "UTC", xxxProc, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, dateClass, "valueOf", xxxProc, EJS_NO_LOCAL);
+ /*
+ UTC: getUTCDate, getUTCDay, getUTCMonth, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCSeconds, getUTCMilliseconds
+ setUTCDate, setUTCDay, setUTCMonth, setUTCFullYear, setUTCHours,
+ setUTCMinutes, setUTCSeconds, setUTCMilliseconds
+ */
+
+ return ejsObjHasErrors(dateClass) ? MPR_ERR_CANT_INITIALIZE : 0;
+}
+
+/******************************************************************************/
+/*
+ Time is since 1970/01/01 GMT
+
+ Normal: Fri Feb 10 2006 05:06:44 GMT-0800 (Pacific Standard Time)
+ UTC: Sat, 11 Feb 2006 05:06:44 GMT
+
+ // Using without New
+
+ println(Date());
+
+ var myDate = new Date();
+ myDate.setFullYear(2010, 0, 14);
+
+ var today = new Date();
+
+ if (myDate > today) {
+ } else {
+ }
+
+
+ X=Date() should be equivalent to X=(new Date()).toString()
+
+ */
+/******************************************************************************/
+
+#else
+void ejsStndClassesDummy() {}
+
+/******************************************************************************/
+#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
+ */
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c
new file mode 100755
index 0000000000..99445afc7c
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c
@@ -0,0 +1,140 @@
+/*
+ * @file ejsError.c
+ * @brief Error class
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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 "ejs.h"
+
+#if BLD_FEATURE_EJS
+
+/************************************ Code ************************************/
+/*
+ * Parse the args and return the message. Convert non-string args using
+ * .toString.
+ */
+
+static char *getMessage(Ejs *ep, int argc, EjsVar **argv)
+{
+ if (argc == 0) {
+ return "";
+
+ } else if (argc == 1) {
+ if (! ejsVarIsString(argv[0])) {
+ if (ejsRunMethod(ep, argv[0], "toString", 0) < 0) {
+ return 0;
+ }
+ return ep->result->string;
+
+ } else {
+ return argv[0]->string;
+ }
+
+ } else {
+ /* Don't call ejsError here or it will go recursive. */
+ return 0;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * Error Constructor and also used for constructor for sub classes.
+ *
+ * Usage: new Error([message])
+ */
+
+int ejsErrorCons(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ char *msg, *stack;
+
+ msg = getMessage(ep, argc, argv);
+ if (msg == 0) {
+ return -1;
+ }
+
+ ejsSetPropertyToString(ep, thisObj, "name", ejsGetBaseClassName(thisObj));
+ ejsSetPropertyToString(ep, thisObj, "message", msg);
+
+ ejsSetPropertyToUndefined(ep, thisObj, "stack");
+
+ stack = ejsFormatStack(ep);
+ if (stack) {
+ ejsSetPropertyToString(ep, thisObj, "stack", stack);
+ mprFree(stack);
+ }
+
+ if (ejsObjHasErrors(thisObj)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+
+int ejsDefineErrorClasses(Ejs *ep)
+{
+ if (ejsDefineClass(ep, "Error", "Object", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "AssertError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "EvalError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "InternalError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "IOError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "MemoryError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "RangeError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "ReferenceError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "SyntaxError", "Error", ejsErrorCons) == 0 ||
+ ejsDefineClass(ep, "TypeError", "Error", ejsErrorCons) == 0) {
+
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+#else
+void ejsErrorDummy() {}
+
+/******************************************************************************/
+#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
+ */
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c
new file mode 100644
index 0000000000..4f2e23beb2
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c
@@ -0,0 +1,588 @@
+/*
+ * @file ejsObject.c
+ * @brief Object class
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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 "ejs.h"
+
+#if BLD_FEATURE_EJS
+
+/****************************** Forward Declarations **************************/
+/*
+ * Support routines
+ */
+
+static void formatVar(Ejs *ep, MprBuf *bp, EjsVar *vp);
+
+/******************************************************************************/
+/*
+ * Routine to create an object of the desired class. Class name may
+ * contain "."
+ *
+ * The created object will be a stand-alone class NOT entered into the
+ * properties of any other object. Callers must do this if required. ClassName
+ * may contain "." and is interpreted relative to "obj" if supplied.
+ *
+ * Note: this does not call the constructors for the various objects and base
+ * classes.
+ */
+
+EjsVar *ejsCreateSimpleObjInternal(EJS_LOC_DEC(ep, loc), const char *className)
+{
+ EjsVar *baseClass;
+
+ if (className && *className) {
+ baseClass = ejsGetClass(ep, 0, className);
+ if (baseClass == 0) {
+ mprError(ep, MPR_LOC, "Can't find base class %s", className);
+ return 0;
+ }
+ } else {
+ baseClass = 0;
+ }
+
+ return ejsCreateSimpleObjUsingClassInt(EJS_LOC_PASS(ep, loc),
+ baseClass);
+}
+
+/******************************************************************************/
+/*
+ * Create an object based upon the specified base class object. It will be a
+ * stand-alone class not entered into the properties of any other object.
+ * Callers must do this if required.
+ *
+ * Note: this does not call the constructors for the various objects and base
+ * classes.
+ */
+
+EjsVar *ejsCreateSimpleObjUsingClassInt(EJS_LOC_DEC(ep, loc),
+ EjsVar *baseClass)
+{
+ EjsVar *vp;
+
+ mprAssert(baseClass);
+
+ if (baseClass == 0) {
+ mprError(ep, MPR_LOC, "Missing base class\n");
+ return 0;
+ }
+
+ vp = ejsCreateObjVarInternal(EJS_LOC_PASS(ep, loc));
+ if (vp == 0) {
+ return vp;
+ }
+
+ ejsSetBaseClass(vp, baseClass);
+
+ /*
+ * This makes all internal method accesses faster
+ * NOTE: this code is duplicated in ejsCreateSimpleClass
+ */
+ mprAssert(vp->objectState);
+ vp->objectState->methods = baseClass->objectState->methods;
+
+ return vp;
+}
+
+/******************************************************************************/
+
+void ejsSetMethods(Ejs *ep, EjsVar *op)
+{
+ op->objectState->methods = ep->global->objectState->methods;
+}
+
+/******************************************************************************/
+/******************************** Internal Methods ****************************/
+/******************************************************************************/
+
+static EjsVar *createObjProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsGetVarPtr(ejsCreateSimpleProperty(ep, obj, property));
+}
+
+/******************************************************************************/
+
+static int deleteObjProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsDeleteProperty(ep, obj, property);
+}
+
+/******************************************************************************/
+
+static EjsVar *getObjProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property));
+}
+
+/******************************************************************************/
+/*
+ * Set the value of a property. Create if it does not exist
+ */
+
+static EjsVar *setObjProperty(Ejs *ep, EjsVar *obj, const char *property,
+ const EjsVar *value)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+
+ pp = ejsCreateSimpleProperty(ep, obj, property);
+ if (pp == 0) {
+ mprAssert(pp);
+ return 0;
+ }
+ vp = ejsGetVarPtr(pp);
+ if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0) {
+ mprAssert(0);
+ return 0;
+ }
+ return ejsGetVarPtr(pp);
+}
+
+/******************************************************************************/
+/*********************************** Constructors *****************************/
+/******************************************************************************/
+#if UNUSED
+/*
+ * Object constructor. We don't use this for speed. Think very carefully if
+ * you add an object constructor.
+ */
+
+int ejsObjectConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ return 0;
+}
+
+#endif
+/******************************************************************************/
+/******************************** Visible Methods *****************************/
+/******************************************************************************/
+
+static int cloneMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ int copyDepth;
+
+ copyDepth = EJS_DEEP_COPY;
+
+ if (argc == 1 && ejsVarToBoolean(argv[0])) {
+ copyDepth = EJS_RECURSIVE_DEEP_COPY;
+ }
+
+ ejsWriteVar(ep, ep->result, thisObj, copyDepth);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static int toStringMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ MprBuf *bp;
+ int saveMaxDepth, saveDepth, saveFlags;
+
+ saveMaxDepth = ep->maxDepth;
+
+ if (argc >= 1) {
+ ep->maxDepth = ejsVarToInteger(argv[0]);
+ } else if (ep->maxDepth == 0) {
+ ep->maxDepth = MAXINT;
+ }
+
+ saveFlags = ep->flags;
+ if (argc >= 2) {
+ if (ejsVarToBoolean(argv[1])) {
+ ep->flags |= EJS_FLAGS_ENUM_HIDDEN;
+ }
+ }
+ if (argc == 3) {
+ if (ejsVarToBoolean(argv[2])) {
+ ep->flags |= EJS_FLAGS_ENUM_BASE;
+ }
+ }
+
+ bp = mprCreateBuf(ep, 0, 0);
+
+ saveDepth = ep->depth;
+
+ formatVar(ep, bp, thisObj);
+
+ ep->depth = saveDepth;
+ ep->maxDepth = saveMaxDepth;
+
+ mprAddNullToBuf(bp);
+
+ ejsWriteVarAsString(ep, ep->result, mprGetBufStart(bp));
+ mprFree(bp);
+
+ ep->flags = saveFlags;
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static int valueOfMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ if (argc != 0) {
+ mprAssert(0);
+ return -1;
+ }
+
+ switch (thisObj->type) {
+ default:
+ case EJS_TYPE_UNDEFINED:
+ case EJS_TYPE_NULL:
+ case EJS_TYPE_CMETHOD:
+ case EJS_TYPE_OBJECT:
+ case EJS_TYPE_METHOD:
+ case EJS_TYPE_STRING_CMETHOD:
+ ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY);
+ break;
+
+ case EJS_TYPE_STRING:
+ ejsWriteVarAsInteger(ep, ep->result, atoi(thisObj->string));
+ break;
+
+ case EJS_TYPE_BOOL:
+ case EJS_TYPE_INT:
+#if BLD_FEATURE_INT64
+ case EJS_TYPE_INT64:
+#endif
+#if BLD_FEATURE_FLOATING_POINT
+ case EJS_TYPE_FLOAT:
+#endif
+ ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY);
+ break;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+static int hashGetAccessor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ ejsSetReturnValueToInteger(ejs, (int) thisObj->objectState);
+ return 0;
+}
+
+/******************************************************************************/
+
+static int classGetAccessor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ if (thisObj->objectState == 0 || thisObj->objectState->baseClass == 0) {
+ ejsSetReturnValueToString(ejs, "object");
+ } else {
+ ejsSetReturnValueToString(ejs,
+ thisObj->objectState->baseClass->objectState->className);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Format an object. Called recursively to format properties and contained
+ * objects.
+ */
+
+static void formatVar(Ejs *ep, MprBuf *bp, EjsVar *vp)
+{
+ EjsProperty *pp, *first;
+ EjsVar *propVar, *baseClass;
+ char *buf, *value;
+ int i;
+
+ if (vp->type == EJS_TYPE_OBJECT) {
+ if (!vp->objectState->visited) {
+
+ mprPutStringToBuf(bp, vp->isArray ? "[\n" : "{\n");
+
+ ep->depth++;
+ vp->objectState->visited = 1;
+
+ if (ep->depth <= ep->maxDepth) {
+ first = ejsGetFirstProperty(vp, EJS_ENUM_ALL);
+
+ if (ep->flags & EJS_FLAGS_ENUM_BASE) {
+ baseClass = vp->objectState->baseClass;
+ if (baseClass) {
+ for (i = 0; i < ep->depth; i++) {
+ mprPutStringToBuf(bp, " ");
+ }
+ mprPutStringToBuf(bp, baseClass->objectState->objName);
+ mprPutStringToBuf(bp, ": /* Base Class */ ");
+ if (baseClass->objectState == vp->objectState) {
+ value = "this";
+ } else if (ejsRunMethodCmd(ep, baseClass, "toString",
+ "%d", ep->maxDepth) < 0) {
+ value = "[object Object]";
+ } else {
+ mprAssert(ejsVarIsString(ep->result));
+ value = ep->result->string;
+ }
+ mprPutStringToBuf(bp, value);
+ if (first) {
+ mprPutStringToBuf(bp, ",\n");
+ }
+ }
+ }
+
+ pp = first;
+ while (pp) {
+ if (! pp->dontEnumerate ||
+ ep->flags & EJS_FLAGS_ENUM_HIDDEN) {
+ for (i = 0; i < ep->depth; i++) {
+ mprPutStringToBuf(bp, " ");
+ }
+
+ if (! vp->isArray) {
+ mprPutStringToBuf(bp, pp->name);
+ mprPutStringToBuf(bp, ": ");
+ }
+
+ propVar = ejsGetVarPtr(pp);
+ if (propVar->type == EJS_TYPE_OBJECT) {
+ if (pp->var.objectState == vp->objectState) {
+ value = "this";
+ } else if (ejsRunMethodCmd(ep, propVar,
+ "toString", "%d", ep->maxDepth) < 0) {
+ value = "[object Object]";
+ } else {
+ mprAssert(ejsVarIsString(ep->result));
+ value = ep->result->string;
+ }
+ mprPutStringToBuf(bp, value);
+
+ } else {
+ formatVar(ep, bp, &pp->var);
+ }
+
+ pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);
+ if (pp) {
+ mprPutStringToBuf(bp, ",\n");
+ }
+ } else {
+ pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);
+ }
+ }
+ }
+ vp->objectState->visited = 0;
+
+ mprPutCharToBuf(bp, '\n');
+
+ ep->depth--;
+ for (i = 0; i < ep->depth; i++) {
+ mprPutStringToBuf(bp, " ");
+ }
+ mprPutCharToBuf(bp, vp->isArray ? ']' : '}');
+ }
+
+ } else if (vp->type == EJS_TYPE_METHOD) {
+
+ mprPutStringToBuf(bp, "function (");
+ for (i = 0; i < vp->method.args->length; i++) {
+ mprPutStringToBuf(bp, vp->method.args->items[i]);
+ if ((i + 1) < vp->method.args->length) {
+ mprPutStringToBuf(bp, ", ");
+ }
+ }
+ mprPutStringToBuf(bp, ") {");
+ mprPutStringToBuf(bp, vp->method.body);
+ for (i = 0; i < ep->depth; i++) {
+ mprPutStringToBuf(bp, " ");
+ }
+ mprPutStringToBuf(bp, "}");
+
+ } else {
+
+ if (vp->type == EJS_TYPE_STRING) {
+ mprPutCharToBuf(bp, '\"');
+ }
+
+ /*
+ * We don't use ejsVarToString for arrays, objects and strings.
+ * This is because ejsVarToString does not call "obj.toString"
+ * and it is not required for strings.
+ * MOB - rc
+ */
+ buf = ejsVarToString(ep, vp);
+ mprPutStringToBuf(bp, buf);
+
+ if (vp->type == EJS_TYPE_STRING) {
+ mprPutCharToBuf(bp, '\"');
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * mixin code. Blends code at the "thisObj" level.
+ */
+
+static int mixinMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsProperty *pp;
+ char *buf;
+ int fid, i, rc;
+
+ mprAssert(argv);
+
+ /*
+ * Create a variable scope block set to the current object
+ */
+ rc = 0;
+ fid = ejsSetBlock(ep, thisObj);
+
+ for (i = 0; i < argc; i++) {
+
+ if (ejsVarIsString(argv[i])) {
+ rc = ejsEvalScript(ep, argv[i]->string, 0);
+
+ } else if (ejsVarIsObject(argv[i])) {
+
+ /* MOB -- OPT. When we have proper scope chains, we should just
+ refer to the module and not copy */
+ pp = ejsGetFirstProperty(argv[i], EJS_ENUM_ALL);
+ while (pp) {
+ ejsSetProperty(ep, thisObj, pp->name, ejsGetVarPtr(pp));
+ pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);
+ }
+
+ } else {
+ /* MOB - rc */
+ buf = ejsVarToString(ep, argv[i]);
+ rc = ejsEvalScript(ep, buf, 0);
+
+ }
+ if (rc < 0) {
+ ejsCloseBlock(ep, fid);
+ return -1;
+ }
+ }
+ ejsCloseBlock(ep, fid);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Create the object class
+ */
+
+int ejsDefineObjectClass(Ejs *ep)
+{
+ EjsMethods *methods;
+ EjsProperty *objectProp, *protoProp;
+ EjsVar *op, *globalClass;
+
+ /*
+ * Must specially hand-craft the object class as it is the base class
+ * of all objects.
+ */
+ op = ejsCreateObjVar(ep);
+ if (op == 0) {
+ return MPR_ERR_CANT_CREATE;
+ }
+ ejsSetClassName(ep, op, "Object");
+
+ /*
+ * Don't use a constructor for objects for speed
+ */
+ ejsMakeClassNoConstructor(op);
+
+ /*
+ * MOB -- should mark properties as public / private and class or instance.
+ */
+ ejsDefineCMethod(ep, op, "clone", cloneMethod, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, op, "toString", toStringMethod, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, op, "valueOf", valueOfMethod, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, op, "mixin", mixinMethod, EJS_NO_LOCAL);
+
+ ejsDefineCAccessors(ep, op, "hash", hashGetAccessor, 0, EJS_NO_LOCAL);
+ ejsDefineCAccessors(ep, op, "baseClass", classGetAccessor, 0, EJS_NO_LOCAL);
+
+ /*
+ * MOB -- make this an accessor
+ */
+ protoProp = ejsSetProperty(ep, op, "prototype", op);
+ if (protoProp == 0) {
+ ejsFreeVar(ep, op);
+ return MPR_ERR_CANT_CREATE;
+ }
+
+ /*
+ * Setup the internal methods. Most classes will never override these.
+ * The XML class will. We rely on talloc to free internal. Use "ep" as
+ * the parent as we need "methods" to live while the interpreter lives.
+ */
+ methods = mprAllocTypeZeroed(ep, EjsMethods);
+ op->objectState->methods = methods;
+
+ methods->createProperty = createObjProperty;
+ methods->deleteProperty = deleteObjProperty;
+ methods->getProperty = getObjProperty;
+ methods->setProperty = setObjProperty;
+
+ objectProp = ejsSetPropertyAndFree(ep, ep->global, "Object", op);
+
+ /*
+ * Change the global class to use Object's methods
+ */
+ globalClass = ep->service->globalClass;
+ globalClass->objectState->methods = methods;
+ globalClass->objectState->baseClass = ejsGetVarPtr(protoProp);
+
+ ep->objectClass = ejsGetVarPtr(objectProp);
+
+ if (ejsObjHasErrors(ejsGetVarPtr(objectProp))) {
+ ejsFreeVar(ep, op);
+ return MPR_ERR_CANT_CREATE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+#else
+void ejsObjectDummy() {}
+
+/******************************************************************************/
+#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
+ */
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c
new file mode 100644
index 0000000000..fd6cda7813
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c
@@ -0,0 +1,144 @@
+/*
+ * @file ejsStndClasses.c
+ * @brief EJS support methods
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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 "ejs.h"
+
+#if BLD_FEATURE_EJS
+
+/******************************************************************************/
+/******************************* Function Class *******************************/
+/******************************************************************************/
+
+int ejsDefineFunctionClass(Ejs *ep)
+{
+ if (ejsDefineClass(ep, "Function", "Object", ejsFunctionConstructor) == 0) {
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Function constructor
+ */
+
+int ejsFunctionConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ int rc;
+
+ if (argc != 1 || !ejsVarIsString(argv[0])) {
+ ejsArgError(ep, "Usage: Function(\"function (arg) { script };\");");
+ }
+
+ rc = ejsEvalScript(ep, argv[0]->string, 0);
+
+ /*
+ * Note: this will convert the object into a method. It will cease to be
+ * an object.
+ */
+ if (rc == 0 && ejsVarIsMethod(ep->result)) {
+ /*
+ * Must make thisObj collectable.
+ */
+ ejsMakeObjPermanent(thisObj, 0);
+ ejsMakeObjLive(thisObj, 1);
+ mprAssert(ejsObjIsCollectable(thisObj));
+ ejsWriteVar(ep, thisObj, ep->result, EJS_SHALLOW_COPY);
+ }
+ return rc;
+}
+
+/******************************************************************************/
+/******************************* Boolean Class ********************************/
+/******************************************************************************/
+
+int ejsDefineBooleanClass(Ejs *ep)
+{
+ if (ejsDefineClass(ep, "Boolean", "Object", ejsBooleanConstructor) == 0){
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Boolean constructor
+ */
+
+int ejsBooleanConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ return 0;
+}
+
+/******************************************************************************/
+/******************************** Number Class ********************************/
+/******************************************************************************/
+
+int ejsDefineNumberClass(Ejs *ep)
+{
+ if (ejsDefineClass(ep, "Number", "Object", ejsNumberConstructor) == 0) {
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Number constructor
+ */
+
+int ejsNumberConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ return 0;
+}
+
+/******************************************************************************/
+
+#else
+void ejsStndClassesDummy() {}
+
+/******************************************************************************/
+#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
+ */
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c
new file mode 100644
index 0000000000..2339650361
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c
@@ -0,0 +1,381 @@
+/*
+ * @file ejsString.c
+ * @brief EJScript string class
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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 "ejs.h"
+
+#if BLD_FEATURE_EJS
+/******************************************************************************/
+/*********************************** Constructors *****************************/
+/******************************************************************************/
+/*
+ * String constructor.
+ */
+
+int ejsStringConstructor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ char *str;
+
+ if (argc == 0) {
+ ejsSetReturnValueToString(ejs, "");
+
+ } else if (argc == 1) {
+ /* MOB -- rc */
+ str = ejsVarToString(ejs, argv[0]);
+ ejsSetReturnValueToString(ejs, str);
+
+ } else {
+ ejsArgError(ejs, "usage: String([var])");
+ return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+/******************************** Visible Methods *****************************/
+/******************************************************************************/
+/*
+ * Return a string containing the character at a given index
+ *
+ * String string.charAt(Number)
+ */
+
+static int charAt(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsNum num;
+ char buf[2];
+
+ if (argc != 1) {
+ ejsArgError(ejs, "usage: charAt(integer)");
+ return -1;
+ }
+
+ num = ejsVarToNumber(argv[0]);
+ if (num < 0 || num >= thisObj->length) {
+ ejsError(ejs, EJS_RANGE_ERROR, "Bad index");
+ return -1;
+ }
+
+ mprAssert(ejsVarIsString(thisObj));
+
+ buf[0] = argv[0]->string[num];
+ buf[1] = '\0';
+ ejsSetReturnValueToString(ejs, buf);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return an integer containing the character at a given index
+ *
+ * Number string.charCodeAt(Number)
+ */
+
+static EjsNum charCodeAt(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsNum num;
+
+ if (argc != 1) {
+ ejsArgError(ejs, "usage: charCodeAt(integer)");
+ return -1;
+ }
+
+ num = ejsVarToNumber(argv[0]);
+ if (num < 0 || num >= thisObj->length) {
+ ejsError(ejs, EJS_RANGE_ERROR, "Bad index");
+ return -1;
+ }
+ ejsSetReturnValueToNumber(ejs, (EjsNum) argv[0]->string[num]);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Catenate
+ *
+ * String string.catenate(var, ...)
+ */
+
+static int concat(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ int i;
+
+ if (argc == 0) {
+ ejsArgError(ejs, "usage: concat(String, ...)");
+ return -1;
+ }
+
+ mprAssert(ejsVarIsString(thisObj));
+
+ for (i = 0; i < argc; i++) {
+ if (ejsStrcat(ejs, thisObj, argv[i]) < 0) {
+ ejsMemoryError(ejs);
+ return -1;
+ }
+ }
+ ejsSetReturnValue(ejs, thisObj);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return the position of the first occurance of a substring
+ *
+ * Number string.indexOf(String subString [, Number start])
+ */
+
+static int indexOf(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ char *pat, *s1, *s2, *origin;
+ int start, i;
+
+ if (argc == 0 || argc > 2) {
+ ejsArgError(ejs, "usage: indexOf(String [, Number])");
+ return -1;
+ }
+
+ pat = ejsVarToString(ejs, argv[0]);
+
+ if (argc == 2) {
+ start = ejsVarToNumber(argv[1]);
+ if (start > thisObj->length) {
+ start = thisObj->length;
+ }
+ } else {
+ start = 0;
+ }
+
+ i = start;
+ for (origin = &thisObj->string[i]; i < thisObj->length; i++, origin++) {
+ s1 = origin;
+ for (s2 = pat; *s1 && *s2; s1++, s2++) {
+ if (*s1 != *s2) {
+ break;
+ }
+ }
+ if (*s2 == '\0') {
+ ejsSetReturnValueToNumber(ejs, (EjsNum) (origin - thisObj->string));
+ }
+ }
+
+ ejsSetReturnValueToNumber(ejs, (EjsNum) -1);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return the position of the last occurance of a substring
+ *
+ * Number string.lastIndexOf(String subString [, Number start])
+ */
+
+static int lastIndexOf(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ char *pat, *s1, *s2, *origin;
+ int start;
+
+ if (argc == 0 || argc > 2) {
+ ejsArgError(ejs, "usage: indexOf(String [, Number])");
+ return -1;
+ }
+
+ pat = ejsVarToString(ejs, argv[0]);
+
+ if (argc == 2) {
+ start = ejsVarToNumber(argv[1]);
+ if (start > thisObj->length) {
+ start = thisObj->length;
+ }
+ } else {
+ start = 0;
+ }
+
+ origin = &thisObj->string[thisObj->length - 1];
+ for (; origin >= &thisObj->string[start]; origin--) {
+
+ s1 = origin;
+ for (s2 = pat; *s1 && *s2; s1++, s2++) {
+ if (*s1 != *s2) {
+ break;
+ }
+ }
+ if (*s2 == '\0') {
+ ejsSetReturnValueToNumber(ejs, (EjsNum) (origin - thisObj->string));
+ }
+ }
+
+ ejsSetReturnValueToNumber(ejs, (EjsNum) -1);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return a substring
+ *
+ * Number string.slice(Number start, Number end)
+ */
+
+static int slice(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsNum start, end;
+
+ if (argc != 2) {
+ ejsArgError(ejs, "usage: slice(Number, Number)");
+ return -1;
+ }
+
+ start = ejsVarToNumber(argv[0]);
+ end = ejsVarToNumber(argv[1]);
+ if (start < 0 || start >= thisObj->length) {
+ ejsError(ejs, EJS_RANGE_ERROR, "Bad start index");
+ return-1;
+ }
+ if (end < 0 || end >= thisObj->length) {
+ ejsError(ejs, EJS_RANGE_ERROR, "Bad end index");
+ return -1;
+ }
+
+ mprAssert(ejsVarIsString(thisObj));
+
+ ejsSetReturnValueToBinaryString(ejs, (uchar*) &thisObj->string[start],
+ end - start);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Split a string
+ *
+ * Number string.split(String delimiter [, Number limit])
+ */
+
+static int split(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsVar *array, *vp;
+ char *delim, *last, *cp;
+ int len, limit, alloc;
+
+ if (argc == 0 || argc > 2) {
+ ejsArgError(ejs, "usage: split(String [, Number])");
+ return -1;
+ }
+
+ delim = ejsVarToStringEx(ejs, argv[0], &alloc);
+
+ limit = ejsVarToNumber(argv[1]);
+
+ array = ejsCreateArray(ejs, 0);
+
+ len = strlen(delim);
+
+ last = thisObj->string;
+ for (cp = last; *cp; cp++) {
+ if (*cp == *delim && strncmp(cp, delim, len) == 0) {
+ if (cp > last) {
+ vp = ejsCreateBinaryStringVar(ejs, (uchar*) last, (cp - last));
+ ejsAddArrayElt(ejs, array, vp, EJS_SHALLOW_COPY);
+ ejsFreeVar(ejs, vp);
+ }
+ }
+ }
+
+ ejsSetReturnValue(ejs, array);
+ ejsFreeVar(ejs, array);
+
+ if (alloc) {
+ mprFree(delim);
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Create the object class
+ */
+
+int ejsDefineStringClass(Ejs *ejs)
+{
+ EjsVar *sc;
+
+ sc = ejsDefineClass(ejs, "String", "Object", ejsStringConstructor);
+ if (sc == 0) {
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+
+ ejsDefineCMethod(ejs, sc, "charAt", charAt, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "charCodeAt", charCodeAt, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "concat", concat, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "indexOf", indexOf, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "lastIndexOf", lastIndexOf, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "slice", slice, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "split", split, EJS_NO_LOCAL);
+#if UNUSED
+ ejsDefineCMethod(ejs, sc, "match", match, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "replace", replace, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "search", search, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "substring", substring, EJS_NO_LOCAL);
+ // MOB bad name
+ ejsDefineCMethod(ejs, sc, "substr", substr, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "toLowerCase", toLowerCase, EJS_NO_LOCAL);
+ ejsDefineCMethod(ejs, sc, "toUpperCase", toUpperCase, EJS_NO_LOCAL);
+
+ // Static method
+ ejsDefineCMethod(ejs, sc, "fromCharCode", fromCharCode, 0, EJS_NO_LOCAL);
+#endif
+
+ if (ejsObjHasErrors(sc)) {
+ ejsFreeVar(ejs, sc);
+ return MPR_ERR_CANT_CREATE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+#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
+ */
diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c
new file mode 100644
index 0000000000..a2ef8d1390
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c
@@ -0,0 +1,1327 @@
+/*
+ * @file ejsXml.c
+ * @brief E4X XML support
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+ * Copyright (c) Michael O'Brien, 1994-1995. 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
+ */
+/************************************ Doc *************************************/
+/*
+ * Javascript class definition
+ *
+ * class XML {
+ * public XML();
+ * public XML(string xmlString); // "<tag... "
+ * public XML(string file); // "file"
+ *
+ * public void load(string file);
+ * public void save(string file);
+ * public Array children();
+ * public Array attributes();
+ * }
+ *
+ [[Internal Properties / Methods]]
+ - prototype - Ptr to class prototype (base class)
+ - class - Type of class
+ Object.prototype.toString
+ - Value -
+ - Get(name) - Returns the value
+ - Put(name, value) - Sets the value
+ - HasProperty(name) - Bool if property exists
+ - Delete(name) - Delete property
+ - DefaultValue(hint) - Return default primitive (not obj) value
+ toString, if result is obj, then call valueOf
+ if hint is number, then call valueOf, then toString
+ - Construct(arg list) - Constructor
+ - Call(arg list) - Function call
+ - HasInstance(value) - ??
+ - Scope - Frame scope chain
+ - Match(string, index) - Regexp match
+
+ - Example:
+ XML attribute @name
+ @*
+ *
+ var node = new XML("<order/>");
+ Operators:
+ var prices = order..price;
+ var urgentItems = order.item(@level == "rush");
+ var itemAttrs = order.item[0].@*; # @ for attributes
+ XML Literals
+ order.customer.address =
+ <address>.....
+ <zip>{zipCode}</zip> Where {var} is a JS var
+ <tag attribute={prefix}> ... Also for attributes
+ </address>
+ Omit namespaces
+ Example:
+ var html = <html/>;
+ html.head.title = "My title";
+ head.body@bgcolor = "#e4e4e4";
+*/
+
+/********************************** Includes **********************************/
+
+#include "ejs.h"
+#include "exml.h"
+
+/************************************ Data ************************************/
+#if BLD_FEATURE_EJS_E4X
+
+/*
+ * Per tag state
+ */
+typedef struct XmlTagState {
+ EjsVar *obj;
+ EjsVar *attributes;
+ EjsVar *comments;
+} XmlTagState;
+
+/*
+ * Parser state
+ */
+typedef struct XmlState {
+ Ejs *ep;
+ EjsVar *xmlClass;
+ EjsVar *xmlListClass;
+ XmlTagState nodeStack[E4X_MAX_NODE_DEPTH];
+ int topOfStack;
+ long inputSize;
+ long inputPos;
+ const char *inputBuf;
+ const char *fileName;
+} XmlState;
+
+/****************************** Forward Declarations **************************/
+/*
+ * XML methods
+ */
+static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int name(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int save(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int toString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int valueOf(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+
+/* MOB -- temp */
+static int getList(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int setText(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+
+#if FUTURE
+static int length(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int toXmlString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+
+static int appendChild(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int attributes(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int child(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int children(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int comments(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int decendants(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int elements(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int insertChildAfter(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int insertChildBefore(Ejs *ep, EjsVar *thisObj, int argc,
+ EjsVar **argv);
+static int replace(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int setName(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);
+#endif
+
+/*
+ * Internal methods
+ */
+static EjsVar *createXmlProperty(Ejs *ep, EjsVar *obj, const char *property);
+static int deleteXmlProperty(Ejs *ep, EjsVar *obj, const char *property);
+static EjsVar *getXmlProperty(Ejs *ep, EjsVar *obj, const char *property);
+static EjsVar *setXmlProperty(Ejs *ep, EjsVar *obj, const char *property,
+ const EjsVar *value);
+static int loadXmlString(Ejs *ep, EjsVar *thisObj, const char *xmlString);
+
+/*
+ * XMLList methods
+ */
+static EjsVar *createXmlListProperty(Ejs *ep, EjsVar *obj,
+ const char *property);
+static int deleteXmlListProperty(Ejs *ep, EjsVar *obj,
+ const char *property);
+static EjsVar *getXmlListProperty(Ejs *ep, EjsVar *obj, const char *property);
+static EjsVar *setXmlListProperty(Ejs *ep, EjsVar *obj, const char *property,
+ const EjsVar *value);
+
+/*
+ * Misc
+ */
+static int readFileData(Exml *xp, void *data, char *buf, int size);
+static int readStringData(Exml *xp, void *data, char *buf, int size);
+static int parserHandler(Exml *xp, int state, const char *tagName,
+ const char *attName, const char *value);
+static void termParser(Exml *xp);
+static Exml *initParser(Ejs *ep, EjsVar *thisObj, const char *fileName);
+static int getNumElements(EjsVar *obj);
+static int getText(MprBuf *buf, EjsVar *obj);
+static int xmlToString(Ejs *ep, MprBuf *buf, EjsVar *obj, int indentLevel);
+static void indent(MprBuf *bp, int level);
+static char *cleanTagName(char *name);
+
+/******************************************************************************/
+/*
+ * Define the E4X classes (XML, XMLList)
+ */
+
+int ejsDefineXmlClasses(Ejs *ep)
+{
+ EjsMethods *methods;
+ EjsVar *xmlClass, *xmlListClass;
+
+ /*
+ * Create the XML class
+ */
+ xmlClass = ejsDefineClass(ep, "XML", "Object", ejsXmlConstructor);
+ if (xmlClass == 0) {
+ return MPR_ERR_CANT_INITIALIZE;
+ }
+
+ /*
+ * Define the XML class methods
+ */
+ ejsDefineCMethod(ep, xmlClass, "text", text, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, xmlClass, "name", name, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, xmlClass, "load", load, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, xmlClass, "save", save, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, xmlClass, "toString", toString, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, xmlClass, "valueOf", valueOf, EJS_NO_LOCAL);
+
+/* MOB -- temporary only */
+ ejsDefineCMethod(ep, xmlClass, "getList", getList, EJS_NO_LOCAL);
+ ejsDefineCMethod(ep, xmlClass, "setText", setText, EJS_NO_LOCAL);
+
+ /*
+ * Setup the XML internal methods.
+ */
+ methods = mprAllocTypeZeroed(ep, EjsMethods);
+ xmlClass->objectState->methods = methods;
+
+ methods->createProperty = createXmlProperty;
+ methods->deleteProperty = deleteXmlProperty;
+ methods->getProperty = getXmlProperty;
+ methods->setProperty = setXmlProperty;
+
+ /*
+ * Create the XMLList class
+ */
+ xmlListClass = ejsDefineClass(ep, "XMLList", "Array",
+ ejsXmlListConstructor);
+
+ /*
+ * Define the XMLList class methods
+ */
+
+ /*
+ * Setup the XML internal methods.
+ */
+ methods = mprAllocTypeZeroed(ep, EjsMethods);
+ xmlListClass->objectState->methods = methods;
+
+ methods->createProperty = createXmlListProperty;
+ methods->deleteProperty = deleteXmlListProperty;
+ methods->getProperty = getXmlListProperty;
+ methods->setProperty = setXmlListProperty;
+
+ /* MOB -- need to complete xmlListClass */
+
+ return (ejsObjHasErrors(xmlClass) || ejsObjHasErrors(xmlListClass))
+ ? MPR_ERR_CANT_INITIALIZE : 0;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Routine to create an XML object using a default constructor
+ */
+
+EjsVar *ejsCreateXml(Ejs *ep)
+{
+ EjsVar *op;
+
+ op = ejsCreateSimpleObj(ep, "XML");
+ if (op == 0) {
+ mprAssert(op);
+ return op;
+ }
+ ejsSetVarName(ep, op, "xmlNode");
+
+ /*
+ * Invoke class constructors manually (for speed and space)
+ */
+ if (ejsXmlConstructor(ep, op, 0, 0) < 0) {
+ mprFree(op);
+ mprAssert(0);
+ return 0;
+ }
+ return op;
+}
+
+/******************************************************************************/
+/*
+ * XML constructor
+ */
+
+int ejsXmlConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsVar *vp;
+ const char *str;
+
+ ejsSetVarFlags(thisObj, EJS_XML_FLAGS_ELEMENT);
+
+ if (argc == 1) {
+ vp = argv[0];
+
+ if (ejsVarIsObject(vp)) {
+ /* Convert DOM to XML. Not implemented */;
+
+ } else if (ejsVarIsString(vp)) {
+ str = vp->string;
+ if (str == 0) {
+ return 0;
+ }
+ if (*str == '<') {
+ /* XML Literal */
+ return loadXmlString(ep, thisObj, str);
+
+ } else {
+ /* Load from file */
+ return load(ep, thisObj, argc, argv);
+ }
+ } else {
+ ejsError(ep, EJS_TYPE_ERROR, "Bad type passed to XML constructor");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Routine to create an XMLList object
+ */
+
+EjsVar *ejsCreateXmlList(Ejs *ep)
+{
+ EjsVar *op;
+
+ /* Sanity limit for size of hash table */
+
+ op = ejsCreateSimpleObj(ep, "XMLList");
+ if (op == 0) {
+ mprAssert(0);
+ return op;
+ }
+ if (ejsArrayConstructor(ep, op, 0, 0) < 0 ||
+ ejsXmlConstructor(ep, op, 0, 0) < 0) {
+ mprFree(op);
+ mprAssert(0);
+ return 0;
+ }
+ return op;
+}
+
+/******************************************************************************/
+/*
+ * XMLList constructor
+ */
+
+int ejsXmlListConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ // ejsSetVarFlags(vp, EJS_XML_FLAGS_ELEMENT);
+ return 0;
+}
+
+/******************************************************************************/
+/******************************** Internal Methods ****************************/
+/******************************************************************************/
+
+static EjsVar *createXmlProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsGetVarPtr(ejsCreateSimpleProperty(ep, obj, property));
+}
+
+/******************************************************************************/
+
+static int deleteXmlProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsDeleteProperty(ep, obj, property);
+}
+
+/******************************************************************************/
+/* MOB -- need ep as an arg */
+static EjsVar *getXmlProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+#if NEW
+ EjsVar *lp;
+
+ lp = ejsCreateXmlList(ep);
+ if (isdigit(*property)) {
+ /* MOB -- where do we store these. Do we need them ? */
+ lp->targetObject = obj
+ lp->targetProperty = property
+ return getXmlListProperty(lp, property);
+ }
+
+ /* What about a simple elment. Should it not return the text */
+
+ if (*property == '@') {
+ ap = ejsGetFirstProperty(obj, EJS_ENUM_ALL);
+ while (ap) {
+ vp = ejsGetVarPtr(ap);
+ /* MOB -- are attributes unique ? */
+ if (vp->flags & EJS_XML_FLAGS_ATTRIBUTE &&
+ strcmp(property, ap->name) == 0) {
+ ejsAppendXml(lp, vp);
+ }
+ ap = ejsGetNexttProperty(ap, EJS_ENUM_ALL);
+ }
+ } else {
+ while (ap) {
+ vp = ejsGetVarPtr(ap);
+ /* MOB -- are attributes unique ? */
+ if (vp->flags & EJS_XML_FLAGS_ELEMENT &&
+ strcmp(property, ap->name) == 0) {
+ ejsAppendXml(lp, vp);
+ }
+ ap = ejsGetNexttProperty(ap, EJS_ENUM_ALL);
+ }
+ }
+ return l;
+
+ // Must always return XML or XMLList event for comments and attributes
+#endif
+ return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property));
+}
+
+/******************************************************************************/
+
+static EjsVar *setXmlProperty(Ejs *ep, EjsVar *obj, const char *property,
+ const EjsVar *value)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+
+ pp = ejsCreateSimpleProperty(ep, obj, property);
+ if (pp == 0) {
+ /* Should never happen */
+ mprAssert(pp);
+ return 0;
+ }
+ vp = ejsGetVarPtr(pp);
+ if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0) {
+ return 0;
+ }
+ return ejsGetVarPtr(pp);
+}
+
+/******************************************************************************/
+/*
+ NEW
+
+static EjsVar *setXmlProperty(Ejs *ep, EjsVar *op, const char *property,
+ EjsVar *value)
+{
+
+ if ((value->objectState->baseClass != XML &&
+ value->objectState->baseClass != XMLList) ||
+ value->string[0] != '<') {
+ ejsVarToString(luevalue.toString();
+ ejsRunMethod(ep, value, "toString", 0);
+ value = ejsDupVar(ep->result);
+
+ } else {
+ value = ejsDupVar(value);
+ }
+
+ if (isdigit(*property)) {
+ // ERROR -- reserved for future versions
+ return 0;
+ }
+
+ if (*property == '@') {
+ if (op->objectState->baseClass == XMLList) {
+ if (op->obj.LENGTH_PROPERTY == 0) {
+ c = "";
+ } else {
+ // Catenate all result of toString on all elts in list
+ }
+ } else {
+ c = c.toString();
+ }
+ // Replace existing attribute of same name or insert
+ return;
+ }
+ for (i = op->obj.LENGTH - 1; i >= 0; i--) {
+ // Delete item of same name
+ }
+ if (not Found) {
+ Append new Xml object
+ - set [[name]], [[class]] == "element"
+ }
+
+ mprFree(value);
+}
+
+ */
+/******************************************************************************/
+/************************************ Methods *********************************/
+/******************************************************************************/
+
+static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ const char *fileName;
+ XmlState *parser;
+ Exml *xp;
+ MprFile *file;
+
+ if (argc != 1 || !ejsVarIsString(argv[0])) {
+ ejsError(ep, EJS_ARG_ERROR, "Bad args. Usage: load(fileName);");
+ return -1;
+ }
+ fileName = argv[0]->string;
+
+ /* MOB -- not romable
+ Need rom code in MPR not MprServices
+ */
+ file = mprOpen(ep, fileName, O_RDONLY, 0664);
+ if (file == 0) {
+ ejsError(ep, EJS_IO_ERROR, "Can't open: %s", fileName);
+ return -1;
+ }
+
+ /* MOB -- should we empty thisObj of all existing properties ? */
+
+ xp = initParser(ep, thisObj, fileName);
+ parser = exmlGetParseArg(xp);
+
+ exmlSetInputStream(xp, readFileData, (void*) file);
+
+ if (exmlParse(xp) < 0) {
+ if (! ejsGotException(ep)) {
+ ejsError(ep, EJS_IO_ERROR, "Can't parse XML file: %s\nDetails %s",
+ fileName, exmlGetErrorMsg(xp));
+ }
+ termParser(xp);
+ mprClose(file);
+ return -1;
+ }
+
+ ejsSetReturnValue(ep, parser->nodeStack[0].obj);
+
+ termParser(xp);
+ mprClose(file);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static int loadXmlString(Ejs *ep, EjsVar *thisObj, const char *xmlString)
+{
+ XmlState *parser;
+ Exml *xp;
+
+ xp = initParser(ep, thisObj, "string");
+ parser = exmlGetParseArg(xp);
+
+ parser->inputBuf = xmlString;
+ parser->inputSize = strlen(xmlString);
+
+ exmlSetInputStream(xp, readStringData, (void*) 0);
+
+ if (exmlParse(xp) < 0) {
+ if (! ejsGotException(ep)) {
+ ejsError(ep, EJS_IO_ERROR, "Can't parse XML string\nError %s",
+ exmlGetErrorMsg(xp));
+ }
+ termParser(xp);
+ return -1;
+ }
+
+ ejsSetReturnValue(ep, parser->nodeStack[0].obj);
+
+ termParser(xp);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsVar *vp;
+
+ vp = ejsGetVarPtr(ejsGetSimpleProperty(ep, thisObj, E4X_TEXT_PROPERTY));
+ if (vp == 0) {
+ ejsSetReturnValueToString(ep, "");
+ return 0;
+ }
+ ejsSetReturnValue(ep, vp);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return the tag name
+ */
+
+static int name(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ EjsVar *vp;
+
+ vp = ejsGetVarPtr(ejsGetSimpleProperty(ep, thisObj, E4X_TAG_NAME_PROPERTY));
+ if (vp == 0) {
+ ejsSetReturnValueToString(ep, "");
+ return 0;
+ }
+ ejsSetReturnValue(ep, vp);
+#if UNDEFINED
+ char *name;
+ /* MOB -- not ideal as we can't guarantee thisObj is a property */
+ name = ejsGetPropertyPtr(thisObj)->name;
+ if (name == 0) {
+ name = "";
+ }
+ ejsSetReturnValueToString(ep, name);
+#endif
+ return 0;
+}
+
+/******************************************************************************/
+/* MOB -- temporary only */
+
+static int setText(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ if (argc != 1) {
+ ejsArgError(ep, "usage: setText(string)");
+ }
+
+ ejsSetProperty(ep, thisObj, E4X_TEXT_PROPERTY, argv[0]);
+ ejsSetReturnValue(ep, argv[0]);
+ return 0;
+}
+
+/******************************************************************************/
+
+static Exml *initParser(Ejs *ep, EjsVar *thisObj, const char *fileName)
+{
+ XmlState *parser;
+ Exml *xp;
+
+ xp = exmlOpen(ep, 512, E4X_BUF_MAX);
+ mprAssert(xp);
+
+ /*
+ * Create the parser stack
+ */
+ parser = mprAllocTypeZeroed(ep, XmlState);
+ parser->ep = ep;
+ parser->nodeStack[0].obj = thisObj;
+ parser->xmlClass = ejsGetClass(ep, 0, "XML");
+ parser->xmlListClass = ejsGetClass(ep, 0, "XMLList");
+ parser->fileName = fileName;
+
+ exmlSetParseArg(xp, parser);
+ exmlSetParserHandler(xp, parserHandler);
+
+ return xp;
+}
+
+/******************************************************************************/
+
+static void termParser(Exml *xp)
+{
+ mprFree(exmlGetParseArg(xp));
+ exmlClose(xp);
+}
+
+/******************************************************************************/
+/*
+ * XML parsing callback. Called for each elt and attribute/value pair.
+ * For speed, we handcraft the object model here rather than calling
+ * putXmlProperty.
+ *
+ * "<!-- txt -->" parseHandler(efd, , EXML_COMMENT);
+ * "<elt" parseHandler(efd, , EXML_NEW_ELT);
+ * "...att=value" parseHandler(efd, , EXML_NEW_ATT);
+ * "<elt ...>" parseHandler(efd, , EXML_ELT_DEFINED);
+ * "<elt/>" parseHandler(efd, , EXML_SOLO_ELT_DEFINED);
+ * "<elt> ...<" parseHandler(efd, , EXML_ELT_DATA);
+ * "...</elt>" parseHandler(efd, , EXML_END_ELT);
+ *
+ * Note: we recurse on every new nested elt.
+ */
+
+static int parserHandler(Exml *xp, int state, const char *tagName,
+ const char *attName, const char *value)
+{
+ XmlState *parser;
+ XmlTagState *tos;
+ EjsVar *currentNode, *vp, *tagNode, *parent, *vpx;
+ EjsProperty *pp;
+ Ejs *ep;
+ char *name;
+
+ parser = (XmlState*) xp->parseArg;
+ ep = parser->ep;
+ tos = &parser->nodeStack[parser->topOfStack];
+ currentNode = tos->obj;
+
+ mprAssert(state >= 0);
+ mprAssert(tagName && *tagName);
+
+ switch (state) {
+ case EXML_PI:
+ /*
+ * By using a property name with a leading space, we can store
+ * non-user-visible processing instructions as regular properties.
+ */
+ pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode, E4X_PI_PROPERTY);
+ ejsMakePropertyEnumerable(pp, 1);
+ vp = ejsGetVarPtr(pp);
+ ejsWriteVarAsString(ep, vp, value);
+ ejsSetVarFlags(vp, EJS_XML_FLAGS_PI);
+ break;
+
+ case EXML_COMMENT:
+ /*
+ * By using a property name with a leading space, we can store
+ * non- user-visible comments as regular properties.
+ */
+ pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode,
+ E4X_COMMENT_PROPERTY);
+ ejsMakePropertyEnumerable(pp, 1);
+ vp = ejsGetVarPtr(pp);
+ ejsWriteVarAsString(ep, vp, value);
+ ejsSetVarFlags(vp, EJS_XML_FLAGS_COMMENT);
+ break;
+
+ case EXML_NEW_ELT:
+ if (parser->topOfStack > E4X_MAX_NODE_DEPTH) {
+ ejsError(ep, EJS_IO_ERROR,
+ "XML nodes nested too deeply in %s at line %d",
+ parser->fileName, exmlGetLineNumber(xp));
+ return MPR_ERR_BAD_SYNTAX;
+ }
+
+ name = mprStrdup(xp, tagName);
+ if (name == 0) {
+ return MPR_ERR_MEMORY;
+ }
+
+ if (cleanTagName(name) < 0) {
+ ejsError(ep, EJS_TYPE_ERROR, "Bad XML tag name in %s at %d",
+ parser->fileName, exmlGetLineNumber(xp));
+ mprFree(name);
+ return MPR_ERR_BAD_SYNTAX;
+ }
+
+ pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode, name);
+ ejsMakePropertyEnumerable(pp, 1);
+
+ tagNode = ejsGetVarPtr(pp);
+
+ /* MOB -- OPT */
+ vpx = ejsCreateXml(ep);
+ vp = ejsWriteVar(ep, tagNode, vpx, EJS_SHALLOW_COPY);
+ ejsMakeObjLive(vp, 1);
+ ejsFreeVar(ep, vpx);
+
+ /* MOB -- return code */
+ pp = ejsSetPropertyToString(ep, vp, E4X_TAG_NAME_PROPERTY, name);
+ ejsMakePropertyEnumerable(pp, 0);
+
+ ejsSetVarFlags(vp, EJS_XML_FLAGS_ELEMENT);
+ ejsMakePropertyEnumerable(ejsGetPropertyPtr(vp), 1);
+
+ tos = &parser->nodeStack[++(parser->topOfStack)];
+ currentNode = tos->obj = vp;
+ tos->attributes = 0;
+ tos->comments = 0;
+ mprFree(name);
+ break;
+
+ case EXML_NEW_ATT:
+ if (mprAllocSprintf(MPR_LOC_ARGS(xp), &name, 0, "@%s", attName) < 0) {
+ return MPR_ERR_MEMORY;
+ }
+ pp = ejsCreateProperty(ep, currentNode, name);
+ ejsMakePropertyEnumerable(pp, 1);
+
+ vp = ejsGetVarPtr(pp);
+ ejsWriteVarAsString(ep, vp, value);
+ ejsSetVarFlags(vp, EJS_XML_FLAGS_ATTRIBUTE);
+ mprFree(name);
+ break;
+
+ case EXML_SOLO_ELT_DEFINED:
+ parser->topOfStack--;
+ mprAssert(parser->topOfStack >= 0);
+ tos = &parser->nodeStack[parser->topOfStack];
+ break;
+
+ case EXML_ELT_DEFINED:
+ if (parser->topOfStack > 0) {
+ parent = parser->nodeStack[parser->topOfStack - 1].obj;
+ ejsSetProperty(ep, currentNode, E4X_PARENT_PROPERTY, parent);
+ }
+ break;
+
+ case EXML_ELT_DATA:
+ case EXML_CDATA:
+ pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode,
+ E4X_TEXT_PROPERTY);
+ ejsMakePropertyEnumerable(pp, 1);
+ vp = ejsGetVarPtr(pp);
+ ejsWriteVarAsString(ep, vp, value);
+ ejsSetVarFlags(vp, EJS_XML_FLAGS_TEXT);
+ break;
+
+ case EXML_END_ELT:
+ /*
+ * This is the closing element in a pair "<x>...</x>".
+ * Pop the stack frame off the elt stack
+ */
+ parser->topOfStack--;
+ mprAssert(parser->topOfStack >= 0);
+ tos = &parser->nodeStack[parser->topOfStack];
+ break;
+
+ default:
+ ejsError(ep, EJS_IO_ERROR, "XML error in %s at %d\nDetails %s",
+ parser->fileName, exmlGetLineNumber(xp), exmlGetErrorMsg(xp));
+ mprAssert(0);
+ return MPR_ERR_BAD_SYNTAX;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+static char *cleanTagName(char *name)
+{
+ char *cp;
+
+ for (cp = name; *cp; cp++) {
+ if (*cp == ':') {
+ *cp = '_';
+ } else if (!isalnum(*cp) && *cp != '_' && *cp != '$' && *cp != '@') {
+ return 0;
+ }
+ }
+ return name;
+}
+
+/******************************************************************************/
+
+static int readFileData(Exml *xp, void *data, char *buf, int size)
+{
+ mprAssert(xp);
+ mprAssert(data);
+ mprAssert(buf);
+ mprAssert(size > 0);
+
+ return mprRead((MprFile*) data, buf, size);
+}
+
+/******************************************************************************/
+
+static int readStringData(Exml *xp, void *data, char *buf, int size)
+{
+ XmlState *parser;
+ int rc, len;
+
+ mprAssert(xp);
+ mprAssert(buf);
+ mprAssert(size > 0);
+
+ parser = (XmlState*) xp->parseArg;
+
+ if (parser->inputPos < parser->inputSize) {
+ len = min(size, (parser->inputSize - parser->inputPos));
+ rc = mprMemcpy(buf, size, &parser->inputBuf[parser->inputPos], len);
+ parser->inputPos += len;
+ return rc;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+static int save(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ const char *fileName;
+ MprBuf *buf;
+ MprFile *file;
+ int bytes, len;
+
+ if (argc != 1 || !ejsVarIsString(argv[0])) {
+ ejsError(ep, EJS_ARG_ERROR, "Bad args. Usage: save(fileName);");
+ return -1;
+ }
+ fileName = argv[0]->string;
+
+ /* MOB -- not romable
+ Need rom code in MPR not MprServices
+ */
+
+ /*
+ * Convert to a string
+ */
+ buf = mprCreateBuf(ep, E4X_BUF_SIZE, E4X_BUF_MAX);
+ if (xmlToString(ep, buf, thisObj, -1) < 0) {
+ mprFree(buf);
+ return -1;
+ }
+
+ file = mprOpen(ep, fileName,
+ O_CREAT | O_TRUNC | O_WRONLY | O_TEXT, 0664);
+ if (file == 0) {
+ ejsError(ep, EJS_IO_ERROR, "Can't open: %s, %d", fileName,
+ mprGetOsError());
+ return -1;
+ }
+
+ len = mprGetBufLength(buf);
+ bytes = mprWrite(file, buf->start, len);
+ if (bytes != len) {
+ ejsError(ep, EJS_IO_ERROR, "Can't write to: %s", fileName);
+ mprClose(file);
+ return -1;
+ }
+ mprWrite(file, "\n", 1);
+ mprFree(buf);
+
+ mprClose(file);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static int toString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ MprBuf *buf;
+
+ buf = mprCreateBuf(ep, E4X_BUF_SIZE, E4X_BUF_MAX);
+
+ if (xmlToString(ep, buf, thisObj, -1) < 0) {
+ mprFree(buf);
+ return -1;
+ }
+ ejsWriteVarAsString(ep, ep->result, (char*) buf->start);
+
+ mprFree(buf);
+
+ return 0;
+}
+
+/******************************************************************************/
+/* MOB -- need to support XMLList */
+
+static int xmlToString(Ejs *ep, MprBuf *buf, EjsVar *obj, int indentLevel)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+ char *varBuf;
+ int endTag, sawElements;
+
+ if (indentLevel < 0) {
+ mprPutStringToBuf(buf, "<?xml version=\"1.0\"?>");
+ }
+
+ switch (obj->type) {
+ case EJS_TYPE_STRING:
+ if (obj->flags & EJS_XML_FLAGS_ATTRIBUTE) {
+ mprPutFmtStringToBuf(buf, " %s=\"%s\"",
+ &ejsGetPropertyPtr(obj)->name[1], obj->string);
+ /* No new line */
+
+ } else if (obj->flags & EJS_XML_FLAGS_COMMENT) {
+ mprPutCharToBuf(buf, '\n');
+ indent(buf, indentLevel);
+ mprPutFmtStringToBuf(buf, "<!-- %s -->", obj->string);
+
+ } else if (obj->flags & EJS_XML_FLAGS_TEXT) {
+ mprPutStringToBuf(buf, obj->string);
+
+ } else {
+// indent(buf, indentLevel);
+ mprPutStringToBuf(buf, obj->string);
+// mprPutCharToBuf(buf, '\n');
+ }
+ break;
+
+ default:
+ /* Primitive types come here */
+ indent(buf, indentLevel);
+ /* MOB -- rc */
+ varBuf = ejsVarToString(ep, obj);
+ mprPutStringToBuf(buf, varBuf);
+ break;
+
+ case EJS_TYPE_OBJECT:
+ if (obj->objectState->baseClass == ejsGetClass(ep, 0, "XML")) {
+ if (!obj->objectState->visited) {
+ obj->objectState->visited = 1;
+
+ /* MOB -- opt. Flags would be quicker */
+ if (strcmp(ejsGetPropertyPtr(obj)->name,
+ E4X_PARENT_PROPERTY) == 0) {
+ return 0;
+ }
+ /*
+ * MOB -- short term fix for tags with no body but with
+ * attributes
+ */
+ if (getNumElements(obj) == 0 && 0) {
+ /*
+ * XML element is simple with no elements, so return just
+ * the text.
+ */
+ if (getText(buf, obj) < 0) {
+ ejsError(ep, EJS_IO_ERROR,
+ "XML is to big to convert to a string");
+ obj->objectState->visited = 0;
+ return -1;
+ }
+
+ } else if (obj->flags & (EJS_XML_FLAGS_ELEMENT)) {
+ /*
+ * XML object is complex (has elements) so return full XML
+ * content.
+ */
+ mprPutCharToBuf(buf, '\n');
+ indent(buf, indentLevel);
+
+ /*
+ * When called from toString, obj is not a property
+ */
+ if (indentLevel >= 0) {
+ mprPutFmtStringToBuf(buf, "<%s",
+ ejsGetPropertyPtr(obj)->name);
+ endTag = 0;
+
+ } else {
+ endTag = 1;
+ }
+
+ sawElements = 0;
+ pp = ejsGetFirstProperty(obj, 0);
+ while (pp) {
+ vp = ejsGetVarPtr(pp);
+
+ if (! (vp->flags & EJS_XML_FLAGS_ATTRIBUTE)) {
+ if (endTag == 0) {
+ endTag++;
+ mprPutStringToBuf(buf, ">");
+ }
+ }
+ if (vp->flags & EJS_XML_FLAGS_ELEMENT) {
+ if (strcmp(ejsGetPropertyPtr(vp)->name,
+ E4X_PARENT_PROPERTY) != 0) {
+ sawElements++;
+ }
+ }
+
+ if (xmlToString(ep, buf, ejsGetVarPtr(pp),
+ indentLevel + 1) < 0){
+ return -1;
+ }
+
+ pp = ejsGetNextProperty(pp, 0);
+ }
+ if (indentLevel >= 0) {
+ if (sawElements) {
+ mprPutCharToBuf(buf, '\n');
+ indent(buf, indentLevel);
+ }
+ mprPutFmtStringToBuf(buf, "</%s>",
+ ejsGetPropertyPtr(obj)->name);
+ }
+ }
+ obj->objectState->visited = 0;
+ }
+ return 0;
+ }
+
+ if (obj->objectState->baseClass == ejsGetClass(ep, 0, "XMLList")) {
+ indent(buf, indentLevel);
+ /* MOB -- TBD */
+ return 0;
+ }
+
+ /*
+ * All other objects. Allow other objects to override toString
+ */
+ if (ejsRunMethod(ep, obj->objectState->baseClass, "toString",
+ 0) < 0) {
+ return -1;
+ }
+ if (ejsVarIsString(ep->result)) {
+ indent(buf, indentLevel);
+ mprPutStringToBuf(buf, obj->string);
+ }
+ break;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+static void indent(MprBuf *bp, int level)
+{
+ int i;
+
+ for (i = 0; i < level; i++) {
+ mprPutCharToBuf(bp, '\t');
+ }
+}
+
+/******************************************************************************/
+
+static int valueOf(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ if (argc != 0) {
+ mprAssert(0);
+ return -1;
+ }
+
+ switch (thisObj->type) {
+ default:
+ case EJS_TYPE_UNDEFINED:
+ case EJS_TYPE_NULL:
+ case EJS_TYPE_CMETHOD:
+ case EJS_TYPE_OBJECT:
+ case EJS_TYPE_METHOD:
+ case EJS_TYPE_STRING_CMETHOD:
+ ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY);
+ break;
+
+ case EJS_TYPE_STRING:
+ ejsWriteVarAsInteger(ep, ep->result, atoi(thisObj->string));
+ break;
+
+ case EJS_TYPE_BOOL:
+ case EJS_TYPE_INT:
+#if BLD_FEATURE_INT64
+ case EJS_TYPE_INT64:
+#endif
+#if BLD_FEATURE_FLOATING_POINT
+ case EJS_TYPE_FLOAT:
+#endif
+ ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY);
+ break;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+static int getList(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv)
+{
+ const char *nodeName;
+ EjsProperty *pp;
+ EjsVar *list, *vp;
+
+ if (argc != 1) {
+ nodeName = 0;
+ } else {
+ nodeName = argv[0]->string;
+ }
+
+ list = ejsCreateArray(ep, 0);
+
+ pp = ejsGetFirstProperty(thisObj, EJS_ENUM_ALL);
+ while (pp) {
+ vp = ejsGetVarPtr(pp);
+ if (vp->type == EJS_TYPE_OBJECT) {
+ if (strcmp(ejsGetPropertyPtr(vp)->name, E4X_PARENT_PROPERTY) != 0) {
+ if (vp->flags & EJS_XML_FLAGS_ELEMENT &&
+ (nodeName == 0 || strcmp(nodeName, pp->name) == 0)) {
+ ejsAddArrayElt(ep, list, vp, EJS_SHALLOW_COPY);
+ }
+ }
+ }
+ pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);
+ }
+
+ ejsSetReturnValueAndFree(ep, list);
+ return 0;
+}
+
+/******************************************************************************/
+
+static int getNumElements(EjsVar *obj)
+{
+ EjsProperty *pp;
+ int count;
+
+ count = 0;
+ pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL);
+ while (pp) {
+ if (ejsGetVarPtr(pp)->flags & EJS_XML_FLAGS_ELEMENT) {
+ count++;
+ }
+ pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);
+ }
+ return count;
+}
+
+/******************************************************************************/
+/* MOB - This needs to be a public method */
+
+static int getText(MprBuf *buf, EjsVar *obj)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+
+ pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL);
+ while (pp) {
+ vp = ejsGetVarPtr(pp);
+ if (vp->flags & EJS_XML_FLAGS_TEXT) {
+ /* MOB -- should test for overflow */
+ mprPutStringToBuf(buf, vp->string);
+ }
+ pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************** Internal Methods ****************************/
+/******************************************************************************/
+
+static EjsVar *createXmlListProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsGetVarPtr(ejsCreateProperty(ep, obj, property));
+}
+
+/******************************************************************************/
+
+static int deleteXmlListProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ return ejsDeleteProperty(ep, obj, property);
+}
+
+/******************************************************************************/
+
+static EjsVar *getXmlListProperty(Ejs *ep, EjsVar *obj, const char *property)
+{
+ // Must always return XML or XMLList event for comments and attributes
+ return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property));
+}
+
+/******************************************************************************/
+
+static EjsVar *setXmlListProperty(Ejs *ep, EjsVar *obj, const char *property,
+ const EjsVar *value)
+{
+ EjsProperty *pp;
+ EjsVar *vp;
+
+ pp = ejsGetSimpleProperty(ep, obj, property);
+ if (pp == 0) {
+ mprAssert(pp);
+ return 0;
+ }
+ vp = ejsGetVarPtr(pp);
+ if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0){
+ mprAssert(0);
+ return 0;
+ }
+ return ejsGetVarPtr(pp);
+}
+
+/******************************************************************************/
+/*
+ NEW
+
+static EjsVar *putXmlListProperty(EjsVar *op, const char *property,
+ EjsVar *value)
+{
+
+ if ((value->objectState->baseClass != XML &&
+ value->objectState->baseClass != XMLList) ||
+ value->string[0] != '<') {
+ c = value.toString();
+ } else {
+ value = ejsDupVar(value);
+ ??
+ }
+ if (isdigit(*property)) {
+ // ERROR
+ return 0;
+ }
+ if (*property == '@') {
+ if (op->objectState->baseClass == XMLList) {
+ if (op->obj.LENGTH_PROPERTY == 0) {
+ c = "";
+ } else {
+ // Catenate all result of toString on all elts in list
+ }
+ } else {
+ c = c.toString();
+ }
+ // Replace existing attribute of same name or insert
+ return;
+ }
+ for (i = op->obj.LENGTH - 1; i >= 0; i--) {
+ // Delete item of same name
+ }
+ if (not Found) {
+ Append new Xml object
+ - set [[name]], [[class]] == "element"
+ }
+}
+
+ */
+
+/******************************************************************************/
+#else
+void ejs4xDummy() {}
+
+/******************************************************************************/
+#endif /* BLD_FEATURE_EJS_E4X */
+
+/*
+ * 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
+ */