wmi-1.3.16 from opsview.com

This commit is contained in:
Are Casilla
2019-02-16 00:16:52 +01:00
parent 163fdd3d1b
commit 17b3af2911
2146 changed files with 678824 additions and 0 deletions
@@ -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
@@ -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
@@ -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
*/
@@ -0,0 +1,218 @@
/**
* @file mprPlatform.c
* @brief Cross platform routines
* @overview This module provides low level cross platform routines.
* @remarks Most routines in this file are not thread-safe. It is the callers
* responsibility to perform all thread synchronization.
*/
/*
* @copy default
*
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http://www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http://www.mbedthis.com
*
* @end
*/
/********************************** Includes **********************************/
/*
* We need to use the underlying str(cpy) routines to implement our safe
* alternatives
*/
#if !DOXYGEN
#define UNSAFE_FUNCTIONS_OK 1
#endif
#include "mpr.h"
/************************************ Code ************************************/
char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
{
#if HAVE_NTOA_R
inet_ntoa_r(in, buffer, bufsize);
#else
uchar *cp;
/* FUTURE -- this is not portable */
cp = (uchar*) &in;
mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
#endif
return buffer;
}
/******************************************************************************/
void mprSetShell(MprCtx ctx, void *shell)
{
}
/******************************************************************************/
void *mprGetShell(MprCtx ctx)
{
return 0;
}
/******************************************************************************/
/*
* Sleep. Period given in milliseconds.
*/
void mprSleep(MprCtx ctx, int milliseconds)
{
struct timespec timeout;
int rc;
mprAssert(milliseconds >= 0);
timeout.tv_sec = milliseconds / 1000;
timeout.tv_nsec = (milliseconds % 1000) * 1000000;
do {
rc = nanosleep(&timeout, 0);
} while (rc < 0 && errno == EINTR);
}
/******************************************************************************/
/*
* Make intervening directories
*/
int mprMakeDirPath(MprCtx ctx, const char *path)
{
char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
char *dirSep;
char *next, *tok;
dir[0] = '\0';
dirSep = "/\\";
if (path == 0 || *path == '\0') {
return MPR_ERR_BAD_ARGS;
}
mprStrcpy(buf, sizeof(buf), path);
next = mprStrTok(buf, dirSep, &tok);
if (*buf == '/') {
dir[0] = '/';
}
while (next != NULL) {
if (strcmp(next, ".") == 0 ) {
next = mprStrTok(NULL, dirSep, &tok);
continue;
}
strcat(dir, next);
if (access(dir, R_OK) != 0) {
if (mkdir(dir, 0666) < 0) {
return MPR_ERR_CANT_CREATE;
}
}
strcat(dir, "/");
next = mprStrTok(NULL, dirSep, &tok);
}
return 0;
}
/******************************************************************************/
/*
* Get a fully qualified file name for the given path. Return with forward
* slashes always
*/
char *mprGetFullPathName(char *buf, int buflen, const char *path)
{
if (mprStrcpy(buf, buflen, path) < 0) {
mprAssert(0);
return 0;
}
return buf;
}
/******************************************************************************/
/*
* Replacement for gethostbyname that is multi-thread safe
*/
struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
{
MprApp *app;
struct hostent *hp;
struct hostent *ip;
int count, i;
hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
memset(hp, 0, sizeof(struct hostent));
app = mprGetApp(ctx);
#undef gethostbyname
mprGlobalLock(app);
ip = gethostbyname(name);
mprGlobalUnlock(app);
if (ip == 0) {
return 0;
}
hp->h_addrtype = ip->h_addrtype;
hp->h_length = ip->h_length;
hp->h_name = mprStrdup(hp, ip->h_name);
hp->h_addr_list = 0;
hp->h_aliases = 0;
for (count = 0; ip->h_addr_list[count] != 0; ) {
count++;
}
if (count > 0) {
count++;
hp->h_addr_list = mprAlloc(hp, count * sizeof(char*));
for (i = 0; ip->h_addr_list[i] != 0; i++) {
memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length);
}
hp->h_addr_list[i] = 0;
}
for (count = 0; ip->h_aliases[count] != 0; ) {
count++;
}
if (count > 0) {
count++;
hp->h_aliases = mprAlloc(hp, count * sizeof(char*));
for (i = 0; ip->h_aliases[i] != 0; i++) {
hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]);
}
hp->h_aliases[i] = 0;
}
return hp;
}
/******************************************************************************/
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
@@ -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
*/
@@ -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
@@ -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
*/
@@ -0,0 +1,191 @@
/**
* @file mprPlatform.c
* @brief Cross platform routines
* @overview This module provides low level cross platform routines.
* @remarks Most routines in this file are not thread-safe. It is the callers
* responsibility to perform all thread synchronization.
*/
/*
* @copy default
*
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http://www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http://www.mbedthis.com
*
* @end
*/
/********************************** Includes **********************************/
/*
* We need to use the underlying str(cpy) routines to implement our safe
* alternatives
*/
#if !DOXYGEN
#define UNSAFE_FUNCTIONS_OK 1
#endif
#include "mpr.h"
/************************************ Code ************************************/
char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
{
#if HAVE_NTOA_R
inet_ntoa_r(in, buffer, bufsize);
#else
uchar *cp;
/* FUTURE -- this is not portable */
cp = (uchar*) &in;
mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
#endif
return buffer;
}
/******************************************************************************/
void mprSetShell(MprCtx ctx, void *shell)
{
}
/******************************************************************************/
void *mprGetShell(MprCtx ctx)
{
return 0;
}
/******************************************************************************/
/*
* Sleep. Period given in milliseconds.
*/
void mprSleep(MprCtx ctx, int milliseconds)
{
struct timeval timeout;
int rc;
timeout.tv_sec = milliseconds / 1000;
timeout.tv_usec = (milliseconds % 1000) * 1000;
do {
rc = select(1, 0, 0, 0, &timeout);
} while (rc < 0 && errno == EINTR);
}
/******************************************************************************/
/*
* Make intervening directories
*/
int mprMakeDirPath(MprCtx ctx, const char *path)
{
char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
char *dirSep;
char *next, *tok;
dir[0] = '\0';
dirSep = "/\\";
if (path == 0 || *path == '\0') {
return MPR_ERR_BAD_ARGS;
}
mprStrcpy(buf, sizeof(buf), path);
next = mprStrTok(buf, dirSep, &tok);
if (*buf == '/') {
dir[0] = '/';
}
while (next != NULL) {
if (strcmp(next, ".") == 0 ) {
next = mprStrTok(NULL, dirSep, &tok);
continue;
}
strcat(dir, next);
if (access(dir, R_OK) != 0) {
if (mkdir(dir) < 0) {
return MPR_ERR_CANT_CREATE;
}
}
strcat(dir, "/");
next = mprStrTok(NULL, dirSep, &tok);
}
return 0;
}
/******************************************************************************/
/*
* Get a fully qualified file name for the given path. Return with forward
* slashes always
*/
char *mprGetFullPathName(char *buf, int buflen, const char *path)
{
if (mprStrcpy(buf, buflen, path) < 0) {
mprAssert(0);
return 0;
}
return buf;
}
/******************************************************************************/
/*
* Replacement for gethostbyname that is multi-thread safe
*/
struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
{
struct hostent *hp;
hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
memset(hp, 0, sizeof(struct hostent));
struct in_addr inaddr;
inaddr.s_addr = (ulong) hostGetByName(name);
if (inaddr.s_addr < 0) {
mprAssert(0);
return 0;
}
hp->h_addrtype = AF_INET;
hp->h_length = sizeof(int);
hp->h_name = mprStrdup(name);
hp->h_addr_list = 0;
hp->h_aliases = 0;
hp->h_addr_list = new char*[2];
hp->h_addr_list[0] = (char *) mprAlloc(hp, sizeof(struct in_addr));
memcpy(&hp->h_addr_list[0], &inaddr, hp->h_length);
hp->h_addr_list[1] = 0;
return hp;
}
/******************************************************************************/
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
+163
View File
@@ -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
*/
@@ -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
@@ -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
*/
@@ -0,0 +1,378 @@
/**
* @file mprPlatform.c
* @brief Cross platform routines
* @overview This module provides low level cross platform routines.
* @remarks Most routines in this file are not thread-safe. It is the callers
* responsibility to perform all thread synchronization.
*/
/*
* @copy default
*
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http://www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http://www.mbedthis.com
*
* @end
*/
/********************************** Includes **********************************/
/*
* We need to use the underlying str(cpy) routines to implement our safe
* alternatives
*/
#if !DOXYGEN
#define UNSAFE_FUNCTIONS_OK 1
#endif
#include "mpr.h"
/**************************** Forward Declarations ****************************/
static const char *getHive(const char *keyPath, HKEY *hive);
/************************************ Code ************************************/
char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
{
#if HAVE_NTOA_R
inet_ntoa_r(in, buffer, bufsize);
#else
uchar *cp;
cp = (uchar*) &in;
mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
#endif
return buffer;
}
/******************************************************************************/
void mprSetShell(MprCtx ctx, void *shell)
{
}
/******************************************************************************/
void *mprGetShell(MprCtx ctx)
{
return 0;
}
/******************************************************************************/
/*
* Sleep. Period given in milliseconds.
*/
void mprSleep(MprCtx ctx, int milliseconds)
{
Sleep(milliseconds);
}
/******************************************************************************/
/*
* Make intervening directories
*/
int mprMakeDirPath(MprCtx ctx, const char *path)
{
char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
char *dirSep;
char *next, *tok;
dir[0] = '\0';
dirSep = "/\\";
if (path == 0 || *path == '\0') {
return MPR_ERR_BAD_ARGS;
}
mprStrcpy(buf, sizeof(buf), path);
next = mprStrTok(buf, dirSep, &tok);
if (*buf == '/') {
dir[0] = '/';
}
while (next != NULL) {
if (strcmp(next, ".") == 0 ) {
next = mprStrTok(NULL, dirSep, &tok);
continue;
}
strcat(dir, next);
if (access(dir, R_OK) != 0) {
if (_mkdir(dir) < 0) {
return MPR_ERR_CANT_CREATE;
}
}
strcat(dir, "/");
next = mprStrTok(NULL, dirSep, &tok);
}
return 0;
}
/******************************************************************************/
/*
* Get a fully qualified file name for the given path. Return with forward
* slashes always
*/
char *mprGetFullPathName(char *buf, int buflen, const char *path)
{
#if (WIN || NW || OS2) && !BLD_FEATURE_ROMFS
char *junk, *cp;
int rc;
--buflen;
rc = GetFullPathName(path, buflen, buf, &junk);
for (cp = buf; *cp; cp++) {
if (*cp == '\\') {
*cp = '/';
}
}
buf[buflen] = '\0';
#else
if (mprStrcpy(buf, buflen, path) < 0) {
mprAssert(0);
return 0;
}
#endif
return buf;
}
/******************************************************************************/
/*
* Replacement for gethostbyname that is multi-thread safe
*/
struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
{
MprApp *app;
struct hostent *hp;
struct hostent *ip;
int count, i;
hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
memset(hp, 0, sizeof(struct hostent));
app = mprGetApp(ctx);
#undef gethostbyname
mprGlobalLock(app);
ip = gethostbyname(name);
mprGlobalUnlock(app);
if (ip == 0) {
return 0;
}
hp->h_addrtype = ip->h_addrtype;
hp->h_length = ip->h_length;
hp->h_name = mprStrdup(hp, ip->h_name);
hp->h_addr_list = 0;
hp->h_aliases = 0;
for (count = 0; ip->h_addr_list[count] != 0; ) {
count++;
}
if (count > 0) {
count++;
hp->h_addr_list = mprAlloc(hp, count * sizeof(char*));
for (i = 0; ip->h_addr_list[i] != 0; i++) {
memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length);
}
hp->h_addr_list[i] = 0;
}
for (count = 0; ip->h_aliases[count] != 0; ) {
count++;
}
if (count > 0) {
count++;
hp->h_aliases = mprAlloc(hp, count * sizeof(char*));
for (i = 0; ip->h_aliases[i] != 0; i++) {
hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]);
}
hp->h_aliases[i] = 0;
}
return hp;
}
/******************************************************************************/
/*
* Read a registry value. Returns allocated memory in buf.
*/
int mprReadRegistry(MprCtx ctx, char **buf, int max, const char *key,
const char *name)
{
HKEY top, h;
char *value;
ulong type, size;
mprAssert(key && *key);
mprAssert(buf);
/*
* Get the registry hive
*/
if ((key = getHive(key, &top)) == 0) {
return MPR_ERR_CANT_ACCESS;
}
if (RegOpenKeyEx(top, key, 0, KEY_READ, &h) != ERROR_SUCCESS) {
return MPR_ERR_CANT_ACCESS;
}
/*
* Get the type
*/
if (RegQueryValueEx(h, name, 0, &type, 0, &size) != ERROR_SUCCESS) {
RegCloseKey(h);
return MPR_ERR_CANT_READ;
}
if (type != REG_SZ && type != REG_EXPAND_SZ) {
RegCloseKey(h);
return MPR_ERR_BAD_TYPE;
}
value = (char*) mprAlloc(ctx, size);
if ((int) size > max) {
RegCloseKey(h);
return MPR_ERR_WONT_FIT;
}
if (RegQueryValueEx(h, name, 0, &type, (uchar*) value, &size) !=
ERROR_SUCCESS) {
mprFree(value);
RegCloseKey(h);
return MPR_ERR_CANT_READ;
}
RegCloseKey(h);
*buf = value;
return 0;
}
/******************************************************************************/
/*
* Write a string registry value. Returns allocated memory in buf.
*/
int mprWriteRegistry(MprCtx ctx, const char *key, const char *name,
const char *value)
{
HKEY top, h, subHandle;
ulong disposition;
mprAssert(key && *key);
mprAssert(name && *name);
mprAssert(value && *value);
/*
* Get the registry hive
*/
if ((key = getHive(key, &top)) == 0) {
return MPR_ERR_CANT_ACCESS;
}
if (name) {
/*
* Write a registry string value
*/
if (RegOpenKeyEx(top, key, 0, KEY_ALL_ACCESS, &h) != ERROR_SUCCESS) {
return MPR_ERR_CANT_ACCESS;
}
if (RegSetValueEx(h, name, 0, REG_SZ, value, strlen(value) + 1)
!= ERROR_SUCCESS) {
RegCloseKey(h);
return MPR_ERR_CANT_READ;
}
} else {
/*
* Create a new sub key
*/
if (RegOpenKeyEx(top, key, 0, KEY_CREATE_SUB_KEY, &h) != ERROR_SUCCESS){
return MPR_ERR_CANT_ACCESS;
}
if (RegCreateKeyEx(h, name, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &subHandle, &disposition) != ERROR_SUCCESS) {
return MPR_ERR_CANT_ACCESS;
}
RegCloseKey(subHandle);
}
RegCloseKey(h);
return 0;
}
/******************************************************************************/
/*
* Determine the registry hive by the first portion of the path. Return
* a pointer to the rest of key path after the hive portion.
*/
static const char *getHive(const char *keyPath, HKEY *hive)
{
char key[MPR_MAX_STRING], *cp;
int len;
mprAssert(keyPath && *keyPath);
*hive = 0;
mprStrcpy(key, sizeof(key), keyPath);
key[sizeof(key) - 1] = '\0';
if (cp = strchr(key, '\\')) {
*cp++ = '\0';
}
if (cp == 0 || *cp == '\0') {
return 0;
}
if (!mprStrcmpAnyCase(key, "HKEY_LOCAL_MACHINE")) {
*hive = HKEY_LOCAL_MACHINE;
} else if (!mprStrcmpAnyCase(key, "HKEY_CURRENT_USER")) {
*hive = HKEY_CURRENT_USER;
} else if (!mprStrcmpAnyCase(key, "HKEY_USERS")) {
*hive = HKEY_USERS;
} else if (!mprStrcmpAnyCase(key, "HKEY_CLASSES_ROOT")) {
*hive = HKEY_CLASSES_ROOT;
} else {
return 0;
}
if (*hive == 0) {
return 0;
}
len = strlen(key) + 1;
return keyPath + len;
}
/******************************************************************************/
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
@@ -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
*/
+14
View File
@@ -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}
+340
View File
@@ -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
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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
*/
@@ -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
*/
@@ -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
*/
@@ -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
*/
@@ -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
*/
@@ -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
*/
+707
View File
@@ -0,0 +1,707 @@
/*
* @file mprOs.h
* @brief Include O/S headers and smooth out per-O/S differences
* @copy default
*
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http://www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http://www.mbedthis.com
*
* @end
*/
/******************************* Documentation ********************************/
/*
* This header is part of the Mbedthis Portable Runtime and aims to include
* all necessary O/S headers and to unify the constants and declarations
* required by Mbedthis products. It can be included by C or C++ programs.
*/
/******************************************************************************/
#ifndef _h_MPR_OS_HDRS
#define _h_MPR_OS_HDRS 1
#include "buildConfig.h"
/********************************* CPU Families *******************************/
/*
* Porters, add your CPU families here and update configure code.
*/
#define MPR_CPU_UNKNOWN 0
#define MPR_CPU_IX86 1
#define MPR_CPU_PPC 2
#define MPR_CPU_SPARC 3
#define MPR_CPU_XSCALE 4
#define MPR_CPU_ARM 5
#define MPR_CPU_MIPS 6
#define MPR_CPU_68K 7
#define MPR_CPU_SIMNT 8 /* VxWorks NT simulator */
#define MPR_CPU_SIMSPARC 9 /* VxWorks sparc simulator */
/********************************* O/S Includes *******************************/
#if LINUX || SOLARIS
#include <sys/types.h>
#include <time.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <grp.h>
#include <errno.h>
#include <libgen.h>
#include <limits.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <pthread.h>
#include <pwd.h>
#include <resolv.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
#if LINUX
#include <stdint.h>
#endif
#if SOLARIS
#include <netinet/in_systm.h>
#endif
#if BLD_FEATURE_FLOATING_POINT
#define __USE_ISOC99 1
#include <math.h>
#include <values.h>
#endif
#endif /* LINUX || SOLARIS */
#if VXWORKS
#include <vxWorks.h>
#include <envLib.h>
#include <sys/types.h>
#include <time.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <loadLib.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysSymTbl.h>
#include <sys/fcntlcom.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <unistd.h>
#include <unldLib.h>
#if BLD_FEATURE_FLOATING_POINT
#include <float.h>
#define __USE_ISOC99 1
#include <math.h>
#endif
#include <sockLib.h>
#include <inetLib.h>
#include <ioLib.h>
#include <pipeDrv.h>
#include <hostLib.h>
#include <netdb.h>
#include <tickLib.h>
#include <taskHookLib.h>
#endif /* VXWORKS */
#if MACOSX
#include <time.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <fcntl.h>
#include <grp.h>
#include <errno.h>
#include <libgen.h>
#include <limits.h>
#include <mach-o/dyld.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <pthread.h>
#include <pwd.h>
#include <resolv.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
#endif /* MACOSX */
#if WIN
/*
* We replace insecure functions with Mbedthis replacements
*/
#define _CRT_SECURE_NO_DEPRECATE 1
#include <ctype.h>
#include <conio.h>
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <limits.h>
#include <malloc.h>
#include <process.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <winbase.h>
#if BLD_FEATURE_FLOATING_POINT
#include <float.h>
#endif
#include <shlobj.h>
#include <shellapi.h>
#include <wincrypt.h>
#if BLD_DEBUG
#include <crtdbg.h>
#endif
#include "mprUnix.h"
#endif /* WIN */
#if BREW
#if BLD_FEATURE_FLOATING_POINT
#warning "Floating point is not supported on Brew"
#endif
#if BLD_FEATURE_MULTITHREAD
#warning "Multithreading is not supported on Brew"
#endif
#include "AEEModGen.h"
#include "AEEAppGen.h"
#include "BREWVersion.h"
#if BREW_MAJ_VER == 2
/*
* Fix for BREW 2.X
*/
#ifdef __GNUC__
#define __inline extern __inline__
#endif
#include "AEENet.h"
#undef __inline
#endif
#include "AEE.h"
#include "AEEBitmap.h"
#include "AEEDisp.h"
#include "AEEFile.h"
#include "AEEHeap.h"
#include "AEEImageCtl.h"
#include "AEEMedia.h"
#include "AEEMediaUtil.h"
#include "AEEMimeTypes.h"
#include "AEEStdLib.h"
#include "AEEShell.h"
#include "AEESoundPlayer.h"
#include "AEEText.h"
#include "AEETransform.h"
#include "AEEWeb.h"
#if BREW_MAJ_VER >= 3
#include "AEESMS.h"
#endif
#include "AEETAPI.h"
#if 0
#include "AEESound.h"
#include "AEEDb.h"
#include "AEEMenu.h"
#endif
#endif /* BREW */
/******************************************************************************/
/******************************* General Defines ******************************/
/******************************************************************************/
#ifndef MAXINT
#if INT_MAX
#define MAXINT INT_MAX
#else
#define MAXINT 0x7fffffff
#endif
#endif
#ifndef BITSPERBYTE
#define BITSPERBYTE (8 * sizeof(char))
#endif
#define BITS(type) (BITSPERBYTE * (int) sizeof(type))
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define MPR_ARRAY_SIZE(type) (sizeof(type) / sizeof(type[0]))
#ifndef PRINTF_ATTRIBUTE
#if (__GNUC__ >= 3) && !DOXYGEN && BLD_FEATURE_ALLOC_LEAK_TRACK
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
* argument. Note that some gcc 2.x versions don't handle this
* properly **/
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
#endif
#endif
typedef char *MprStr; /* Used for dynamic strings */
#ifdef __cplusplus
extern "C" {
#else
typedef int bool;
#endif
/******************************************************************************/
/******************************** Linux Defines *******************************/
/******************************************************************************/
#if LINUX
typedef unsigned char uchar;
#if BLD_FEATURE_INT64
__extension__ typedef long long int int64;
__extension__ typedef unsigned long long int uint64;
#define INT64(x) (x##LL)
#define UINT64(x) (x##ULL)
#endif
#define closesocket(x) close(x)
#define MPR_BINARY ""
#define MPR_TEXT ""
#define O_BINARY 0
#define O_TEXT 0
#define SOCKET_ERROR -1
#define MPR_DLL_EXT ".so"
#if BLD_FEATURE_FLOATING_POINT
#define MAX_FLOAT MAXFLOAT
#endif
/*
* For some reason it is removed from fedora pthreads.h and only
* comes in for UNIX96
*/
extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
__attr, int *__restrict __kind) __THROW;
/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
PTHREAD_MUTEX_DEFAULT). */
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
__THROW;
#endif /* LINUX */
/******************************************************************************/
/******************************* VxWorks Defines ******************************/
/******************************************************************************/
#if VXWORKS
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
#define HAVE_SOCKLEN_T
typedef int socklen_t;
#if BLD_FEATURE_INT64
typedef long long int int64;
typedef unsigned long long int uint64;
#define INT64(x) (x##LL)
#define UINT64(x) (x##ULL)
#endif
#define closesocket(x) close(x)
#define getpid() taskIdSelf()
#define MPR_BINARY ""
#define MPR_TEXT ""
#define O_BINARY 0
#define O_TEXT 0
#define SOCKET_ERROR -1
#define MPR_DLL_EXT ".so"
#if BLD_FEATURE_FLOATING_POINT
#define MAX_FLOAT FLT_MAX
#endif
#undef R_OK
#define R_OK 4
#undef W_OK
#define W_OK 2
#undef X_OK
#define X_OK 1
#undef F_OK
#define F_OK 0
#define MSG_NOSIGNAL 0
extern int access(char *path, int mode);
extern int sysClkRateGet();
#endif /* VXWORKS */
/******************************************************************************/
/******************************** MacOsx Defines ******************************/
/******************************************************************************/
#if MACOSX
typedef unsigned long ulong;
typedef unsigned char uchar;
#if BLD_FEATURE_INT64
__extension__ typedef long long int int64;
__extension__ typedef unsigned long long int uint64;
#define INT64(x) (x##LL)
#define UINT64(x) (x##ULL)
#endif
#define closesocket(x) close(x)
#define MPR_BINARY ""
#define MPR_TEXT ""
#define O_BINARY 0
#define O_TEXT 0
#define SOCKET_ERROR -1
#define MPR_DLL_EXT ".dylib"
#define MSG_NOSIGNAL 0
#define __WALL 0x40000000
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
#if BLD_FEATURE_FLOATING_POINT
#define MAX_FLOAT MAXFLOAT
#endif
#endif /* MACOSX */
/******************************************************************************/
/******************************* Windows Defines ******************************/
/******************************************************************************/
#if WIN
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned short ushort;
/*
* We always define INT64 types on windows
*/
#if BLD_FEATURE_INT64 || 1
typedef __int64 int64;
typedef unsigned __int64 uint64;
#define INT64(x) (x##i64)
#define UINT64(x) (x##Ui64)
#endif
typedef int uid_t;
typedef void *handle;
typedef char *caddr_t;
typedef long pid_t;
typedef int gid_t;
typedef ushort mode_t;
typedef void *siginfo_t;
#define HAVE_SOCKLEN_T
typedef int socklen_t;
#undef R_OK
#define R_OK 4
#undef W_OK
#define W_OK 2
/*
* On windows map X_OK to R_OK
*/
#undef X_OK
#define X_OK 4
#undef F_OK
#define F_OK 0
#ifndef EADDRINUSE
#define EADDRINUSE 46
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifndef ENETDOWN
#define ENETDOWN 43
#endif
#ifndef ECONNRESET
#define ECONNRESET 44
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED 45
#endif
#define MSG_NOSIGNAL 0
#define MPR_BINARY "b"
#define MPR_TEXT "t"
#if BLD_FEATURE_FLOATING_POINT
#define MAX_FLOAT DBL_MAX
#endif
#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
#endif
#define MPR_DLL_EXT ".dll"
#endif /* WIN */
/******************************************************************************/
/****************************** Solaris Defines *******************************/
/******************************************************************************/
#if SOLARIS
typedef unsigned char uchar;
#if BLD_FEATURE_INT64
typedef long long int int64;
typedef unsigned long long int uint64;
#define INT64(x) (x##LL)
#define UINT64(x) (x##ULL)
#endif
#define closesocket(x) close(x)
#define MPR_BINARY ""
#define MPR_TEXT ""
#define O_BINARY 0
#define O_TEXT 0
#define SOCKET_ERROR -1
#define MPR_DLL_EXT ".so"
#define MSG_NOSIGNAL 0
#define INADDR_NONE ((in_addr_t) 0xffffffff)
#define __WALL 0
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
#if BLD_FEATURE_FLOATING_POINT
#define MAX_FLOAT MAXFLOAT
#endif
#endif /* SOLARIS */
/******************************************************************************/
/********************************* BREW Defines *******************************/
/******************************************************************************/
#if BREW
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef uint off_t;
typedef long pid_t;
#if UNUSED
typedef int uid_t;
typedef void *handle;
typedef char *caddr_t;
typedef int gid_t;
typedef ushort mode_t;
typedef void *siginfo_t;
#define HAVE_SOCKLEN_T
typedef int socklen_t;
#ifndef EADDRINUSE
#define EADDRINUSE 46
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifndef ENETDOWN
#define ENETDOWN 43
#endif
#ifndef ECONNRESET
#define ECONNRESET 44
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED 45
#endif
#define MSG_NOSIGNAL 0
#define MPR_BINARY "b"
#define MPR_TEXT "t"
#define MPR_DLL_EXT ".dll"
#endif
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#define O_CREAT 0x200
#define O_TRUNC 0x400
#define O_BINARY 0
#define O_TEXT 0x20000
#define O_EXCL 0x40000
#define O_APPEND 0x80000
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#if UNUSED
struct stat {
uint st_size;
};
#endif
extern int getpid();
extern int isalnum(int c);
extern int isalpha(int c);
extern int isdigit(int c);
extern int islower(int c);
extern int isupper(int c);
extern int isspace(int c);
extern int isxdigit(int c);
extern uint strlen(const char *str);
extern char *strstr(const char *string, const char *strSet);
extern void *memset(const void *dest, int c, uint count);
extern void exit(int status);
extern char *strpbrk(const char *str, const char *set);
extern uint strspn(const char *str, const char *set);
extern int tolower(int c);
extern int toupper(int c);
extern void *memcpy(void *dest, const void *src, uint count);
extern void *memmove(void *dest, const void *src, uint count);
extern int atoi(const char *str);
extern void free(void *ptr);
extern void *malloc(uint size);
extern void *realloc(void *ptr, uint size);
extern char *strcat(char *dest, const char *src);
extern char *strchr(const char *str, int c);
extern int strcmp(const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, uint count);
extern char *strcpy(char *dest, const char *src);
extern char *strncpy(char *dest, const char *src, uint count);
extern char *strrchr(const char *str, int c);
#undef printf
#define printf DBGPRINTF
#if BREW_SIMULATOR && BLD_DEBUG
extern _CRTIMP int __cdecl _CrtCheckMemory(void);
extern _CRTIMP int __cdecl _CrtSetReportHook();
#endif
#endif /* BREW */
/******************************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* _h_MPR_OS_HDRS */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
@@ -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
*/
@@ -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
*/
@@ -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
*/
@@ -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
*/