From 77e8402dd68079c0e245fc8826daf2c6ad334766 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 26 Sep 2006 16:58:27 +0000 Subject: r18925: Add current snapshot of the ejs-2.0 code. Tridge, will you be incorporating this? (This used to be commit 917af234a8d517f82bd42256a940608a16b988f4) --- source4/lib/appweb/ejs-2.0/mpr/Makefile | 41 + source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile | 16 + source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c | 86 + source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c | 218 +++ source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c | 163 ++ source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile | 16 + source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c | 85 + .../lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c | 191 +++ source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c | 163 ++ source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile | 16 + source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c | 123 ++ source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c | 378 +++++ source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c | 192 +++ source4/lib/appweb/ejs-2.0/mpr/files | 14 + source4/lib/appweb/ejs-2.0/mpr/mpr.c | 340 ++++ source4/lib/appweb/ejs-2.0/mpr/mpr.h | 1027 +++++++++++ source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c | 1775 ++++++++++++++++++++ source4/lib/appweb/ejs-2.0/mpr/mprArray.c | 385 +++++ source4/lib/appweb/ejs-2.0/mpr/mprBuf.c | 535 ++++++ source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c | 336 ++++ source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c | 195 +++ source4/lib/appweb/ejs-2.0/mpr/mprLock.c | 266 +++ source4/lib/appweb/ejs-2.0/mpr/mprLog.c | 602 +++++++ source4/lib/appweb/ejs-2.0/mpr/mprOs.h | 707 ++++++++ source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c | 924 ++++++++++ source4/lib/appweb/ejs-2.0/mpr/mprString.c | 727 ++++++++ source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c | 279 +++ source4/lib/appweb/ejs-2.0/mpr/mprUnix.h | 105 ++ 28 files changed, 9905 insertions(+) create mode 100644 source4/lib/appweb/ejs-2.0/mpr/Makefile create mode 100644 source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile create mode 100644 source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile create mode 100644 source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c create mode 100755 source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile create mode 100644 source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/files create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mpr.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mpr.h create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprArray.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprBuf.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprLock.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprLog.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprOs.h create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprString.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprUnix.h (limited to 'source4/lib/appweb/ejs-2.0/mpr') 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*) ∈ + 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*) ∈ + 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*) ∈ + 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 + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + +#if LINUX + #include +#endif + +#if SOLARIS + #include +#endif + +#if BLD_FEATURE_FLOATING_POINT + #define __USE_ISOC99 1 + #include + #include +#endif + +#endif /* LINUX || SOLARIS */ + +#if VXWORKS + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #if BLD_FEATURE_FLOATING_POINT + #include + #define __USE_ISOC99 1 + #include + #endif + + #include + #include + #include + #include + #include + #include + #include + #include + +#endif /* VXWORKS */ + +#if MACOSX + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif /* MACOSX */ + +#if WIN + /* + * We replace insecure functions with Mbedthis replacements + */ + #define _CRT_SECURE_NO_DEPRECATE 1 + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #define WIN32_LEAN_AND_MEAN + #include + #include + #include + #if BLD_FEATURE_FLOATING_POINT + #include + #endif + #include + #include + #include + +#if BLD_DEBUG + #include +#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..b688667bcc --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/mpr/mprString.c @@ -0,0 +1,727 @@ +/** + * @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; +} + +/******************************************************************************/ + +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; +} + +/******************************************************************************/ + +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; +} + +/******************************************************************************/ + +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 + */ -- cgit