summaryrefslogtreecommitdiff
path: root/source4/lib/appweb/ejs-2.0/mpr
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/mpr')
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/Makefile41
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile16
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c86
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c218
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c163
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile16
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c85
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c191
-rwxr-xr-xsource4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c163
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile16
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c123
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c378
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c192
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/files14
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mpr.c340
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mpr.h1027
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c1775
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprArray.c385
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprBuf.c535
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c336
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c195
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprLock.c266
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprLog.c602
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprOs.h707
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c924
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprString.c733
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c279
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprUnix.h105
28 files changed, 9911 insertions, 0 deletions
diff --git a/source4/lib/appweb/ejs-2.0/mpr/Makefile b/source4/lib/appweb/ejs-2.0/mpr/Makefile
new file mode 100644
index 0000000000..6dd0e45d9e
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for the Mbedthis Portable Runtime (MPR) library
+#
+# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+#
+
+COMPILE := *.c
+EXPORT_OBJECTS := yes
+
+include make.dep
+
+ifeq ($(BLD_HOST_UNIX),1)
+PRE_DIRS = UNIX
+else
+PRE_DIRS = $(BLD_HOST_OS)
+endif
+
+POST_DIRS = package
+
+TARGETS += $(BLD_BIN_DIR)/libmpr$(BLD_LIB)
+
+compileExtra: $(TARGETS)
+
+#
+# Build the mpr libraries
+#
+$(BLD_BIN_DIR)/libmpr$(BLD_LIB): files \
+ $(shell BLD_OBJ=$(BLD_OBJ) \; BLD_OBJ_DIR=$(BLD_OBJ_DIR) \; \
+ eval echo `cat files`)
+ @bld --library $(BLD_BIN_DIR)/libmpr \
+ --objectsDir $(BLD_OBJ_DIR) --objectList files
+
+cleanExtra:
+ @echo "rm -f $(TARGETS)" | $(BLDOUT)
+ @rm -f $(TARGETS)
+ @rm -f $(BLD_BIN_DIR)/libmpr.*
+
+## Local variables:
+## tab-width: 4
+## End:
+## vim: tw=78 sw=4 ts=4
diff --git a/source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile b/source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile
new file mode 100644
index 0000000000..5259b1e3a0
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Mbedthis Portable Runtime (MPR) library for UNIX
+#
+# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+#
+
+COMPILE := *.c
+EXPORT_OBJECTS := yes
+MAKE_IFLAGS := -I..
+
+include make.dep
+
+## Local variables:
+## tab-width: 4
+## End:
+## vim: tw=78 sw=4 ts=4
diff --git a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c
new file mode 100644
index 0000000000..f647f1ed56
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c
@@ -0,0 +1,86 @@
+/**
+ * @file mprFile.c
+ * @brief File services for Unix
+ * @overview
+ * @remarks
+ * See mprGenFile.c for other file services.
+ */
+
+/******************************************************************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/************************************ Code ************************************/
+
+int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info)
+{
+ struct stat s;
+
+ mprAssert(path);
+ mprAssert(info);
+
+ if (stat(path, &s) < 0) {
+ return -1;
+ }
+
+ info->size = s.st_size;
+ info->ctime = s.st_ctime;
+ info->mtime = s.st_mtime;
+ info->inode = s.st_ino;
+ info->isDir = (s.st_mode & S_IFDIR) != 0;
+ info->isReg = (s.st_mode & S_IFREG) != 0;
+
+ if (strcmp(path, "/dev/null") == 0) {
+ info->isReg = 0;
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprMakeDir(MprCtx ctx, const char *path, int perms)
+{
+ return mkdir(path, perms);
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/UNIX/mprPlatform.c b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c
new file mode 100644
index 0000000000..2c7fbf8a00
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c
@@ -0,0 +1,218 @@
+/**
+ * @file mprPlatform.c
+ * @brief Cross platform routines
+ * @overview This module provides low level cross platform routines.
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 **********************************/
+/*
+ * We need to use the underlying str(cpy) routines to implement our safe
+ * alternatives
+ */
+#if !DOXYGEN
+#define UNSAFE_FUNCTIONS_OK 1
+#endif
+
+#include "mpr.h"
+
+/************************************ Code ************************************/
+
+char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
+{
+#if HAVE_NTOA_R
+ inet_ntoa_r(in, buffer, bufsize);
+#else
+ uchar *cp;
+ /* FUTURE -- this is not portable */
+ cp = (uchar*) &in;
+ mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
+#endif
+ return buffer;
+}
+
+/******************************************************************************/
+
+void mprSetShell(MprCtx ctx, void *shell)
+{
+}
+
+/******************************************************************************/
+
+void *mprGetShell(MprCtx ctx)
+{
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Sleep. Period given in milliseconds.
+ */
+
+void mprSleep(MprCtx ctx, int milliseconds)
+{
+ struct timespec timeout;
+ int rc;
+
+ mprAssert(milliseconds >= 0);
+ timeout.tv_sec = milliseconds / 1000;
+ timeout.tv_nsec = (milliseconds % 1000) * 1000000;
+ do {
+ rc = nanosleep(&timeout, 0);
+ } while (rc < 0 && errno == EINTR);
+}
+
+/******************************************************************************/
+/*
+ * Make intervening directories
+ */
+
+int mprMakeDirPath(MprCtx ctx, const char *path)
+{
+ char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
+ char *dirSep;
+ char *next, *tok;
+
+ dir[0] = '\0';
+ dirSep = "/\\";
+
+ if (path == 0 || *path == '\0') {
+ return MPR_ERR_BAD_ARGS;
+ }
+
+ mprStrcpy(buf, sizeof(buf), path);
+ next = mprStrTok(buf, dirSep, &tok);
+ if (*buf == '/') {
+ dir[0] = '/';
+ }
+ while (next != NULL) {
+ if (strcmp(next, ".") == 0 ) {
+ next = mprStrTok(NULL, dirSep, &tok);
+ continue;
+ }
+ strcat(dir, next);
+ if (access(dir, R_OK) != 0) {
+ if (mkdir(dir, 0666) < 0) {
+ return MPR_ERR_CANT_CREATE;
+ }
+ }
+ strcat(dir, "/");
+ next = mprStrTok(NULL, dirSep, &tok);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Get a fully qualified file name for the given path. Return with forward
+ * slashes always
+ */
+
+char *mprGetFullPathName(char *buf, int buflen, const char *path)
+{
+ if (mprStrcpy(buf, buflen, path) < 0) {
+ mprAssert(0);
+ return 0;
+ }
+ return buf;
+}
+
+/******************************************************************************/
+/*
+ * Replacement for gethostbyname that is multi-thread safe
+ */
+
+struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
+{
+ MprApp *app;
+ struct hostent *hp;
+ struct hostent *ip;
+ int count, i;
+
+ hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
+ memset(hp, 0, sizeof(struct hostent));
+
+ app = mprGetApp(ctx);
+
+ #undef gethostbyname
+
+ mprGlobalLock(app);
+ ip = gethostbyname(name);
+ mprGlobalUnlock(app);
+
+ if (ip == 0) {
+ return 0;
+ }
+ hp->h_addrtype = ip->h_addrtype;
+ hp->h_length = ip->h_length;
+ hp->h_name = mprStrdup(hp, ip->h_name);
+ hp->h_addr_list = 0;
+ hp->h_aliases = 0;
+
+ for (count = 0; ip->h_addr_list[count] != 0; ) {
+ count++;
+ }
+ if (count > 0) {
+ count++;
+ hp->h_addr_list = mprAlloc(hp, count * sizeof(char*));
+ for (i = 0; ip->h_addr_list[i] != 0; i++) {
+ memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length);
+ }
+ hp->h_addr_list[i] = 0;
+ }
+
+ for (count = 0; ip->h_aliases[count] != 0; ) {
+ count++;
+ }
+ if (count > 0) {
+ count++;
+ hp->h_aliases = mprAlloc(hp, count * sizeof(char*));
+ for (i = 0; ip->h_aliases[i] != 0; i++) {
+ hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]);
+ }
+ hp->h_aliases[i] = 0;
+ }
+ return hp;
+}
+
+/******************************************************************************/
+
+/*
+ * 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/mpr/UNIX/mprTime.c b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c
new file mode 100644
index 0000000000..0153c0622d
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c
@@ -0,0 +1,163 @@
+/**
+ * @file mprTime.c
+ * @brief Time handling for Unix
+ * @overview
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef localtime
+#undef localtime_r
+#undef gmtime
+#undef gmtime_r
+#undef ctime
+#undef ctime_r
+#undef asctime
+#undef asctime_r
+
+/******************************************************************************/
+/*
+ * Returns time in seconds and milliseconds. This is NOT time-of-day.
+ */
+
+MprTime *mprGetTime(MprCtx ctx, MprTime *tp)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, 0) < 0) {
+ mprAssert(0);
+ tp->sec = 0;
+ tp->msec = 0;
+ return tp;
+ }
+ tp->sec = tv.tv_sec;
+ tp->msec = tv.tv_usec / 1000;
+ return tp;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of localtime
+ */
+
+struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now)
+{
+ localtime_r(now, timep);
+
+ return timep;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of gmtime
+ */
+
+struct tm *mprGmtime(MprCtx ctx, time_t *now, struct tm *timep)
+{
+ gmtime_r(now, timep);
+
+ return timep;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of ctime
+ */
+
+int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer)
+{
+ char localBuf[80];
+ char *cp;
+ int len;
+
+ mprAssert(buf);
+
+ mprGlobalLock(ctx);
+
+ cp = ctime_r(timer, localBuf);
+ if ((int) strlen(cp) >= bufsize) {
+ mprStrcpy(buf, bufsize, "WONT FIT");
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ len = mprStrcpy(buf, bufsize, cp);
+
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = '\0';
+ }
+
+ mprGlobalUnlock(ctx);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of asctime
+ */
+
+int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr)
+{
+ char *cp;
+ char localBuf[80];
+
+ cp = asctime_r(timeptr, localBuf);
+ if ((int) strlen(cp) >= bufsize) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ mprStrcpy(buf, bufsize, cp);
+
+ return strlen(buf);
+}
+
+/******************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * 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/mpr/VXWORKS/Makefile b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile
new file mode 100644
index 0000000000..f3a2394b6e
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Mbedthis Portable Runtime (MPR) library for VXWORKS
+#
+# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+#
+
+COMPILE := *.c
+EXPORT_OBJECTS := yes
+MAKE_IFLAGS := -I..
+
+include make.dep
+
+## Local variables:
+## tab-width: 4
+## End:
+## vim: tw=78 sw=4 ts=4
diff --git a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c
new file mode 100644
index 0000000000..ae0b523faa
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c
@@ -0,0 +1,85 @@
+/**
+ * @file mprUnixFile.c
+ * @brief File services for Unix
+ * @overview
+ * @remarks
+ */
+
+/******************************************************************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/************************************ Code ************************************/
+
+int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info)
+{
+ struct stat s;
+
+ mprAssert(path);
+ mprAssert(info);
+
+ if (stat(path, &s) < 0) {
+ return -1;
+ }
+
+ info->size = s.st_size;
+ info->ctime = s.st_ctime;
+ info->mtime = s.st_mtime;
+ info->inode = s.st_ino;
+ info->isDir = (s.st_mode & S_IFDIR) != 0;
+ info->isReg = (s.st_mode & S_IFREG) != 0;
+
+ if (strcmp(path, "/dev/null") == 0) {
+ info->isReg = 0;
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprMakeDir(MprCtx ctx, const char *path, int perms)
+{
+ return mkdir(path, perms);
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/VXWORKS/mprPlatform.c b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c
new file mode 100644
index 0000000000..29258dfe1c
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c
@@ -0,0 +1,191 @@
+/**
+ * @file mprPlatform.c
+ * @brief Cross platform routines
+ * @overview This module provides low level cross platform routines.
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 **********************************/
+/*
+ * We need to use the underlying str(cpy) routines to implement our safe
+ * alternatives
+ */
+#if !DOXYGEN
+#define UNSAFE_FUNCTIONS_OK 1
+#endif
+
+#include "mpr.h"
+
+/************************************ Code ************************************/
+
+char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
+{
+#if HAVE_NTOA_R
+ inet_ntoa_r(in, buffer, bufsize);
+#else
+ uchar *cp;
+ /* FUTURE -- this is not portable */
+ cp = (uchar*) &in;
+ mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
+#endif
+ return buffer;
+}
+
+/******************************************************************************/
+
+void mprSetShell(MprCtx ctx, void *shell)
+{
+}
+
+/******************************************************************************/
+
+void *mprGetShell(MprCtx ctx)
+{
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Sleep. Period given in milliseconds.
+ */
+
+void mprSleep(MprCtx ctx, int milliseconds)
+{
+ struct timeval timeout;
+ int rc;
+
+ timeout.tv_sec = milliseconds / 1000;
+ timeout.tv_usec = (milliseconds % 1000) * 1000;
+ do {
+ rc = select(1, 0, 0, 0, &timeout);
+ } while (rc < 0 && errno == EINTR);
+}
+
+/******************************************************************************/
+/*
+ * Make intervening directories
+ */
+
+int mprMakeDirPath(MprCtx ctx, const char *path)
+{
+ char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
+ char *dirSep;
+ char *next, *tok;
+
+ dir[0] = '\0';
+ dirSep = "/\\";
+
+ if (path == 0 || *path == '\0') {
+ return MPR_ERR_BAD_ARGS;
+ }
+
+ mprStrcpy(buf, sizeof(buf), path);
+ next = mprStrTok(buf, dirSep, &tok);
+ if (*buf == '/') {
+ dir[0] = '/';
+ }
+ while (next != NULL) {
+ if (strcmp(next, ".") == 0 ) {
+ next = mprStrTok(NULL, dirSep, &tok);
+ continue;
+ }
+ strcat(dir, next);
+ if (access(dir, R_OK) != 0) {
+ if (mkdir(dir) < 0) {
+ return MPR_ERR_CANT_CREATE;
+ }
+ }
+ strcat(dir, "/");
+ next = mprStrTok(NULL, dirSep, &tok);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Get a fully qualified file name for the given path. Return with forward
+ * slashes always
+ */
+
+char *mprGetFullPathName(char *buf, int buflen, const char *path)
+{
+ if (mprStrcpy(buf, buflen, path) < 0) {
+ mprAssert(0);
+ return 0;
+ }
+ return buf;
+}
+
+/******************************************************************************/
+/*
+ * Replacement for gethostbyname that is multi-thread safe
+ */
+
+struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
+{
+ struct hostent *hp;
+
+ hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
+ memset(hp, 0, sizeof(struct hostent));
+
+ struct in_addr inaddr;
+ inaddr.s_addr = (ulong) hostGetByName(name);
+ if (inaddr.s_addr < 0) {
+ mprAssert(0);
+ return 0;
+ }
+ hp->h_addrtype = AF_INET;
+ hp->h_length = sizeof(int);
+ hp->h_name = mprStrdup(name);
+ hp->h_addr_list = 0;
+ hp->h_aliases = 0;
+
+ hp->h_addr_list = new char*[2];
+ hp->h_addr_list[0] = (char *) mprAlloc(hp, sizeof(struct in_addr));
+ memcpy(&hp->h_addr_list[0], &inaddr, hp->h_length);
+ hp->h_addr_list[1] = 0;
+
+ return hp;
+}
+
+/******************************************************************************/
+
+/*
+ * 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/mpr/VXWORKS/mprTime.c b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c
new file mode 100755
index 0000000000..c9b7560f46
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c
@@ -0,0 +1,163 @@
+/**
+ * @file mprTime.c
+ * @brief Time handling for VxWorks
+ * @overview
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef localtime
+#undef localtime_r
+#undef gmtime
+#undef gmtime_r
+#undef ctime
+#undef ctime_r
+#undef asctime
+#undef asctime_r
+
+/******************************************************************************/
+/*
+ * Returns time in seconds and milliseconds. This is NOT time-of-day.
+ */
+
+MprTime *mprGetTime(MprCtx ctx, MprTime *tp)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, 0) < 0) {
+ mprAssert(0);
+ tp->sec = 0;
+ tp->msec = 0;
+ return tp;
+ }
+ tp->sec = tv.tv_sec;
+ tp->msec = tv.tv_usec / 1000;
+ return tp;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of localtime
+ */
+
+struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now)
+{
+ localtime_r(now, timep);
+
+ return timep;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of gmtime
+ */
+
+struct tm *mprGmtime(MprCtx ctx, time_t *now, struct tm *timep)
+{
+ gmtime_r(now, timep);
+
+ return timep;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of ctime
+ */
+
+int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer)
+{
+ char localBuf[80];
+ char *cp;
+ int len;
+
+ mprAssert(buf);
+
+ mprGlobalLock(ctx);
+
+ cp = ctime_r(timer, localBuf);
+ if ((int) strlen(cp) >= bufsize) {
+ mprStrcpy(buf, bufsize, "WONT FIT");
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ len = mprStrcpy(buf, bufsize, cp);
+
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = '\0';
+ }
+
+ mprGlobalUnlock(ctx);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of asctime
+ */
+
+int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr)
+{
+ char *cp;
+ char localBuf[80];
+
+ cp = asctime_r(timeptr, localBuf);
+ if ((int) strlen(cp) >= bufsize) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ mprStrcpy(buf, bufsize, cp);
+
+ return strlen(buf);
+}
+
+/******************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * 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/mpr/WIN/Makefile b/source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile
new file mode 100644
index 0000000000..84e30ff8f1
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Mbedthis Portable Runtime (MPR) library for Windows
+#
+# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
+#
+
+COMPILE := *.c
+EXPORT_OBJECTS := yes
+MAKE_IFLAGS := -I..
+
+include make.dep
+
+## Local variables:
+## tab-width: 4
+## End:
+## vim: tw=78 sw=4 ts=4
diff --git a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c
new file mode 100644
index 0000000000..9ac1669f3d
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c
@@ -0,0 +1,123 @@
+/**
+ * @file mprWinFile.c
+ * @brief File services for Windows
+ * @overview
+ * @remarks
+ */
+
+/******************************************************************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/************************************ Code ************************************/
+
+int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info)
+{
+ struct stat s;
+
+ mprAssert(path);
+ mprAssert(info);
+
+ if (stat(path, &s) < 0) {
+ return -1;
+ }
+
+ info->size = s.st_size;
+ /*
+ * MOB -- these are time64_t. Loss of precision
+ */
+ info->ctime = (uint) s.st_ctime;
+ info->mtime = (uint) s.st_mtime;
+ info->inode = s.st_ino;
+ info->isDir = (s.st_mode & S_IFDIR) != 0;
+ info->isReg = (s.st_mode & S_IFREG) != 0;
+
+ /*
+ * Work hard on windows to determine if the file is a regular file.
+ * FUTURE -- OPT. Eliminate this CreateFile.
+ */
+ if (info->isReg) {
+ long fileType, att;
+
+ if ((att = GetFileAttributes(path)) == -1) {
+ return -1;
+ }
+ if (att & (FILE_ATTRIBUTE_REPARSE_POINT |
+ FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_ENCRYPTED |
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_OFFLINE)) {
+ /*
+ * Catch accesses to devices like CON, AUX, NUL, LPT etc
+ * att will be set to ENCRYPTED on Win9X and NT.
+ */
+ info->isReg = 0;
+ }
+ if (info->isReg) {
+ HANDLE handle;
+ handle = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, OPEN_EXISTING, 0, 0);
+ if (handle == INVALID_HANDLE_VALUE) {
+ info->isReg = 0;
+ } else {
+ fileType = GetFileType(handle);
+ if (fileType == FILE_TYPE_CHAR || fileType == FILE_TYPE_PIPE) {
+ info->isReg = 0;
+ }
+ CloseHandle(handle);
+ }
+ }
+ }
+ if (strcmp(path, "nul") == 0) {
+ info->isReg = 0;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprMakeDir(MprCtx ctx, const char *path, int perms)
+{
+ return mkdir(path, perms);
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/WIN/mprPlatform.c b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c
new file mode 100644
index 0000000000..65718694b1
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c
@@ -0,0 +1,378 @@
+/**
+ * @file mprPlatform.c
+ * @brief Cross platform routines
+ * @overview This module provides low level cross platform routines.
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 **********************************/
+/*
+ * We need to use the underlying str(cpy) routines to implement our safe
+ * alternatives
+ */
+#if !DOXYGEN
+#define UNSAFE_FUNCTIONS_OK 1
+#endif
+
+#include "mpr.h"
+
+/**************************** Forward Declarations ****************************/
+
+static const char *getHive(const char *keyPath, HKEY *hive);
+
+/************************************ Code ************************************/
+
+char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
+{
+#if HAVE_NTOA_R
+ inet_ntoa_r(in, buffer, bufsize);
+#else
+ uchar *cp;
+ cp = (uchar*) &in;
+ mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
+#endif
+ return buffer;
+}
+
+/******************************************************************************/
+
+void mprSetShell(MprCtx ctx, void *shell)
+{
+}
+
+/******************************************************************************/
+
+void *mprGetShell(MprCtx ctx)
+{
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Sleep. Period given in milliseconds.
+ */
+
+void mprSleep(MprCtx ctx, int milliseconds)
+{
+ Sleep(milliseconds);
+}
+
+/******************************************************************************/
+/*
+ * Make intervening directories
+ */
+
+int mprMakeDirPath(MprCtx ctx, const char *path)
+{
+ char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
+ char *dirSep;
+ char *next, *tok;
+
+ dir[0] = '\0';
+ dirSep = "/\\";
+
+ if (path == 0 || *path == '\0') {
+ return MPR_ERR_BAD_ARGS;
+ }
+
+ mprStrcpy(buf, sizeof(buf), path);
+ next = mprStrTok(buf, dirSep, &tok);
+ if (*buf == '/') {
+ dir[0] = '/';
+ }
+ while (next != NULL) {
+ if (strcmp(next, ".") == 0 ) {
+ next = mprStrTok(NULL, dirSep, &tok);
+ continue;
+ }
+ strcat(dir, next);
+ if (access(dir, R_OK) != 0) {
+ if (_mkdir(dir) < 0) {
+ return MPR_ERR_CANT_CREATE;
+ }
+ }
+ strcat(dir, "/");
+ next = mprStrTok(NULL, dirSep, &tok);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Get a fully qualified file name for the given path. Return with forward
+ * slashes always
+ */
+
+char *mprGetFullPathName(char *buf, int buflen, const char *path)
+{
+#if (WIN || NW || OS2) && !BLD_FEATURE_ROMFS
+ char *junk, *cp;
+ int rc;
+
+ --buflen;
+ rc = GetFullPathName(path, buflen, buf, &junk);
+ for (cp = buf; *cp; cp++) {
+ if (*cp == '\\') {
+ *cp = '/';
+ }
+ }
+ buf[buflen] = '\0';
+#else
+ if (mprStrcpy(buf, buflen, path) < 0) {
+ mprAssert(0);
+ return 0;
+ }
+#endif
+ return buf;
+}
+
+/******************************************************************************/
+/*
+ * Replacement for gethostbyname that is multi-thread safe
+ */
+
+struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
+{
+ MprApp *app;
+ struct hostent *hp;
+ struct hostent *ip;
+ int count, i;
+
+ hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
+ memset(hp, 0, sizeof(struct hostent));
+
+ app = mprGetApp(ctx);
+
+ #undef gethostbyname
+
+ mprGlobalLock(app);
+ ip = gethostbyname(name);
+ mprGlobalUnlock(app);
+
+ if (ip == 0) {
+ return 0;
+ }
+ hp->h_addrtype = ip->h_addrtype;
+ hp->h_length = ip->h_length;
+ hp->h_name = mprStrdup(hp, ip->h_name);
+ hp->h_addr_list = 0;
+ hp->h_aliases = 0;
+
+ for (count = 0; ip->h_addr_list[count] != 0; ) {
+ count++;
+ }
+ if (count > 0) {
+ count++;
+ hp->h_addr_list = mprAlloc(hp, count * sizeof(char*));
+ for (i = 0; ip->h_addr_list[i] != 0; i++) {
+ memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length);
+ }
+ hp->h_addr_list[i] = 0;
+ }
+
+ for (count = 0; ip->h_aliases[count] != 0; ) {
+ count++;
+ }
+ if (count > 0) {
+ count++;
+ hp->h_aliases = mprAlloc(hp, count * sizeof(char*));
+ for (i = 0; ip->h_aliases[i] != 0; i++) {
+ hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]);
+ }
+ hp->h_aliases[i] = 0;
+ }
+ return hp;
+}
+
+/******************************************************************************/
+/*
+ * Read a registry value. Returns allocated memory in buf.
+ */
+
+int mprReadRegistry(MprCtx ctx, char **buf, int max, const char *key,
+ const char *name)
+{
+ HKEY top, h;
+ char *value;
+ ulong type, size;
+
+ mprAssert(key && *key);
+ mprAssert(buf);
+
+ /*
+ * Get the registry hive
+ */
+ if ((key = getHive(key, &top)) == 0) {
+ return MPR_ERR_CANT_ACCESS;
+ }
+
+ if (RegOpenKeyEx(top, key, 0, KEY_READ, &h) != ERROR_SUCCESS) {
+ return MPR_ERR_CANT_ACCESS;
+ }
+
+ /*
+ * Get the type
+ */
+ if (RegQueryValueEx(h, name, 0, &type, 0, &size) != ERROR_SUCCESS) {
+ RegCloseKey(h);
+ return MPR_ERR_CANT_READ;
+ }
+ if (type != REG_SZ && type != REG_EXPAND_SZ) {
+ RegCloseKey(h);
+ return MPR_ERR_BAD_TYPE;
+ }
+
+ value = (char*) mprAlloc(ctx, size);
+ if ((int) size > max) {
+ RegCloseKey(h);
+ return MPR_ERR_WONT_FIT;
+ }
+ if (RegQueryValueEx(h, name, 0, &type, (uchar*) value, &size) !=
+ ERROR_SUCCESS) {
+ mprFree(value);
+ RegCloseKey(h);
+ return MPR_ERR_CANT_READ;
+ }
+
+ RegCloseKey(h);
+ *buf = value;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Write a string registry value. Returns allocated memory in buf.
+ */
+
+int mprWriteRegistry(MprCtx ctx, const char *key, const char *name,
+ const char *value)
+{
+ HKEY top, h, subHandle;
+ ulong disposition;
+
+ mprAssert(key && *key);
+ mprAssert(name && *name);
+ mprAssert(value && *value);
+
+ /*
+ * Get the registry hive
+ */
+ if ((key = getHive(key, &top)) == 0) {
+ return MPR_ERR_CANT_ACCESS;
+ }
+
+ if (name) {
+ /*
+ * Write a registry string value
+ */
+ if (RegOpenKeyEx(top, key, 0, KEY_ALL_ACCESS, &h) != ERROR_SUCCESS) {
+ return MPR_ERR_CANT_ACCESS;
+ }
+ if (RegSetValueEx(h, name, 0, REG_SZ, value, strlen(value) + 1)
+ != ERROR_SUCCESS) {
+ RegCloseKey(h);
+ return MPR_ERR_CANT_READ;
+ }
+
+ } else {
+ /*
+ * Create a new sub key
+ */
+ if (RegOpenKeyEx(top, key, 0, KEY_CREATE_SUB_KEY, &h) != ERROR_SUCCESS){
+ return MPR_ERR_CANT_ACCESS;
+ }
+ if (RegCreateKeyEx(h, name, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS, NULL, &subHandle, &disposition) != ERROR_SUCCESS) {
+ return MPR_ERR_CANT_ACCESS;
+ }
+ RegCloseKey(subHandle);
+ }
+ RegCloseKey(h);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Determine the registry hive by the first portion of the path. Return
+ * a pointer to the rest of key path after the hive portion.
+ */
+
+static const char *getHive(const char *keyPath, HKEY *hive)
+{
+ char key[MPR_MAX_STRING], *cp;
+ int len;
+
+ mprAssert(keyPath && *keyPath);
+
+ *hive = 0;
+
+ mprStrcpy(key, sizeof(key), keyPath);
+ key[sizeof(key) - 1] = '\0';
+
+ if (cp = strchr(key, '\\')) {
+ *cp++ = '\0';
+ }
+ if (cp == 0 || *cp == '\0') {
+ return 0;
+ }
+
+ if (!mprStrcmpAnyCase(key, "HKEY_LOCAL_MACHINE")) {
+ *hive = HKEY_LOCAL_MACHINE;
+ } else if (!mprStrcmpAnyCase(key, "HKEY_CURRENT_USER")) {
+ *hive = HKEY_CURRENT_USER;
+ } else if (!mprStrcmpAnyCase(key, "HKEY_USERS")) {
+ *hive = HKEY_USERS;
+ } else if (!mprStrcmpAnyCase(key, "HKEY_CLASSES_ROOT")) {
+ *hive = HKEY_CLASSES_ROOT;
+ } else {
+ return 0;
+ }
+
+ if (*hive == 0) {
+ return 0;
+ }
+ len = strlen(key) + 1;
+ return keyPath + len;
+}
+
+/******************************************************************************/
+
+/*
+ * 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/mpr/WIN/mprTime.c b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c
new file mode 100644
index 0000000000..74e59c9c73
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c
@@ -0,0 +1,192 @@
+/**
+ * @file mprTime.c
+ * @brief Time handling for Windows
+ * @overview
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************************ Code ************************************/
+/*
+ * Returns time in seconds and milliseconds. This is NOT time-of-day.
+ */
+
+MprTime *mprGetTime(MprCtx ctx, MprTime *tp)
+{
+ FILETIME fileTime;
+ int64 now, base;
+
+ GetSystemTimeAsFileTime(&fileTime);
+
+ now = ((((int64) fileTime.dwHighDateTime) << BITS(uint)) +
+ ((int64) fileTime.dwLowDateTime));
+
+ /*
+ * Convert from 100-nanosec units to milliseconds
+ */
+ now = (now / 10000);
+
+ /*
+ * Adjust to be seconds since Jan 1 1970. Do this to be consistent with
+ * UNIX but not really required by the API definition.
+ */
+ base = ((UINT64(365) * 86400 * (1970 - 1601)) * 1000);
+ now -= base;
+ tp->sec = (uint) (now / 1000);
+ tp->msec = (uint) (now % 1000);
+
+#if UNUSED
+{
+ static int64 start;
+
+ if (start == 0) {
+ start = now;
+ }
+ if (now < start) {
+ mprLog(ctx, 0, "TIME WENT BACKWARDS");
+ mprLog(ctx, 0, "start %Ld", start);
+ mprLog(ctx, 0, "now %Ld", now);
+ }
+ mprLog(ctx, 0, "getTime %Ld", now);
+ start = now;
+}
+#endif
+
+ return tp;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of localtime
+ */
+
+struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now)
+{
+ struct tm *tbuf;
+ mprGlobalLock(ctx);
+ tbuf = localtime(now);
+ *timep = *tbuf;
+ mprGlobalUnlock(ctx);
+
+ return timep;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of gmtime
+ */
+
+struct tm *mprGmtime(MprCtx ctx, time_t *now, struct tm *timep)
+{
+ struct tm *tbuf;
+ tbuf = gmtime(now);
+ *timep = *tbuf;
+
+ return timep;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of ctime
+ */
+
+int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer)
+{
+ char *cp;
+ int len;
+
+ mprAssert(buf);
+
+ mprGlobalLock(ctx);
+
+ cp = ctime(timer);
+ if ((int) strlen(cp) >= bufsize) {
+ mprStrcpy(buf, bufsize, "WONT FIT");
+ mprAssert(0);
+ mprGlobalUnlock(ctx);
+ return MPR_ERR_WONT_FIT;
+ }
+
+ len = mprStrcpy(buf, bufsize, cp);
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = '\0';
+ }
+
+ mprGlobalUnlock(ctx);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of asctime
+ */
+
+int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr)
+{
+ char *cp;
+
+ mprAssert(buf);
+ mprGlobalLock(ctx);
+ cp = asctime(timeptr);
+ if ((int) strlen(cp) >= bufsize) {
+ mprAssert(0);
+ mprGlobalUnlock(ctx);
+ return MPR_ERR_WONT_FIT;
+ }
+ mprStrcpy(buf, bufsize, cp);
+ mprGlobalUnlock(ctx);
+
+ return strlen(buf);
+}
+
+/******************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * 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/mpr/files b/source4/lib/appweb/ejs-2.0/mpr/files
new file mode 100644
index 0000000000..290c9ce790
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/files
@@ -0,0 +1,14 @@
+${BLD_OBJ_DIR}/mpr${BLD_OBJ}
+${BLD_OBJ_DIR}/mprAlloc${BLD_OBJ}
+${BLD_OBJ_DIR}/mprArray${BLD_OBJ}
+${BLD_OBJ_DIR}/mprBuf${BLD_OBJ}
+${BLD_OBJ_DIR}/mprFile${BLD_OBJ}
+${BLD_OBJ_DIR}/mprGenFile${BLD_OBJ}
+${BLD_OBJ_DIR}/mprGenTime${BLD_OBJ}
+${BLD_OBJ_DIR}/mprLock${BLD_OBJ}
+${BLD_OBJ_DIR}/mprLog${BLD_OBJ}
+${BLD_OBJ_DIR}/mprPlatform${BLD_OBJ}
+${BLD_OBJ_DIR}/mprPrintf${BLD_OBJ}
+${BLD_OBJ_DIR}/mprString${BLD_OBJ}
+${BLD_OBJ_DIR}/mprSymbol${BLD_OBJ}
+${BLD_OBJ_DIR}/mprTime${BLD_OBJ}
diff --git a/source4/lib/appweb/ejs-2.0/mpr/mpr.c b/source4/lib/appweb/ejs-2.0/mpr/mpr.c
new file mode 100644
index 0000000000..163b51eccf
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mpr.c
@@ -0,0 +1,340 @@
+/**
+ * @file mpr.c
+ * @brief Mpr initialization
+ * @overview
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 **********************************/
+/*
+ * We need to use the underlying str(cpy) routines to implement our safe
+ * alternatives
+ */
+#if !DOXYGEN
+#define UNSAFE_FUNCTIONS_OK 1
+#endif
+
+#include "mpr.h"
+
+/******************************************************************************/
+/*
+ * Initialize the MPR. Create the top level memory context. This routine is
+ * the first call an MPR application must do. If using MprServices, the
+ * creation of an Mpr object will call this routine.
+ */
+
+MprApp *mprInit(MprAllocCback cback)
+{
+ return mprInitEx(cback, 0);
+}
+
+/******************************************************************************/
+/*
+ * Add a shell parameter then do the regular init
+ */
+
+MprApp *mprInitEx(MprAllocCback cback, void *shell)
+{
+ MprApp *app;
+
+ app = (MprApp*) mprAllocInit(cback);
+
+ mprAssert(app);
+ if (app == 0) {
+ return 0;
+ }
+
+ app->name = mprStrdup(app, BLD_PRODUCT);
+ app->title = mprStrdup(app, BLD_NAME);
+ app->version = mprStrdup(app, BLD_VERSION);
+
+ mprSetShell(app, shell);
+
+ app->table = mprCreateSymbolTable(app, 0);
+
+ if (mprStartFileServices(app) < 0) {
+ mprAllocTerm(app);
+ return 0;
+ }
+
+#if BLD_FEATURE_MULTITHREAD
+ mprInitThreads(app);
+#endif
+
+ /*
+ * See if any of the preceeding allocations failed
+ */
+ if (mprGetAllocErrors(app) > 0) {
+ mprAllocTerm(app);
+ return 0;
+ }
+
+ /*
+ * Mark all blocks allocated so far as required. They will then be
+ * omitted from leak reports.
+ */
+ mprSetRequiredAlloc(app, 1);
+
+ return app;
+}
+
+/******************************************************************************/
+/*
+ * Terminate the MPR. If doStats is true, then output a memory allocation
+ * report.
+ */
+
+void mprTerm(MprApp *app, bool doStats)
+{
+#if BLD_FEATURE_ALLOC_STATS
+ if (doStats) {
+ mprPrintAllocReport(app, 1, "MPR Memory Allocation Report");
+ }
+#endif
+
+#if BLD_FEATURE_MULTITHREAD
+ mprTermThreads(app);
+#endif
+
+ mprStopFileServices(app);
+
+#if BLD_DEBUG
+ mprValidateAllocTree(app);
+#endif
+ mprAllocTerm(app);
+}
+
+/******************************************************************************/
+
+bool mprIsExiting(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ if (app == 0) {
+ return 1;
+ }
+ return app->flags & MPR_APP_EXITING;
+}
+
+/******************************************************************************/
+
+int mprHasAllocError(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ if (app == 0) {
+ return 1;
+ }
+
+ return app->flags & MPR_APP_ALLOC_ERROR;
+}
+
+/******************************************************************************/
+
+void mprSignalExit(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ app->flags |= MPR_APP_EXITING;
+}
+
+/******************************************************************************/
+
+void mprSignalAllocError(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ app->flags |= MPR_APP_ALLOC_ERROR;
+}
+
+/******************************************************************************/
+
+int mprSetAppName(MprCtx ctx, const char *name, const char *title,
+ const char *version)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+
+ if (name) {
+ mprFree(app->name);
+ if ((app->name = mprStrdup(ctx, name)) == 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ }
+
+ if (title) {
+ mprFree(app->title);
+ if ((app->title = mprStrdup(ctx, title)) == 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ }
+
+ if (version) {
+ mprFree(app->version);
+ if ((app->version = mprStrdup(ctx, version)) == 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+const char *mprGetAppName(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ return app->name;
+}
+
+/******************************************************************************/
+
+const char *mprGetAppTitle(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ return app->title;
+}
+
+/******************************************************************************/
+
+const char *mprGetAppVersion(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ return app->version;
+}
+
+/******************************************************************************/
+
+int mprSetKeyValue(MprCtx ctx, const char *key, void *ptr)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ if (mprInsertSymbol(app->table, key, ptr) == 0) {
+ return MPR_ERR_CANT_WRITE;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprRemoveKeyValue(MprCtx ctx, const char *key)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ return mprRemoveSymbol(app->table, key);
+}
+
+/******************************************************************************/
+
+void *mprGetKeyValue(MprCtx ctx, const char *key)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ return mprLookupSymbol(app->table, key);
+}
+
+/******************************************************************************/
+
+bool mprGetDebugMode(MprCtx ctx)
+{
+ return mprGetApp(ctx)->debugMode;
+}
+
+/******************************************************************************/
+
+void mprSetDebugMode(MprCtx ctx, bool on)
+{
+ mprGetApp(ctx)->debugMode = on;
+}
+
+/******************************************************************************/
+
+void mprSetLogHandler(MprCtx ctx, MprLogHandler handler)
+{
+ mprGetApp(ctx)->logHandler = handler;
+}
+
+/******************************************************************************/
+
+MprLogHandler mprGetLogHandler(MprCtx ctx)
+{
+ return mprGetApp(ctx)->logHandler;
+}
+
+#if UNUSED
+/******************************************************************************/
+
+void mprSetMprInstance(MprCtx ctx, void *mprInstance)
+{
+ mprGetApp(ctx)->mprInstance = mprInstance;
+}
+
+/******************************************************************************/
+
+void *mprGetMprInstance(MprCtx ctx)
+{
+ return mprGetApp(ctx)->mprInstance;
+}
+
+#endif
+/******************************************************************************/
+
+const char *mprCopyright()
+{
+ return "Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.";
+}
+
+/******************************************************************************/
+
+/*
+ * 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/mpr/mpr.h b/source4/lib/appweb/ejs-2.0/mpr/mpr.h
new file mode 100644
index 0000000000..67505a6e01
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mpr.h
@@ -0,0 +1,1027 @@
+/*
+ * @file mpr.h
+ * @brief Header for the Mbedthis Portable Runtime (MPR) Base.
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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
+ */
+/******************************* Documentation ********************************/
+/*
+ * See mpr.dox for additional documentation.
+ */
+
+/******************************************************************************/
+
+#ifndef _h_MPR
+#define _h_MPR 1
+
+/***********************************Includes **********************************/
+
+#include "mprOs.h"
+
+/******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/********************************** Constants *********************************/
+
+#if BLD_FEATURE_SQUEEZE
+#if BREW || DOXYGEN
+/*
+ * Maximum length of a file path name. Reduced from the system maximum to
+ * save memory space.
+ */
+#define MPR_MAX_FNAME 64 /**< Reasonable filename size */
+#define MPR_MAX_PATH 64 /**< Reasonable path name size */
+#define MPR_DEFAULT_STACK (16 * 1024) /**< Default stack size */
+#else
+#define MPR_MAX_FNAME 128 /**< Reasonable filename size */
+#define MPR_MAX_PATH 256 /**< Reasonable path name size */
+#define MPR_DEFAULT_STACK (32 * 1024) /**< Default stack size */
+#endif
+/*
+ * Reasonable length of a file name used by the product. Use where you know
+ * the expected file name and it is certain to be less than this limit.
+ */
+#define MPR_DEFAULT_ALLOC 64 /**< Default small alloc size */
+#define MPR_DEFAULT_HASH_SIZE 23 /**< Default size of hash table */
+#define MPR_MAX_ARGC 32 /**< Reasonable max of args */
+#define MPR_MAX_STRING 512 /**< Maximum (stack) string size */
+#define MPR_MAX_LOG_STRING 512 /**< Maximum log message */
+#define MPR_MAX_URL 256 /**< Reasonable size of a URL */
+#define MPR_BUFSIZE 512 /**< Reasonable size for buffers */
+#define MPR_SLAB_STR_MAX 32 /**< Size of string slab blocks */
+#define MPR_SLAB_STR_INC 32 /**< Pre-allocate increment */
+#define MPR_SLAB_DEFAULT_INC 8 /**< Default pre-allocate inc */
+#define MPR_ARRAY_INCR 8 /**< Default array growth inc */
+#define MPR_BUF_INCR 1024 /**< Default array growth inc */
+#define MPR_MAX_BUF (1024*4096) /**< Default array growth inc */
+
+#define MPR_BLK_HDR_SIZE ((sizeof(struct MprBlk) + 3) & ~3)
+
+#else
+#define MPR_MAX_FNAME 256
+#define MPR_MAX_PATH 1024
+#define MPR_DEFAULT_ALLOC 256
+#define MPR_DEFAULT_HASH_SIZE 43
+#define MPR_DEFAULT_STACK (64 * 1024)
+#define MPR_MAX_ARGC 128
+#define MPR_MAX_STRING 4096
+#define MPR_MAX_LOG_STRING 8192
+#define MPR_MAX_URL 1024
+#define MPR_BUFSIZE 1024
+#define MPR_SLAB_STR_MAX 32
+#define MPR_SLAB_STR_INC 64
+#define MPR_SLAB_DEFAULT_INC 16
+#define MPR_ARRAY_INCR 16
+#define MPR_BUF_INCR 1024
+#define MPR_MAX_BUF (1024*4096)
+
+#define MPR_BLK_HDR_SIZE ((sizeof(struct MprBlk) + 15) & ~15)
+#endif
+
+/**
+ * Maximum size of a host name string
+ */
+#define MPR_MAX_IP_NAME 64
+
+/**
+ * Maximum size of an IP address
+ */
+#define MPR_MAX_IP_ADDR 16
+
+/**
+ * Maximum size of an IP address including port number
+ */
+#define MPR_MAX_IP_ADDR_PORT 32
+
+#define MPR_MAX_SLAB 16 /* Slabs from 32-512 bytes */
+
+#define MPR_MAX_TIME_SYNC (10 * 1000) /* Time sync adjustments */
+
+/**
+ * @overview Memory context type
+ * @description Blocks of memory are allocated using a memory context
+ * as the parent with the \ref MprApp structure being the root of the
+ * tree. Any allocated memory block may serve as the memory context for
+ * subsequent memory allocations. Freeing a block via \ref mprFree will
+ * release the allocated block and all child blocks.
+ * @stability Prototype.
+ * @library libmpr.
+ * @see mprInit, mprAlloc, mprFree
+ */
+typedef const void *MprCtx;
+
+/*
+ * Allocated memory destructor type
+ */
+typedef int (*MprDestructor)(void *);
+
+/******************************** Error Codes *********************************/
+
+/*
+ * Standard MPR return and error codes
+ */
+
+#define MPR_ERR_OK (0)
+/**< Success */
+
+#define MPR_ERR_BASE (-200)
+/**< Base error code */
+
+#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1)
+/**< General error */
+#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2)
+/**< Action aborted */
+#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3)
+/**< Item already exists */
+#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4)
+/**< Bad arguments or paramaeters */
+#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5)
+/**< Bad input format */
+#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6)
+#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7)
+/**< Module is in a bad state */
+#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8)
+/**< Input has bad syntax */
+#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9)
+#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10)
+#define MPR_ERR_BUSY (MPR_ERR_BASE - 11)
+#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12)
+/**< Can't access the file or resource */
+#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13)
+#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14)
+/**< Can't create the file or resource */
+#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15)
+#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16)
+/**< Can't open the file or resource */
+#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17)
+/**< Can't read from the file or resource */
+#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18)
+/**< Can't write to the file or resource */
+#define MPR_ERR_DELETED (MPR_ERR_BASE - 19)
+#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20)
+#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21)
+#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22)
+/**< Module or resource is not initialized */
+#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23)
+#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24)
+/**< The operation timed out */
+#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25)
+#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26)
+#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27)
+#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28)
+#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29)
+// MOB -- rename NO_MEMORY
+#define MPR_ERR_MEMORY (MPR_ERR_BASE - 30)
+#define MPR_ERR_CANT_DELETE (MPR_ERR_BASE - 31)
+#define MPR_ERR_MAX (MPR_ERR_BASE - 32)
+
+/*
+ * Standard logging trace levels are 0 to 9 with 0 being the most verbose.
+ * the These are ored with the error source and type flags. The MPR_LOG_MASK
+ * is used to extract the trace level from a flags word. We expect most apps
+ * to run with level 2 trace enabled.
+ */
+#define MPR_ERROR 1 /**< Hard error trace level */
+#define MPR_WARN 2 /**< Soft warning trace level */
+#define MPR_CONFIG 2 /**< Configuration settings trace level. */
+#define MPR_INFO 3 /**< Informational trace only */
+#define MPR_DEBUG 4 /**< Debug information trace level */
+#define MPR_VERBOSE 9 /**< Highest level of trace */
+#define MPR_LEVEL_MASK 0xf /**< Level mask */
+
+/*
+ * Error source flags
+ */
+#define MPR_ERROR_SRC 0x10 /**< Originated from mprError */
+#define MPR_LOG_SRC 0x20 /**< Originated from mprLog */
+#define MPR_ASSERT_SRC 0x40 /**< Originated from mprAssert */
+#define MPR_FATAL_SRC 0x80 /**< Fatal error. Log and exit */
+
+/*
+ * Log message type flags. Specify what kind of log / error message it is.
+ * Listener handlers examine this flag to determine if they should process
+ * the message.Assert messages are trapped when in DEV mode. Otherwise ignored.
+ */
+#define MPR_LOG_MSG 0x100 /**< Log trace message - not an error */
+#define MPR_ERROR_MSG 0x200 /**< General error */
+#define MPR_ASSERT_MSG 0x400 /**< Assert flags -- trap in debugger */
+#define MPR_USER_MSG 0x800 /**< User message */
+
+/*
+ * Log output modifiers
+ */
+#define MPR_RAW 0x1000 /**< Raw trace output */
+
+/*
+ * Error line number information.
+ */
+#define MPR_LINE(s) #s
+#define MPR_LINE2(s) MPR_LINE(s)
+#define MPR_LINE3 MPR_LINE2(__LINE__)
+#define MPR_LOC __FILE__ ":" MPR_LINE3
+
+/*
+ * Macros to pass file and line number information
+ * Use MPR_LOC_ARGS in normal user code.
+ * Use MPR_LOC_DEC in declarations.
+ * Use MPR_LOC_PASS in layered APIs to pass original line info down.
+ */
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+#define MPR_LOC_ARGS(ctx) ctx, MPR_LOC
+#define MPR_LOC_DEC(ctx, loc) MprCtx ctx, const char *loc
+#define MPR_LOC_PASS(ctx, loc) ctx, loc
+#else
+#define MPR_LOC_ARGS(ctx) ctx
+#define MPR_LOC_DEC(ctx, loc) MprCtx ctx
+#define MPR_LOC_PASS(ctx, loc) ctx
+#endif
+
+/******************************* Debug and Assert *****************************/
+
+extern void mprBreakpoint(const char *loc, const char *msg);
+
+#if BLD_FEATURE_ASSERT
+ #define mprAssert(C) if (C) ; else mprStaticAssert(MPR_LOC, #C)
+#else
+ #define mprAssert(C) if (1) ; else
+#endif
+
+/********************************* Safe Strings *******************************/
+/*
+ * Unsafe functions that should not be used. Define UNSAFE_STRINGS_OK before
+ * including mpr.h if you really want to use these functions. A better approach
+ * is to undefine them just prior to using them in your C/C++ source file.
+ */
+#if BLD_FEATURE_SAFE_STRINGS
+
+#if BLD_FEATURE_PHP4_MODULE || BLD_FEATURE_PHP5_MODULE
+ #ifndef UNSAFE_FUNCTIONS_OK
+ #define UNSAFE_FUNCTIONS_OK 1
+ #endif
+#endif
+
+#ifndef UNSAFE_FUNCTIONS_OK
+ #define sprintf UseMprSprintfInstead
+ #define fprintf UseMprFprintfInstead
+ #define vsprintf UseMprVsprintfInstead
+ #define strtok UseMprStrTokInstead
+ #define gethostbyname UseMprGetHostByNameInstead
+ #define ctime UseMprCtimeInstead
+ #define asctime UseMprAsctimeInstead
+ #define localtime UseMprLocaltimeInstead
+ #define gmtime UseMprGmtimeInstead
+ #define malloc UseMprMallocInstead
+ #define free UseMprFreeInstead
+ #define realloc UseMprReallocInstead
+ #define strncpy UseMprStrcpyInstead
+ #define inet_ntoa UseMprInetToStrInstead
+
+#if !BREW
+ #define printf UseMprPrintfInstead
+#endif
+
+ #if FUTURE
+ #define strlen UseMprStrlenInstead
+ #define strcpy UseMprStrcpyInstead
+ #endif
+
+#endif /* UNSAFE_FUNCTIONS_OK */
+#endif /* BLD_FEATURE_SAFE_STRINGS */
+
+/******************************************************************************/
+
+struct MprBuf;
+typedef int (*MprBufProc)(struct MprBuf* bp, void *arg);
+
+/**
+ * @overview Dynamic buffer structure
+ * @description MprBuf is a flexible, dynamic growable buffer structure. It
+ * utilizes a ring buffer mechanism and is suitable for high performance
+ * buffering in a variety of situations.
+ * @stability Prototype.
+ * @library libmpr.
+ * @see mprCreateBuf, mprFree, MprArray
+ */
+typedef struct MprBuf {
+ uchar *buf; /* Actual buffer for data */
+ uchar *endbuf; /* Pointer one past the end of buffer */
+ uchar *start; /* Pointer to next data char */
+ uchar *end; /* Pointer one past the last data chr */
+ int buflen; /* Current size of buffer */
+ int maxsize; /* Max size the buffer can ever grow */
+ int growBy; /* Next growth increment to use */
+ MprBufProc refillProc; /* Auto-refill procedure */
+ void *refillArg; /* Refill arg */
+} MprBuf;
+
+/**
+ * @overview File structure
+ * @description MprFile is the cross platform File I/O abstraction control
+ * structure.
+ * @stability Prototype.
+ * @library libmpr.
+ * @see mprOpen, mprClose, mprRead, mprWrite
+ */
+typedef struct MprFile
+{
+ MprBuf *buf; /* Buffer for I/O */
+#if BREW
+ IFile *fd; /* File handle */
+#else
+ int fd;
+#endif
+} MprFile;
+
+/**
+ * File information structure
+ * @overview File information structure
+ * @description MprFileInfo is the cross platform File information structure.
+ * @stability Prototype.
+ * @see mprGetFileInfo, mprOpen, mprClose, mprRead, mprWrite
+ */
+typedef struct MprFileInfo
+{
+ uint size; /* File length */
+ uint ctime; /* Create time */
+ uint mtime; /* Modified time */
+ uint inode; /* Inode number */
+ int isDir; /* Set if directory */
+ int isReg; /* Set if a regular file */
+} MprFileInfo;
+
+/**
+ * @overview Mpr time structure.
+ * @description MprTime is the cross platform time abstraction structure.
+ * @stability Prototype.
+ * @library libmpr.
+ * @see mprGetTime
+ */
+typedef struct MprTime
+{
+ uint sec; /* Seconds */
+ uint msec; /* Milliseconds */
+} MprTime;
+
+
+/**
+ * @overview Generic array type
+ * @description The MprArray is a dynamic growable array suitable for storing
+ * pointers to arbitrary objects.
+ * @stability Prototype.
+ * @library libmpr.
+ * @see mprCreateItemArray, mprFree, MprBuf
+ */
+typedef struct MprArray
+{
+ int capacity; /* Current capacity of the array */
+ int length; /* Count of used items */
+ int incr; /* Growth increment */
+ int maxSize; /* Maximum capacity */
+ void **items;
+} MprArray;
+
+
+#if BLD_FEATURE_MULTITHREAD
+/**
+ * @overview Multithreading lock control structure
+ * @description MprLock is used for multithread locking in multithreaded
+ * applications.
+ * @library libmpr.
+ * @see mprCreateLock, mprDestroyLock, mprLock, mprUnlock
+ */
+typedef struct
+{
+ #if WIN
+ CRITICAL_SECTION cs; /* O/S critical section */
+ #endif
+ #if LINUX || MACOSX || SOLARIS
+ pthread_mutex_t cs; /* O/S critical section */
+ #endif
+ #if VXWORKS
+ SEM_ID cs; /* Semaphore */
+ #endif
+} MprLock;
+#endif
+
+/*
+ * Error and Logging callback
+ */
+typedef void (*MprLogHandler)(MPR_LOC_DEC(ctx, loc), int flags,
+ int level, const char *msg);
+
+/*
+ * Symbol table
+ * MOB -- rename hash
+ */
+typedef struct MprSymbol
+{
+ struct MprSymbol *next; /* Next symbol in hash chain */
+ char *key; /* Symbol key */
+ void *data; /* Pointer to symbol data */
+ int bucket; /* Hash bucket index */
+} MprSymbol;
+
+typedef struct MprSymbolTable
+{
+ MprSymbol **buckets;
+ int hashSize; /* Size of the buckets array */
+ int count; /* Number of symbols in the table */
+} MprSymbolTable;
+
+
+/*
+ * Memory allocation error callback
+ */
+struct MprApp;
+typedef int (*MprAllocCback)(struct MprApp *app, uint size, uint total,
+ bool granted);
+
+
+/*
+ * Slab block pointer links
+ */
+typedef struct MprSlabBlock {
+ struct MprSlabBlock *next;
+} MprSlabBlock;
+
+
+#if BLD_FEATURE_ALLOC_STATS
+/*
+ * Memory Slab Statistics
+ */
+typedef struct MprSlabStats {
+ uint allocCount; /* Number of allocated blocks */
+ uint freeCount; /* Number of blocks on the slab freelist */
+ uint peakAllocCount; /* Peak allocated */
+ uint totalAllocCount; /* Total count of allocation calls */
+ uint peakFreeCount; /* Peak on the free list */
+ MprSlabBlock *next;
+} MprSlabStats;
+#endif
+
+
+/*
+ * Slab control structure
+ */
+typedef struct MprSlab {
+ MprSlabBlock *next;
+ uint preAllocateIncr; /* Pre-allocation increment */
+#if BLD_FEATURE_ALLOC_STATS
+ MprSlabStats stats;
+#endif
+} MprSlab;
+
+/*
+ * Allocation stats (kept even in production code so we can detect memory
+ * allocation failures)
+ */
+typedef struct MprAllocStats
+{
+ uint bytesAllocated; /* Bytes currently allocated */
+ uint peakAllocated; /* Peak bytes allocated */
+ uint allocCount; /* Number of allocated blocks */
+ uint redLine; /* Warn above this level */
+ uint maxMemory; /* Max memory to allocate */
+ uint errors; /* Allocation errors */
+} MprAllocStats;
+
+/*
+ * Memory allocation control
+ */
+
+typedef struct MprAlloc {
+ MprSlab *slabs; /* Array[MPR_MAX_SLAB] of MprSlab */
+ MprAllocCback cback; /* Memory allocation callback */
+ MprAllocStats stats; /* Keep stats even in release */
+ int inAllocException; /* Recursive protect */
+} MprAlloc;
+
+
+/*
+ * MprApp State Flags
+ */
+#define MPR_APP_EXITING 0x1 /* App is exiting */
+#define MPR_APP_ALLOC_ERROR 0x2 /* App has allocation error */
+
+/* MOB -- temporary */
+#define MPR_APP_NEED_GC 0x4 /* App needs GC */
+
+/**
+ * @overview Primary MPR application control structure
+ * @description The MprApp structure stores critical application state
+ * information and is the root memory allocation context block. It is
+ * used as the MprCtx context for other memory allocations and is thus
+ * the ultimate parent of all allocated memory.
+ * \n\n
+ * The MprApp structure is allocated by the mprInit API.
+ */
+typedef struct MprApp
+{
+ uint magic; /* Corruption protection */
+ MprFile *console; /* Stdout file */
+ bool debugMode; /* Run in debug mode (no timers) */
+ MprFile *error; /* Stderr file */
+ int logLevel; /* Log trace level */
+ MprFile *logFile; /* Log file */
+ MprLogHandler logHandler; /* Current log handler callback */
+ MprSymbolTable *table;
+ char *name; /* Product name */
+ char *title; /* Product title */
+ char *version; /* Product version */
+
+#if BREW
+ uint classId; /* Brew class ID */
+ IShell *shell; /* Brew shell object */
+ IDisplay *display; /* Brew display object */
+ IFileMgr *fileMgr; /* File manager */
+ ITAPI *tapi; /* TAPI object */
+ int displayHeight; /* Display height */
+ int displayWidth; /* Display width */
+ char *args; /* Command line args */
+#endif
+
+ void *stackStart; /* Start of app stack */
+ uint maxStack; /* Max stack size recorded */
+
+ MprAlloc alloc; /* Memory allocation data */
+ int flags; /* App state flags */
+
+#if BLD_FEATURE_MULTITHREAD
+ MprLock *globalLock;
+ MprLock *allocLock;
+#endif
+} MprApp;
+
+
+/*
+ * String type. Minimum size is 8 words (32 bytes).
+ */
+#define MPR_MAX_INLINE_STR 24
+
+
+/*
+ * The block header structure for all allocated memory blocks (32 bytes)
+ * WARNING: Don't increase the size of this structure. It just fits into
+ * 32 bytes currently. Alignment requirements will double this size if you
+ * add one byte!
+ */
+typedef struct MprBlk
+{
+ MprApp *app; /* app is the top level alloc context */
+ struct MprBlk *parent; /* Parent block */
+ struct MprBlk *children; /* First child block */
+ struct MprBlk *next; /* Next sibling */
+ struct MprBlk *prev; /* Previous sibling */
+ MprDestructor destructor; /* Destructor function (optional) */
+ uint size; /* Size of block sans HDR_SIZE */
+ uint flags; /* Allocation flags and magic number */
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ const char *location; /* Allocating code (file + line) */
+#endif
+} MprBlk;
+
+/******************************************************************************/
+/****************************** Internal Prototypes ***************************/
+/******************************************************************************/
+
+extern void mprSignalAllocError(MprCtx ctx);
+
+/******************************************************************************/
+/********************************** Prototypes ********************************/
+/******************************************************************************/
+
+extern MprApp *mprInit(MprAllocCback cback);
+extern MprApp *mprInitEx(MprAllocCback cback, void *shell);
+extern void mprTerm(MprApp *app, bool doStats);
+extern void mprSignalExit(MprCtx ctx);
+extern bool mprIsExiting(MprCtx ctx);
+extern bool mprHasAllocError(MprCtx ctx);
+
+#if BLD_DEBUG && UNUSED
+extern MprApp *mprGetApp(MprCtx ctx);
+#else
+#define mprGetApp(ctx) \
+ (((MprBlk*) ((char*) ctx - MPR_BLK_HDR_SIZE))->app)
+#endif
+
+/******************************************************************************/
+
+extern int mprSetKeyValue(MprCtx ctx, const char *key, void *ptr);
+/* MOB -- should this be delete or remove or unset */
+extern int mprRemoveKeyValue(MprCtx ctx, const char *key);
+extern void *mprGetKeyValue(MprCtx ctx, const char *key);
+/* MOB -- should be setAppName, getAppName */
+extern int mprSetAppName(MprCtx ctx, const char *name, const char *title,
+ const char *version);
+extern const char *mprGetAppName(MprCtx ctx);
+extern const char *mprGetAppTitle(MprCtx ctx);
+extern const char *mprGetAppVersion(MprCtx ctx);
+
+/*
+ * File services
+ */
+extern void mprStopFileServices(MprCtx ctx);
+extern int mprStartFileServices(MprCtx ctx);
+
+/*
+ * Item Array
+ */
+#define mprCreateItemArray(ctx, initialSize, maxSize) \
+ mprCreateItemArrayInternal(MPR_LOC_ARGS(ctx), initialSize, \
+ maxSize)
+
+extern MprArray *mprCreateItemArrayInternal(MPR_LOC_DEC(ctx, loc),
+ int initialSize, int maxSize);
+/* MOB -- should be insert not add/delete or insert / remove */
+extern int mprAddItem(MprArray *array, void *item);
+extern void mprClearItems(MprArray *array);
+extern void mprClearAndFreeItems(MprArray *array);
+extern int mprFindItem(MprArray *array, void *item);
+extern void *mprGetFirstItem(MprArray *array, int *lastIndex);
+extern void *mprGetItem(MprArray *array, int index);
+extern int mprGetItemCapacity(MprArray *array);
+extern int mprGetItemCount(MprArray *array);
+extern void *mprGetNextItem(MprArray *array, int *lastIndex);
+extern void *mprGetPrevItem(MprArray *array, int *lastIndex);
+extern int mprRemoveItem(MprArray *array, void *item);
+extern int mprRemoveItemByIndex(MprArray *array, int index);
+extern int mprRemoveRangeOfItems(MprArray *array, int start, int end);
+
+
+/*
+ * Printf replacements
+ */
+extern int mprSprintf(char *buf, int maxSize, const char *fmt, ...)
+ PRINTF_ATTRIBUTE(3,4);
+extern int mprVsprintf(char *buf, int maxSize, const char *fmt,
+ va_list arg) PRINTF_ATTRIBUTE(3,0);
+extern char *mprItoa(char *buf, int size, int value);
+extern int mprAtoi(const char *str, int radix);
+
+extern int mprPrintf(MprCtx ctx, const char *fmt, ...)
+ PRINTF_ATTRIBUTE(2,3);
+/* MOB -- NEED DOC */
+extern int mprErrorPrintf(MprCtx ctx, const char *fmt, ...)
+ PRINTF_ATTRIBUTE(2,3);
+extern int mprStaticPrintf(MprCtx ctx, const char *fmt, ...)
+ PRINTF_ATTRIBUTE(2,3);
+extern int mprPrintfError(MprCtx ctx, const char *fmt, ...)
+ PRINTF_ATTRIBUTE(2,3);
+extern int mprFprintf(MprFile *file, const char *fmt, ...)
+ PRINTF_ATTRIBUTE(2,3);
+
+/*
+ * Safe string routines
+ */
+extern char *mprGetWordTok(char *buf, int bufsize, const char *str,
+ const char *delim, const char **tok);
+extern int mprMemcpy(char *dest, int destMax, const char *src,
+ int nbytes);
+extern int mprStrcat(char *dest, int max, const char *delim,
+ const char *src, ...);
+extern int mprStrcpy(char *dest, int destMax, const char *src);
+
+extern int mprStrcmpAnyCase(const char *str1, const char *str2);
+extern int mprStrcmpAnyCaseCount(const char *str1, const char *str2,
+ int len);
+extern int mprStrlen(const char *src, int max);
+
+extern char *mprStrLower(char *str);
+extern char *mprStrUpper(char *str);
+extern char *mprStrTrim(char *str, const char *set);
+extern char *mprStrTok(char *str, const char *delim, char **last);
+
+/*
+ * Symbol table
+ */
+extern MprSymbolTable *mprCreateSymbolTable(MprCtx ctx, int hashSize);
+extern MprSymbol *mprGetFirstSymbol(MprSymbolTable *table);
+extern MprSymbol *mprGetNextSymbol(MprSymbolTable *table, MprSymbol *last);
+extern int mprGetSymbolCount(MprSymbolTable *table);
+extern MprSymbol *mprInsertSymbol(MprSymbolTable *table, const char *key,
+ void *ptr);
+extern void *mprLookupSymbol(MprSymbolTable *table, const char *key);
+extern int mprRemoveSymbol(MprSymbolTable *table, const char *key);
+
+/*
+ * File I/O support
+ */
+extern void mprClose(MprFile *file);
+extern int mprDelete(MprCtx ctx, const char *path);
+extern int mprDeleteDir(MprCtx ctx, const char *path);
+extern int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info);
+extern char *mprGets(MprFile *file, char *buf, uint size);
+extern int mprMakeDir(MprCtx ctx, const char *path, int perms);
+extern MprFile *mprOpen(MprCtx ctx, const char *path, int omode, int perms);
+extern int mprPuts(MprFile *file, const char *buf, uint size);
+extern int mprRead(MprFile *file, void *buf, uint size);
+extern int mprSeek(MprFile *file, int seekType, long distance);
+extern int mprWrite(MprFile *file, const void *buf, uint count);
+
+extern int mprMakeTempFileName(MprCtx ctx, char *buf, int bufsize,
+ const char *tmpDir);
+
+
+/*
+ * Error handling and logging
+ */
+extern void mprSetLogHandler(MprCtx ctx, MprLogHandler handler);
+extern MprLogHandler mprGetLogHandler(MprCtx ctx);
+
+extern void mprAssertError(MPR_LOC_DEC(ctx, loc), const char *msg);
+extern void mprError(MPR_LOC_DEC(ctx, loc),
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+extern void mprFatalError(MPR_LOC_DEC(ctx, loc),
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+extern void mprLog(MprCtx ctx, int level,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+extern void mprRawLog(MprCtx ctx, const char *fmt, ...);
+extern void mprStaticAssert(const char *loc, const char *msg);
+extern void mprStaticError(MPR_LOC_DEC(ctx, loc),
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+extern void mprUserError(MPR_LOC_DEC(ctx, loc),
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+
+/*
+ * Dynamic Buffering routines
+ */
+extern MprBuf *mprCreateBuf(MprCtx ctx, int initialSize, int maxSize);
+extern char *mprStealBuf(MprCtx ctx, MprBuf *bp);
+extern void mprAddNullToBuf(MprBuf *bp);
+extern void mprAdjustBufStart(MprBuf *bp, int size);
+extern void mprAdjustBufEnd(MprBuf *bp, int size);
+extern void mprCopyBufDown(MprBuf *bp);
+extern void mprFlushBuf(MprBuf *bp);
+extern int mprGetCharFromBuf(MprBuf *bp);
+extern int mprGetBlockFromBuf(MprBuf *bp, uchar *buf, int len);
+extern int mprGetBufLength(MprBuf *bp);
+extern int mprGetBufLinearSpace(MprBuf *bp);
+extern int mprGetBufLinearData(MprBuf *bp);
+extern char *mprGetBufOrigin(MprBuf *bp);
+extern int mprGetBufSize(MprBuf *bp);
+extern int mprGetBufSpace(MprBuf *bp);
+extern char *mprGetBufStart(MprBuf *bp);
+extern char *mprGetBufEnd(MprBuf *bp);
+extern int mprInsertCharToBuf(MprBuf *bp, int c);
+extern int mprLookAtNextCharInBuf(MprBuf *bp);
+extern int mprLookAtLastCharInBuf(MprBuf *bp);
+extern int mprPutCharToBuf(MprBuf *bp, int c);
+extern int mprPutBlockToBuf(MprBuf *bp, const char *str, int size);
+extern int mprPutIntToBuf(MprBuf *bp, int i);
+extern int mprPutStringToBuf(MprBuf *bp, const char *str);
+extern int mprPutFmtStringToBuf(MprBuf *bp, const char *fmt, ...);
+extern int mprRefillBuf(MprBuf *bp);
+extern void mprResetBufIfEmpty(MprBuf *bp);
+extern void mprSetBufSize(MprBuf *bp, int initialSize, int maxSize);
+extern MprBufProc mprGetBufRefillProc(MprBuf *bp);
+extern void mprSetBufRefillProc(MprBuf *bp, MprBufProc fn, void *arg);
+
+/*
+ * General other xPlatform routines
+ */
+extern const char *mprGetBaseName(const char *name);
+extern bool mprGetDebugMode(MprCtx ctx);
+extern char *mprGetDirName(char *buf, int bufsize, const char *path);
+extern char *mprGetFullPathName(char *buf, int buflen, const char *path);
+extern int mprGetLogLevel(MprCtx ctx);
+extern int mprGetOsError();
+
+
+extern int mprMakeArgv(MprCtx ctx, const char *prog, const char *cmd,
+ char ***argv, int *argc);
+extern int mprMakeDirPath(MprCtx ctx, const char *path);
+extern void mprSetDebugMode(MprCtx ctx, bool on);
+extern void mprSetLogLevel(MprCtx ctx, int level);
+extern void mprSleep(MprCtx ctx, int msec);
+extern void mprSetShell(MprCtx ctx, void *shell);
+extern void *mprGetShell(MprCtx ctx);
+extern void mprSetClassId(MprCtx ctx, uint classId);
+extern uint mprGetClassId(MprCtx ctx);
+
+#if BREW
+extern void mprSetDisplay(MprCtx ctx, void *display);
+extern void *mprGetDisplay(MprCtx ctx);
+extern void mprSetFileMgr(MprCtx ctx, void *fileMgr);
+extern void *mprGetFileMgr(MprCtx ctx);
+#else
+extern char *mprInetToStr(char *buf, int size, const struct in_addr in);
+#endif
+
+/*
+ * Memory allocation
+ */
+extern MprApp *mprAllocInit(MprAllocCback cback);
+extern void mprAllocTerm(MprApp *app);
+extern void mprAllocAbort();
+
+extern void *mprAllocBlock(MPR_LOC_DEC(ctx, loc), uint size);
+extern void *mprAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size);
+extern void *mprReallocBlock(MPR_LOC_DEC(ctx, loc), void *ptr, uint size);
+extern int mprFree(void *ptr);
+extern int mprStealAllocBlock(MPR_LOC_DEC(ctx, loc), const void *ptr);
+extern void *mprMemdupInternal(MPR_LOC_DEC(ctx, loc), const void *ptr,
+ uint size);
+extern char *mprStrndupInternal(MPR_LOC_DEC(ctx, loc), const char *str,
+ uint size);
+extern char *mprStrdupInternal(MPR_LOC_DEC(ctx, loc), const char *str);
+
+extern void *mprSlabAllocBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc);
+extern void *mprSlabAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size,
+ uint inc);
+
+extern uint mprGetAllocBlockSize(MprCtx ctx);
+extern uint mprGetAllocBlockCount(MprCtx ctx);
+extern uint mprGetAllocBlockMemory(MprCtx ctx);
+extern void *mprGetAllocParent(MprCtx ctx);
+extern uint mprGetAllocatedMemory(MprCtx ctx);
+extern uint mprGetPeakAllocatedMemory(MprCtx ctx);
+extern uint mprGetAllocatedSlabMemory(MprCtx ctx);
+extern int mprIsAllocBlockValid(MprCtx ctx);
+extern int mprStackCheck(MprCtx ctx);
+extern int mprStackSize(MprCtx ctx);
+extern int mprGetAllocErrors(MprCtx ctx);
+extern void mprClearAllocErrors(MprCtx ctx);
+
+extern MprDestructor mprSetDestructor(MprCtx ctx, MprDestructor destructor);
+extern MprAllocCback mprSetAllocCallback(MprApp *app, MprAllocCback cback);
+extern void mprSetAllocLimits(MprApp *app, uint redLine, uint maxMemory);
+
+#if BLD_FEATURE_ALLOC_STATS
+extern MprSlabStats *mprGetSlabAllocStats(MprApp *app, int slabIndex);
+extern MprAllocStats *mprGetAllocStats(MprApp *app);
+extern void mprPrintAllocReport(MprApp *app, bool doBlocks,
+ const char *msg);
+#endif
+
+#if BLD_DEBUG
+extern int mprPrintAllocBlocks(MprCtx ctx, int indent);
+extern const char *mprGetAllocLocation(MprCtx ptr);
+#endif
+
+extern int mprValidateBlock(MprCtx ctx);
+extern int mprValidateAllocTree(MprCtx ptr);
+extern void mprSetRequiredAlloc(MprCtx ptr, bool recurse);
+
+/*
+ * Sprintf style allocators
+ */
+extern int mprAllocSprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(5,6);
+extern int mprAllocVsprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize,
+ const char *fmt, va_list arg) PRINTF_ATTRIBUTE(5,0);
+extern int mprAllocMemcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax,
+ const void *src, int nbytes);
+extern int mprAllocStrcat(MPR_LOC_DEC(ctx, loc), char **dest, int max,
+ const char *delim, const char *src, ...);
+extern int mprAllocStrcpy(MPR_LOC_DEC(ctx, loc), char **dest, int max,
+ const char *src);
+extern int mprReallocStrcat(MPR_LOC_DEC(ctx, loc), char **dest, int max,
+ int existingLen, const char *delim, const char *src, ...);
+
+/*
+ * MACROS: These are the convenience macros to automatically supply file
+ * names and line numbers when debugging.
+ */
+#define mprNew(ctx) new(MPR_LOC_ARGS(ctx))
+
+#define mprAlloc(ctx, size) mprAllocBlock(MPR_LOC_ARGS(ctx), size)
+
+#define mprAllocZeroed(ctx, size) mprAllocZeroedBlock(MPR_LOC_ARGS(ctx), size)
+
+#define mprSlabAlloc(ctx, size, inc) \
+ ((type*) mprSlabAllocBlock(MPR_LOC_ARGS(ctx), size, inc))
+
+#define mprSlabAllocZeroed(ctx, size, inc) \
+ ((type*) mprSlabAllocBlock(MPR_LOC_ARGS(ctx), size, inc))
+
+#define mprRealloc(ctx, ptr, size) mprReallocBlock(MPR_LOC_ARGS(ctx), ptr, size)
+
+#define mprMemdup(ctx, ptr, size) \
+ mprMemdupInternal(MPR_LOC_ARGS(ctx), ptr, size)
+
+#define mprStrdup(ctx, str) mprStrdupInternal(MPR_LOC_ARGS(ctx), str)
+
+#define mprStrndup(ctx, str, size) mprStrndupDebug(MPR_LOC_ARGS(ctx), str, size)
+
+/*
+ * Allocate type macros
+ */
+#define mprAllocType(ctx, type) \
+ ((type*) mprAllocBlock(MPR_LOC_ARGS(ctx), sizeof(type)))
+
+#define mprAllocTypeZeroed(ctx, type) \
+ ((type*) mprAllocZeroedBlock(MPR_LOC_ARGS(ctx), sizeof(type)))
+
+#define mprSlabAllocType(ctx, type, inc) \
+ ((type*) mprSlabAllocBlock(MPR_LOC_ARGS(ctx), sizeof(type), inc))
+
+#define mprSlabAllocTypeZeroed(ctx, type, inc) \
+ ((type*) mprSlabAllocZeroedBlock(MPR_LOC_ARGS(ctx), sizeof(type), \
+ inc))
+
+/*
+ * Multithread locking
+ */
+#if BLD_FEATURE_MULTITHREAD
+extern void mprInitThreads(MprApp *app);
+extern void mprTermThreads(MprApp *app);
+extern MprLock *mprCreateLock(MprCtx ctx);
+extern void mprDestroyLock(MprLock *lock);
+extern void mprLock(MprLock *lock);
+extern int mprTryLock(MprLock *lock);
+extern void mprUnlock(MprLock *lock);
+extern void mprGlobalLock(MprCtx ctx);
+extern void mprGlobalUnlock(MprCtx ctx);
+extern int mprGetCurrentThreadID();
+#else
+/*
+ * Disable multithreading
+ */
+#define mprInitThreads(ctx, app)
+#define mprTermThreads(app)
+#define mprCreateLock(ctx)
+#define mprDestroyLock(lock)
+#define mprLock(lock)
+#define mprTryLock(lock)
+#define mprUnlock(lock)
+#define mprGlobalLock(app)
+#define mprGlobalUnlock(app)
+#define mprGetCurrentThreadID()
+#endif
+
+/*
+ * Time
+ */
+extern MprTime *mprGetTime(MprCtx ctx, MprTime *tp);
+extern int mprGetTimeRemaining(MprCtx ctx, MprTime mark, uint timeout);
+extern int mprGetElapsedTime(MprCtx ctx, MprTime mark);
+extern int mprCompareTime(MprTime *t1, MprTime *t2);
+extern uint mprSubtractTime(MprTime *t1, MprTime *t2);
+extern void mprAddElapsedToTime(MprTime *time, uint elapsed);
+
+#if !BREW
+extern int mprAsctime(MprCtx ctx, char *buf, int bufsize,
+ const struct tm *timeptr);
+extern int mprCtime(MprCtx ctx, char *buf, int bufsize,
+ const time_t *timer);
+extern struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now);
+extern struct tm *mprGmtime(MprCtx ctx, time_t* now, struct tm *timep);
+extern int mprRfcTime(MprCtx ctx, char *buf, int bufsize,
+ const struct tm *timep);
+#endif /* !BREW */
+
+/*
+ * Host name
+ */
+extern struct hostent* mprGetHostByName(MprCtx ctx, const char *name);
+
+#if WIN
+extern int mprReadRegistry(MprCtx ctx, char **buf, int max,
+ const char *key, const char *val);
+extern int mprWriteRegistry(MprCtx ctx, const char *key, const char *name,
+ const char *value);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _h_MPR */
+
+
+/*
+ * 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/mpr/mprAlloc.c b/source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c
new file mode 100644
index 0000000000..6fcaa63a6c
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c
@@ -0,0 +1,1775 @@
+/**
+ * @file mprAlloc.c
+ * @brief Memory Allocation
+ * @overview
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 ***********************************/
+
+#define UNSAFE_FUNCTIONS_OK 1
+
+#include "mpr.h"
+
+/******************************* Local Defines ********************************/
+/*
+ * Set to 1 to disable slab based allocations
+ */
+#define NO_SLAB 0
+
+/*
+ * Validation mode is quite slow
+ */
+#define VALIDATE_ALLOC 0
+#if VALIDATE_ALLOC
+#define VALIDATE_BLOCK(ptr) mprValidateBlock(ptr)
+#else
+#define VALIDATE_BLOCK(ptr)
+#endif
+
+/*
+ * Align on 4 bytes if squeeze, Otherwize on 16 bytes.
+ */
+#define HDR_SIZE MPR_BLK_HDR_SIZE
+
+#define APP_MAGIC 0xa571cb80
+#define ALLOC_MAGIC 0xe814ecc0
+
+/*
+ * This must be at least one word to ensure that the smallest allocation is
+ * 4 bytes. Slab allocations need at least one word to store their next ptr.
+ */
+#define ALLOC_ALIGN(x) (((x)+3)&~3)
+#define GET_HDR(ptr) ((MprBlk*) (((char*) (ptr)) - HDR_SIZE))
+#define GET_PTR(bp) ((void*) (((char*) (bp)) + HDR_SIZE))
+#define VALID_HDR(bp) (((bp)->flags & ~0x3F) == ALLOC_MAGIC)
+#define VALID_BLK(ptr) (VALID_HDR(GET_HDR(ptr)))
+
+/*
+ * In production releases, mprAssert will compile out (not be included)
+ * but CHECK_HDR will remain even in production builds.
+ */
+#define CHECK_HDR(bp) \
+ if (1) { if (! VALID_HDR(bp)) { mprAllocAbort(); } } else
+
+/*
+ * Chunk the slabs into 32 byte increments.
+ * This allows for allocations up to 512 bytes via slabs and maximizes
+ * sharing of slab allocations.
+ *
+ * Index map:
+ * 0 == 32 bytes
+ * 1 == 64 bytes
+ * 2 == 96 bytes
+ * 3 == 128 bytes
+ * 4 == 160 bytes
+ * 5 == 192 bytes
+ * 6 == 224 bytes
+ * 7 == 256 bytes
+ * 8 == 288 bytes
+ * 9 == 320 bytes
+ * 10 == 352 bytes
+ * 11 == 384 bytes
+ * 12 == 416 bytes
+ * 13 == 448 bytes
+ * 14 == 480 bytes
+ * 15 == 512 bytes
+ */
+#define SLAB_ALIGN(size) ((size + 31) & ~31)
+#define GET_SLAB(size) (size >> 6)
+
+/*
+ * Block flags
+ */
+#define ALLOC_FLAGS_FREE 0x1 /* Block is free */
+#define ALLOC_FLAGS_FREEING 0x2 /* Block is being freed */
+#define ALLOC_FLAGS_SLAB_BLOCK 0x4 /* Block was allocated from slab */
+#define ALLOC_FLAGS_REQUIRED 0x8 /* Block is required by alloc */
+#define ALLOC_FLAGS_KEEP 0x10 /* Keep block - don't mprFree */
+#define ALLOC_FLAGS_DONT_OS_FREE 0x20 /* Don't return mem to O/S */
+#define ALLOC_FLAGS_IS_SLAB 0x40 /* Block is a slab */
+
+#if BLD_DEBUG && !BREW
+/*
+ * Set this address to break when this address is allocated or freed. This is
+ * a block address (not a user ptr).
+ */
+static MprBlk *stopAlloc;
+#endif
+
+#if !BREW
+static MprCtx rootCtx; /* Root context if none supplied */
+#endif
+
+/***************************** Forward Declarations ***************************/
+
+static int mprAllocException(MPR_LOC_DEC(ptr, loc), uint size, bool granted);
+static void slabFree(MprBlk *bp);
+static int growSlab(MPR_LOC_DEC(ctx, loc), MprSlab *slab, uint size, uint inc);
+
+/******************************************************************************/
+/*
+ * Put first in file so it is easy to locate in a debugger
+ */
+
+void mprBreakpoint(const char *loc, const char *msg)
+{
+}
+
+/******************************************************************************/
+#if (WIN || BREW_SIMULATOR) && BLD_DEBUG
+
+int crtReportHook(int type, char *msg, int *retval)
+{
+ printf("%s\n", msg);
+ *retval = 0;
+ return TRUE;
+}
+
+#endif
+/******************************************************************************/
+/*
+ * Initialize the memory subsystem
+ */
+
+MprApp *mprAllocInit(MprAllocCback cback)
+{
+ MprAllocStats *stats;
+ MprApp *app;
+ MprSlab *slab;
+ MprBlk *bp, *sp;
+ int i;
+
+ bp = malloc(sizeof(MprApp) + HDR_SIZE);
+ mprAssert(bp);
+ if (bp == 0) {
+ if (cback) {
+ (*cback)(0, sizeof(MprApp), 0, 0);
+ }
+ return 0;
+ }
+ memset(bp, 0, sizeof(MprApp) + HDR_SIZE);
+
+ bp->parent = bp;
+ bp->size = sizeof(MprApp);
+ bp->flags = ALLOC_MAGIC;
+ bp->next = bp->prev = bp;
+
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ bp->location = MPR_LOC;
+#endif
+
+ app = (MprApp*) GET_PTR(bp);
+ app->magic = APP_MAGIC;
+
+ app->alloc.cback = cback;
+ app->stackStart = (void*) &app;
+
+ bp->app = app;
+
+ app->alloc.slabs = mprAllocZeroedBlock(MPR_LOC_PASS(app, MPR_LOC),
+ sizeof(MprSlab) * MPR_MAX_SLAB);
+ if (app->alloc.slabs == 0) {
+ mprFree(app);
+ return 0;
+ }
+
+ /*
+ * The slab control structures must not be freed. Set keep to safeguard
+ * against accidents.
+ */
+ sp = GET_HDR(app->alloc.slabs);
+ sp->flags |= ALLOC_FLAGS_KEEP;
+
+ for (i = 0; i < MPR_MAX_SLAB; i++) {
+ /*
+ * This is overriden by requestors calling slabAlloc
+ */
+ slab = &app->alloc.slabs[i];
+ slab->preAllocateIncr = MPR_SLAB_DEFAULT_INC;
+ }
+
+ /*
+ * Keep aggregated stats even in production code
+ */
+ stats = &app->alloc.stats;
+ stats->bytesAllocated += sizeof(MprApp);
+ if (stats->bytesAllocated > stats->peakAllocated) {
+ stats->peakAllocated = stats->bytesAllocated;
+ }
+ stats->allocCount++;
+
+#if !BREW
+ rootCtx = app;
+#endif
+#if (WIN || BREW_SIMULATOR) && BLD_DEBUG
+ _CrtSetReportHook(crtReportHook);
+#endif
+ return app;
+}
+
+/******************************************************************************/
+/*
+ * Terminate the alloc module
+ */
+
+void mprAllocTerm(MprApp *app)
+{
+ MprSlab *slabs;
+ MprBlk *appBlk, *slabBlk;
+
+ /*
+ * Must do a carefully ordered cleanup. Need to free all children blocks
+ * before freeing the slab memory. Save a local pointer to the slabs.
+ */
+ slabs = app->alloc.slabs;
+
+ /*
+ * Free the app and all children. Set DONT_OS_FREE to prevent free() being
+ * called on app itself. We need that so we can free the slabs below.
+ */
+ appBlk = GET_HDR(app);
+ appBlk->flags |= ALLOC_FLAGS_DONT_OS_FREE;
+ mprFree(app);
+
+ /*
+ * Slabs are initially marked don't free. We must preserve them while all
+ * other blocks are freed. Then we clear the don't free flag and free.
+ * Now we don't have an app structure which is used by mprFree. We must
+ * fake it.
+ */
+ slabBlk = GET_HDR(slabs);
+ slabBlk->flags &= ~ALLOC_FLAGS_KEEP;
+ mprFree(slabs);
+
+ /*
+ * Now we can finally free the memory for the app structure
+ */
+ free(appBlk);
+}
+
+/******************************************************************************/
+/*
+ * Allocate a block
+ */
+
+void *mprAllocBlock(MPR_LOC_DEC(ctx, loc), uint size)
+{
+ MprAllocStats *stats;
+ MprBlk *bp, *parent;
+ MprApp *app;
+ int diff;
+
+ mprAssert(size > 0);
+
+ if (ctx == 0) {
+#if BREW
+ mprAssert(ctx);
+ return 0;
+#else
+ ctx = rootCtx;
+#endif
+ }
+ if (size == 0) {
+ size = 1;
+ }
+
+ mprAssert(VALID_BLK(ctx));
+ parent = GET_HDR(ctx);
+ mprAssert(VALID_HDR(parent));
+
+ CHECK_HDR(parent);
+
+ size = ALLOC_ALIGN(size);
+
+ app = parent->app;
+
+ stats = &app->alloc.stats;
+
+ mprLock(app->allocLock);
+
+ stats->bytesAllocated += size + HDR_SIZE;
+ if (stats->bytesAllocated > stats->peakAllocated) {
+ stats->peakAllocated = stats->bytesAllocated;
+ }
+
+ /*
+ * Prevent allocation if over the maximum
+ */
+ if (stats->maxMemory && stats->bytesAllocated > stats->maxMemory) {
+ stats->bytesAllocated -= (size + HDR_SIZE);
+ mprUnlock(app->allocLock);
+ if (mprAllocException(MPR_LOC_PASS(ctx, loc), size, 0) < 0) {
+ return 0;
+ }
+ mprLock(app->allocLock);
+ }
+
+ if ((bp = malloc(size + HDR_SIZE)) == 0) {
+ mprAssert(bp);
+ stats->errors++;
+ mprUnlock(app->allocLock);
+ mprAllocException(MPR_LOC_PASS(ctx, loc), size, 0);
+ return 0;
+ }
+
+#if BLD_DEBUG
+ memset(bp, 0xf7, size + HDR_SIZE);
+#endif
+
+#if BLD_DEBUG && !BREW
+ if (bp == stopAlloc) {
+ mprBreakpoint(MPR_LOC, "breakOnAddr");
+ }
+#endif
+
+ /*
+ * Warn if allocation puts us over the red line
+ */
+ if (stats->redLine && stats->bytesAllocated > stats->redLine) {
+ mprUnlock(app->allocLock);
+ if (mprAllocException(MPR_LOC_PASS(ctx, loc), size, 1) < 0) {
+ return 0;
+ }
+ mprLock(app->allocLock);
+ }
+
+ bp->size = size;
+ bp->flags = ALLOC_MAGIC;
+ bp->destructor = 0;
+
+ bp->parent = parent;
+
+ if (parent->children == 0) {
+ parent->children = bp;
+ bp->next = bp->prev = bp;
+
+ } else {
+ /*
+ * Append to the end of the list. Preserve alloc order
+ */
+ bp->next = parent->children;
+ bp->prev = parent->children->prev;
+ parent->children->prev->next = bp;
+ parent->children->prev = bp;
+ }
+
+ bp->children = 0;
+
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ bp->location = loc;
+#endif
+
+ bp->app = parent->app;
+
+ VALIDATE_BLOCK(GET_PTR(bp));
+
+ stats->allocCount++;
+
+ /*
+ * Monitor stack usage
+ */
+ diff = (int) bp->app->stackStart - (int) &stats;
+ if (diff < 0) {
+ app->maxStack -= diff;
+ app->stackStart = (void*) &stats;
+ diff = 0;
+ }
+
+ if ((uint) diff > app->maxStack) {
+ app->maxStack = diff;
+ }
+ mprUnlock(app->allocLock);
+
+ return GET_PTR(bp);
+}
+
+/******************************************************************************/
+/*
+ * Allocate and zero a block
+ */
+
+void *mprAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size)
+{
+ void *newBlock;
+
+ MprBlk *bp;
+
+ bp = GET_HDR(ctx);
+ mprAssert(VALID_BLK(ctx));
+
+ newBlock = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
+ if (newBlock) {
+ memset(newBlock, 0, size);
+ }
+ return newBlock;
+}
+
+/******************************************************************************/
+/*
+ * Free a block of memory. Free all children recursively.
+ */
+
+int mprFree(void *ptr)
+{
+ MprAllocStats *stats;
+ MprBlk *bp, *parent, *cp, *firstChild, *prev;
+ MprApp *app;
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ mprAssert(VALID_BLK(ptr));
+ VALIDATE_BLOCK(ptr);
+
+ bp = GET_HDR(ptr);
+
+#if BLD_DEBUG && !BREW
+ if (bp == stopAlloc) {
+ mprBreakpoint(MPR_LOC, "breakOnAddr");
+ }
+#endif
+
+ mprAssert(bp);
+ mprAssert(VALID_HDR(bp));
+
+ CHECK_HDR(bp);
+
+ /*
+ * Test if already freed
+ */
+ mprAssert(! (bp->flags & ALLOC_FLAGS_FREE));
+ if (bp->flags & ALLOC_FLAGS_FREE) {
+ return 0;
+ }
+
+ /*
+ * Return if recursive freeing or this is a permanent block
+ */
+ app = bp->app;
+ mprLock(app->allocLock);
+ if (bp->flags & (ALLOC_FLAGS_FREEING | ALLOC_FLAGS_KEEP)) {
+ mprUnlock(app->allocLock);
+ return 0;
+ }
+ bp->flags |= ALLOC_FLAGS_FREEING;
+
+
+ /*
+ * Call any destructors
+ */
+ if (bp->destructor) {
+ mprUnlock(app->allocLock);
+ if ((bp->destructor)(ptr) < 0) {
+ return -1;
+ }
+ mprLock(app->allocLock);
+ bp->destructor = 0;
+ }
+
+ /*
+ * Free the children. Free in reverse order so firstChild is preserved
+ * during the list scan as an end of list marker.
+ */
+ if ((firstChild = bp->children) != 0) {
+ cp = firstChild->prev;
+ while (cp != firstChild) {
+
+ mprAssert(VALID_HDR(cp));
+ VALIDATE_BLOCK(GET_PTR(cp));
+
+ prev = cp->prev;
+
+ /*
+ * FUTURE - OPT. Make this inline
+ */
+ mprFree(GET_PTR(cp));
+
+ cp = prev;
+ }
+
+ mprFree(GET_PTR(firstChild));
+
+ /*
+ * Just for clarity
+ */
+ bp->children = 0;
+ }
+
+ parent = bp->parent;
+
+ mprAssert(VALID_HDR(parent));
+
+ /*
+ * Unlink from the parent
+ */
+ if (parent->children == bp) {
+ if (bp->next == bp) {
+ parent->children = 0;
+ } else {
+ parent->children = bp->next;
+ }
+ }
+
+ /*
+ * Remove from the sibling chain
+ */
+ bp->prev->next = bp->next;
+ bp->next->prev = bp->prev;
+
+ bp->flags |= ALLOC_FLAGS_FREE;
+
+ /*
+ * Release the memory. If from a slab, return to the slab. Otherwise,
+ * return to the O/S.
+ */
+ if (bp->flags & ALLOC_FLAGS_SLAB_BLOCK) {
+ slabFree(bp);
+
+ } else {
+ mprAssert(bp);
+
+ /*
+ * Update the stats
+ */
+ stats = &bp->app->alloc.stats;
+ stats->bytesAllocated -= (bp->size + HDR_SIZE);
+ mprAssert(stats->bytesAllocated >= 0);
+
+ stats->allocCount--;
+ mprAssert(stats->allocCount >= 0);
+
+#if BLD_DEBUG && !BREW
+ if (bp == stopAlloc) {
+ mprBreakpoint(MPR_LOC, "breakOnAddr");
+ }
+#endif
+
+ /*
+ * Return to the O/S
+ */
+ if (! (bp->flags & ALLOC_FLAGS_DONT_OS_FREE)) {
+ free(bp);
+ }
+ }
+ /* OPT */
+ if (app != ptr) {
+ mprUnlock(app->allocLock);
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Rallocate a block
+ */
+
+void *mprReallocBlock(MPR_LOC_DEC(ctx, loc), void *ptr, uint size)
+{
+ MprBlk *bp, *newbp, *firstChild, *cp;
+ MprApp *app;
+ void *newPtr;
+
+ mprAssert(VALID_BLK(ctx));
+ mprAssert(size > 0);
+
+ if (ptr == 0) {
+ return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
+ }
+
+ mprAssert(VALID_BLK(ptr));
+ bp = GET_HDR(ptr);
+ mprAssert(bp);
+ mprAssert(VALID_HDR(bp));
+
+ CHECK_HDR(bp);
+
+ if (size < bp->size) {
+ return ptr;
+ }
+
+ newPtr = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
+ if (newPtr == 0) {
+ bp->flags &= ~ALLOC_FLAGS_FREE;
+ free(bp);
+ return 0;
+ }
+
+ newbp = GET_HDR(newPtr);
+ mprAssert(newbp->size >= size);
+ memcpy((char*) newbp + HDR_SIZE, (char*) bp + HDR_SIZE, bp->size);
+ mprAssert(newbp->size >= size);
+
+ /*
+ * Fix the next / prev pointers
+ */
+ app = bp->app;
+ mprLock(app->allocLock);
+ newbp->next->prev = newbp;
+ newbp->prev->next = newbp;
+
+ /*
+ * Need to fix the parent pointer of all children
+ */
+ if ((firstChild = newbp->children) != 0) {
+ cp = firstChild;
+ do {
+ cp->parent = newbp;
+ cp = cp->next;
+ } while (cp != firstChild);
+ }
+
+ /*
+ * May need to set the children pointer of our parent
+ */
+ if (newbp->parent->children == bp) {
+ newbp->parent->children = newbp;
+ }
+
+ /*
+ * Free the original block
+ */
+ mprFree(ptr);
+
+ mprUnlock(app->allocLock);
+
+ return GET_PTR(newbp);
+}
+
+/******************************************************************************/
+/*
+ * Allocate a block from a slab
+ */
+
+void *mprSlabAllocBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc)
+{
+
+#if NO_SLAB
+ return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
+#else
+
+ MprBlk *parent, *bp;
+ MprSlabBlock *sb;
+ MprApp *app;
+ MprSlab *slab;
+ int slabIndex;
+
+ if (ctx == 0) {
+ mprAssert(ctx);
+ return 0;
+ }
+
+ mprAssert(size > 0);
+ mprAssert(VALID_BLK(ctx));
+
+ parent = GET_HDR(ctx);
+ mprAssert(VALID_HDR(parent));
+
+ CHECK_HDR(parent);
+
+ size = SLAB_ALIGN(size);
+
+ app = parent->app;
+ mprAssert(app);
+
+ slabIndex = GET_SLAB(size);
+
+ if (slabIndex < 0 || slabIndex >= MPR_MAX_SLAB) {
+ return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
+ }
+
+ /*
+ * Dequeue a block from the slab. "sb" will point to the user data
+ * portion of the block (i.e. after the MprBlk header). Slabs must be
+ * allocated off the "slabs" context to ensure they don't get freed
+ * until after all other blocks are freed.
+ */
+ mprLock(app->allocLock);
+ slab = &app->alloc.slabs[slabIndex];
+ if ((sb = slab->next) == 0) {
+ if (growSlab(MPR_LOC_ARGS(parent->app->alloc.slabs),
+ slab, size, inc) < 0) {
+ mprUnlock(app->allocLock);
+ return 0;
+ }
+ sb = slab->next;
+ }
+ mprAssert(sb);
+
+ /*
+ * Dequeue the block
+ */
+ slab->next = sb->next;
+
+#if BLD_FEATURE_ALLOC_STATS
+{
+ MprSlabStats *slabStats;
+ /*
+ * Update the slab stats
+ */
+ slabStats = &slab->stats;
+ slabStats->totalAllocCount++;
+ slabStats->freeCount--;
+ slabStats->allocCount++;
+ if (slabStats->allocCount > slabStats->peakAllocCount) {
+ slabStats->peakAllocCount = slabStats->allocCount;
+ }
+}
+#endif /* BLD_FEATURE_ALLOC_STATS */
+
+ bp = GET_HDR(sb);
+
+#if BLD_DEBUG && !BREW
+ if (bp == stopAlloc) {
+ mprBreakpoint(MPR_LOC, "breakOnAddr");
+ }
+#endif
+
+ bp->size = size;
+ bp->flags = ALLOC_MAGIC | ALLOC_FLAGS_SLAB_BLOCK;
+ bp->destructor = 0;
+
+ bp->parent = parent;
+
+ if (parent->children == 0) {
+ parent->children = bp;
+ bp->next = bp->prev = bp;
+
+ } else {
+ /*
+ * Append to the end of the list. Preserve alloc order
+ */
+ bp->next = parent->children;
+ bp->prev = parent->children->prev;
+ parent->children->prev->next = bp;
+ parent->children->prev = bp;
+ }
+
+ bp->children = 0;
+
+ bp->app = app;
+
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ bp->location = loc;
+#endif
+ mprUnlock(app->allocLock);
+
+ return GET_PTR(bp);
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Return a block back to its slab
+ */
+
+static void slabFree(MprBlk *bp)
+{
+ MprSlab *slab;
+ MprApp *app;
+ void *ptr;
+ int slabIndex;
+
+ mprAssert(VALID_HDR(bp));
+
+ slabIndex = GET_SLAB(bp->size);
+ mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB);
+
+ if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) {
+ mprLock(bp->app->allocLock);
+ slab = &bp->app->alloc.slabs[slabIndex];
+ app = bp->app;
+
+#if BLD_DEBUG
+ memset(bp, 0xfc, bp->size + HDR_SIZE);
+#endif
+
+ ptr = GET_PTR(bp);
+ ((MprSlabBlock*) ptr)->next = slab->next;
+ slab->next = ((MprSlabBlock*) ptr);
+
+#if BLD_FEATURE_ALLOC_STATS
+{
+ MprSlabStats *slabStats;
+ slabStats = &slab->stats;
+
+ slabStats->freeCount++;
+ slabStats->allocCount--;
+
+ if (slabStats->freeCount >= slabStats->peakFreeCount) {
+ slabStats->peakFreeCount = slabStats->freeCount;
+ }
+}
+#endif
+ mprUnlock(app->allocLock);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Grow the slab and return the next free block
+ * Must be called locked.
+ */
+
+static int growSlab(MPR_LOC_DEC(ctx, loc), MprSlab *slab, uint size, uint inc)
+{
+ MprBlk *bp;
+ MprSlabBlock *sb;
+ int i, chunkSize, len;
+
+ mprAssert(VALID_BLK(ctx));
+ mprAssert(slab);
+ mprAssert(size > 0);
+
+ /*
+ * Take the maximum requested by anyone
+ */
+ slab->preAllocateIncr = max(slab->preAllocateIncr, inc);
+
+ /*
+ * We allocate an array of blocks each of user "size" bytes.
+ */
+ chunkSize = HDR_SIZE + size;
+ len = chunkSize * slab->preAllocateIncr;
+ bp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);
+
+#if BLD_DEBUG
+ memset(bp, 0xf1, len);
+#endif
+
+ if (bp == 0) {
+ mprAssert(0);
+ return MPR_ERR_MEMORY;
+ }
+ bp->flags |= ALLOC_FLAGS_IS_SLAB;
+
+ /*
+ * We store the slab information in the user data portion
+ */
+ sb = (MprSlabBlock*) GET_PTR(bp);
+
+
+ sb = (MprSlabBlock*) ((char*) sb + len - chunkSize);
+ for (i = slab->preAllocateIncr - 1; i >= 0; i--) {
+ sb->next = slab->next;
+ slab->next = sb;
+ sb = (MprSlabBlock*) ((char*) sb - chunkSize);
+ }
+
+#if BLD_FEATURE_ALLOC_STATS
+{
+ MprSlabStats *stats;
+ stats = &slab->stats;
+ stats->freeCount += slab->preAllocateIncr;
+ if (stats->freeCount > stats->peakFreeCount) {
+ stats->peakFreeCount = stats->freeCount;
+ }
+}
+#endif
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Set the pre-allocate amount
+ */
+
+int mprSetSlabPreAllocate(MprCtx ctx, int slabIndex, int preAllocateIncr)
+{
+ MprApp *app;
+ MprSlab *slab;
+
+ mprAssert(VALID_BLK(ctx));
+ mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB);
+ mprAssert(preAllocateIncr > 0);
+
+ if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) {
+ app = mprGetApp(ctx);
+ slab = &app->alloc.slabs[slabIndex];
+ slab->preAllocateIncr = preAllocateIncr;
+ } else {
+ return MPR_ERR_BAD_ARGS;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+void *mprSlabAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc)
+{
+ void *newBlock;
+
+ mprAssert(VALID_BLK(ctx));
+ mprAssert(size > 0);
+
+ newBlock = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), size, inc);
+ if (newBlock) {
+ memset(newBlock, 0, size);
+ }
+ return newBlock;
+}
+
+/******************************************************************************/
+/*
+ * Internal strdup function. Will use the slab allocator for small strings
+ */
+
+char *mprStrdupInternal(MPR_LOC_DEC(ctx, loc), const char *str)
+{
+ char *newp;
+ int len;
+
+ mprAssert(VALID_BLK(ctx));
+
+ if (str == 0) {
+ str = "";
+ }
+
+ len = strlen(str) + 1;
+
+ if (len < MPR_SLAB_STR_MAX) {
+ newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX,
+ MPR_SLAB_STR_INC);
+ } else {
+ newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);
+ }
+
+ if (newp) {
+ memcpy(newp, str, len);
+ }
+
+ return newp;
+}
+
+/******************************************************************************/
+/*
+ * Internal strndup function. Will use the slab allocator for small strings
+ */
+
+char *mprStrndupInternal(MPR_LOC_DEC(ctx, loc), const char *str, uint size)
+{
+ char *newp;
+ uint len;
+
+ mprAssert(VALID_BLK(ctx));
+
+ if (str == 0) {
+ str = "";
+ }
+ len = strlen(str) + 1;
+ len = min(len, size);
+
+ if (len < MPR_SLAB_STR_MAX) {
+ newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX,
+ MPR_SLAB_STR_INC);
+ } else {
+ newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);
+ }
+
+ if (newp) {
+ memcpy(newp, str, len);
+ }
+
+ return newp;
+}
+
+/******************************************************************************/
+/*
+ * Internal memcpy function. Will use the slab allocator for small strings
+ */
+
+void *mprMemdupInternal(MPR_LOC_DEC(ctx, loc), const void *ptr, uint size)
+{
+ char *newp;
+
+ mprAssert(VALID_BLK(ctx));
+
+ if (size < MPR_SLAB_STR_MAX) {
+ newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX,
+ MPR_SLAB_STR_INC);
+ } else {
+ newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
+ }
+
+ if (newp) {
+ memcpy(newp, ptr, size);
+ }
+
+ return newp;
+}
+
+/******************************************************************************/
+/*
+ * Steal a block from one context and insert in another
+ */
+
+int mprStealAllocBlock(MPR_LOC_DEC(ctx, loc), const void *ptr)
+{
+ MprBlk *bp, *parent;
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ mprAssert(VALID_BLK(ctx));
+ mprAssert(VALID_BLK(ptr));
+
+ bp = GET_HDR(ptr);
+
+#if BLD_DEBUG && !BREW
+ if (bp == stopAlloc) {
+ mprBreakpoint(MPR_LOC, "breakOnAddr");
+ }
+#endif
+
+ mprAssert(bp);
+ mprAssert(VALID_HDR(bp));
+ mprAssert(ptr != mprGetAllocParent(ptr));
+
+ CHECK_HDR(bp);
+
+ mprAssert(bp->prev);
+ mprAssert(bp->prev->next);
+ mprAssert(bp->next);
+ mprAssert(bp->next->prev);
+
+ parent = bp->parent;
+ mprAssert(VALID_HDR(parent));
+
+ mprLock(bp->app->allocLock);
+ if (parent->children == bp) {
+ if (bp->next == bp) {
+ parent->children = 0;
+ } else {
+ parent->children = bp->next;
+ }
+ }
+
+ bp->prev->next = bp->next;
+ bp->next->prev = bp->prev;
+
+ parent = GET_HDR(ctx);
+ mprAssert(VALID_HDR(parent));
+ bp->parent = parent;
+
+ if (parent->children == 0) {
+ parent->children = bp;
+ bp->next = bp->prev = bp;
+
+ } else {
+ bp->next = parent->children;
+ bp->prev = parent->children->prev;
+ parent->children->prev->next = bp;
+ parent->children->prev = bp;
+ }
+
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ bp->location = loc;
+#endif
+
+ VALIDATE_BLOCK(GET_PTR(bp));
+
+ mprUnlock(bp->app->allocLock);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+void mprSetRequiredAlloc(MprCtx ptr, bool recurse)
+{
+ MprBlk *bp, *firstChild, *cp;
+
+ bp = GET_HDR(ptr);
+
+ bp->flags |= ALLOC_FLAGS_REQUIRED;
+
+ if (recurse && (firstChild = bp->children) != 0) {
+ cp = firstChild;
+ do {
+ mprSetRequiredAlloc(GET_PTR(cp), recurse);
+ cp = cp->next;
+ } while (cp != firstChild);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Monitor stack usage. Return true if the stack has grown
+ */
+
+int mprStackCheck(MprCtx ptr)
+{
+ MprApp *app;
+ int size;
+
+ mprAssert(VALID_BLK(ptr));
+
+ app = mprGetApp(ptr);
+
+ size = (int) app->stackStart - (int) &app;
+ if (size < 0) {
+ app->maxStack -= size;
+ app->stackStart = (void*) &app;
+ size = 0;
+ }
+ if ((uint) size > app->maxStack) {
+ app->maxStack = size;
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return the stack size
+ */
+
+int mprStackSize(MprCtx ptr)
+{
+ MprApp *app;
+
+ mprAssert(VALID_BLK(ptr));
+
+ app = mprGetApp(ptr);
+ return app->maxStack;
+}
+
+/******************************************************************************/
+
+static int mprAllocException(MPR_LOC_DEC(ctx, loc), uint size, bool granted)
+{
+ MprApp *app;
+ MprAlloc *alloc;
+ int rc;
+
+ mprAssert(VALID_BLK(ctx));
+
+ app = mprGetApp(ctx);
+ alloc = &app->alloc;
+
+ if (alloc->cback == 0) {
+ return 0;
+ }
+
+ mprLock(app->allocLock);
+ if (alloc->inAllocException == 0) {
+ alloc->inAllocException = 1;
+ mprUnlock(app->allocLock);
+
+ rc = (alloc->cback)(app, size, alloc->stats.bytesAllocated, granted);
+
+ mprLock(app->allocLock);
+ app->alloc.inAllocException = 0;
+ mprUnlock(app->allocLock);
+
+ return rc;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+void mprSetAllocLimits(MprApp *app, uint redLine, uint maxMemory)
+{
+ app->alloc.stats.redLine = redLine;
+ app->alloc.stats.maxMemory = maxMemory;
+}
+
+/******************************************************************************/
+
+MprAllocCback mprSetAllocCallback(MprApp *app, MprAllocCback cback)
+{
+ MprAllocCback old;
+
+ mprAssert(app);
+ mprAssert(VALID_BLK(app));
+
+ old = app->alloc.cback;
+ app->alloc.cback = cback;
+ return old;
+}
+
+/******************************************************************************/
+
+uint mprGetAllocBlockSize(MprCtx ptr)
+{
+ MprBlk *bp;
+
+ mprAssert(VALID_BLK(ptr));
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ bp = GET_HDR(ptr);
+ mprAssert(VALID_HDR(bp));
+
+ CHECK_HDR(bp);
+
+ return bp->size;
+}
+
+/******************************************************************************/
+/*
+ * Return the total block count used by a block including all children
+ */
+
+uint mprGetAllocBlockCount(MprCtx ptr)
+{
+ MprBlk *bp, *firstChild, *cp;
+ uint count;
+
+ mprAssert(VALID_BLK(ptr));
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ bp = GET_HDR(ptr);
+ mprAssert(VALID_HDR(bp));
+
+ /*
+ * Add one for itself
+ */
+ count = 1;
+ if ((firstChild = bp->children) != 0) {
+ cp = firstChild;
+ do {
+ count += mprGetAllocBlockCount(GET_PTR(cp));
+ cp = cp->next;
+ } while (cp != firstChild);
+ }
+ return count;
+}
+
+/******************************************************************************/
+/*
+ * Return the total of all memory allocated including slabs
+ */
+
+uint mprGetAllocBlockMemory(MprCtx ptr)
+{
+ MprBlk *bp, *firstChild, *cp;
+ uint count;
+
+ mprAssert(VALID_BLK(ptr));
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ bp = GET_HDR(ptr);
+ mprAssert(VALID_HDR(bp));
+
+ count = bp->size + HDR_SIZE;
+ if ((firstChild = bp->children) != 0) {
+ cp = firstChild;
+ do {
+ count += mprGetAllocBlockMemory(GET_PTR(cp));
+ cp = cp->next;
+ } while (cp != firstChild);
+ }
+ return count;
+}
+
+/******************************************************************************/
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+
+const char *mprGetAllocLocation(MprCtx ptr)
+{
+ MprBlk *bp;
+
+ if (ptr == 0) {
+ return 0;
+ }
+ mprAssert(VALID_BLK(ptr));
+
+ bp = GET_HDR(ptr);
+ mprAssert(VALID_HDR(bp));
+ return bp->location;
+}
+
+#endif
+/******************************************************************************/
+
+void *mprGetAllocParent(MprCtx ptr)
+{
+ MprBlk *bp;
+
+ mprAssert(VALID_BLK(ptr));
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ bp = GET_HDR(ptr);
+ mprAssert(VALID_HDR(bp));
+
+ CHECK_HDR(bp);
+
+ return GET_PTR(bp->parent);
+}
+
+/******************************************************************************/
+
+MprAllocStats *mprGetAllocStats(MprApp *app)
+{
+ mprAssert(VALID_BLK(app));
+
+ return &app->alloc.stats;
+}
+
+/******************************************************************************/
+#if BLD_FEATURE_ALLOC_STATS
+
+MprSlabStats *mprGetSlabAllocStats(MprApp *app, int slabIndex)
+{
+ MprSlab *slab;
+
+ mprAssert(VALID_BLK(app));
+
+ if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) {
+ slab = &app->alloc.slabs[slabIndex];
+ return &slab->stats;
+ }
+
+ mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB);
+ return 0;
+}
+
+#endif /* BLD_FEATURE_ALLOC_STATS */
+/******************************************************************************/
+#if BLD_DEBUG
+
+int mprPrintAllocBlocks(MprCtx ptr, int indent)
+{
+ MprBlk *bp, *firstChild, *cp;
+ const char *location;
+ int subTotal, size, indentSpaces, code;
+
+ subTotal = 0;
+
+ bp = GET_HDR(ptr);
+
+ if (! (bp->flags & ALLOC_FLAGS_REQUIRED)) {
+ size = bp->size + HDR_SIZE;
+
+ /*
+ * Take one level off because we don't trace app
+ */
+ indentSpaces = indent;
+
+ if (bp->flags & ALLOC_FLAGS_REQUIRED) {
+ code = 'R';
+ } else if (bp->flags & ALLOC_FLAGS_IS_SLAB) {
+ code = 'S';
+ } else {
+ code = ' ';
+ }
+
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ location = bp->location;
+#else
+ location = "";
+#endif
+ mprLog(bp->app, 0,
+ "%c %.*s %-16s %.*s size %5d has %3d deps, total %6d", code,
+ indentSpaces, " ",
+ mprGetBaseName(location),
+ 8 - indent, " ",
+ size,
+ mprGetAllocBlockCount(GET_PTR(bp)),
+ mprGetAllocBlockMemory(GET_PTR(bp))
+ /* (uint) bp */
+ );
+
+ subTotal += size;
+ }
+
+ if ((firstChild = bp->children) != 0) {
+ cp = firstChild;
+ do {
+ subTotal += mprPrintAllocBlocks(GET_PTR(cp), indent + 2);
+ cp = cp->next;
+ } while (cp != firstChild);
+ }
+
+ return subTotal;
+}
+
+#endif
+/******************************************************************************/
+#if BLD_FEATURE_ALLOC_STATS
+/*
+ * Print a memory allocation report that includes a list of allocated blocks
+ * and a statistics summary
+ */
+
+void mprPrintAllocReport(MprApp *app, bool printBlocks, const char *msg)
+{
+ MprSlabStats *stats;
+ uint total;
+ int i, size;
+
+ mprAssert(VALID_BLK(app));
+
+ if (msg) {
+ mprLog(app, 0, " ");
+ mprLog(app, 0, "%s", msg);
+ }
+
+#if BLD_DEBUG
+ /*
+ * Do block stats
+ */
+ if (printBlocks) {
+ int sum;
+ mprLog(app, 0, " ");
+ sum = mprPrintAllocBlocks(app, 0);
+ if (sum) {
+ mprLog(app, 0, " Sum of blocks %d", sum);
+ } else {
+ mprLog(app, 0, " None");
+ }
+ }
+#endif
+
+ /*
+ * Do Slab stats
+ */
+ mprLog(app, 0, " ");
+ mprLog(app, 0, "MPR Slab Memory Stats");
+ mprLog(app, 0, " ");
+
+ mprLog(app, 0,
+ " Index Size Total Allocated Free PeakAlloc PeakFree TotalAlloc");
+
+ total = 0;
+ for (i = 0; i < MPR_MAX_SLAB; i++) {
+ stats = &app->alloc.slabs[i].stats;
+ size = 1 << (i + 5);
+ if (stats->totalAllocCount > 0) {
+ mprLog(app, 0, " %2d %6d %8d %9d %6d %9d %8d %10d",
+ i, size, size * (stats->allocCount + stats->freeCount),
+ stats->allocCount, stats->freeCount,
+ stats->peakAllocCount, stats->peakFreeCount,
+ stats->totalAllocCount);
+ total += size * (stats->allocCount + stats->freeCount);
+ }
+ }
+ mprLog(app, 0, " ");
+ mprLog(app, 0, "MPR Total Allocated Slab RAM: %10d", total);
+ mprLog(app, 0, "MPR Total Allocated RAM: %10d",
+ mprGetAllocatedMemory(app));
+ mprLog(app, 0, "MPR Peak Allocated RAM: %10d",
+ mprGetPeakAllocatedMemory(app));
+ mprLog(app, 0, " ");
+}
+
+/******************************************************************************/
+/*
+ * Return the total memory allocated.
+ */
+
+uint mprGetAllocatedMemory(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+
+ return app->alloc.stats.bytesAllocated;
+}
+
+/******************************************************************************/
+/*
+ * Return the peak memory allocated.
+ */
+
+uint mprGetPeakAllocatedMemory(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+
+ return app->alloc.stats.peakAllocated;
+}
+
+/******************************************************************************/
+/*
+ * Return memory in the MPR slab. This excludes the EJS slabs
+ */
+
+uint mprGetAllocatedSlabMemory(MprCtx ctx)
+{
+ MprApp *app;
+ MprSlabStats *stats;
+ uint total;
+ int i, size;
+
+ app = mprGetApp(ctx);
+
+ total = 0;
+ for (i = 0; i < MPR_MAX_SLAB; i++) {
+ stats = &app->alloc.slabs[i].stats;
+ size = 1 << (i + 5);
+ if (stats->totalAllocCount > 0) {
+ total += size * (stats->allocCount + stats->freeCount);
+ }
+ }
+ return total;
+}
+
+#endif /* BLD_FEATURE_ALLOC_STATS */
+/******************************************************************************/
+
+MprDestructor mprSetDestructor(MprCtx ptr, MprDestructor destructor)
+{
+ MprDestructor old;
+ MprBlk *bp;
+
+ mprAssert(VALID_BLK(ptr));
+
+ if (ptr == 0) {
+ return 0;
+ }
+
+ bp = GET_HDR(ptr);
+
+ mprAssert(bp);
+ mprAssert(VALID_HDR(bp));
+ mprAssert(ptr != mprGetAllocParent(ptr));
+
+ CHECK_HDR(bp);
+
+ old = bp->destructor;
+ bp->destructor = destructor;
+
+ return old;
+}
+
+/******************************************************************************/
+
+int mprIsAllocBlockValid(MprCtx ptr)
+{
+ MprBlk *bp;
+
+ bp = GET_HDR(ptr);
+ return (bp && VALID_HDR(bp));
+}
+
+/******************************************************************************/
+#if VALIDATE_ALLOC
+/*
+ * Exhaustive validation of the block and its children. Does not go recursive
+ * as it would be too slow.
+ */
+
+int mprValidateBlock(MprCtx ptr)
+{
+ MprBlk *bp, *parent, *cp, *firstChild;
+ int count;
+
+ mprAssert(ptr);
+ mprAssert(VALID_BLK(ptr));
+
+ bp = GET_HDR(ptr);
+
+ mprAssert(bp);
+ mprAssert(VALID_HDR(bp));
+ mprAssert(VALID_HDR(bp->parent));
+
+ if (ptr != bp->app) {
+ mprAssert(bp != bp->parent);
+ }
+ mprAssert(! (bp->flags & ALLOC_FLAGS_FREE));
+ mprAssert(! (bp->flags & ALLOC_FLAGS_FREEING));
+
+ /*
+ *
+ */
+ count = 0;
+ parent = bp->parent;
+
+ if ((firstChild = bp->children) != 0) {
+ cp = firstChild;
+ mprAssert((int) cp != 0xfeefee);
+ do {
+ mprAssert(bp->next->prev == bp);
+ mprAssert(bp->prev->next == bp);
+ mprAssert(bp->prev->parent == parent);
+ mprAssert(bp->next->parent == parent);
+
+ count++;
+ cp = cp->next;
+
+ if (bp->next == bp) {
+ mprAssert(bp->prev == bp);
+ if (ptr != bp->app) {
+ mprAssert(parent->children == bp);
+ }
+ }
+ if (bp->prev == bp) {
+ mprAssert(bp->next == bp);
+ if (ptr != bp->app) {
+ mprAssert(parent->children == bp);
+ }
+ }
+ } while (cp != firstChild);
+ }
+
+ return 0;
+}
+
+#endif
+/******************************************************************************/
+/*
+ * Validate a block and all children
+ */
+
+int mprValidateAllocTree(MprCtx ptr)
+{
+#if VALIDATE_ALLOC
+ MprBlk *bp, *cp, *firstChild;
+
+ mprAssert(ptr);
+ mprAssert(VALID_BLK(ptr));
+
+ bp = GET_HDR(ptr);
+
+ mprValidateBlock(GET_PTR(bp));
+
+ if ((firstChild = bp->children) != 0) {
+ cp = firstChild;
+ do {
+ mprValidateAllocTree(GET_PTR(cp));
+ cp = cp->next;
+ } while (cp != firstChild);
+ }
+
+#endif
+ return 0;
+}
+
+/******************************************************************************/
+#if UNUSED && FUTURE
+/*
+ * Exhaustive validation of the block and its children. Does not go recursive
+ * as it would be too slow.
+ */
+
+int mprValidateSlabs(MprApp *app)
+{
+ MprSlab *slab;
+ MprSlabStats *slabStats;
+ MprSlabBlock *sp;
+ int count, i;
+
+ for (i = 0; i < MPR_MAX_SLAB; i++) {
+ slab = &app->alloc.slabs[i];
+ slabStats = &slab->stats;
+
+ count = 0;
+ for (sp = slab->next; sp; sp = sp->next) {
+ count++;
+ }
+ mprAssert(count == (int) slabStats->freeCount);
+ }
+ return 0;
+}
+
+#endif
+/******************************************************************************/
+
+void mprAllocAbort()
+{
+#if BREW
+ printf("Bad block header");
+#else
+ exit(255);
+#endif
+}
+
+/******************************************************************************/
+#undef mprGetApp
+/*
+ * Get the root parent from any block (which is the MprApp structure)
+ */
+
+MprApp *mprGetApp(MprCtx ptr)
+{
+ MprBlk *bp;
+
+ mprAssert(ptr);
+
+ bp = GET_HDR(ptr);
+ mprAssert(VALID_HDR(bp));
+
+ CHECK_HDR(bp);
+
+ mprAssert(bp->app->magic == APP_MAGIC);
+
+ return bp->app;
+}
+
+/******************************************************************************/
+
+int mprGetAllocErrors(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ return app->alloc.stats.errors;
+}
+
+/******************************************************************************/
+
+void mprClearAllocErrors(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ app->alloc.stats.errors = 0;
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/mprArray.c b/source4/lib/appweb/ejs-2.0/mpr/mprArray.c
new file mode 100644
index 0000000000..95b0a14450
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprArray.c
@@ -0,0 +1,385 @@
+/**
+ * @file mprArray.c
+ * @brief Growable array structure
+ * @overview Simple growable array structure.
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/******************************************************************************/
+/*
+ * Create a general growable array structure. Use mprFree to destroy.
+ */
+
+MprArray *mprCreateItemArrayInternal(MPR_LOC_DEC(ctx, loc), int initialSize,
+ int maxSize)
+{
+ MprArray *array;
+ int size;
+
+ mprAssert(initialSize <= maxSize);
+
+ array = (MprArray*) mprSlabAllocZeroedBlock(MPR_LOC_PASS(ctx, loc),
+ sizeof(MprArray), 0);
+ if (array == 0) {
+ return 0;
+ }
+
+ if (initialSize == 0) {
+ initialSize = MPR_ARRAY_INCR;
+ }
+ if (maxSize == 0) {
+ maxSize = MAXINT;
+ }
+ size = initialSize * sizeof(void*);
+
+ array->items = (void**) mprSlabAllocBlock(MPR_LOC_PASS(array, loc),
+ size, 0);
+
+ if (array->items == 0) {
+ mprFree(array);
+ return 0;
+ }
+
+ array->capacity = initialSize;
+ array->maxSize = maxSize;
+ array->incr = min(initialSize * 2, (array->maxSize - array->length));
+ array->length = 0;
+
+ return array;
+}
+
+/******************************************************************************/
+/*
+ * Add an item to the array
+ */
+
+int mprAddItem(MprArray *array, void *item)
+{
+ int memsize, index, len;
+
+ mprAssert(array);
+ mprAssert(array->capacity >= 0);
+ mprAssert(array->length >= 0);
+
+ if (array->length < array->capacity) {
+ /*
+ * Room to fit in the current capacity
+ */
+ index = array->length++;
+ array->items[index] = item;
+ return index;
+ }
+ mprAssert(array->length == array->capacity);
+
+ /*
+ * Need to grow the array
+ */
+ if (array->capacity >= array->maxSize) {
+ mprAssert(array->capacity < array->maxSize);
+ return MPR_ERR_TOO_MANY;
+ }
+
+ len = array->capacity + array->incr;
+ memsize = len * sizeof(void*);
+
+ /*
+ * Grow the array of items
+ */
+
+ array->items = (void**) mprRealloc(array, array->items, memsize);
+
+ /*
+ * Zero the new portion
+ */
+ memset(&array->items[array->capacity], 0, sizeof(void*) * array->incr);
+ array->capacity = len;
+
+ array->incr = min(array->incr * 2, (array->maxSize - array->length));
+
+ index = array->length++;
+ array->items[index] = item;
+
+ return index;
+}
+
+/******************************************************************************/
+/*
+ * Remove an item from the array
+ */
+
+int mprRemoveItem(MprArray *array, void *item)
+{
+ int index;
+
+ mprAssert(array);
+ mprAssert(array->capacity > 0);
+ mprAssert(array->length > 0);
+
+ index = mprFindItem(array, item);
+ if (index < 0) {
+ return index;
+ }
+
+ return mprRemoveItemByIndex(array, index);
+}
+
+/******************************************************************************/
+/*
+ * Remove an index from the array
+ */
+
+int mprRemoveItemByIndex(MprArray *array, int index)
+{
+ void **items;
+ int i;
+
+ mprAssert(array);
+ mprAssert(array->capacity > 0);
+ mprAssert(index >= 0 && index < array->capacity);
+ mprAssert(array->items[index] != 0);
+ mprAssert(array->length > 0);
+
+ if (index < 0 || index >= array->length) {
+ return MPR_ERR_NOT_FOUND;
+ }
+
+ /*
+ * Copy down to compress
+ */
+ items = array->items;
+ for (i = index; i < (array->length - 1); i++) {
+ items[i] = items[i + 1];
+ }
+ array->length--;
+
+#if BLD_DEBUG
+ if (array->length < array->capacity) {
+ items[array->length] = 0;
+ }
+#endif
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprRemoveRangeOfItems(MprArray *array, int start, int end)
+{
+ void **items;
+ int i, count;
+
+ mprAssert(array);
+ mprAssert(array->capacity > 0);
+ mprAssert(array->length > 0);
+ mprAssert(start > end);
+
+ if (start < 0 || start >= array->length) {
+ return MPR_ERR_NOT_FOUND;
+ }
+ if (end < 0 || end >= array->length) {
+ return MPR_ERR_NOT_FOUND;
+ }
+ if (start > end) {
+ return MPR_ERR_BAD_ARGS;
+ }
+
+ /*
+ * Copy down to compress
+ */
+ items = array->items;
+ count = end - start;
+ for (i = start; i < (array->length - count); i++) {
+ items[i] = items[i + count];
+ }
+ array->length -= count;
+
+#if BLD_DEBUG
+ if (array->length < array->capacity) {
+ for (i = array->length; i < array->capacity; i++) {
+ items[i] = 0;
+ }
+ }
+#endif
+ return 0;
+}
+
+/******************************************************************************/
+
+void *mprGetItem(MprArray *array, int index)
+{
+ mprAssert(array);
+
+ if (index < 0 || index >= array->length) {
+ return 0;
+ }
+ return array->items[index];
+}
+
+/******************************************************************************/
+
+void *mprGetFirstItem(MprArray *array, int *last)
+{
+ mprAssert(array);
+ mprAssert(last);
+
+ if (array == 0) {
+ return 0;
+ }
+
+ *last = 0;
+
+ if (array->length == 0) {
+ return 0;
+ }
+ return array->items[0];
+}
+
+/******************************************************************************/
+
+void *mprGetNextItem(MprArray *array, int *last)
+{
+ int index;
+
+ mprAssert(array);
+ mprAssert(last);
+ mprAssert(*last >= 0);
+
+ index = *last;
+
+ if (++index < array->length) {
+ *last = index;
+ return array->items[index];
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+void *mprGetPrevItem(MprArray *array, int *last)
+{
+ int index;
+
+ mprAssert(array);
+ mprAssert(last);
+ mprAssert(*last >= 0);
+
+ if (array == 0) {
+ return 0;
+ }
+
+ index = *last;
+
+ if (--index < array->length && index >= 0) {
+ *last = index;
+ return array->items[index];
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprGetItemCount(MprArray *array)
+{
+ mprAssert(array);
+
+ if (array == 0) {
+ return 0;
+ }
+
+ return array->length;
+}
+
+/******************************************************************************/
+
+int mprGetItemCapacity(MprArray *array)
+{
+ mprAssert(array);
+
+ if (array == 0) {
+ return 0;
+ }
+
+ return array->capacity;
+}
+
+/******************************************************************************/
+
+void mprClearAndFreeItems(MprArray *array)
+{
+ int i;
+
+ mprAssert(array);
+
+ for (i = 0; i < array->length; i++) {
+ mprFree(array->items[i]);
+ }
+}
+
+/******************************************************************************/
+
+void mprClearItems(MprArray *array)
+{
+ mprAssert(array);
+
+ array->length = 0;
+}
+
+/******************************************************************************/
+
+int mprFindItem(MprArray *array, void *item)
+{
+ int i;
+
+ mprAssert(array);
+
+ for (i = 0; i < array->length; i++) {
+ if (array->items[i] == item) {
+ return i;
+ }
+ }
+ return MPR_ERR_NOT_FOUND;
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/mprBuf.c b/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c
new file mode 100644
index 0000000000..ba9888a9fc
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c
@@ -0,0 +1,535 @@
+/**
+ * @file mprBuf.c
+ * @brief Dynamic buffer module
+ * @overview
+ * @remarks
+ */
+
+/******************************************************************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/**************************** Forward Declarations ****************************/
+
+static int grow(MprBuf *bp);
+
+/*********************************** Code *************************************/
+/*
+ * Create a new buffer. "maxsize" is the limit to which the buffer can
+ * ever grow. -1 means no limit. The buffer can ever only fix maxsize-1 bytes.
+ * "initialSize" is used to define the amount to increase the size of the
+ * buffer each time if it becomes full. (Note: grow() will exponentially
+ * increase this number for performance.)
+ */
+
+MprBuf *mprCreateBuf(MprCtx ctx, int initialSize, int maxSize)
+{
+ MprBuf *bp;
+
+ if (initialSize <= 0) {
+ initialSize = MPR_DEFAULT_ALLOC;
+ }
+ bp = mprAllocTypeZeroed(ctx, MprBuf);
+ bp->growBy = MPR_BUFSIZE;
+ bp->maxsize = 0;
+ mprSetBufSize(bp, initialSize, maxSize);
+ return bp;
+}
+
+/******************************************************************************/
+/*
+ * Set the initial buffer parameters and create the first buffer
+ */
+
+void mprSetBufSize(MprBuf *bp, int initialSize, int max)
+{
+ mprAssert(initialSize > 0);
+
+ if (max > 0 && initialSize > max) {
+ initialSize = max;
+ }
+
+ if (bp->buf && bp->growBy > 0) {
+ mprFree(bp->buf);
+ }
+
+ bp->buf = (uchar*) mprAlloc(bp, initialSize);
+ bp->growBy = initialSize;
+ bp->maxsize = max;
+ bp->buflen = initialSize;
+ bp->endbuf = &bp->buf[bp->buflen];
+ bp->start = bp->buf;
+ bp->end = bp->buf;
+ *bp->start = '\0';
+}
+
+/******************************************************************************/
+
+char *mprStealBuf(MprCtx ctx, MprBuf *bp)
+{
+ char *str;
+
+ str = (char*) bp->start;
+
+ mprStealAllocBlock(MPR_LOC_ARGS(ctx), bp->start);
+
+ bp->start = bp->end = bp->buf = bp->endbuf = 0;
+ bp->buflen = 0;
+
+ return str;
+}
+
+/******************************************************************************/
+
+void mprAddNullToBuf(MprBuf *bp)
+{
+ *((char*) bp->end) = (char) '\0';
+}
+
+/******************************************************************************/
+
+void mprAdjustBufEnd(MprBuf *bp, int size)
+{
+ mprAssert(bp->buflen == (bp->endbuf - bp->buf));
+ mprAssert(size < bp->buflen);
+
+ bp->end += size;
+ if (bp->end >= bp->endbuf) {
+ bp->end -= bp->buflen;
+ }
+ if (bp->end < bp->buf) {
+ bp->end += bp->buflen;
+ }
+
+ if (bp->end >= bp->endbuf) {
+ mprAssert(bp->end < bp->endbuf);
+ mprFlushBuf(bp);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Adjust the start pointer after a user copy
+ */
+
+void mprAdjustBufStart(MprBuf *bp, int size)
+{
+ mprAssert(bp->buflen == (bp->endbuf - bp->buf));
+ mprAssert(size < bp->buflen);
+
+ bp->start += size;
+ while (bp->start >= bp->endbuf) {
+ bp->start -= bp->buflen;
+ }
+ while (bp->start < bp->buf) {
+ bp->start += bp->buflen;
+ }
+
+ /*
+ * Flush the buffer if the start pointer is corrupted via a bad size
+ */
+ if (bp->start >= bp->endbuf) {
+ mprAssert(bp->start < bp->endbuf);
+ mprFlushBuf(bp);
+ }
+}
+
+
+/******************************************************************************/
+
+void mprFlushBuf(MprBuf *bp)
+{
+ bp->start = bp->buf;
+ bp->end = bp->buf;
+}
+
+/******************************************************************************/
+
+int mprGetCharFromBuf(MprBuf *bp)
+{
+ int c;
+
+ if (bp->start == bp->end) {
+ return -1;
+ }
+ c = (uchar) *bp->start++;
+ if (bp->start >= bp->endbuf) {
+ bp->start = bp->buf;
+ }
+ return c;
+}
+
+/******************************************************************************/
+
+int mprGetBlockFromBuf(MprBuf *bp, uchar *buf, int size)
+{
+ int thisLen, bytesRead;
+
+ mprAssert(buf);
+ mprAssert(size > 0);
+ mprAssert(bp->buflen == (bp->endbuf - bp->buf));
+
+ /*
+ * Get the max bytes in a straight copy
+ */
+ bytesRead = 0;
+ while (size > 0) {
+ thisLen = mprGetBufLinearData(bp);
+ thisLen = min(thisLen, size);
+ if (thisLen <= 0) {
+ break;
+ }
+
+ memcpy(buf, bp->start, thisLen);
+ buf += thisLen;
+ bp->start += thisLen;
+ size -= thisLen;
+ bytesRead += thisLen;
+
+ if (bp->start >= bp->endbuf) {
+ bp->start = bp->buf;
+ }
+ }
+ return bytesRead;
+}
+
+/******************************************************************************/
+
+int mprGetBufLength(MprBuf *bp)
+{
+ if (bp->start > bp->end) {
+ return (bp->buflen + (bp->end - bp->start));
+ } else {
+ return (bp->end - bp->start);
+ }
+}
+
+/******************************************************************************/
+
+int mprGetBufLinearData(MprBuf *bp)
+{
+ return min(mprGetBufLength(bp), (bp->endbuf - bp->start));
+}
+
+/******************************************************************************/
+
+int mprGetBufLinearSpace(MprBuf *bp)
+{
+ int len = mprGetBufLength(bp);
+ int space = bp->buflen - len - 1;
+ return min((bp->endbuf - bp->end), space);
+}
+
+/******************************************************************************/
+
+int mprGetBufSize(MprBuf *bp)
+{
+ return bp->buflen;
+}
+
+/******************************************************************************/
+
+int mprGetBufSpace(MprBuf *bp)
+{
+ return bp->buflen - mprGetBufLength(bp) - 1;
+}
+
+/******************************************************************************/
+
+char *mprGetBufOrigin(MprBuf *bp)
+{
+ return (char*) bp->buf;
+}
+
+/******************************************************************************/
+
+char *mprGetBufStart(MprBuf *bp)
+{
+ return (char*) bp->start;
+}
+
+/******************************************************************************/
+
+char *mprGetBufEnd(MprBuf *bp)
+{
+ return (char*) bp->end;
+}
+
+/******************************************************************************/
+
+int mprInsertCharToBuf(MprBuf *bp, int c)
+{
+ char *cp;
+ int space;
+
+ mprAssert(bp->buflen == (bp->endbuf - bp->buf));
+
+ space = bp->buflen - mprGetBufLength(bp) - 1;
+ if (space < (int) sizeof(char)) {
+ if (!grow(bp)) {
+ return -1;
+ }
+ }
+ if (bp->start <= bp->buf) {
+ bp->start = bp->endbuf;
+ }
+ cp = (char*) bp->start;
+ *--cp = (char) c;
+ bp->start = (uchar *) cp;
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprLookAtNextCharInBuf(MprBuf *bp)
+{
+ if (bp->start == bp->end) {
+ return -1;
+ }
+ return *bp->start;
+}
+
+/******************************************************************************/
+
+int mprLookAtLastCharInBuf(MprBuf *bp)
+{
+ if (bp->start == bp->end) {
+ return -1;
+ }
+ return (bp->end == bp->buf) ? bp->endbuf[-1] : bp->end[-1];
+}
+
+/******************************************************************************/
+
+int mprPutCharToBuf(MprBuf *bp, int c)
+{
+ char *cp;
+ int space;
+
+ mprAssert(bp->buflen == (bp->endbuf - bp->buf));
+
+ space = bp->buflen - mprGetBufLength(bp) - 1;
+ if (space < (int) sizeof(char)) {
+ if (! grow(bp)) {
+ return -1;
+ }
+ }
+
+ cp = (char*) bp->end;
+ *cp++ = (char) c;
+ bp->end = (uchar *) cp;
+ if (bp->end >= bp->endbuf) {
+ bp->end = bp->buf;
+ }
+ *((char*) bp->end) = (char) '\0';
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprPutBlockToBuf(MprBuf *bp, const char *str, int size)
+{
+ int thisLen, bytes, space;
+
+ mprAssert(str);
+ mprAssert(size >= 0);
+ mprAssert(bp->buflen == (bp->endbuf - bp->buf));
+
+ /*
+ * Add the max we can in one copy
+ */
+ bytes = 0;
+ while (size > 0) {
+ space = mprGetBufLinearSpace(bp);
+ thisLen = min(space, size);
+ if (thisLen <= 0) {
+ if (! grow(bp)) {
+ break;
+ }
+ space = mprGetBufLinearSpace(bp);
+ thisLen = min(space, size);
+ }
+
+ memcpy(bp->end, str, thisLen);
+ str += thisLen;
+ bp->end += thisLen;
+ size -= thisLen;
+ bytes += thisLen;
+
+ if (bp->end >= bp->endbuf) {
+ bp->end = bp->buf;
+ }
+ }
+ *((char*) bp->end) = (char) '\0';
+ return bytes;
+}
+
+/******************************************************************************/
+
+int mprPutStringToBuf(MprBuf *bp, const char *str)
+{
+ return mprPutBlockToBuf(bp, str, strlen(str));
+}
+
+/******************************************************************************/
+
+int mprPutFmtStringToBuf(MprBuf *bp, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ int rc, len, space;
+
+ va_start(ap, fmt);
+ space = mprGetBufLinearSpace(bp);
+
+ /*
+ * Add max that the buffer can grow
+ */
+ space += (bp->maxsize - bp->buflen - 1);
+
+ len = mprAllocVsprintf(MPR_LOC_ARGS(bp), &buf, space, fmt, ap);
+ rc = mprPutBlockToBuf(bp, buf, len);
+
+ mprFree(buf);
+ va_end(ap);
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Grow the buffer to fit new data. Return 1 if the buffer can grow.
+ * Grow using the growBy size specified when creating the buffer.
+ */
+
+static int grow(MprBuf *bp)
+{
+ uchar *newbuf;
+
+ if (bp->maxsize > 0 && bp->buflen >= bp->maxsize) {
+ return 0;
+ }
+
+ newbuf = (uchar*) mprAlloc(bp, bp->buflen + bp->growBy);
+ if (bp->buf) {
+ memcpy(newbuf, bp->buf, bp->buflen);
+ mprFree(bp->buf);
+ }
+
+ bp->buflen += bp->growBy;
+ bp->end = newbuf + (bp->end - bp->buf);
+ bp->start = newbuf + (bp->start - bp->buf);
+ bp->buf = newbuf;
+ bp->endbuf = &bp->buf[bp->buflen];
+
+ /*
+ * Increase growBy to reduce overhead
+ */
+ bp->growBy *= 2;
+ if (bp->maxsize > 0 && (bp->buflen + bp->growBy) > bp->maxsize) {
+ bp->growBy = bp->maxsize - bp->buflen;
+ }
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Add a number to the buffer (always null terminated).
+ */
+
+int mprPutIntToBuf(MprBuf *bp, int i)
+{
+ char numBuf[16];
+ int rc;
+
+ mprItoa(numBuf, sizeof(numBuf), i);
+ rc = mprPutStringToBuf(bp, numBuf);
+ *((char*) bp->end) = (char) '\0';
+
+ return rc;
+}
+
+/******************************************************************************/
+
+void mprCopyBufDown(MprBuf *bp)
+{
+ if (mprGetBufLength(bp) == 0) {
+ mprFlushBuf(bp);
+ return;
+ }
+ memmove(bp->buf, bp->start, (bp->end - bp->start));
+ bp->end -= (bp->start - bp->buf);
+ bp->start = bp->buf;
+}
+
+/******************************************************************************/
+
+MprBufProc mprGetBufRefillProc(MprBuf *bp)
+{
+ return bp->refillProc;
+}
+
+/******************************************************************************/
+
+void mprSetBufRefillProc(MprBuf *bp, MprBufProc fn, void *arg)
+{
+ bp->refillProc = fn;
+ bp->refillArg = arg;
+}
+
+/******************************************************************************/
+
+int mprRefillBuf(MprBuf *bp)
+{
+ return (bp->refillProc) ? (bp->refillProc)(bp, bp->refillArg) : 0;
+}
+
+/******************************************************************************/
+
+void mprResetBufIfEmpty(MprBuf *bp)
+{
+ if (mprGetBufLength(bp) == 0) {
+ mprFlushBuf(bp);
+ }
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/mprGenFile.c b/source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c
new file mode 100644
index 0000000000..517e43853f
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c
@@ -0,0 +1,336 @@
+/**
+ * @file mprGenFile.c
+ * @brief Generic File services
+ * @overview
+ * @remarks
+ * See OS/mprFile.c for the per O/S portions
+ */
+
+/******************************************************************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/****************************** Forward Declarations **************************/
+#if !BREW
+
+static int closeDestructor(void *data);
+
+/************************************ Code ************************************/
+
+int mprStartFileServices(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ app->console = mprAllocTypeZeroed(ctx, MprFile);
+ app->error = mprAllocTypeZeroed(ctx, MprFile);
+
+ /*
+ * We assume that STDOUT is 1 and STDERR is 2
+ */
+ app->console->fd = 1;
+ app->error->fd = 2;
+
+ return 0;
+}
+
+/******************************************************************************/
+
+void mprStopFileServices(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+
+ mprFree(app->console);
+ app->console = 0;
+ mprFree(app->error);
+ app->error = 0;
+}
+
+/******************************************************************************/
+
+MprFile *mprOpen(MprCtx ctx, const char *path, int omode, int perms)
+{
+ MprFile *file;
+
+ mprAssert(path && *path);
+
+ file = mprAllocTypeZeroed(ctx, MprFile);
+
+ file->fd = open(path, omode, perms);
+ if (file->fd < 0) {
+ mprFree(file);
+ return 0;
+ }
+
+ mprSetDestructor(file, closeDestructor);
+ return file;
+}
+
+/******************************************************************************/
+
+static int closeDestructor(void *data)
+{
+ MprFile *file = (MprFile*) data;
+
+ mprAssert(file);
+
+ mprClose(file);
+ return 0;
+}
+
+/******************************************************************************/
+
+void mprClose(MprFile *file)
+{
+ mprAssert(file);
+
+ if (file < 0) {
+ return;
+ }
+
+ mprAssert(file->fd >= 0);
+ close(file->fd);
+
+ mprSetDestructor(file, 0);
+ mprFree(file);
+}
+
+/******************************************************************************/
+
+int mprRead(MprFile *file, void *buf, uint size)
+{
+ mprAssert(file);
+
+ if (file == 0) {
+ return MPR_ERR_BAD_HANDLE;
+ }
+
+ return read(file->fd, buf, size);
+}
+
+/******************************************************************************/
+
+int mprWrite(MprFile *file, const void *buf, uint count)
+{
+ mprAssert(file);
+
+ if (file == 0) {
+ return MPR_ERR_BAD_HANDLE;
+ }
+
+ return write(file->fd, buf, count);
+}
+
+/******************************************************************************/
+
+int mprSeek(MprFile *file, int seekType, long distance)
+{
+ mprAssert(file);
+
+ if (file == 0) {
+ return MPR_ERR_BAD_HANDLE;
+ }
+
+ return lseek(file->fd, seekType, distance);
+}
+
+/******************************************************************************/
+
+int mprDelete(MprCtx ctx, const char *path)
+{
+ return unlink(path);
+}
+
+/******************************************************************************/
+
+int mprDeleteDir(MprCtx ctx, const char *path)
+{
+ return rmdir(path);
+}
+
+#endif /* !BREW */
+/******************************************************************************/
+
+char *mprGets(MprFile *file, char *buf, uint size)
+{
+ MprBuf *bp;
+ int count, len, c;
+
+ mprAssert(file);
+
+ if (file == 0) {
+ return 0;
+ }
+
+ if (file->buf == 0) {
+ file->buf = mprCreateBuf(file, MPR_DEFAULT_ALLOC, MPR_MAX_STRING);
+ }
+ bp = file->buf;
+
+ /*
+ * Must leave room for null
+ */
+ count = 0;
+ while (--size > 0) {
+ if (mprGetBufLength(bp) == 0) {
+ mprFlushBuf(bp);
+ len = mprRead(file, mprGetBufEnd(bp),
+ mprGetBufLinearSpace(bp));
+ if (len <= 0) {
+ return 0;
+ }
+ mprAdjustBufEnd(bp, len);
+ mprAddNullToBuf(bp);
+ }
+ if ((c = mprGetCharFromBuf(bp)) == '\n') {
+ buf[count] = '\0';
+ return buf;
+ }
+ buf[count++] = c;
+ }
+ buf[count] = '\0';
+ return buf;
+}
+
+/******************************************************************************/
+
+int mprPuts(MprFile *file, const char *writeBuf, uint count)
+{
+ MprBuf *bp;
+ char *buf;
+ int total, bytes, len;
+
+ mprAssert(file);
+
+ /*
+ * Buffer output and flush when full.
+ */
+ if (file->buf == 0) {
+ file->buf = mprCreateBuf(file, MPR_BUFSIZE, 0);
+ if (file->buf == 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ }
+ bp = file->buf;
+
+ if (mprGetBufLength(bp) > 0 && mprGetBufSpace(bp) < (int) count) {
+ len = mprGetBufLength(bp);
+ if (mprWrite(file, mprGetBufStart(bp), len) != len) {
+ return MPR_ERR_CANT_WRITE;
+ }
+ mprFlushBuf(bp);
+ }
+
+ total = 0;
+ buf = (char*) writeBuf;
+
+ while (count > 0) {
+ bytes = mprPutBlockToBuf(bp, buf, count);
+ if (bytes <= 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ count -= bytes;
+ buf += bytes;
+ total += bytes;
+ mprAddNullToBuf(bp);
+
+ if (count > 0) {
+ len = mprGetBufLength(bp);
+ if (mprWrite(file, mprGetBufStart(bp), len) != len) {
+ return MPR_ERR_CANT_WRITE;
+ }
+ mprFlushBuf(bp);
+ }
+ }
+ return total;
+}
+
+/******************************************************************************/
+
+int mprMakeTempFileName(MprCtx ctx, char *buf, int bufsize, const char *tempDir)
+{
+ MprFile *file;
+ MprTime now;
+ char *dir;
+ int seed, i;
+
+ if (tempDir == 0) {
+#if WIN
+ char *cp;
+ dir = mprStrdup(ctx, getenv("TEMP"));
+ for (cp = dir; *cp; cp++) {
+ if (*cp == '\\') {
+ *cp = '/';
+ }
+ }
+#else
+ dir = mprStrdup(ctx, "/tmp");
+#endif
+ } else {
+ dir = mprStrdup(ctx, tempDir);
+ }
+
+ mprGetTime(ctx, &now);
+ seed = now.msec % 64000;
+ file = 0;
+
+ for (i = 0; i < 128; i++) {
+ mprSprintf(buf, bufsize, "%s/MPR_%d_%d.tmp", dir, getpid(), seed++);
+ file = mprOpen(ctx, buf, O_CREAT | O_EXCL | O_BINARY, 0664);
+ if (file) {
+ break;
+ }
+ }
+
+ if (file == 0) {
+ return MPR_ERR_CANT_CREATE;
+ }
+
+ mprClose(file);
+ mprFree(dir);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/mprGenTime.c b/source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c
new file mode 100644
index 0000000000..6b0ed97bbc
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c
@@ -0,0 +1,195 @@
+/**
+ * @file mprGenTime.c
+ * @brief Generic Time handling
+ * @overview
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************/
+/*
+ * Return the number of milliseconds until the given timeout has expired.
+ */
+
+int mprGetTimeRemaining(MprCtx ctx, MprTime mark, uint timeout)
+{
+ MprTime now;
+ uint diff;
+
+ mprGetTime(ctx, &now);
+ diff = ((now.sec - mark.sec) * 1000) + (now.msec - mark.msec);
+
+ if (diff < 0) {
+ /*
+ * Detect time going backwards
+ */
+ mprAssert(diff >= 0);
+ diff = 0;
+ }
+ return (int) (timeout - diff);
+}
+
+/******************************************************************************/
+/*
+ * Return the number of milliseconds until the given timeout has expired.
+ */
+
+int mprGetElapsedTime(MprCtx ctx, MprTime mark)
+{
+ MprTime now;
+
+ mprGetTime(ctx, &now);
+ return ((now.sec - mark.sec) * 1000) + (now.msec - mark.msec);
+}
+
+/******************************************************************************/
+
+void mprAddElapsedToTime(MprTime *time, uint elapsed)
+{
+ time->sec += elapsed / 1000;
+ time->msec += elapsed % 1000;
+ if (time->msec > 1000) {
+ time->msec -= 1000;
+ time->sec++;
+ }
+}
+
+/******************************************************************************/
+
+int mprCompareTime(MprTime *t1, MprTime *t2)
+{
+ if (t1->sec < t2->sec) {
+ return -1;
+ } else if (t1->sec == t2->sec) {
+ if (t1->msec < t2->msec) {
+ return -1;
+ } else if (t1->msec == t2->msec) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+
+uint mprSubtractTime(MprTime *t1, MprTime *t2)
+{
+ return ((t1->sec - t2->sec) * 1000) + (t1->msec - t2->msec);
+}
+
+/******************************************************************************/
+#if !BREW
+/*
+ * Thread-safe RFC822 dates (Eg: "Fri, 07 Jan 2003 12:12:21 GMT")
+ */
+
+int mprRfcTime(MprCtx ctx, char *buf, int bufsize, const struct tm *timep)
+{
+ char months[12][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"
+ };
+
+ char days[7][4] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+
+ char *dayp, *monthp;
+ int year;
+
+ if (bufsize < 30) {
+ return MPR_ERR_WONT_FIT;
+ }
+ dayp = &days[timep->tm_wday][0];
+ *buf++ = *dayp++;
+ *buf++ = *dayp++;
+ *buf++ = *dayp++;
+ *buf++ = ',';
+ *buf++ = ' ';
+
+ *buf++ = timep->tm_mday / 10 + '0';
+ *buf++ = timep->tm_mday % 10 + '0';
+ *buf++ = ' ';
+
+ monthp = &months[timep->tm_mon][0];
+ *buf++ = *monthp++;
+ *buf++ = *monthp++;
+ *buf++ = *monthp++;
+ *buf++ = ' ';
+
+ year = 1900 + timep->tm_year;
+ /* This routine isn't y10k ready. */
+ *buf++ = year / 1000 + '0';
+ *buf++ = year % 1000 / 100 + '0';
+ *buf++ = year % 100 / 10 + '0';
+ *buf++ = year % 10 + '0';
+ *buf++ = ' ';
+
+ *buf++ = timep->tm_hour / 10 + '0';
+ *buf++ = timep->tm_hour % 10 + '0';
+ *buf++ = ':';
+ *buf++ = timep->tm_min / 10 + '0';
+ *buf++ = timep->tm_min % 10 + '0';
+ *buf++ = ':';
+ *buf++ = timep->tm_sec / 10 + '0';
+ *buf++ = timep->tm_sec % 10 + '0';
+ *buf++ = ' ';
+
+ *buf++ = 'G';
+ *buf++ = 'M';
+ *buf++ = 'T';
+ *buf++ = 0;
+ return 0;
+}
+
+#endif
+/******************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * 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/mpr/mprLock.c b/source4/lib/appweb/ejs-2.0/mpr/mprLock.c
new file mode 100644
index 0000000000..df9ce276d4
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprLock.c
@@ -0,0 +1,266 @@
+/**
+ * @file mprThread.c
+ * @brief Mbedthis Portable Runtime Base Thread Locking Support
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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
+ */
+
+#include "mpr.h"
+
+#if BLD_FEATURE_MULTITHREAD
+/************************************ Code ************************************/
+
+void mprInitThreads(MprApp *app)
+{
+ mprAssert(app);
+
+ if (app->globalLock == 0) {
+ app->globalLock = mprCreateLock(app);
+ app->allocLock = mprCreateLock(app);
+ }
+}
+
+/******************************************************************************/
+
+void mprTermThreads(MprApp *app)
+{
+ mprAssert(app);
+
+ if (app->globalLock) {
+ mprDestroyLock(app->globalLock);
+ app->globalLock = 0;
+ }
+ if (app->allocLock) {
+ MprLock *lock = app->allocLock;
+ app->allocLock = 0;
+ mprDestroyLock(lock);
+ }
+}
+
+/******************************************************************************/
+
+MprLock *mprCreateLock(MprCtx ctx)
+{
+ MprLock *lock;
+
+ mprAssert(ctx);
+
+ lock = mprAllocType(ctx, MprLock);
+
+#if BLD_HOST_UNIX
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+ pthread_mutex_init(&lock->cs, &attr);
+ pthread_mutexattr_destroy(&attr);
+#elif WIN
+ InitializeCriticalSectionAndSpinCount(&lock->cs, 5000);
+#elif VXWORKS
+ lock->cs = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE |
+ SEM_INVERSION_SAFE);
+ if (lock->cs == 0) {
+ mprAssert(0);
+ mprFree(lock);
+ return 0;
+ }
+#endif
+ return lock;
+}
+
+/******************************************************************************/
+/*
+ * Destroy a lock. Must be locked on entrance.
+ */
+
+void mprDestroyLock(MprLock *lock)
+{
+ mprAssert(lock);
+ if (lock == 0) {
+ return;
+ }
+
+#if BLD_HOST_UNIX
+ pthread_mutex_unlock(&lock->cs);
+ pthread_mutex_destroy(&lock->cs);
+#elif WIN
+ DeleteCriticalSection(&lock->cs);
+#elif VXWORKS
+ semDelete(lock->cs);
+#endif
+ mprFree(lock);
+}
+
+/******************************************************************************/
+/*
+ * Lock a mutex
+ */
+
+void mprLock(MprLock *lock)
+{
+ /*
+ * OPT -- Do this just so we can allocate MprApp before we have created its
+ * lock. Should remove this test here and in mprUnlock.
+ */
+ if (lock == 0) {
+ return;
+ }
+
+#if BLD_HOST_UNIX
+ pthread_mutex_lock(&lock->cs);
+#elif WIN
+ EnterCriticalSection(&lock->cs);
+#elif VXWORKS
+ semTake(lock->cs, WAIT_FOREVER);
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Try to attain a lock. Do not block!
+ */
+
+int mprTryLock(MprLock *lock)
+{
+ mprAssert(lock);
+
+#if BLD_HOST_UNIX
+ {
+ int err;
+
+ if ((err = pthread_mutex_trylock(&lock->cs)) != 0) {
+ if (err == EBUSY) {
+ return MPR_ERR_BUSY;
+ } else {
+ return MPR_ERR_CANT_ACCESS;
+ }
+ }
+ return 0;
+ }
+#elif WIN
+ if (TryEnterCriticalSection(&lock->cs) == 0) {
+ return MPR_ERR_BUSY;
+ }
+#elif VXWORKS
+ {
+ int rc;
+
+ rc = semTake(cs, NO_WAIT);
+ if (rc == -1) {
+ mprAssert(0);
+ }
+ if (rc == S_objLib_OBJ_UNAVAILABLE) {
+ return MPR_ERR_BUSY;
+ } else {
+ return MPR_ERR_CANT_ACCESS;
+ }
+ /* Success */
+ return 0;
+ }
+#endif
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Unlock.
+ */
+
+void mprUnlock(MprLock *lock)
+{
+ if (lock == 0) {
+ return;
+ }
+
+#if BLD_HOST_UNIX
+ pthread_mutex_unlock(&lock->cs);
+#elif WIN
+ LeaveCriticalSection(&lock->cs);
+#elif VXWORKS
+ semGive(lock->cs);
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Big global lock. Avoid using this.
+ */
+
+void mprGlobalLock(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ mprAssert(app);
+
+ if (app && app->globalLock) {
+ mprLock(app->globalLock);
+ }
+}
+
+/******************************************************************************/
+
+void mprGlobalUnlock(MprCtx ctx)
+{
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+ mprAssert(app);
+
+ if (app && app->globalLock) {
+ mprUnlock(app->globalLock);
+ }
+}
+
+/******************************************************************************/
+
+int mprGetCurrentThreadID()
+{
+#if BLD_HOST_UNIX
+ return (int) pthread_self();
+#elif WIN
+ return GetCurrentThreadId();
+#elif VXWORKS
+ return (int) pthread_self();
+#endif
+}
+
+/******************************************************************************/
+#endif /* BLD_FEATURE_MULTITHREAD */
+
+/*
+ * 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/mpr/mprLog.c b/source4/lib/appweb/ejs-2.0/mpr/mprLog.c
new file mode 100644
index 0000000000..1eb175ed95
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprLog.c
@@ -0,0 +1,602 @@
+/**
+ * @file mprLog.c
+ * @brief Mbedthis Portable Runtime (MPR) Logging and error reporting.
+ * @remarks We always provide these routines.
+ */
+
+/*********************************** License **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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
+ */
+
+#include "mpr.h"
+
+/****************************** Forward Declarations **************************/
+
+static void defaultLogHandler(MPR_LOC_DEC(ctx, loc), int flags,
+ int level, const char *msg);
+static void logOutput(MPR_LOC_DEC(ctx, loc), int flags, int level,
+ const char *msg);
+
+/************************************ Code ************************************/
+
+void mprLog(MprCtx ctx, int level, const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+
+ if (level > mprGetLogLevel(ctx)) {
+ return;
+ }
+
+ va_start(args, fmt);
+ mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
+ va_end(args);
+
+ logOutput(MPR_LOC_ARGS(ctx), MPR_LOG_SRC, level, buf);
+
+ va_end(args);
+ mprFree(buf);
+}
+
+/*****************************************************************************/
+/*
+ * Do raw output
+ */
+
+void mprRawLog(MprCtx ctx, const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int len;
+
+ va_start(args, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
+ va_end(args);
+
+ logOutput(MPR_LOC_ARGS(ctx), MPR_RAW, 0, buf);
+ mprFree(buf);
+}
+
+/*****************************************************************************/
+/*
+ * Handle an error
+ */
+
+void mprError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int len;
+
+ va_start(args, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
+ va_end(args);
+
+ logOutput(MPR_LOC_PASS(ctx, loc), MPR_ERROR_MSG | MPR_ERROR_SRC, 0, buf);
+
+ mprFree(buf);
+}
+
+/*****************************************************************************/
+/*
+ * Handle an error that should be displayed to the user
+ */
+
+void mprUserError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int len;
+
+ va_start(args, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
+ va_end(args);
+
+ logOutput(MPR_LOC_PASS(ctx, loc), MPR_USER_MSG | MPR_ERROR_SRC, 0, buf);
+
+ mprFree(buf);
+}
+
+/*****************************************************************************/
+/*
+ * Handle a fatal error. Forcibly shutdown the application.
+ */
+
+void mprFatalError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int len;
+
+ va_start(args, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
+ va_end(args);
+
+ logOutput(MPR_LOC_PASS(ctx, loc), MPR_USER_MSG | MPR_FATAL_SRC, 0, buf);
+
+ mprFree(buf);
+
+#if BREW
+ mprSignalExit(ctx);
+#else
+ exit(2);
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * Handle a program assertion
+ */
+
+void mprAssertError(MPR_LOC_DEC(ctx, loc), const char *msg)
+{
+ logOutput(MPR_LOC_PASS(ctx, loc), MPR_ASSERT_MSG | MPR_ASSERT_SRC, 0, msg);
+}
+
+/*****************************************************************************/
+/*
+ * Handle an error
+ */
+
+void mprStaticError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
+{
+ va_list args;
+ int len;
+ char buf[MPR_MAX_STRING];
+
+ va_start(args, fmt);
+ len = mprVsprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ logOutput(MPR_LOC_PASS(ctx, loc), MPR_ERROR_MSG | MPR_ERROR_SRC, 0, buf);
+}
+
+/*****************************************************************************/
+/*
+ * Direct output to the standard output. Does not hook into the logging
+ * system and does not allocate memory.
+ */
+
+void mprStaticAssert(const char *loc, const char *msg)
+{
+#if BLD_DEBUG
+ char buf[MPR_MAX_STRING];
+ int len;
+
+ len = mprSprintf(buf, sizeof(buf), "Assertion %s, failed at %s\n",
+ msg, loc);
+ mprBreakpoint(loc, buf);
+
+#if BLD_HOST_UNIX
+ /*
+ * MOB -- but is stdout always okay to use
+ */
+ write(1, buf, len);
+#elif BREW || WIN
+ /*
+ * Only time we use printf. We can't get an alloc context so we have
+ * to use real print
+ */
+#if BREW && !BREW_SIMULATOR
+ printf(" MP: %s\n", buf);
+#else
+ printf("%s\n", buf);
+#endif
+
+#endif
+#endif
+}
+
+/*****************************************************************************/
+
+int mprGetLogLevel(MprCtx ctx)
+{
+ return mprGetApp(ctx)->logLevel;
+}
+
+/******************************************************************************/
+
+void mprSetLogLevel(MprCtx ctx, int level)
+{
+ mprGetApp(ctx)->logLevel = level;
+}
+
+/*****************************************************************************/
+/*
+ * Output a log message to the log handler
+ */
+
+static void logOutput(MPR_LOC_DEC(ctx, loc), int flags, int level,
+ const char *msg)
+{
+ MprLogHandler handler;
+
+ if (flags & (MPR_ERROR_SRC | MPR_FATAL_SRC | MPR_ASSERT_SRC)) {
+ mprBreakpoint(MPR_LOC, 0);
+ }
+
+ mprAssert(ctx != 0);
+ handler = mprGetApp(ctx)->logHandler;
+ if (handler != 0) {
+ (handler)(MPR_LOC_PASS(ctx, loc), flags, level, msg);
+ return;
+ }
+ defaultLogHandler(MPR_LOC_PASS(ctx, loc), flags, level, msg);
+}
+
+/*****************************************************************************/
+/*
+ * Default log output is just to the console
+ */
+
+static void defaultLogHandler(MPR_LOC_DEC(ctx, loc), int flags,
+ int level, const char *msg)
+{
+ MprApp *app;
+ char *prefix;
+
+ app = mprGetApp(ctx);
+ prefix = app->name;
+
+ while (*msg == '\n') {
+ mprPrintf(ctx, "\n");
+ msg++;
+ }
+
+ if (flags & MPR_LOG_SRC) {
+#if BREW && !BREW_SIMULATOR
+ mprPrintf(ctx, "%s\n", msg);
+#else
+ mprPrintf(ctx, "%s: %d: %s\n", prefix, level, msg);
+#endif
+
+ } else if (flags & MPR_ERROR_SRC) {
+ /*
+ * Use static printing to avoid malloc when the messages are small.
+ * This is important for memory allocation errors.
+ */
+ if (strlen(msg) < (MPR_MAX_STRING - 32)) {
+ mprStaticPrintf(ctx, "%s: Error: %s\n", prefix, msg);
+ } else {
+ mprPrintf(ctx, "%s: Error: %s\n", prefix, msg);
+ }
+
+ } else if (flags & MPR_FATAL_SRC) {
+ mprPrintf(ctx, "%s: Fatal: %s\n", prefix, msg);
+
+ } else if (flags & MPR_ASSERT_SRC) {
+#if BLD_FEATURE_ALLOC_LEAK_TRACK
+ mprPrintf(ctx, "%s: Assertion %s, failed at %s\n", prefix, msg, loc);
+#else
+ mprPrintf(ctx, "%s: Assertion %s, failed\n", prefix, msg);
+#endif
+
+ } else if (flags & MPR_RAW) {
+ mprPrintf(ctx, "%s", msg);
+
+ } else {
+ return;
+ }
+}
+
+/*****************************************************************************/
+/*
+ * Map the O/S error code to portable error codes.
+ */
+
+int mprGetOsError()
+{
+#if WIN
+ int rc;
+ rc = GetLastError();
+
+ /*
+ * Client has closed the pipe
+ */
+ if (rc == ERROR_NO_DATA) {
+ return EPIPE;
+ }
+ return rc;
+#endif
+#if LINUX || VXWORKS || SOLARIS
+ return errno;
+#endif
+#if BREW
+ /*
+ * No such thing on Brew. Errors are per class
+ */
+ return 0;
+#endif
+}
+
+/******************************************************************************/
+#if UNUSED
+
+const char *mprGetErrorMsg(int err)
+{
+ /*
+ * MPR error messages. Declare here so we don't have any globals.
+ */
+ char *mprErrMessages[] = {
+ /* 0 MPR_ERR_OK */ "Success",
+ /* -201 MPR_ERR_GENERAL */ "General error",
+ /* -202 MPR_ERR_ABORTED */ "Aborted",
+ /* -203 MPR_ERR_ALREADY_EXISTS */ "Already exists",
+ /* -204 MPR_ERR_BAD_ARGS */ "Bad args",
+ /* -205 MPR_ERR_BAD_FORMAT */ "Bad format",
+ /* -206 MPR_ERR_BAD_HANDLE */ "Bad handle",
+ /* -207 MPR_ERR_BAD_STATE */ "Bad state",
+ /* -208 MPR_ERR_BAD_SYNTAX */ "Bad syntax",
+ /* -209 MPR_ERR_BAD_TYPE */ "Bad type",
+ /* -210 MPR_ERR_BAD_VALUE */ "Bad value",
+ /* -211 MPR_ERR_BUSY */ "Busy",
+ /* -212 MPR_ERR_CANT_ACCESS */ "Can't access",
+ /* -213 MPR_ERR_CANT_COMPLETE */ "Can't complete",
+ /* -214 MPR_ERR_CANT_CREATE */ "Can't create",
+ /* -215 MPR_ERR_CANT_INITIALIZE */ "Can't initialize",
+ /* -216 MPR_ERR_CANT_OPEN */ "Can't open",
+ /* -217 MPR_ERR_CANT_READ */ "Can't read",
+ /* -218 MPR_ERR_CANT_WRITE */ "Can't write",
+ /* -219 MPR_ERR_DELETED */ "Already deleted",
+ /* -220 MPR_ERR_NETWORK */ "Network error",
+ /* -221 MPR_ERR_NOT_FOUND */ "Not found",
+ /* -222 MPR_ERR_NOT_INITIALIZED */ "Not initialized",
+ /* -223 MPR_ERR_NOT_READY */ "Not ready",
+ /* -224 MPR_ERR_READ_ONLY */ "Read only",
+ /* -225 MPR_ERR_TIMEOUT */ "Timeout",
+ /* -226 MPR_ERR_TOO_MANY */ "Too many",
+ /* -227 MPR_ERR_WONT_FIT */ "Won't fit",
+ /* -228 MPR_ERR_WOULD_BLOCK */ "Would block",
+ /* -229 MPR_ERR_CANT_ALLOCATE */ "Can't allocate",
+ };
+ int mprNumErr = sizeof(mprErrMessages) / sizeof(char*);
+
+/*
+ * Operating system error messages
+ */
+#if WIN
+char *osErrMessages[] =
+{
+ /* 0 */ "No error",
+ /* 1 EPERM */ "Operation not permitted",
+ /* 2 ENOENT */ "No such file or directory",
+ /* 3 ESRCH */ "No such process",
+ /* 4 EINTR */ "Interrupted function call",
+ /* 5 EIO */ "I/O error",
+ /* 6 ENXIO */ "No such device or address",
+ /* 7 E2BIG */ "Arg list too long",
+ /* 8 ENOEXEC */ "Exec format error",
+ /* 9 EBADF */ "Bad file number",
+ /* 10 ECHILD */ "No child processes",
+ /* 11 EAGAIN */ "Try again",
+ /* 12 ENOMEM */ "Out of memory",
+ /* 13 EACCES */ "Permission denied",
+ /* 14 EFAULT */ "Bad address",
+ /* 15 ENOTBLK */ "Unknown error",
+ /* 16 EBUSY */ "Resource busy",
+ /* 17 EEXIST */ "File exists",
+ /* 18 EXDEV */ "Improper link",
+ /* 19 ENODEV */ "No such device",
+ /* 20 ENOTDIR */ "Not a directory",
+ /* 21 EISDIR */ "Is a directory",
+ /* 22 EINVAL */ "Invalid argument",
+ /* 23 ENFILE */ "Too many open files in system",
+ /* 24 EMFILE */ "Too many open files",
+ /* 25 ENOTTY */ "Inappropriate I/O control operation",
+ /* 26 ETXTBSY */ "Unknown error",
+ /* 27 EFBIG */ "File too large",
+ /* 28 ENOSPC */ "No space left on device",
+ /* 29 ESPIPE */ "Invalid seek",
+ /* 30 EROFS */ "Read-only file system",
+ /* 31 EMLINK */ "Too many links",
+ /* 32 EPIPE */ "Broken pipe",
+ /* 33 EDOM */ "Domain error",
+ /* 34 ERANGE */ "Result too large",
+ /* 35 EUCLEAN */ "Unknown error",
+ /* 36 EDEADLK */ "Resource deadlock would occur",
+ /* 37 UNKNOWN */ "Unknown error",
+ /* 38 ENAMETOOLONG */ "Filename too long",
+ /* 39 ENOLCK */ "No locks available",
+ /* 40 ENOSYS */ "Function not implemented",
+ /* 41 ENOTEMPTY */ "Directory not empty",
+ /* 42 EILSEQ */ "Illegal byte sequence",
+ /* 43 ENETDOWN */ "Network is down",
+ /* 44 ECONNRESET */ "Connection reset",
+ /* 45 ECONNREFUSED */ "Connection refused",
+ /* 46 EADDRINUSE */ "Address already in use"
+
+};
+
+#else /* WIN */
+
+char *osErrMessages[] =
+{
+ /* 0 */ "Success"
+ /* 1 EPERM */ "Operation not permitted"
+ /* 2 ENOENT */ "No such file or directory"
+ /* 3 ESRCH */ "No such process"
+ /* 4 EINTR */ "Interrupted system call"
+ /* 5 EIO */ "I/O error"
+ /* 6 ENXIO */ "No such device or address"
+ /* 7 E2BIG */ "Arg list too long"
+ /* 8 ENOEXEC */ "Exec format error"
+ /* 9 EBADF */ "Bad file number"
+ /* 10 ECHILD */ "No child processes"
+ /* 11 EAGAIN */ "Try again"
+ /* 12 ENOMEM */ "Out of memory"
+ /* 13 EACCES */ "Permission denied"
+ /* 14 EFAULT */ "Bad address"
+ /* 15 ENOTBLK */ "Block device required"
+ /* 16 EBUSY */ "Device or resource busy"
+ /* 17 EEXIST */ "File exists"
+ /* 18 EXDEV */ "Cross-device link"
+ /* 19 ENODEV */ "No such device"
+ /* 20 ENOTDIR */ "Not a directory"
+ /* 21 EISDIR */ "Is a directory"
+ /* 22 EINVAL */ "Invalid argument"
+ /* 23 ENFILE */ "File table overflow"
+ /* 24 EMFILE */ "Too many open files"
+ /* 25 ENOTTY */ "Not a typewriter"
+ /* 26 ETXTBSY */ "Text file busy"
+ /* 27 EFBIG */ "File too large"
+ /* 28 ENOSPC */ "No space left on device"
+ /* 29 ESPIPE */ "Illegal seek"
+ /* 30 EROFS */ "Read-only file system"
+ /* 31 EMLINK */ "Too many links"
+ /* 32 EPIPE */ "Broken pipe"
+ /* 33 EDOM */ "Math argument out of domain of func"
+ /* 34 ERANGE */ "Math result not representable"
+ /* 35 EDEADLK */ "Resource deadlock would occur"
+ /* 36 ENAMETOOLONG */ "File name too long"
+ /* 37 ENOLCK */ "No record locks available"
+ /* 38 ENOSYS */ "Function not implemented"
+ /* 39 ENOTEMPTY */ "Directory not empty"
+ /* 40 ELOOP */ "Too many symbolic links encountered"
+ /* 41 EWOULDBLOCK EAGAIN */"Operation would block"
+ /* 42 ENOMSG */ "No message of desired type"
+ /* 43 EIDRM */ "Identifier removed"
+
+#if !BLD_FEATURE_SQUEEZE
+ /* 44 ECHRNG */ "Channel number out of range"
+ /* 45 EL2NSYNC */ "Level 2 not synchronized"
+ /* 46 EL3HLT */ "Level 3 halted"
+ /* 47 EL3RST */ "Level 3 reset"
+ /* 48 ELNRNG */ "Link number out of range"
+ /* 49 EUNATCH */ "Protocol driver not attached"
+ /* 50 ENOCSI */ "No CSI structure available"
+ /* 51 EL2HLT */ "Level 2 halted"
+ /* 52 EBADE */ "Invalid exchange"
+ /* 53 EBADR */ "Invalid request descriptor"
+ /* 54 EXFULL */ "Exchange full"
+ /* 55 ENOANO */ "No anode"
+ /* 56 EBADRQC */ "Invalid request code"
+ /* 57 EBADSLT */ "Invalid slot"
+ /* 59 EBFONT */ "Bad font file format"
+ /* 60 ENOSTR */ "Device not a stream"
+ /* 61 ENODATA */ "No data available"
+ /* 62 ETIME */ "Timer expired"
+ /* 63 ENOSR */ "Out of streams resources"
+ /* 64 ENONET */ "Machine is not on the network"
+ /* 65 ENOPKG */ "Package not installed"
+ /* 66 EREMOTE */ "Object is remote"
+ /* 67 ENOLINK */ "Link has been severed"
+ /* 68 EADV */ "Advertise error"
+ /* 69 ESRMNT */ "Srmount error"
+ /* 70 ECOMM */ "Communication error on send"
+ /* 71 EPROTO */ "Protocol error"
+ /* 72 EMULTIHOP */ "Multihop attempted"
+ /* 73 EDOTDOT */ "RFS specific error"
+ /* 74 EBADMSG */ "Not a data message"
+ /* 75 EOVERFLOW */ "Value too large for defined data type"
+ /* 76 ENOTUNIQ */ "Name not unique on network"
+ /* 77 EBADFD */ "File descriptor in bad state"
+ /* 78 EREMCHG */ "Remote address changed"
+ /* 79 ELIBACC */ "Can not access a needed shared library"
+ /* 80 ELIBBAD */ "Accessing a corrupted shared library"
+ /* 81 ELIBSCN */ ".lib section in a.out corrupted"
+ /* 82 ELIBMAX */ "Linking in too many shared libraries"
+ /* 83 ELIBEXEC */ "Cannot exec a shared library directly"
+ /* 84 EILSEQ */ "Illegal byte sequence"
+ /* 85 ERESTART */ "Interrupted system call should be restarted"
+ /* 86 ESTRPIPE */ "Streams pipe error"
+ /* 87 EUSERS */ "Too many users"
+ /* 88 ENOTSOCK */ "Socket operation on non-socket"
+ /* 89 EDESTADDRREQ */ "Destination address required"
+ /* 90 EMSGSIZE */ "Message too long"
+ /* 91 EPROTOTYPE */ "Protocol wrong type for socket"
+ /* 92 ENOPROTOOPT */ "Protocol not available"
+ /* 93 EPROTONOSUPPORT */ "Protocol not supported"
+ /* 94 ESOCKTNOSUPPORT */ "Socket type not supported"
+ /* 95 EOPNOTSUPP */ "Operation not supported on transport endpoint"
+ /* 96 EPFNOSUPPORT */ "Protocol family not supported"
+ /* 97 EAFNOSUPPORT */ "Address family not supported by protocol"
+ /* 98 EADDRINUSE */ "Address already in use"
+ /* 99 EADDRNOTAVAIL */ "Cannot assign requested address"
+ /* 100 ENETDOWN */ "Network is down"
+ /* 101 ENETUNREACH */ "Network is unreachable"
+ /* 102 ENETRESET */ "Network dropped connection because of reset"
+ /* 103 ECONNABORTED */ "Software caused connection abort"
+ /* 104 ECONNRESET */ "Connection reset by peer"
+ /* 105 ENOBUFS */ "No buffer space available"
+ /* 106 EISCONN */ "Transport endpoint is already connected"
+ /* 107 ENOTCONN */ "Transport endpoint is not connected"
+ /* 108 ESHUTDOWN */ "Cannot send after transport endpoint shutdown"
+ /* 109 ETOOMANYREFS */ "Too many references: cannot splice"
+ /* 110 ETIMEDOUT */ "Connection timed out"
+ /* 111 ECONNREFUSED */ "Connection refused"
+ /* 112 EHOSTDOWN */ "Host is down"
+ /* 113 EHOSTUNREACH */ "No route to host"
+ /* 114 EALREADY */ "Operation already in progress"
+ /* 115 EINPROGRESS */ "Operation now in progress"
+ /* 116 ESTALE */ "Stale NFS file handle"
+ /* 117 EUCLEAN */ "Structure needs cleaning"
+ /* 118 ENOTNAM */ "Not a XENIX named type file"
+ /* 119 ENAVAIL */ "No XENIX semaphores available"
+ /* 120 EISNAM */ "Is a named type file"
+ /* 121 EREMOTEIO */ "Remote I/O error"
+ /* 122 EDQUOT */ "Quota exceeded"
+ /* 123 ENOMEDIUM */ "No medium found"
+ /* 124 EMEDIUMTYPE */ "Wrong medium type"
+};
+#endif /* BLD_FEATURE_SQUEEZE */
+#endif /* WIN */
+
+ int osNumErr = sizeof(osErrMessages) / sizeof(char*);
+
+ if (err < MPR_ERR_BASE) {
+ err = MPR_ERR_BASE - err;
+ if (err < 0 || err >= mprNumErr) {
+ return "Bad error code";
+ }
+ return mprErrMessages[err];
+
+ } else {
+ /*
+ * Negative O/S error code. Map to a positive standard Posix error.
+ */
+ err = -err;
+ if (err < 0 || err >= osNumErr) {
+ return "Bad O/S error code";
+ }
+ return osErrMessages[err];
+ }
+}
+
+#endif
+/*****************************************************************************/
+
+/*
+ * 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/mpr/mprOs.h b/source4/lib/appweb/ejs-2.0/mpr/mprOs.h
new file mode 100644
index 0000000000..bed4ca5979
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprOs.h
@@ -0,0 +1,707 @@
+/*
+ * @file mprOs.h
+ * @brief Include O/S headers and smooth out per-O/S differences
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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
+ */
+
+/******************************* Documentation ********************************/
+
+/*
+ * This header is part of the Mbedthis Portable Runtime and aims to include
+ * all necessary O/S headers and to unify the constants and declarations
+ * required by Mbedthis products. It can be included by C or C++ programs.
+ */
+
+/******************************************************************************/
+
+#ifndef _h_MPR_OS_HDRS
+#define _h_MPR_OS_HDRS 1
+
+#include "buildConfig.h"
+
+/********************************* CPU Families *******************************/
+/*
+ * Porters, add your CPU families here and update configure code.
+ */
+#define MPR_CPU_UNKNOWN 0
+#define MPR_CPU_IX86 1
+#define MPR_CPU_PPC 2
+#define MPR_CPU_SPARC 3
+#define MPR_CPU_XSCALE 4
+#define MPR_CPU_ARM 5
+#define MPR_CPU_MIPS 6
+#define MPR_CPU_68K 7
+#define MPR_CPU_SIMNT 8 /* VxWorks NT simulator */
+#define MPR_CPU_SIMSPARC 9 /* VxWorks sparc simulator */
+
+/********************************* O/S Includes *******************************/
+
+#if LINUX || SOLARIS
+ #include <sys/types.h>
+ #include <time.h>
+ #include <arpa/inet.h>
+ #include <ctype.h>
+ #include <dirent.h>
+ #include <dlfcn.h>
+ #include <fcntl.h>
+ #include <grp.h>
+ #include <errno.h>
+ #include <libgen.h>
+ #include <limits.h>
+ #include <netdb.h>
+ #include <net/if.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+ #include <netinet/ip.h>
+ #include <pthread.h>
+ #include <pwd.h>
+ #include <resolv.h>
+ #include <signal.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <syslog.h>
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <sys/param.h>
+ #include <sys/resource.h>
+ #include <sys/sem.h>
+ #include <sys/shm.h>
+ #include <sys/socket.h>
+ #include <sys/select.h>
+ #include <sys/time.h>
+ #include <sys/times.h>
+ #include <sys/utsname.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+
+#if LINUX
+ #include <stdint.h>
+#endif
+
+#if SOLARIS
+ #include <netinet/in_systm.h>
+#endif
+
+#if BLD_FEATURE_FLOATING_POINT
+ #define __USE_ISOC99 1
+ #include <math.h>
+ #include <values.h>
+#endif
+
+#endif /* LINUX || SOLARIS */
+
+#if VXWORKS
+ #include <vxWorks.h>
+ #include <envLib.h>
+ #include <sys/types.h>
+ #include <time.h>
+ #include <arpa/inet.h>
+ #include <ctype.h>
+ #include <dirent.h>
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <limits.h>
+ #include <loadLib.h>
+ #include <netdb.h>
+ #include <net/if.h>
+ #include <netinet/tcp.h>
+ #include <netinet/in.h>
+ #include <netinet/ip.h>
+ #include <signal.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sysSymTbl.h>
+ #include <sys/fcntlcom.h>
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ #include <sys/times.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include <unldLib.h>
+
+ #if BLD_FEATURE_FLOATING_POINT
+ #include <float.h>
+ #define __USE_ISOC99 1
+ #include <math.h>
+ #endif
+
+ #include <sockLib.h>
+ #include <inetLib.h>
+ #include <ioLib.h>
+ #include <pipeDrv.h>
+ #include <hostLib.h>
+ #include <netdb.h>
+ #include <tickLib.h>
+ #include <taskHookLib.h>
+
+#endif /* VXWORKS */
+
+#if MACOSX
+ #include <time.h>
+ #include <arpa/inet.h>
+ #include <ctype.h>
+ #include <fcntl.h>
+ #include <grp.h>
+ #include <errno.h>
+ #include <libgen.h>
+ #include <limits.h>
+ #include <mach-o/dyld.h>
+ #include <netdb.h>
+ #include <net/if.h>
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+ #include <netinet/ip.h>
+ #include <pthread.h>
+ #include <pwd.h>
+ #include <resolv.h>
+ #include <signal.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdint.h>
+ #include <string.h>
+ #include <syslog.h>
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/param.h>
+ #include <sys/resource.h>
+ #include <sys/sem.h>
+ #include <sys/shm.h>
+ #include <sys/socket.h>
+ #include <sys/select.h>
+ #include <sys/time.h>
+ #include <sys/times.h>
+ #include <sys/types.h>
+ #include <sys/utsname.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+#endif /* MACOSX */
+
+#if WIN
+ /*
+ * We replace insecure functions with Mbedthis replacements
+ */
+ #define _CRT_SECURE_NO_DEPRECATE 1
+
+ #include <ctype.h>
+ #include <conio.h>
+ #include <direct.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <io.h>
+ #include <limits.h>
+ #include <malloc.h>
+ #include <process.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #include <stddef.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <time.h>
+ #define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>
+ #include <windows.h>
+ #include <winbase.h>
+ #if BLD_FEATURE_FLOATING_POINT
+ #include <float.h>
+ #endif
+ #include <shlobj.h>
+ #include <shellapi.h>
+ #include <wincrypt.h>
+
+#if BLD_DEBUG
+ #include <crtdbg.h>
+#endif
+ #include "mprUnix.h"
+#endif /* WIN */
+
+#if BREW
+ #if BLD_FEATURE_FLOATING_POINT
+ #warning "Floating point is not supported on Brew"
+ #endif
+ #if BLD_FEATURE_MULTITHREAD
+ #warning "Multithreading is not supported on Brew"
+ #endif
+
+ #include "AEEModGen.h"
+ #include "AEEAppGen.h"
+ #include "BREWVersion.h"
+
+ #if BREW_MAJ_VER == 2
+ /*
+ * Fix for BREW 2.X
+ */
+ #ifdef __GNUC__
+ #define __inline extern __inline__
+ #endif
+ #include "AEENet.h"
+ #undef __inline
+ #endif
+
+ #include "AEE.h"
+ #include "AEEBitmap.h"
+ #include "AEEDisp.h"
+ #include "AEEFile.h"
+ #include "AEEHeap.h"
+ #include "AEEImageCtl.h"
+ #include "AEEMedia.h"
+ #include "AEEMediaUtil.h"
+ #include "AEEMimeTypes.h"
+ #include "AEEStdLib.h"
+ #include "AEEShell.h"
+ #include "AEESoundPlayer.h"
+ #include "AEEText.h"
+ #include "AEETransform.h"
+ #include "AEEWeb.h"
+ #if BREW_MAJ_VER >= 3
+ #include "AEESMS.h"
+ #endif
+ #include "AEETAPI.h"
+
+#if 0
+ #include "AEESound.h"
+ #include "AEEDb.h"
+ #include "AEEMenu.h"
+#endif
+
+#endif /* BREW */
+
+/******************************************************************************/
+/******************************* General Defines ******************************/
+/******************************************************************************/
+
+#ifndef MAXINT
+#if INT_MAX
+ #define MAXINT INT_MAX
+#else
+ #define MAXINT 0x7fffffff
+#endif
+#endif
+
+#ifndef BITSPERBYTE
+#define BITSPERBYTE (8 * sizeof(char))
+#endif
+
+#define BITS(type) (BITSPERBYTE * (int) sizeof(type))
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define MPR_ARRAY_SIZE(type) (sizeof(type) / sizeof(type[0]))
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3) && !DOXYGEN && BLD_FEATURE_ALLOC_LEAK_TRACK
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+typedef char *MprStr; /* Used for dynamic strings */
+
+#ifdef __cplusplus
+extern "C" {
+#else
+typedef int bool;
+#endif
+
+/******************************************************************************/
+/******************************** Linux Defines *******************************/
+/******************************************************************************/
+
+#if LINUX
+ typedef unsigned char uchar;
+
+#if BLD_FEATURE_INT64
+ __extension__ typedef long long int int64;
+ __extension__ typedef unsigned long long int uint64;
+ #define INT64(x) (x##LL)
+ #define UINT64(x) (x##ULL)
+#endif
+
+ #define closesocket(x) close(x)
+ #define MPR_BINARY ""
+ #define MPR_TEXT ""
+ #define O_BINARY 0
+ #define O_TEXT 0
+ #define SOCKET_ERROR -1
+ #define MPR_DLL_EXT ".so"
+
+#if BLD_FEATURE_FLOATING_POINT
+ #define MAX_FLOAT MAXFLOAT
+#endif
+
+/*
+ * For some reason it is removed from fedora pthreads.h and only
+ * comes in for UNIX96
+ */
+extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
+ __attr, int *__restrict __kind) __THROW;
+/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
+ PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
+ PTHREAD_MUTEX_DEFAULT). */
+extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
+ __THROW;
+
+#endif /* LINUX */
+
+/******************************************************************************/
+/******************************* VxWorks Defines ******************************/
+/******************************************************************************/
+
+#if VXWORKS
+
+ typedef unsigned char uchar;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+
+ #define HAVE_SOCKLEN_T
+ typedef int socklen_t;
+
+#if BLD_FEATURE_INT64
+ typedef long long int int64;
+ typedef unsigned long long int uint64;
+ #define INT64(x) (x##LL)
+ #define UINT64(x) (x##ULL)
+#endif
+
+ #define closesocket(x) close(x)
+ #define getpid() taskIdSelf()
+ #define MPR_BINARY ""
+ #define MPR_TEXT ""
+ #define O_BINARY 0
+ #define O_TEXT 0
+ #define SOCKET_ERROR -1
+ #define MPR_DLL_EXT ".so"
+
+#if BLD_FEATURE_FLOATING_POINT
+ #define MAX_FLOAT FLT_MAX
+#endif
+
+ #undef R_OK
+ #define R_OK 4
+ #undef W_OK
+ #define W_OK 2
+ #undef X_OK
+ #define X_OK 1
+ #undef F_OK
+ #define F_OK 0
+
+ #define MSG_NOSIGNAL 0
+
+ extern int access(char *path, int mode);
+ extern int sysClkRateGet();
+
+#endif /* VXWORKS */
+
+/******************************************************************************/
+/******************************** MacOsx Defines ******************************/
+/******************************************************************************/
+#if MACOSX
+ typedef unsigned long ulong;
+ typedef unsigned char uchar;
+
+#if BLD_FEATURE_INT64
+ __extension__ typedef long long int int64;
+ __extension__ typedef unsigned long long int uint64;
+ #define INT64(x) (x##LL)
+ #define UINT64(x) (x##ULL)
+#endif
+
+ #define closesocket(x) close(x)
+ #define MPR_BINARY ""
+ #define MPR_TEXT ""
+ #define O_BINARY 0
+ #define O_TEXT 0
+ #define SOCKET_ERROR -1
+ #define MPR_DLL_EXT ".dylib"
+ #define MSG_NOSIGNAL 0
+ #define __WALL 0x40000000
+ #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+
+#if BLD_FEATURE_FLOATING_POINT
+ #define MAX_FLOAT MAXFLOAT
+#endif
+
+#endif /* MACOSX */
+
+/******************************************************************************/
+/******************************* Windows Defines ******************************/
+/******************************************************************************/
+
+#if WIN
+ typedef unsigned char uchar;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+ typedef unsigned short ushort;
+
+/*
+ * We always define INT64 types on windows
+ */
+#if BLD_FEATURE_INT64 || 1
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+ #define INT64(x) (x##i64)
+ #define UINT64(x) (x##Ui64)
+#endif
+
+ typedef int uid_t;
+ typedef void *handle;
+ typedef char *caddr_t;
+ typedef long pid_t;
+ typedef int gid_t;
+ typedef ushort mode_t;
+ typedef void *siginfo_t;
+
+ #define HAVE_SOCKLEN_T
+ typedef int socklen_t;
+
+ #undef R_OK
+ #define R_OK 4
+ #undef W_OK
+ #define W_OK 2
+
+ /*
+ * On windows map X_OK to R_OK
+ */
+ #undef X_OK
+ #define X_OK 4
+ #undef F_OK
+ #define F_OK 0
+
+ #ifndef EADDRINUSE
+ #define EADDRINUSE 46
+ #endif
+ #ifndef EWOULDBLOCK
+ #define EWOULDBLOCK EAGAIN
+ #endif
+ #ifndef ENETDOWN
+ #define ENETDOWN 43
+ #endif
+ #ifndef ECONNRESET
+ #define ECONNRESET 44
+ #endif
+ #ifndef ECONNREFUSED
+ #define ECONNREFUSED 45
+ #endif
+
+ #define MSG_NOSIGNAL 0
+ #define MPR_BINARY "b"
+ #define MPR_TEXT "t"
+
+#if BLD_FEATURE_FLOATING_POINT
+ #define MAX_FLOAT DBL_MAX
+#endif
+
+#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
+#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
+#endif
+
+ #define MPR_DLL_EXT ".dll"
+#endif /* WIN */
+
+/******************************************************************************/
+/****************************** Solaris Defines *******************************/
+/******************************************************************************/
+
+#if SOLARIS
+ typedef unsigned char uchar;
+
+#if BLD_FEATURE_INT64
+ typedef long long int int64;
+ typedef unsigned long long int uint64;
+ #define INT64(x) (x##LL)
+ #define UINT64(x) (x##ULL)
+#endif
+
+ #define closesocket(x) close(x)
+ #define MPR_BINARY ""
+ #define MPR_TEXT ""
+ #define O_BINARY 0
+ #define O_TEXT 0
+ #define SOCKET_ERROR -1
+ #define MPR_DLL_EXT ".so"
+ #define MSG_NOSIGNAL 0
+ #define INADDR_NONE ((in_addr_t) 0xffffffff)
+ #define __WALL 0
+ #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+
+#if BLD_FEATURE_FLOATING_POINT
+ #define MAX_FLOAT MAXFLOAT
+#endif
+
+#endif /* SOLARIS */
+
+/******************************************************************************/
+/********************************* BREW Defines *******************************/
+/******************************************************************************/
+
+#if BREW
+ typedef unsigned char uchar;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+ typedef unsigned short ushort;
+
+ typedef uint off_t;
+ typedef long pid_t;
+
+#if UNUSED
+ typedef int uid_t;
+ typedef void *handle;
+ typedef char *caddr_t;
+ typedef int gid_t;
+ typedef ushort mode_t;
+ typedef void *siginfo_t;
+
+ #define HAVE_SOCKLEN_T
+ typedef int socklen_t;
+
+ #ifndef EADDRINUSE
+ #define EADDRINUSE 46
+ #endif
+ #ifndef EWOULDBLOCK
+ #define EWOULDBLOCK EAGAIN
+ #endif
+ #ifndef ENETDOWN
+ #define ENETDOWN 43
+ #endif
+ #ifndef ECONNRESET
+ #define ECONNRESET 44
+ #endif
+ #ifndef ECONNREFUSED
+ #define ECONNREFUSED 45
+ #endif
+
+ #define MSG_NOSIGNAL 0
+ #define MPR_BINARY "b"
+ #define MPR_TEXT "t"
+
+ #define MPR_DLL_EXT ".dll"
+#endif
+
+ #define O_RDONLY 0
+ #define O_WRONLY 1
+ #define O_RDWR 2
+ #define O_CREAT 0x200
+ #define O_TRUNC 0x400
+ #define O_BINARY 0
+ #define O_TEXT 0x20000
+ #define O_EXCL 0x40000
+ #define O_APPEND 0x80000
+
+ #define R_OK 4
+ #define W_OK 2
+ #define X_OK 1
+ #define F_OK 0
+
+ #define SEEK_SET 0
+ #define SEEK_CUR 1
+ #define SEEK_END 2
+
+#if UNUSED
+struct stat {
+ uint st_size;
+};
+#endif
+
+extern int getpid();
+extern int isalnum(int c);
+extern int isalpha(int c);
+extern int isdigit(int c);
+extern int islower(int c);
+extern int isupper(int c);
+extern int isspace(int c);
+extern int isxdigit(int c);
+
+extern uint strlen(const char *str);
+extern char *strstr(const char *string, const char *strSet);
+extern void *memset(const void *dest, int c, uint count);
+extern void exit(int status);
+extern char *strpbrk(const char *str, const char *set);
+extern uint strspn(const char *str, const char *set);
+extern int tolower(int c);
+extern int toupper(int c);
+extern void *memcpy(void *dest, const void *src, uint count);
+extern void *memmove(void *dest, const void *src, uint count);
+
+extern int atoi(const char *str);
+extern void free(void *ptr);
+extern void *malloc(uint size);
+extern void *realloc(void *ptr, uint size);
+extern char *strcat(char *dest, const char *src);
+extern char *strchr(const char *str, int c);
+extern int strcmp(const char *s1, const char *s2);
+extern int strncmp(const char *s1, const char *s2, uint count);
+extern char *strcpy(char *dest, const char *src);
+extern char *strncpy(char *dest, const char *src, uint count);
+extern char *strrchr(const char *str, int c);
+
+#undef printf
+#define printf DBGPRINTF
+
+#if BREW_SIMULATOR && BLD_DEBUG
+extern _CRTIMP int __cdecl _CrtCheckMemory(void);
+extern _CRTIMP int __cdecl _CrtSetReportHook();
+#endif
+
+#endif /* BREW */
+
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _h_MPR_OS_HDRS */
+
+/*
+ * 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/mpr/mprPrintf.c b/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c
new file mode 100644
index 0000000000..2d0951acfa
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c
@@ -0,0 +1,924 @@
+/**
+ * @file mprPrintf.c
+ * @brief Printf routines safe for embedded programming
+ * @overview This module provides safe replacements for the standard
+ * printf formatting routines.
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 **********************************/
+/*
+ * We need to use the underlying str(cpy) routines to implement our safe
+ * alternatives
+ */
+#if !DOXYGEN
+#define UNSAFE_FUNCTIONS_OK 1
+#endif
+
+#include "mpr.h"
+
+/*********************************** Defines **********************************/
+/*
+ * Class definitions
+ */
+#define CLASS_NORMAL 0 /* [All other] Normal characters */
+#define CLASS_PERCENT 1 /* [%] Begin format */
+#define CLASS_MODIFIER 2 /* [-+ #,] Modifiers */
+#define CLASS_ZERO 3 /* [0] Special modifier */
+#define CLASS_STAR 4 /* [*] Width supplied by arg */
+#define CLASS_DIGIT 5 /* [1-9] Field widths */
+#define CLASS_DOT 6 /* [.] Introduce precision */
+#define CLASS_BITS 7 /* [hlL] Length bits */
+#define CLASS_TYPE 8 /* [cdfinopsSuxX] Type specifiers */
+
+#define STATE_NORMAL 0 /* Normal chars in format string */
+#define STATE_PERCENT 1 /* "%" */
+#define STATE_MODIFIER 2 /* Read flag */
+#define STATE_WIDTH 3 /* Width spec */
+#define STATE_DOT 4 /* "." */
+#define STATE_PRECISION 5 /* Precision spec */
+#define STATE_BITS 6 /* Size spec */
+#define STATE_TYPE 7 /* Data type */
+#define STATE_COUNT 8
+
+/*
+ * Format: %[modifier][width][precision][bits][type]
+ *
+ * #define CLASS_MODIFIER 2 [-+ #,] Modifiers
+ * #define CLASS_BITS 7 [hlL] Length bits
+ */
+
+
+/*
+ * Flags
+ */
+#define SPRINTF_LEFT 0x1 /* Left align */
+#define SPRINTF_SIGN 0x2 /* Always sign the result */
+#define SPRINTF_LEAD_SPACE 0x4 /* put leading space for +ve numbers */
+#define SPRINTF_ALTERNATE 0x8 /* Alternate format */
+#define SPRINTF_LEAD_ZERO 0x10 /* Zero pad */
+#define SPRINTF_SHORT 0x20 /* 16-bit */
+#define SPRINTF_LONG 0x40 /* 32-bit */
+#if BLD_FEATURE_INT64
+#define SPRINTF_LONGLONG 0x80 /* 64-bit */
+#endif
+#define SPRINTF_COMMA 0x100 /* Thousand comma separators */
+#define SPRINTF_UPPER_CASE 0x200 /* As the name says for numbers */
+
+typedef struct Format {
+ uchar *buf;
+ uchar *endbuf;
+ uchar *start;
+ uchar *end;
+ int growBy;
+ int maxsize;
+
+ int precision;
+ int radix;
+ int width;
+ int flags;
+ int len;
+} Format;
+
+static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt);
+
+#define BPUT(ctx, loc, fmt, c) \
+ if (1) { \
+ /* Less one to allow room for the null */ \
+ if ((fmt)->end >= ((fmt)->endbuf - sizeof(char))) { \
+ if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \
+ *(fmt)->end++ = (c); \
+ } \
+ } else { \
+ *(fmt)->end++ = (c); \
+ } \
+ } else
+
+#define BPUTNULL(ctx, loc, fmt) \
+ if (1) { \
+ if ((fmt)->end > (fmt)->endbuf) { \
+ if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \
+ *(fmt)->end = '\0'; \
+ } \
+ } else { \
+ *(fmt)->end = '\0'; \
+ } \
+ } else
+
+/******************************************************************************/
+
+#if BLD_FEATURE_INT64
+#define unum uint64
+#define num int64
+#else
+#define unum uint
+#define num int
+#endif
+
+/***************************** Forward Declarations ***************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static int getState(char c, int state);
+static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **s,
+ int maxsize, const char *fmt, va_list arg);
+static void outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix,
+ unum val);
+
+#if BLD_FEATURE_FLOATING_POINT
+static void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar,
+ double value);
+#endif
+
+/******************************************************************************/
+
+int mprPrintf(MprCtx ctx, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ int len;
+ MprApp *app;
+
+ /* No asserts here as this is used as part of assert reporting */
+
+ app = mprGetApp(ctx);
+
+ va_start(ap, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap);
+ va_end(ap);
+ if (len >= 0 && app->console) {
+ len = mprWrite(app->console, buf, len);
+ }
+ mprFree(buf);
+
+ return len;
+}
+
+/******************************************************************************/
+
+int mprErrorPrintf(MprCtx ctx, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ int len;
+ MprApp *app;
+
+ /* No asserts here as this is used as part of assert reporting */
+
+ app = mprGetApp(ctx);
+
+ va_start(ap, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap);
+ va_end(ap);
+ if (len >= 0 && app->error) {
+ len = mprWrite(app->error, buf, len);
+ }
+ mprFree(buf);
+
+ return len;
+}
+
+/******************************************************************************/
+
+int mprFprintf(MprFile *file, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ int len;
+
+ if (file == 0) {
+ return MPR_ERR_BAD_HANDLE;
+ }
+
+ va_start(ap, fmt);
+ len = mprAllocVsprintf(MPR_LOC_ARGS(file), &buf, 0, fmt, ap);
+ va_end(ap);
+
+ if (len >= 0) {
+ len = mprWrite(file, buf, len);
+ }
+ mprFree(buf);
+ return len;
+}
+
+/******************************************************************************/
+/*
+ * Printf with a static buffer. Used internally only. WILL NOT MALLOC.
+ */
+
+int mprStaticPrintf(MprCtx ctx, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[MPR_MAX_STRING];
+ char *bufp;
+ int len;
+ MprApp *app;
+
+ app = mprGetApp(ctx);
+
+ va_start(ap, fmt);
+ bufp = buf;
+ len = mprSprintfCore(MPR_LOC_ARGS(0), &bufp, MPR_MAX_STRING, fmt, ap);
+ va_end(ap);
+ if (len >= 0) {
+ len = mprWrite(app->console, buf, len);
+ }
+ return len;
+}
+
+/******************************************************************************/
+
+int mprSprintf(char *buf, int n, const char *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ mprAssert(buf);
+ mprAssert(fmt);
+ mprAssert(n > 0);
+
+ va_start(ap, fmt);
+ result = mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+/******************************************************************************/
+
+int mprVsprintf(char *buf, int n, const char *fmt, va_list arg)
+{
+ mprAssert(buf);
+ mprAssert(fmt);
+ mprAssert(n > 0);
+
+ return mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, arg);
+}
+
+/******************************************************************************/
+
+int mprAllocSprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ mprAssert(buf);
+ mprAssert(fmt);
+
+ *buf = 0;
+ va_start(ap, fmt);
+ result = mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+/******************************************************************************/
+
+int mprAllocVsprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize,
+ const char *fmt, va_list arg)
+{
+ mprAssert(buf);
+ mprAssert(fmt);
+
+ *buf = 0;
+ return mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, arg);
+}
+
+/******************************************************************************/
+
+static int getState(char c, int state)
+{
+ /*
+ * Declared here to remove all static / globals
+ * FUTURE OPT -- need to measure this. Could be slow on BREW.
+ */
+
+ char stateMap[] = {
+ /* STATES: Normal Percent Modifier Width Dot Prec Bits Type */
+ /* CLASS 0 1 2 3 4 5 6 7 */
+ /* Normal 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Percent 1 */ 1, 0, 1, 1, 1, 1, 1, 1,
+ /* Modifier 2 */ 0, 2, 2, 0, 0, 0, 0, 0,
+ /* Zero 3 */ 0, 2, 2, 3, 0, 5, 0, 0,
+ /* Star 4 */ 0, 3, 3, 0, 5, 0, 0, 0,
+ /* Digit 5 */ 0, 3, 3, 3, 5, 5, 0, 0,
+ /* Dot 6 */ 0, 4, 4, 4, 0, 0, 0, 0,
+ /* Bits 7 */ 0, 6, 6, 6, 6, 6, 6, 0,
+ /* Types 8 */ 0, 7, 7, 7, 7, 7, 7, 0,
+ };
+
+ /*
+ * Format: %[modifier][width][precision][bits][type]
+ */
+ char classMap[] = {
+ /* 0 ' ' ! " # $ % & ' */
+ 2, 0, 0, 2, 0, 1, 0, 0,
+ /* 07 ( ) * + , - . / */
+ 0, 0, 4, 2, 2, 2, 6, 0,
+ /* 10 0 1 2 3 4 5 6 7 */
+ 3, 5, 5, 5, 5, 5, 5, 5,
+ /* 17 8 9 : ; < = > ? */
+ 5, 5, 0, 0, 0, 0, 0, 0,
+ /* 20 @ A B C D E F G */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 27 H I J K L M N O */
+ 0, 0, 0, 0, 7, 0, 0, 0,
+ /* 30 P Q R S T U V W */
+ 0, 0, 0, 8, 0, 0, 0, 0,
+ /* 37 X Y Z [ \ ] ^ _ */
+ 8, 0, 0, 0, 0, 0, 0, 0,
+ /* 40 ' a b c d e f g */
+ 0, 0, 0, 8, 8, 0, 8, 0,
+ /* 47 h i j k l m n o */
+ 7, 8, 0, 0, 7, 0, 8, 8,
+ /* 50 p q r s t u v w */
+ 8, 0, 0, 8, 0, 8, 0, 0,
+ /* 57 x y z */
+ 8, 0, 0,
+ };
+
+ int chrClass;
+
+ if (c < ' ' || c > 'z') {
+ chrClass = CLASS_NORMAL;
+ } else {
+ mprAssert((c - ' ') < (int) sizeof(classMap));
+ chrClass = classMap[(c - ' ')];
+ }
+ mprAssert((chrClass * STATE_COUNT + state) < (int) sizeof(stateMap));
+ state = stateMap[chrClass * STATE_COUNT + state];
+ return state;
+}
+
+/******************************************************************************/
+
+static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **bufPtr,
+ int maxsize, const char *spec, va_list arg)
+{
+ Format fmt;
+ char *cp;
+ char c;
+ char *sValue;
+ num iValue;
+ unum uValue;
+ int count, i, len, state;
+
+ mprAssert(bufPtr);
+ mprAssert(spec);
+
+ if (*bufPtr != 0) {
+ mprAssert(maxsize > 0);
+ fmt.buf = (uchar*) *bufPtr;
+ fmt.endbuf = &fmt.buf[maxsize];
+ fmt.growBy = 0;
+ } else {
+ if (maxsize <= 0) {
+ maxsize = MAXINT;
+ }
+
+ len = min(MPR_DEFAULT_ALLOC, maxsize);
+ fmt.buf = (uchar*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);
+ fmt.endbuf = &fmt.buf[len];
+ fmt.growBy = MPR_DEFAULT_ALLOC * 2;
+ }
+
+ fmt.maxsize = maxsize;
+ fmt.start = fmt.buf;
+ fmt.end = fmt.buf;
+ fmt.len = 0;
+ *fmt.start = '\0';
+
+ state = STATE_NORMAL;
+
+ while ((c = *spec++) != '\0') {
+ state = getState(c, state);
+
+ switch (state) {
+ case STATE_NORMAL:
+ BPUT(ctx, loc, &fmt, c);
+ break;
+
+ case STATE_PERCENT:
+ fmt.precision = -1;
+ fmt.width = 0;
+ fmt.flags = 0;
+ break;
+
+ case STATE_MODIFIER:
+ switch (c) {
+ case '+':
+ fmt.flags |= SPRINTF_SIGN;
+ break;
+ case '-':
+ fmt.flags |= SPRINTF_LEFT;
+ break;
+ case '#':
+ fmt.flags |= SPRINTF_ALTERNATE;
+ break;
+ case '0':
+ fmt.flags |= SPRINTF_LEAD_ZERO;
+ break;
+ case ' ':
+ fmt.flags |= SPRINTF_LEAD_SPACE;
+ break;
+ case ',':
+ fmt.flags |= SPRINTF_COMMA;
+ break;
+ }
+ break;
+
+ case STATE_WIDTH:
+ if (c == '*') {
+ fmt.width = va_arg(arg, int);
+ if (fmt.width < 0) {
+ fmt.width = -fmt.width;
+ fmt.flags |= SPRINTF_LEFT;
+ }
+ } else {
+ while (isdigit((int)c)) {
+ fmt.width = fmt.width * 10 + (c - '0');
+ c = *spec++;
+ }
+ spec--;
+ }
+ break;
+
+ case STATE_DOT:
+ fmt.precision = 0;
+ fmt.flags &= ~SPRINTF_LEAD_ZERO;
+ break;
+
+ case STATE_PRECISION:
+ if (c == '*') {
+ fmt.precision = va_arg(arg, int);
+ } else {
+ while (isdigit((int) c)) {
+ fmt.precision = fmt.precision * 10 + (c - '0');
+ c = *spec++;
+ }
+ spec--;
+ }
+ break;
+
+ case STATE_BITS:
+ switch (c) {
+#if BLD_FEATURE_INT64
+ case 'L':
+ fmt.flags |= SPRINTF_LONGLONG; /* 64 bit */
+ break;
+#endif
+
+ case 'l':
+ fmt.flags |= SPRINTF_LONG;
+ break;
+
+ case 'h':
+ fmt.flags |= SPRINTF_SHORT;
+ break;
+ }
+ break;
+
+ case STATE_TYPE:
+ switch (c) {
+#if BLD_FEATURE_FLOATING_POINT
+ case 'e':
+ case 'g':
+ case 'f':
+ fmt.radix = 10;
+ outFloat(MPR_LOC_PASS(ctx, loc), &fmt, c,
+ (double) va_arg(arg, double));
+ break;
+#endif
+ case 'c':
+ BPUT(ctx, loc, &fmt, (char) va_arg(arg, int));
+ break;
+
+ case 's':
+ case 'S':
+ sValue = va_arg(arg, char*);
+ if (sValue == 0) {
+ sValue = "null";
+ len = strlen(sValue);
+ } else if (fmt.flags & SPRINTF_ALTERNATE) {
+ sValue++;
+ len = (int) *sValue;
+ } else if (fmt.precision >= 0) {
+ /*
+ * Can't use strlen(), the string may not have a null
+ */
+ cp = sValue;
+ for (len = 0; len < fmt.precision; len++) {
+ if (*cp++ == '\0') {
+ break;
+ }
+ }
+ } else {
+ len = strlen(sValue);
+ }
+ if (!(fmt.flags & SPRINTF_LEFT)) {
+ for (i = len; i < fmt.width; i++) {
+ BPUT(ctx, loc, &fmt, (char) ' ');
+ }
+ }
+ for (i = 0; i < len && *sValue; i++) {
+ BPUT(ctx, loc, &fmt, *sValue++);
+ }
+ if (fmt.flags & SPRINTF_LEFT) {
+ for (i = len; i < fmt.width; i++) {
+ BPUT(ctx, loc, &fmt, (char) ' ');
+ }
+ }
+ break;
+
+ case 'i':
+ ;
+ case 'd':
+ fmt.radix = 10;
+ if (fmt.flags & SPRINTF_SHORT) {
+ iValue = (short) va_arg(arg, int);
+ } else if (fmt.flags & SPRINTF_LONG) {
+ iValue = va_arg(arg, long);
+#if BLD_FEATURE_INT64
+ } else if (fmt.flags & SPRINTF_LONGLONG) {
+ iValue = va_arg(arg, num);
+#endif
+ } else {
+ iValue = va_arg(arg, int);
+ }
+ if (iValue >= 0) {
+ if (fmt.flags & SPRINTF_LEAD_SPACE) {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, " ", iValue);
+ } else if (fmt.flags & SPRINTF_SIGN) {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, "+", iValue);
+ } else {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, iValue);
+ }
+ } else {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, "-", -iValue);
+ }
+ break;
+
+ case 'X':
+ fmt.flags |= SPRINTF_UPPER_CASE;
+ /* Fall through */
+ case 'o':
+ case 'x':
+ case 'u':
+ if (fmt.flags & SPRINTF_SHORT) {
+ uValue = (ushort) va_arg(arg, uint);
+ } else if (fmt.flags & SPRINTF_LONG) {
+ uValue = va_arg(arg, ulong);
+#if BLD_FEATURE_INT64
+ } else if (fmt.flags & SPRINTF_LONGLONG) {
+ uValue = va_arg(arg, unum);
+#endif
+ } else {
+ uValue = va_arg(arg, uint);
+ }
+ if (c == 'u') {
+ fmt.radix = 10;
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue);
+ } else if (c == 'o') {
+ fmt.radix = 8;
+ if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0", uValue);
+ } else {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue);
+ }
+ } else {
+ fmt.radix = 16;
+ if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) {
+ if (c == 'X') {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0X", uValue);
+ } else {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0x", uValue);
+ }
+ } else {
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue);
+ }
+ }
+ break;
+
+ case 'n': /* Count of chars seen thus far */
+ if (fmt.flags & SPRINTF_SHORT) {
+ short *count = va_arg(arg, short*);
+ *count = fmt.end - fmt.start;
+ } else if (fmt.flags & SPRINTF_LONG) {
+ long *count = va_arg(arg, long*);
+ *count = fmt.end - fmt.start;
+ } else {
+ int *count = va_arg(arg, int *);
+ *count = fmt.end - fmt.start;
+ }
+ break;
+
+ case 'p': /* Pointer */
+#if __WORDSIZE == 64 && BLD_FEATURE_INT64
+ uValue = (unum) va_arg(arg, void*);
+#else
+ uValue = (uint) (int) va_arg(arg, void*);
+#endif
+ fmt.radix = 16;
+ outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0x", uValue);
+ break;
+
+ default:
+ BPUT(ctx, loc, &fmt, c);
+ }
+ }
+ }
+ BPUTNULL(ctx, loc, &fmt);
+
+ count = fmt.end - fmt.start;
+ if (*bufPtr == 0) {
+ *bufPtr = (char*) fmt.buf;
+ }
+ return count;
+}
+
+/******************************************************************************/
+/*
+ * Output a number according to the given format. If BLD_FEATURE_INT64 is
+ * defined, then uses 64 bits universally. Slower but smaller code.
+ */
+
+static void outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix,
+ unum value)
+{
+ char numBuf[64];
+ char *cp;
+ char *endp;
+ char c;
+ int letter, len, leadingZeros, i, fill;
+
+ endp = &numBuf[sizeof(numBuf) - 1];
+ *endp = '\0';
+ cp = endp;
+
+ /*
+ * Convert to ascii
+ */
+ if (fmt->radix == 16) {
+ do {
+ letter = (int) (value % fmt->radix);
+ if (letter > 9) {
+ if (fmt->flags & SPRINTF_UPPER_CASE) {
+ letter = 'A' + letter - 10;
+ } else {
+ letter = 'a' + letter - 10;
+ }
+ } else {
+ letter += '0';
+ }
+ *--cp = letter;
+ value /= fmt->radix;
+ } while (value > 0);
+
+ } else if (fmt->flags & SPRINTF_COMMA) {
+ i = 1;
+ do {
+ *--cp = '0' + (int) (value % fmt->radix);
+ value /= fmt->radix;
+ if ((i++ % 3) == 0 && value > 0) {
+ *--cp = ',';
+ }
+ } while (value > 0);
+ } else {
+ do {
+ *--cp = '0' + (int) (value % fmt->radix);
+ value /= fmt->radix;
+ } while (value > 0);
+ }
+
+ len = endp - cp;
+ fill = fmt->width - len;
+
+ if (prefix != 0) {
+ fill -= strlen(prefix);
+ }
+ leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0;
+ fill -= leadingZeros;
+
+ if (!(fmt->flags & SPRINTF_LEFT)) {
+ c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' ';
+ for (i = 0; i < fill; i++) {
+ BPUT(ctx, loc, fmt, c);
+ }
+ }
+ if (prefix != 0) {
+ while (*prefix) {
+ BPUT(ctx, loc, fmt, *prefix++);
+ }
+ }
+ for (i = 0; i < leadingZeros; i++) {
+ BPUT(ctx, loc, fmt, '0');
+ }
+ while (*cp) {
+ BPUT(ctx, loc, fmt, *cp);
+ cp++;
+ }
+ if (fmt->flags & SPRINTF_LEFT) {
+ for (i = 0; i < fill; i++) {
+ BPUT(ctx, loc, fmt, ' ');
+ }
+ }
+}
+
+/******************************************************************************/
+#if BLD_FEATURE_FLOATING_POINT
+/*
+ * Output a floating point number
+ */
+
+static void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar,
+ double value)
+{
+ char *cp;
+#if FUTURE
+ char numBuf[64];
+ char *endp;
+ char c;
+ int letter, len, leadingZeros, i, fill, width, precision;
+
+ endp = &numBuf[sizeof(numBuf) - 1];
+ *endp = '\0';
+
+ precision = fmt->precision;
+ if (precision < 0) {
+ precision = 6;
+ } else if (precision > (sizeof(numBuf) - 1)) {
+ precision = (sizeof(numBuf) - 1);
+ }
+ width = min(fmt->width, sizeof(numBuf) - 1);
+
+ if (__isnanl(value)) {
+ "nan"
+ } else if (__isinfl(value)) {
+ "infinity"
+ } else if (value < 0) {
+ prefix = "-";
+ } else if (fmt.flags & SPRINTF_LEAD_SPACE) {
+ prefix = " ";
+ } else if (fmt.flags & SPRINTF_SIGN) {
+ prefix = "+";
+ }
+
+
+ /*
+ * Do the exponent part
+ */
+ cp = &numBuf[sizeof(numBuf) - precision];
+ for (i = 0; i < precision; i++) {
+ *cp++ = '0' + (int) (value % fmt->radix);
+ value /= fmt->radix;
+ }
+
+ /*
+ * Do the decimal part
+ */
+ if (fmt->flags & SPRINTF_COMMA) {
+ i = 1;
+ do {
+ *--cp = '0' + (int) (value % fmt->radix);
+ value /= fmt->radix;
+ if ((i++ % 3) == 0 && value > 0) {
+ *--cp = ',';
+ }
+ } while (value >= 1.0);
+
+ } else {
+ do {
+ *--cp = '0' + (int) (value % fmt->radix);
+ value /= fmt->radix;
+ } while (value > 1.0);
+ }
+
+ len = endp - cp;
+ fill = fmt->width - len;
+
+ if (prefix != 0) {
+ fill -= strlen(prefix);
+ }
+
+ leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0;
+ fill -= leadingZeros;
+
+ if (!(fmt->flags & SPRINTF_LEFT)) {
+ c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' ';
+ for (i = 0; i < fill; i++) {
+ BPUT(ctx, loc, fmt, c);
+ }
+ }
+ if (prefix != 0) {
+ BPUT(ctx, loc, fmt, prefix);
+ }
+ for (i = 0; i < leadingZeros; i++) {
+ BPUT(ctx, loc, fmt, '0');
+ }
+ BPUT(ctx, loc, fmt, cp);
+ if (fmt->flags & SPRINTF_LEFT) {
+ for (i = 0; i < fill; i++) {
+ BPUT(ctx, loc, fmt, ' ');
+ }
+ }
+#else
+ char numBuf[64];
+ if (specChar == 'f') {
+ sprintf(numBuf, "%*.*f", fmt->width, fmt->precision, value);
+ } else if (specChar == 'g') {
+ sprintf(numBuf, "%*.*g", fmt->width, fmt->precision, value);
+ } else if (specChar == 'e') {
+ sprintf(numBuf, "%*.*e", fmt->width, fmt->precision, value);
+ }
+ for (cp = numBuf; *cp; cp++) {
+ BPUT(ctx, loc, fmt, *cp);
+ }
+#endif
+}
+
+#endif /* BLD_FEATURE_FLOATING_POINT */
+/******************************************************************************/
+/*
+ * Grow the buffer to fit new data. Return 1 if the buffer can grow.
+ * Grow using the growBy size specified when creating the buffer.
+ */
+
+static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt)
+{
+ uchar *newbuf;
+ int buflen;
+
+ buflen = fmt->endbuf - fmt->buf;
+ if (fmt->maxsize >= 0 && buflen >= fmt->maxsize) {
+ return 0;
+ }
+ if (fmt->growBy < 0) {
+ /*
+ * User supplied buffer
+ */
+ return 0;
+ }
+
+ newbuf = (uchar*) mprAlloc(ctx, buflen + fmt->growBy);
+ if (fmt->buf) {
+ memcpy(newbuf, fmt->buf, buflen);
+ mprFree(fmt->buf);
+ }
+
+ buflen += fmt->growBy;
+ fmt->end = newbuf + (fmt->end - fmt->buf);
+ fmt->start = newbuf + (fmt->start - fmt->buf);
+ fmt->buf = newbuf;
+ fmt->endbuf = &fmt->buf[buflen];
+
+ /*
+ * Increase growBy to reduce overhead
+ */
+ if ((buflen + (fmt->growBy * 2)) < fmt->maxsize) {
+ fmt->growBy *= 2;
+ }
+ return 1;
+}
+
+/******************************************************************************/
+
+/*
+ * 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/mpr/mprString.c b/source4/lib/appweb/ejs-2.0/mpr/mprString.c
new file mode 100644
index 0000000000..d39fc8b746
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprString.c
@@ -0,0 +1,733 @@
+/**
+ * @file mprString.c
+ * @brief String routines safe for embedded programming
+ * @overview This module provides safe replacements for the standard
+ * string library.
+ * @remarks Most routines in this file are not thread-safe. It is the callers
+ * responsibility to perform all thread synchronization.
+ */
+
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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
+ */
+
+#include "mpr.h"
+
+/********************************** Includes **********************************/
+/*
+ * We need to use the underlying str(cpy) routines to implement our safe
+ * alternatives
+ */
+#if !DOXYGEN
+#define UNSAFE_FUNCTIONS_OK 1
+#endif
+
+/******************************************************************************/
+/**************************** Safe String Handling ****************************/
+/******************************************************************************/
+
+int mprStrcpy(char *dest, int destMax, const char *src)
+{
+ int len;
+
+ mprAssert(dest);
+ mprAssert(destMax >= 0);
+ mprAssert(src);
+
+ len = strlen(src);
+ if (destMax > 0 && len >= destMax && len > 0) {
+ return MPR_ERR_WONT_FIT;
+ }
+ if (len > 0) {
+ memcpy(dest, src, len);
+ dest[len] = '\0';
+ } else {
+ *dest = '\0';
+ len = 0;
+ }
+ return len;
+}
+
+/******************************************************************************/
+
+int mprAllocStrcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax,
+ const char *src)
+{
+ int len;
+
+ mprAssert(dest);
+ mprAssert(destMax >= 0);
+ mprAssert(src);
+
+ len = strlen(src);
+ if (destMax > 0 && len >= destMax) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ if (len > 0) {
+ *dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);
+ memcpy(*dest, src, len);
+ (*dest)[len] = '\0';
+ } else {
+ *dest = (char*) mprAlloc(ctx, 1);
+ *dest = '\0';
+ len = 0;
+ }
+ return len;
+}
+
+/******************************************************************************/
+
+int mprMemcpy(char *dest, int destMax, const char *src, int nbytes)
+{
+ mprAssert(dest);
+ mprAssert(destMax <= 0 || destMax >= nbytes);
+ mprAssert(src);
+ mprAssert(nbytes >= 0);
+
+ if (destMax > 0 && nbytes > destMax) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ if (nbytes > 0) {
+ memcpy(dest, src, nbytes);
+ return nbytes;
+ } else {
+ return 0;
+ }
+}
+
+/******************************************************************************/
+
+int mprAllocMemcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax,
+ const void *src, int nbytes)
+{
+ mprAssert(dest);
+ mprAssert(src);
+ mprAssert(nbytes > 0);
+ mprAssert(destMax <= 0 || destMax >= nbytes);
+
+ if (destMax > 0 && nbytes > destMax) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ if (nbytes > 0) {
+ *dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx,loc), nbytes);
+ if (*dest == 0) {
+ return MPR_ERR_MEMORY;
+ }
+ memcpy(*dest, src, nbytes);
+ } else {
+ *dest = (char*) mprAlloc(ctx, 1);
+ }
+ return nbytes;
+}
+
+/******************************************************************************/
+
+static int mprCoreStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax,
+ int existingLen, const char *delim, const char *src, va_list args)
+{
+ va_list ap;
+ char *dest, *str, *dp;
+ int sepLen, addBytes, required;
+
+ mprAssert(destp);
+ mprAssert(destMax >= 0);
+ mprAssert(src);
+
+ dest = *destp;
+ sepLen = (delim) ? strlen(delim) : 0;
+
+#ifdef __va_copy
+ __va_copy(ap, args);
+#else
+ ap = args;
+#endif
+ addBytes = 0;
+ if (existingLen > 0) {
+ addBytes += sepLen;
+ }
+ str = (char*) src;
+
+ while (str) {
+ addBytes += strlen(str);
+ str = va_arg(ap, char*);
+ if (str) {
+ addBytes += sepLen;
+ }
+ }
+
+ required = existingLen + addBytes + 1;
+ if (destMax > 0 && required >= destMax) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+
+ if (ctx != 0) {
+ if (dest == 0) {
+ dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), required);
+ } else {
+ dest = (char*) mprReallocBlock(MPR_LOC_PASS(ctx, loc), dest,
+ required);
+ }
+ } else {
+ dest = (char*) *destp;
+ }
+
+ dp = &dest[existingLen];
+ if (delim && existingLen > 0) {
+ strcpy(dp, delim);
+ dp += sepLen;
+ }
+
+ if (addBytes > 0) {
+#ifdef __va_copy
+ __va_copy(ap, args);
+#else
+ ap = args;
+#endif
+ str = (char*) src;
+ while (str) {
+ strcpy(dp, str);
+ dp += strlen(str);
+ str = va_arg(ap, char*);
+ if (delim && str) {
+ strcpy(dp, delim);
+ dp += sepLen;
+ }
+ }
+ } else if (dest == 0) {
+ dest = (char*) mprAlloc(ctx, 1);
+ }
+ *dp = '\0';
+
+ *destp = dest;
+ mprAssert(dp < &dest[required]);
+ return required - 1;
+}
+
+/*****************************************************************************
+ Note that this VARARGS function must be NULL (not 0, this must be a
+ pointer) terminated
+*/
+int mprStrcat(char *dest, int destMax, const char *delim, const char *src, ...)
+{
+ va_list ap;
+ int rc;
+
+ mprAssert(dest);
+ mprAssert(src);
+
+ va_start(ap, src);
+ rc = mprCoreStrcat(MPR_LOC_ARGS(0), &dest, destMax, strlen(dest),
+ delim, src, ap);
+ va_end(ap);
+ return rc;
+}
+
+/*****************************************************************************
+ Note that this VARARGS function must be NULL (not 0, this must be a
+ pointer) terminated
+*/
+int mprAllocStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax,
+ const char *delim, const char *src, ...)
+{
+ va_list ap;
+ int rc;
+
+ mprAssert(destp);
+ mprAssert(src);
+
+ *destp = 0;
+ va_start(ap, src);
+ rc = mprCoreStrcat(MPR_LOC_PASS(ctx, loc), destp, destMax, 0, delim,
+ src, ap);
+ va_end(ap);
+ return rc;
+}
+
+/*****************************************************************************
+ Note that this VARARGS function must be NULL (not 0, this must be a
+ pointer) terminated
+*/
+int mprReallocStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax,
+ int existingLen, const char *delim, const char *src,...)
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, src);
+ rc = mprCoreStrcat(MPR_LOC_PASS(ctx, loc), destp, destMax, existingLen,
+ delim, src, ap);
+ va_end(ap);
+ return rc;
+}
+
+/******************************************************************************/
+
+int mprStrlen(const char *src, int max)
+{
+ int len;
+
+ len = strlen(src);
+ if (len >= max) {
+ mprAssert(0);
+ return MPR_ERR_WONT_FIT;
+ }
+ return len;
+}
+
+/******************************************************************************/
+
+char *mprStrTrim(char *str, const char *set)
+{
+ int len, i;
+
+ if (str == 0 || set == 0) {
+ return str;
+ }
+
+ i = strspn(str, set);
+ str += i;
+
+ len = strlen(str);
+ while (strspn(&str[len - 1], set) > 0) {
+ str[len - 1] = '\0';
+ len--;
+ }
+ return str;
+}
+
+/******************************************************************************/
+/*
+ * Map a string to lower case (overwrites original string)
+ */
+
+char *mprStrLower(char *str)
+{
+ char *cp;
+
+ mprAssert(str);
+
+ if (str == 0) {
+ return 0;
+ }
+
+ for (cp = str; *cp; cp++) {
+ if (isupper(*cp)) {
+ *cp = (char) tolower(*cp);
+ }
+ }
+ return str;
+}
+
+/******************************************************************************/
+/*
+ * Map a string to upper case (overwrites buffer)
+ */
+
+char *mprStrUpper(char *str)
+{
+ char *cp;
+
+ mprAssert(str);
+ if (str == 0) {
+ return 0;
+ }
+
+ for (cp = str; *cp; cp++) {
+ if (islower(*cp)) {
+ *cp = (char) toupper(*cp);
+ }
+ }
+ return str;
+}
+
+/******************************************************************************/
+/*
+ * Case insensitive string comparison. Stop at the end of str1.
+ */
+
+int mprStrcmpAnyCase(const char *str1, const char *str2)
+{
+ int rc;
+
+ if (str1 == 0 || str2 == 0) {
+ return -1;
+ }
+ if (str1 == str2) {
+ return 0;
+ }
+
+ for (rc = 0; *str1 && rc == 0; str1++, str2++) {
+ rc = tolower(*str1) - tolower(*str2);
+ }
+ if (*str2) {
+ return -1;
+ }
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Case insensitive string comparison. Limited by length
+ */
+
+int mprStrcmpAnyCaseCount(const char *str1, const char *str2, int len)
+{
+ int rc;
+
+ if (str1 == 0 || str2 == 0) {
+ return -1;
+ }
+ if (str1 == str2) {
+ return 0;
+ }
+
+ for (rc = 0; len-- > 0 && *str1 && rc == 0; str1++, str2++) {
+ rc = tolower(*str1) - tolower(*str2);
+ }
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Return the last portion of a pathname
+ */
+
+const char *mprGetBaseName(const char *name)
+{
+ char *cp;
+
+ cp = strrchr(name, '/');
+
+ if (cp == 0) {
+ cp = strrchr(name, '\\');
+ if (cp == 0) {
+ return name;
+ }
+ }
+ if (cp == name) {
+ if (cp[1] == '\0') {
+ return name;
+ }
+ } else {
+ if (cp[1] == '\0') {
+ return "";
+ }
+ }
+ return &cp[1];
+}
+
+/******************************************************************************/
+/*
+ * Return the directory portion of a pathname into the users buffer.
+ */
+
+char *mprGetDirName(char *buf, int bufsize, const char *path)
+{
+ char *cp;
+ int dlen;
+
+ mprAssert(path);
+ mprAssert(buf);
+ mprAssert(bufsize > 0);
+
+ cp = strrchr(path, '/');
+ if (cp == 0) {
+#if WIN
+ cp = strrchr(path, '\\');
+ if (cp == 0)
+#endif
+ {
+ buf[0] = '\0';
+ return buf;
+ }
+ }
+
+ if (cp == path && cp[1] == '\0') {
+ strcpy(buf, ".");
+ return buf;
+ }
+
+ dlen = cp - path;
+ if (dlen < bufsize) {
+ if (dlen == 0) {
+ dlen++;
+ }
+ mprMemcpy(buf, bufsize, path, dlen);
+ buf[dlen] = '\0';
+ return buf;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok()
+ */
+
+char *mprStrTok(char *str, const char *delim, char **last)
+{
+ char *start, *end;
+ int i;
+
+ start = str ? str : *last;
+
+ if (start == 0) {
+ return 0;
+ }
+
+ i = strspn(start, delim);
+ start += i;
+ if (*start == '\0') {
+ *last = 0;
+ return 0;
+ }
+ end = strpbrk(start, delim);
+ if (end) {
+ *end++ = '\0';
+ i = strspn(end, delim);
+ end += i;
+ }
+ *last = end;
+ return start;
+}
+
+/******************************************************************************/
+/*
+ * Split the buffer into word tokens
+ */
+
+char *mprGetWordTok(char *buf, int bufsize, const char *str, const char *delim,
+ const char **tok)
+{
+ const char *start, *end;
+ int i, len;
+
+ start = str ? str : *tok;
+
+ if (start == 0) {
+ return 0;
+ }
+
+ i = strspn(start, delim);
+ start += i;
+ if (*start =='\0') {
+ *tok = 0;
+ return 0;
+ }
+ end = strpbrk(start, delim);
+ if (end) {
+ len = min(end - start, bufsize - 1);
+ mprMemcpy(buf, bufsize, start, len);
+ buf[len] = '\0';
+ } else {
+ if (mprStrcpy(buf, bufsize, start) < 0) {
+ buf[bufsize - 1] = '\0';
+ return 0;
+ }
+ buf[bufsize - 1] = '\0';
+ }
+ *tok = end;
+ return buf;
+}
+
+/******************************************************************************/
+/*
+ * Format a number as a string.
+ */
+
+char *mprItoa(char *buf, int size, int value)
+{
+ char numBuf[16];
+ char *cp, *dp, *endp;
+ int negative;
+
+ cp = &numBuf[sizeof(numBuf)];
+ *--cp = '\0';
+
+ if (value < 0) {
+ negative = 1;
+ value = -value;
+ size--;
+ } else {
+ negative = 0;
+ }
+
+ do {
+ *--cp = '0' + (value % 10);
+ value /= 10;
+ } while (value > 0);
+
+ if (negative) {
+ *--cp = '-';
+ }
+
+ dp = buf;
+ endp = &buf[size];
+ while (dp < endp && *cp) {
+ *dp++ = *cp++;
+ }
+ *dp++ = '\0';
+ return buf;
+}
+
+/******************************************************************************/
+/*
+ * Parse an ascii number. Supports radix 10 or 16.
+ */
+
+int mprAtoi(const char *str, int radix)
+{
+ int c, val, negative;
+
+ mprAssert(radix == 10 || radix == 16);
+
+ if (str == 0) {
+ return 0;
+ }
+
+ val = 0;
+ if (radix == 10 && *str == '-') {
+ negative = 1;
+ str++;
+ } else {
+ negative = 0;
+ }
+
+ if (radix == 10) {
+ while (*str && isdigit(*str)) {
+ val = (val * radix) + *str - '0';
+ str++;
+ }
+ } else if (radix == 16) {
+ if (*str == '0' && tolower(str[1]) == 'x') {
+ str += 2;
+ }
+ while (*str) {
+ c = tolower(*str);
+ if (isdigit(c)) {
+ val = (val * radix) + c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ val = (val * radix) + c - 'a' + 10;
+ } else {
+ break;
+ }
+ str++;
+ }
+ }
+
+ return (negative) ? -val: val;
+}
+
+/******************************************************************************/
+/*
+ * Make an argv array. Caller must free by calling mprFree(argv) to free
+ * everything.
+ */
+
+int mprMakeArgv(MprCtx ctx, const char *program, const char *cmd,
+ char ***argvp, int *argcp)
+{
+ char *cp, **argv, *buf, *args;
+ int size, argc;
+
+ /*
+ * Allocate one buffer for argv and the actual args themselves
+ */
+ size = strlen(cmd) + 1;
+
+ buf = (char*) mprAlloc(ctx, (MPR_MAX_ARGC * sizeof(char*)) + size);
+ if (buf == 0) {
+ return MPR_ERR_MEMORY;
+ }
+
+ args = &buf[MPR_MAX_ARGC * sizeof(char*)];
+ strcpy(args, cmd);
+ argv = (char**) buf;
+
+ argc = 0;
+ if (program) {
+ argv[argc++] = (char*) mprStrdup(ctx, program);
+ }
+
+ for (cp = args; cp && *cp != '\0'; argc++) {
+ if (argc >= MPR_MAX_ARGC) {
+ mprAssert(argc < MPR_MAX_ARGC);
+ mprFree(buf);
+ *argvp = 0;
+ if (argcp) {
+ *argcp = 0;
+ }
+ return MPR_ERR_TOO_MANY;
+ }
+ while (isspace(*cp)) {
+ cp++;
+ }
+ if (*cp == '\0') {
+ break;
+ }
+ if (*cp == '"') {
+ cp++;
+ argv[argc] = cp;
+ while ((*cp != '\0') && (*cp != '"')) {
+ cp++;
+ }
+ } else {
+ argv[argc] = cp;
+ while (*cp != '\0' && !isspace(*cp)) {
+ cp++;
+ }
+ }
+ if (*cp != '\0') {
+ *cp++ = '\0';
+ }
+ }
+ argv[argc] = 0;
+
+ if (argcp) {
+ *argcp = argc;
+ }
+ *argvp = argv;
+
+ return argc;
+}
+
+/******************************************************************************/
+
+/*
+ * 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/mpr/mprSymbol.c b/source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c
new file mode 100644
index 0000000000..11ac278db4
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c
@@ -0,0 +1,279 @@
+/*
+ * @file mprSym.cpp
+ * @brief Fast hashing symbol table lookup module
+ * @overview This symbol table uses a fast key lookup mechanism. Keys are
+ * strings and the value entries are arbitrary pointers. The keys are
+ * hashed into a series of buckets which then have a chain of hash
+ * entries using the standard doubly linked list classes (List/Link).
+ * The chain in in collating sequence so search time through the chain
+ * is on average (N/hashSize)/2.
+ * @remarks This module is not thread-safe. It is the callers responsibility
+ * to perform all thread synchronization.
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 "mpr.h"
+
+/**************************** Forward Declarations ****************************/
+
+static int hashIndex(const char *key, int size);
+static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp,
+ MprSymbolTable *table, const char *key);
+
+/*********************************** Code *************************************/
+/*
+ * Create a new symbol table of a given size. Caller should provide a size
+ * that is a prime number for the greatest efficiency. Caller should use
+ * mprFree to free the symbol table.
+ */
+
+MprSymbolTable *mprCreateSymbolTable(MprCtx ctx, int hashSize)
+{
+ MprSymbolTable *table;
+
+ table = mprAllocTypeZeroed(ctx, MprSymbolTable);
+ if (table == 0) {
+ return 0;
+ }
+
+ if (hashSize < MPR_DEFAULT_HASH_SIZE) {
+ hashSize = MPR_DEFAULT_HASH_SIZE;
+ }
+ table->hashSize = hashSize;
+
+ table->count = 0;
+ table->hashSize = hashSize;
+ table->buckets = mprAllocZeroedBlock(MPR_LOC_ARGS(table),
+ sizeof(MprSymbol*) * hashSize);
+
+ if (table->buckets == 0) {
+ mprFree(table);
+ return 0;
+ }
+
+ return table;
+}
+
+/******************************************************************************/
+/*
+ * Insert an entry into the symbol table. If the entry already exists, update
+ * its value. Order of insertion is not preserved.
+ */
+
+MprSymbol *mprInsertSymbol(MprSymbolTable *table, const char *key, void *ptr)
+{
+ MprSymbol *sp, *prevSp;
+ int index;
+
+ sp = lookupInner(&index, &prevSp, table, key);
+
+ if (sp != 0) {
+ /*
+ * Already exists. Just update the data.
+ */
+ sp->data = ptr;
+ return sp;
+ }
+
+ /*
+ * New entry
+ */
+ sp = mprAllocTypeZeroed(table, MprSymbol);
+ if (sp == 0) {
+ return 0;
+ }
+
+ sp->data = ptr;
+ sp->key = mprStrdup(sp, key);
+ sp->bucket = index;
+
+ sp->next = table->buckets[index];
+ table->buckets[index] = sp;
+
+ table->count++;
+ return sp;
+}
+
+/******************************************************************************/
+/*
+ * Remove an entry from the table
+ */
+
+int mprRemoveSymbol(MprSymbolTable *table, const char *key)
+{
+ MprSymbol *sp, *prevSp;
+ int index;
+
+ if ((sp = lookupInner(&index, &prevSp, table, key)) == 0) {
+ return MPR_ERR_NOT_FOUND;
+ }
+
+ if (prevSp) {
+ prevSp->next = sp->next;
+ } else {
+ table->buckets[index] = sp->next;
+ }
+ table->count--;
+
+ mprFree(sp);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Lookup a key and return the hash entry
+ */
+
+void *mprLookupSymbol(MprSymbolTable *table, const char *key)
+{
+ MprSymbol *sp;
+
+ mprAssert(key);
+
+ sp = lookupInner(0, 0, table, key);
+ if (sp == 0) {
+ return 0;
+ }
+ return sp->data;
+}
+
+/******************************************************************************/
+
+static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp,
+ MprSymbolTable *table, const char *key)
+{
+ MprSymbol *sp, *prev;
+ int index, rc;
+
+ mprAssert(key);
+
+ index = hashIndex(key, table->hashSize);
+ if (bucketIndex) {
+ *bucketIndex = index;
+ }
+
+ sp = table->buckets[index];
+ prev = 0;
+
+ while (sp) {
+ rc = strcmp(sp->key, key);
+ if (rc == 0) {
+ if (prevSp) {
+ *prevSp = prev;
+ }
+ return sp;
+ }
+ prev = sp;
+ mprAssert(sp != sp->next);
+ sp = sp->next;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+int mprGetSymbolCount(MprSymbolTable *table)
+{
+ return table->count;
+}
+
+/******************************************************************************/
+/*
+ * Return the first entry in the table.
+ */
+
+MprSymbol *mprGetFirstSymTab(MprSymbolTable *table)
+{
+ MprSymbol *sp;
+ int i;
+
+ mprAssert(table);
+
+ for (i = 0; i < table->hashSize; i++) {
+ if ((sp = (MprSymbol*) table->buckets[i]) != 0) {
+ return sp;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return the next entry in the table
+ */
+
+MprSymbol *mprGetNextSymTab(MprSymbolTable *table, MprSymbol *last)
+{
+ MprSymbol *sp;
+ int i;
+
+ mprAssert(table);
+
+ if (last->next) {
+ return last->next;
+ }
+
+ for (i = last->bucket + 1; i < table->hashSize; i++) {
+ if ((sp = (MprSymbol*) table->buckets[i]) != 0) {
+ return sp;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Hash the key to produce a hash index.
+ */
+
+static int hashIndex(const char *key, int size)
+{
+ uint sum;
+
+ sum = 0;
+ while (*key) {
+ sum += (sum * 33) + *key++;
+ }
+
+ return sum % size;
+}
+
+/******************************************************************************/
+/*
+ * 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/mpr/mprUnix.h b/source4/lib/appweb/ejs-2.0/mpr/mprUnix.h
new file mode 100644
index 0000000000..fbbe29ae9c
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprUnix.h
@@ -0,0 +1,105 @@
+/*
+ * @file mprUnix.h
+ * @brief Make windows a bit more unix like
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2006. 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
+ */
+
+/******************************* Documentation ********************************/
+
+/*
+ * This header is part of the Mbedthis Portable Runtime and aims to include
+ * all necessary O/S headers and to unify the constants and declarations
+ * required by Mbedthis products. It can be included by C or C++ programs.
+ */
+
+/******************************************************************************/
+
+#ifndef _h_MPR_UNIX
+#define _h_MPR_UNIX 1
+
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Define BLD_NO_POSIX_REMAP if these defines mess with your app
+ */
+#if WIN && !BLD_NO_POSIX_REMAP
+/*
+ * MOB -- clashes with ATL
+ */
+#define access _access
+#define close _close
+#define fileno _fileno
+#define fstat _fstat
+#define getpid _getpid
+#define open _open
+#define putenv _putenv
+#define read _read
+#define stat _stat
+#define umask _umask
+#define unlink _unlink
+#define write _write
+#define strdup _strdup
+#define lseek _lseek
+#define getcwd _getcwd
+#define chdir _chdir
+
+#define mkdir(a,b) _mkdir(a)
+#define rmdir(a) _rmdir(a)
+
+#define R_OK 4
+#define W_OK 2
+#define MPR_TEXT "t"
+
+extern void srand48(long);
+extern long lrand48(void);
+extern long ulimit(int, ...);
+extern long nap(long);
+extern int getuid(void);
+extern int geteuid(void);
+#endif
+
+
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _h_MPR_UNIX */
+
+/*
+ * 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
+ */