wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -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*) ∈
|
||||
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*) ∈
|
||||
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
@@ -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*) ∈
|
||||
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
|
||||
*/
|
||||
@@ -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}
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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
|
||||
*/
|
||||
Reference in New Issue
Block a user