First merge of 2.064 beta.

This corresponds to DMD commit a913ce4bc59a94a022a27e390fc841f4aededffb.

Doesn't build Phobos yet.
This commit is contained in:
David Nadlinger
2013-10-19 23:21:53 +02:00
committed by Kai Nacke
parent c400d180d2
commit cb341586e3
130 changed files with 13566 additions and 9190 deletions

View File

@@ -14,20 +14,17 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "aav.h"
static const size_t prime_list[] = {
31UL,
97UL, 389UL,
1543UL, 6151UL,
24593UL, 98317UL,
393241UL, 1572869UL,
6291469UL, 25165843UL,
100663319UL, 402653189UL,
1610612741UL, 4294967291UL,
};
inline size_t hash(size_t a)
{
a ^= (a >> 20) ^ (a >> 12);
return a ^ (a >> 7) ^ (a >> 4);
}
struct aaA
{
@@ -42,9 +39,9 @@ struct AA
size_t b_length;
size_t nodes; // total number of aaA nodes
aaA* binit[4]; // initial value of b[]
};
static const AA bbinit = { NULL, };
aaA aafirst; // a lot of these AA's have only one entry
};
/****************************************************
* Determine number of entries in associative array.
@@ -67,16 +64,20 @@ Value* _aaGet(AA** paa, Key key)
if (!*paa)
{ AA *a = new AA();
*a = bbinit;
a->b = a->binit;
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
a->nodes = 0;
a->binit[0] = NULL;
a->binit[1] = NULL;
a->binit[2] = NULL;
a->binit[3] = NULL;
*paa = a;
assert((*paa)->b_length == 4);
}
//printf("paa = %p, *paa = %p\n", paa, *paa);
assert((*paa)->b_length);
size_t i = (size_t)key % (*paa)->b_length;
size_t i = hash((size_t)key) & ((*paa)->b_length - 1);
aaA** pe = &(*paa)->b[i];
aaA *e;
while ((e = *pe) != NULL)
@@ -88,15 +89,17 @@ Value* _aaGet(AA** paa, Key key)
// Not found, create new elem
//printf("create new one\n");
e = new aaA();
size_t nodes = ++(*paa)->nodes;
e = (nodes != 1) ? new aaA() : &(*paa)->aafirst;
//e = new aaA();
e->next = NULL;
e->key = key;
e->value = NULL;
*pe = e;
size_t nodes = ++(*paa)->nodes;
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
if (nodes > (*paa)->b_length * 4)
//printf("length = %d, nodes = %d\n", (*paa)->b_length, nodes);
if (nodes > (*paa)->b_length * 2)
{
//printf("rehash\n");
_aaRehash(paa);
@@ -114,14 +117,11 @@ Value* _aaGet(AA** paa, Key key)
Value _aaGetRvalue(AA* aa, Key key)
{
//printf("_aaGetRvalue(key = %p)\n", key);
if (!aa)
return NULL;
size_t len = aa->b_length;
if (len)
if (aa)
{
size_t i = (size_t)key % len;
size_t i;
size_t len = aa->b_length;
i = hash((size_t)key) & (len-1);
aaA* e = aa->b[i];
while (e)
{
@@ -143,39 +143,33 @@ void _aaRehash(AA** paa)
//printf("Rehash\n");
if (*paa)
{
AA newb = bbinit;
AA *aa = *paa;
size_t len = _aaLen(*paa);
if (len)
{ size_t i;
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
{
if (len <= prime_list[i])
break;
}
len = prime_list[i];
newb.b = new aaA*[len];
memset(newb.b, 0, len * sizeof(aaA*));
newb.b_length = len;
if (aa)
{
size_t len = aa->b_length;
if (len == 4)
len = 32;
else
len *= 4;
aaA** newb = new aaA*[len];
memset(newb, 0, len * sizeof(aaA*));
for (size_t k = 0; k < aa->b_length; k++)
{ aaA *e = aa->b[k];
while (e)
{ aaA* enext = e->next;
size_t j = (size_t)e->key % len;
e->next = newb.b[j];
newb.b[j] = e;
size_t j = hash((size_t)e->key) & (len-1);
e->next = newb[j];
newb[j] = e;
e = enext;
}
}
if (aa->b != aa->binit)
delete[] aa->b;
newb.nodes = aa->nodes;
aa->b = newb;
aa->b_length = len;
}
**paa = newb;
}
}

View File

@@ -1,222 +0,0 @@
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "port.h"
#include "root.h"
#include "rmem.h"
/********************************* Array ****************************/
Array::Array()
{
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
dim = 0;
allocdim = SMALLARRAYCAP;
}
Array::~Array()
{
if (data != &smallarray[0])
mem.free(data);
}
void Array::mark()
{
mem.mark(data);
for (size_t u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
void Array::reserve(size_t nentries)
{
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
if (allocdim - dim < nentries)
{
if (allocdim == 0)
{ // Not properly initialized, someone memset it to zero
if (nentries <= SMALLARRAYCAP)
{ allocdim = SMALLARRAYCAP;
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
}
else
{ allocdim = nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data));
}
}
else if (allocdim == SMALLARRAYCAP)
{
allocdim = dim + nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data));
memcpy(data, &smallarray[0], dim * sizeof(*data));
}
else
{ allocdim = dim + nentries;
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
}
}
}
void Array::setDim(size_t newdim)
{
if (dim < newdim)
{
reserve(newdim - dim);
}
dim = newdim;
}
void Array::fixDim()
{
if (dim != allocdim)
{
if (allocdim >= SMALLARRAYCAP)
{
if (dim <= SMALLARRAYCAP)
{
memcpy(&smallarray[0], data, dim * sizeof(*data));
mem.free(data);
}
else
data = (void **)mem.realloc(data, dim * sizeof(*data));
}
allocdim = dim;
}
}
void Array::push(void *ptr)
{
reserve(1);
data[dim++] = ptr;
}
void *Array::pop()
{
return data[--dim];
}
void Array::shift(void *ptr)
{
reserve(1);
memmove(data + 1, data, dim * sizeof(*data));
data[0] = ptr;
dim++;
}
void Array::insert(size_t index, void *ptr)
{
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = ptr;
dim++;
}
void Array::insert(size_t index, Array *a)
{
if (a)
{
size_t d = a->dim;
reserve(d);
if (dim != index)
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
memcpy(data + index, a->data, d * sizeof(*data));
dim += d;
}
}
/***********************************
* Append array a to this array.
*/
void Array::append(Array *a)
{
insert(dim, a);
}
void Array::remove(size_t i)
{
if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
dim--;
}
char *Array::toChars()
{
char **buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
size_t len = 2;
for (size_t u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
char *str = (char *)mem.malloc(len);
str[0] = '[';
char *p = str + 1;
for (size_t u = 0; u < dim; u++)
{
if (u)
*p++ = ',';
len = strlen(buf[u]);
memcpy(p,buf[u],len);
p += len;
}
*p++ = ']';
*p = 0;
free(buf);
return str;
}
void Array::zero()
{
memset(data,0,dim * sizeof(data[0]));
}
void *Array::tos()
{
return dim ? data[dim - 1] : NULL;
}
int
#if _WIN32
__cdecl
#endif
Array_sort_compare(const void *x, const void *y)
{
Object *ox = *(Object **)x;
Object *oy = *(Object **)y;
return ox->compare(oy);
}
void Array::sort()
{
if (dim)
{
qsort(data, dim, sizeof(Object *), Array_sort_compare);
}
}
Array *Array::copy()
{
Array *a = new Array();
a->setDim(dim);
memcpy(a->data, data, dim * sizeof(void *));
return a;
}

View File

@@ -481,9 +481,9 @@ FM1: // We don't use fprem1 because for some inexplicable
//////////////////////////////////////////////////////////////
longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 };
longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 };
longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 };
longdouble ld_qnan = { 0xC000000000000000ULL, 0x7fff, 0 };
longdouble ld_snan = { 0xC000000000000001ULL, 0x7fff, 0 };
longdouble ld_inf = { 0x8000000000000000ULL, 0x7fff, 0 };
longdouble ld_zero = { 0, 0, 0 };
longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 };

View File

@@ -13,19 +13,7 @@
#ifndef __LONG_DOUBLE_H__
#define __LONG_DOUBLE_H__
#if IN_GCC
#include "d-gcc-real.h"
typedef real_t longdouble;
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
inline size_t ld_sprint(char* str, int fmt, longdouble x)
{
if(fmt == 'a' || fmt == 'A')
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
return x.format(buffer, 46);
}
#elif !_MSC_VER // has native 10 byte doubles
#if !_MSC_VER // has native 10 byte doubles
#include <stdio.h>
typedef long double longdouble;
typedef volatile long double volatile_longdouble;
@@ -143,8 +131,18 @@ inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
d.sign = sign;
return d;
}
template<typename T> inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
//template<typename T> inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; }
// codegen bug in VS2010/VS2012, if the set() function not inlined
// (this passed on stack, but expected in ECX; RVO?)
#if _MSC_VER >= 1600
#define LDOUBLE_INLINE __declspec(noinline)
#else
#define LDOUBLE_INLINE inline
#endif
template<typename T> LDOUBLE_INLINE longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
#undef LDOUBLE_INLINE
longdouble operator+(longdouble ld1, longdouble ld2);
longdouble operator-(longdouble ld1, longdouble ld2);
@@ -200,6 +198,7 @@ longdouble tanl (longdouble ld);
longdouble fmodl(longdouble x, longdouble y);
longdouble ldexpl(longdouble ldval, int exp); // see strtold
longdouble strtold(const char *p,char **endp);
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
@@ -236,38 +235,6 @@ extern longdouble ld_inf;
extern longdouble ld_qnan;
extern longdouble ld_snan;
///////////////////////////////////////////////////////////////////////
// CLASS numeric_limits<longdouble>
template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
: public _Num_float_base
{ // limits for type long double
public:
typedef longdouble _Ty;
static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; }
static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; }
static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; }
static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); }
static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); }
static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; }
static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; }
static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; }
_STCONS(int, digits, LDBL_MANT_DIG);
_STCONS(int, digits10, LDBL_DIG);
_STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
_STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
_STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
};
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
size_t ld_sprint(char* str, int fmt, longdouble x);
#endif // !_MSC_VER

View File

@@ -16,11 +16,33 @@
#include <wchar.h>
double Port::nan = NAN;
longdouble Port::ldbl_nan = NAN;
longdouble Port::snan;
double Port::infinity = INFINITY;
longdouble Port::ldbl_infinity = INFINITY;
double Port::dbl_max = DBL_MAX;
double Port::dbl_min = DBL_MIN;
longdouble Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
PortInitializer();
};
static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
union
{ unsigned int ui[4];
longdouble ld;
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
Port::snan = snan.ld;
}
int Port::isNan(double r)
{
return ::isnan(r);
@@ -47,68 +69,22 @@ int Port::isSignallingNan(longdouble r)
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
int Port::isFinite(double r)
{
return ::isfinite(r);
}
int Port::isInfinity(double r)
{
return (::fpclassify(r) == FP_INFINITE);
}
int Port::Signbit(double r)
{
return ::signbit(r);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
longdouble Port::fmodl(longdouble x, longdouble y)
{
return ::fmodl(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
int Port::fequal(longdouble x, longdouble y)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
// LOCALE_SLIST for Windows
return ",";
}
const wchar_t *Port::wlist_separator()
{
// LOCALE_SLIST for Windows
return L",";
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
return memcmp(&x, &y, 10) == 0;
}
char *Port::strupr(char *s)
@@ -126,6 +102,36 @@ int Port::stricmp(const char *s1, const char *s2)
return ::stricmp(s1, s2);
}
extern "C" const char * __cdecl __locale_decpoint;
float Port::strtof(const char *buffer, char **endp)
{
const char *save = __locale_decpoint;
__locale_decpoint = ".";
float result = ::strtof(buffer, endp);
__locale_decpoint = save;
return result;
}
double Port::strtod(const char *buffer, char **endp)
{
const char *save = __locale_decpoint;
__locale_decpoint = ".";
double result = ::strtod(buffer, endp);
__locale_decpoint = save;
return result;
}
longdouble Port::strtold(const char *buffer, char **endp)
{
const char *save = __locale_decpoint;
__locale_decpoint = ".";
longdouble result = ::strtold(buffer, endp);
__locale_decpoint = save;
return result;
}
#endif
#if _MSC_VER
@@ -134,7 +140,7 @@ int Port::stricmp(const char *s1, const char *s2)
#pragma warning (disable : 4514)
#include <math.h>
#include <float.h>
#include <float.h> // for _isnan
#include <time.h>
#include <errno.h>
#include <string.h>
@@ -143,13 +149,12 @@ int Port::stricmp(const char *s1, const char *s2)
#include <stdlib.h>
#include <limits> // for std::numeric_limits
static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
//static unsigned long nanarray[2] = {0,0x7FF80000 };
double Port::nan = (*(double *)nanarray);
double Port::nan;
longdouble Port::ldbl_nan;
longdouble Port::snan;
//static unsigned long infinityarray[2] = {0,0x7FF00000 };
static double zero = 0;
double Port::infinity = 1 / zero;
double Port::infinity;
longdouble Port::ldbl_infinity;
double Port::dbl_max = DBL_MAX;
double Port::dbl_min = DBL_MIN;
@@ -164,7 +169,16 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
union {
unsigned long ul[2];
double d;
} nan = {{ 0, 0x7FF80000 }};
Port::nan = nan.d;
Port::ldbl_nan = ld_qnan;
Port::snan = ld_snan;
Port::infinity = std::numeric_limits<double>::infinity();
Port::ldbl_infinity = ld_inf;
}
int Port::isNan(double r)
@@ -192,145 +206,22 @@ int Port::isSignallingNan(longdouble r)
return isSignallingNan((double) r);
}
int Port::isFinite(double r)
{
return ::_finite(r);
}
int Port::isInfinity(double r)
{
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
}
int Port::Signbit(double r)
{
return (long)(((long *)&(r))[1] & 0x80000000);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
if (y == 0)
return 1; // even if x is NAN
return ::pow(x, y);
}
longdouble Port::fmodl(longdouble x, longdouble y)
{
return ::fmodl(x, y);
}
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
int Port::fequal(longdouble x, longdouble y)
{
unsigned _int64 number = 0;
int c;
int error;
#ifndef ULLONG_MAX
#define ULLONG_MAX ((unsigned _int64)~0I64)
#endif
while (isspace((unsigned char)*p)) /* skip leading white space */
p++;
if (*p == '+')
p++;
switch (base)
{ case 0:
base = 10; /* assume decimal base */
if (*p == '0')
{ base = 8; /* could be octal */
p++;
switch (*p)
{ case 'x':
case 'X':
base = 16; /* hex */
p++;
break;
#if BINARY
case 'b':
case 'B':
base = 2; /* binary */
p++;
break;
#endif
}
}
break;
case 16: /* skip over '0x' and '0X' */
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
p += 2;
break;
#if BINARY
case 2: /* skip over '0b' and '0B' */
if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
p += 2;
break;
#endif
}
error = 0;
for (;;)
{ c = *p;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c = (c & ~0x20) - ('A' - 10);
else /* unrecognized character */
break;
if (c >= base) /* not in number base */
break;
if ((ULLONG_MAX - c) / base < number)
error = 1;
number = number * base + c;
p++;
}
if (pend)
*pend = (char *)p;
if (error)
{ number = ULLONG_MAX;
errno = ERANGE;
}
return number;
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
_ui64toa(ull, buffer, 10);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
_ui64tow(ull, buffer, 10);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{ double d;
if ((__int64) ull < 0)
{
// MSVC doesn't implement the conversion
d = (double) (__int64)(ull - 0x8000000000000000i64);
d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
}
else
d = (double)(__int64)ull;
return d;
}
const char *Port::list_separator()
{
// LOCALE_SLIST for Windows
return ",";
}
const wchar_t *Port::wlist_separator()
{
// LOCALE_SLIST for Windows
return L",";
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
return memcmp(&x, &y, 10) == 0;
}
char *Port::strupr(char *s)
@@ -348,6 +239,197 @@ int Port::stricmp(const char *s1, const char *s2)
return ::stricmp(s1, s2);
}
float Port::strtof(const char *p, char **endp)
{
return static_cast<float>(::strtod(p, endp));
}
double Port::strtod(const char *p, char **endp)
{
return ::strtod(p, endp);
}
// See backend/strtold.c.
longdouble Port::strtold(const char *p, char **endp)
{
return ::strtold(p, endp);
}
#endif
#if __MINGW32__
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <float.h>
#include <assert.h>
double Port::nan;
longdouble Port::ldbl_nan;
longdouble Port::snan;
static double zero = 0;
double Port::infinity = 1 / zero;
longdouble Port::ldbl_infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
longdouble Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
PortInitializer();
};
static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
union
{ unsigned int ui[2];
double d;
} nan = {{ 0, 0x7FF80000 }};
Port::nan = nan.d;
assert(!signbit(Port::nan));
union
{ unsigned int ui[4];
longdouble ld;
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
Port::ldbl_nan = ldbl_nan.ld;
assert(!signbit(Port::ldbl_nan));
union
{ unsigned int ui[4];
longdouble ld;
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
Port::snan = snan.ld;
}
int Port::isNan(double r)
{
return isnan(r);
}
int Port::isNan(longdouble r)
{
return isnan(r);
}
int Port::isSignallingNan(double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
*/
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
}
int Port::isSignallingNan(longdouble r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 62 of 0..79 for 80 bit reals.
*/
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
int Port::isInfinity(double r)
{
return isinf(r);
}
longdouble Port::fmodl(longdouble x, longdouble y)
{
return ::fmodl(x, y);
}
int Port::fequal(longdouble x, longdouble y)
{
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
return memcmp(&x, &y, 10) == 0;
}
char *Port::strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
int Port::memicmp(const char *s1, const char *s2, int n)
{
int result = 0;
for (int i = 0; i < n; i++)
{ char c1 = s1[i];
char c2 = s2[i];
result = c1 - c2;
if (result)
{
result = toupper(c1) - toupper(c2);
if (result)
break;
}
}
return result;
}
int Port::stricmp(const char *s1, const char *s2)
{
int result = 0;
for (;;)
{ char c1 = *s1;
char c2 = *s2;
result = c1 - c2;
if (result)
{
result = toupper(c1) - toupper(c2);
if (result)
break;
}
if (!c1)
break;
s1++;
s2++;
}
return result;
}
float Port::strtof(const char *p, char **endp)
{
return ::strtof(p, endp);
}
double Port::strtod(const char *p, char **endp)
{
return ::strtod(p, endp);
}
longdouble Port::strtold(const char *p, char **endp)
{
return ::__mingw_strtold(p, endp);
}
// See vcbuild/strtold.c.
longdouble strtold(const char *p, char **endp);
@@ -557,14 +639,20 @@ longdouble Port::strtold(const char *p, char **endp)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <float.h>
#include <assert.h>
double Port::nan;
longdouble Port::ldbl_nan;
longdouble Port::snan;
static double zero = 0;
double Port::nan = copysign(NAN, 1.0);
double Port::infinity = 1 / zero;
longdouble Port::ldbl_infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
longdouble Port::ldbl_max = LDBL_MAX;
@@ -578,8 +666,29 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
union
{ unsigned int ui[2];
double d;
} nan = {{ 0, 0x7FF80000 }};
Port::nan = nan.d;
assert(!signbit(Port::nan));
union
{ unsigned int ui[4];
longdouble ld;
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
Port::ldbl_nan = ldbl_nan.ld;
assert(!signbit(Port::ldbl_nan));
union
{ unsigned int ui[4];
longdouble ld;
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
Port::snan = snan.ld;
#if __FreeBSD__ && __i386__
// LDBL_MAX comes out as infinity. Fix.
static unsigned char x[sizeof(longdouble)] =
@@ -640,14 +749,6 @@ int Port::isSignallingNan(longdouble r)
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
#undef isfinite
int Port::isFinite(double r)
{
return ::finite(r);
}
#if !defined __HAIKU__
#endif
int Port::isInfinity(double r)
{
#if __APPLE__
@@ -660,24 +761,6 @@ int Port::isInfinity(double r)
#endif
}
#undef signbit
int Port::Signbit(double r)
{
union { double d; long long ll; } u;
u.d = r;
return u.ll < 0;
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
longdouble Port::fmodl(longdouble x, longdouble y)
{
#if __FreeBSD__ || __OpenBSD__
@@ -687,40 +770,12 @@ longdouble Port::fmodl(longdouble x, longdouble y)
#endif
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
int Port::fequal(longdouble x, longdouble y)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
#if __OpenBSD__
assert(0);
#else
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
#endif
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
return ",";
}
const wchar_t *Port::wlist_separator()
{
return L",";
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
return memcmp(&x, &y, 10) == 0;
}
char *Port::strupr(char *s)
@@ -778,6 +833,16 @@ int Port::stricmp(const char *s1, const char *s2)
return result;
}
float Port::strtof(const char *p, char **endp)
{
return ::strtof(p, endp);
}
double Port::strtod(const char *p, char **endp)
{
return ::strtod(p, endp);
}
longdouble Port::strtold(const char *p, char **endp)
{
return ::strtold(p, endp);
@@ -794,14 +859,20 @@ longdouble Port::strtold(const char *p, char **endp)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <float.h>
#include <ieeefp.h>
double Port::nan;
longdouble Port::ldbl_nan;
longdouble Port::snan;
static double zero = 0;
double Port::nan = NAN;
double Port::infinity = 1 / zero;
longdouble Port::ldbl_infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
longdouble Port::ldbl_max = LDBL_MAX;
@@ -815,14 +886,28 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
// gcc nan's have the sign bit set by default, so turn it off
// Need the volatile to prevent gcc from doing incorrect
// constant folding.
volatile longdouble foo;
foo = NAN;
if (signbit(foo)) // signbit sometimes, not always, set
foo = -foo; // turn off sign bit
Port::nan = foo;
union
{ unsigned int ui[2];
double d;
} nan = {{ 0, 0x7FF80000 }};
Port::nan = nan.d;
assert(!signbit(Port::nan));
union
{ unsigned int ui[4];
longdouble ld;
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
Port::ldbl_nan = ldbl_nan.ld;
assert(!signbit(Port::ldbl_nan));
union
{ unsigned int ui[4];
longdouble ld;
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
Port::snan = snan.ld;
}
int Port::isNan(double r)
@@ -851,68 +936,22 @@ int Port::isSignallingNan(longdouble r)
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
#undef isfinite
int Port::isFinite(double r)
{
return finite(r);
}
int Port::isInfinity(double r)
{
return isinf(r);
}
#undef signbit
int Port::Signbit(double r)
{
return (long)(((long *)&r)[1] & 0x80000000);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
longdouble Port::fmodl(longdouble x, longdouble y)
{
return ::fmodl(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
int Port::fequal(longdouble x, longdouble y)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
return ",";
}
const wchar_t *Port::wlist_separator()
{
return L",";
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
return memcmp(&x, &y, 10) == 0;
}
char *Port::strupr(char *s)
@@ -928,6 +967,21 @@ char *Port::strupr(char *s)
return t;
}
float Port::strtof(const char *p, char **endp)
{
return ::strtof(p, endp);
}
double Port::strtod(const char *p, char **endp)
{
return ::strtod(p, endp);
}
longdouble Port::strtold(const char *p, char **endp)
{
return ::strtold(p, endp);
}
longdouble Port::strtold(const char *p, char **endp)
{
return ::strtold(p, endp);

View File

@@ -13,15 +13,13 @@
#if defined(IN_LLVM) && (LDC_LLVM_VER >= 303)
#include "llvm/Config/config.h"
#endif
#include <stdlib.h> // for alloca
#include <stdint.h>
#include "longdouble.h"
#if _MSC_VER
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
#define strtof strtod
#define isnan _isnan
#include <alloca.h>
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
@@ -29,12 +27,17 @@ typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
typedef double d_time;
typedef unsigned char utf8_t;
struct Port
{
static double nan;
static longdouble ldbl_nan;
static longdouble snan;
static double infinity;
static longdouble ldbl_infinity;
static double dbl_max;
static double dbl_min;
static longdouble ldbl_max;
@@ -45,32 +48,18 @@ struct Port
static int isSignallingNan(double);
static int isSignallingNan(longdouble);
static int isFinite(double);
static int isInfinity(double);
static int Signbit(double);
static double floor(double);
static double pow(double x, double y);
static longdouble fmodl(longdouble x, longdouble y);
static ulonglong strtoull(const char *p, char **pend, int base);
static char *ull_to_string(char *buffer, ulonglong ull);
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
// Convert ulonglong to double
static double ull_to_double(ulonglong ull);
// Get locale-dependent list separator
static const char *list_separator();
static const wchar_t *wlist_separator();
static int fequal(longdouble x, longdouble y);
static char *strupr(char *);
static int memicmp(const char *s1, const char *s2, int n);
static int stricmp(const char *s1, const char *s2);
static float strtof(const char *p, char **endp);
static double strtod(const char *p, char **endp);
static longdouble strtold(const char *p, char **endp);
};

View File

@@ -11,11 +11,7 @@
#include <stdlib.h>
#include <string.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include "../root/rmem.h"
#else
#include "rmem.h"
#endif
/* This implementation of the storage allocator uses the standard C allocation package.
*/
@@ -142,6 +138,61 @@ void Mem::addroots(char* pStart, char* pEnd)
/* =================================================== */
#if 1
/* Allocate, but never release
*/
// Allocate a little less than 64kB because the C runtime adds some overhead that
// causes the actual memory block to be larger than 64kB otherwise. E.g. the dmc
// runtime rounds the size up to 128kB, but the remaining space in the chunk is less
// than 64kB, so it cannot be used by another chunk.
#define CHUNK_SIZE (4096 * 16 - 64)
static size_t heapleft = 0;
static void *heapp;
void * operator new(size_t m_size)
{
// 16 byte alignment is better (and sometimes needed) for doubles
m_size = (m_size + 15) & ~15;
// The layout of the code is selected so the most common case is straight through
if (m_size <= heapleft)
{
L1:
heapleft -= m_size;
void *p = heapp;
heapp = (void *)((char *)heapp + m_size);
return p;
}
if (m_size > CHUNK_SIZE)
{
void *p = malloc(m_size);
if (p)
return p;
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
return p;
}
heapleft = CHUNK_SIZE;
heapp = malloc(CHUNK_SIZE);
if (!heapp)
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
goto L1;
}
void operator delete(void *p)
{
}
#else
void * operator new(size_t m_size)
{
void *p = malloc(m_size);
@@ -157,4 +208,4 @@ void operator delete(void *p)
free(p);
}
#endif

View File

@@ -98,42 +98,42 @@ void warning(const char *format, ...)
/****************************** Object ********************************/
int Object::equals(Object *o)
bool RootObject::equals(RootObject *o)
{
return o == this;
}
hash_t Object::hashCode()
hash_t RootObject::hashCode()
{
return (hash_t) this;
}
int Object::compare(Object *obj)
int RootObject::compare(RootObject *obj)
{
return this - obj;
}
void Object::print()
void RootObject::print()
{
printf("%s %p\n", toChars(), this);
}
char *Object::toChars()
char *RootObject::toChars()
{
return (char *)"Object";
}
int Object::dyncast()
int RootObject::dyncast()
{
return 0;
}
void Object::toBuffer(OutBuffer *b)
void RootObject::toBuffer(OutBuffer *b)
{
b->writestring("Object");
}
void Object::mark()
void RootObject::mark()
{
}
@@ -206,12 +206,12 @@ size_t String::len()
return strlen(str);
}
int String::equals(Object *obj)
bool String::equals(RootObject *obj)
{
return strcmp(str,((String *)obj)->str) == 0;
}
int String::compare(Object *obj)
int String::compare(RootObject *obj)
{
return strcmp(str,((String *)obj)->str);
}
@@ -279,7 +279,7 @@ Strings *FileName::splitPath(const char *path)
do
{ char instring = 0;
while (isspace((unsigned char)*p)) // skip leading whitespace
while (isspace((utf8_t)*p)) // skip leading whitespace
p++;
buf.reserve(strlen(p) + 1); // guess size of path
for (; ; p++)
@@ -345,7 +345,7 @@ hash_t FileName::hashCode()
// We need a different hashCode because it must be case-insensitive
size_t len = strlen(str);
hash_t hash = 0;
unsigned char *s = (unsigned char *)str;
utf8_t *s = (utf8_t *)str;
for (;;)
{
@@ -384,7 +384,7 @@ hash_t FileName::hashCode()
#endif
}
int FileName::compare(Object *obj)
int FileName::compare(RootObject *obj)
{
return compare(str, ((FileName *)obj)->str);
}
@@ -398,7 +398,7 @@ int FileName::compare(const char *name1, const char *name2)
#endif
}
int FileName::equals(Object *obj)
bool FileName::equals(RootObject *obj)
{
return compare(obj) == 0;
}
@@ -696,7 +696,7 @@ const char *FileName::searchPath(Strings *path, const char *name, int cwd)
for (size_t i = 0; i < path->dim; i++)
{
const char *p = path->tdata()[i];
const char *p = (*path)[i];
const char *n = combine(p, name);
if (exists(n))
@@ -756,7 +756,7 @@ const char *FileName::safeSearchPath(Strings *path, const char *name)
for (size_t i = 0; i < path->dim; i++)
{
const char *cname = NULL;
const char *cpath = canonicalName(path->tdata()[i]);
const char *cpath = canonicalName((*path)[i]);
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
// name, (char *)path->data[i], cpath);
if (cpath == NULL)
@@ -829,7 +829,8 @@ void FileName::ensurePathExists(const char *path)
{
#if _WIN32
size_t len = strlen(path);
if (len > 2 && p[-1] == ':' && path + 2 == p)
if ((len > 2 && p[-1] == ':' && strcmp(path + 2, p) == 0) ||
len == strlen(p))
{ mem.free((void *)p);
return;
}
@@ -838,19 +839,20 @@ void FileName::ensurePathExists(const char *path)
mem.free((void *)p);
}
#if _WIN32
if (path[strlen(path) - 1] != '\\')
#endif
#if POSIX
if (path[strlen(path) - 1] != '\\')
char sep = '\\';
#elif POSIX
char sep = '/';
#endif
if (path[strlen(path) - 1] != sep)
{
//printf("mkdir(%s)\n", path);
#if _WIN32
if (_mkdir(path))
int r = _mkdir(path);
#endif
#if POSIX
if (mkdir(path, 0777))
int r = mkdir(path, 0777);
#endif
if (r)
{
/* Don't error out if another instance of dmd just created
* this directory
@@ -1017,7 +1019,7 @@ int File::read()
goto err2;
}
size = buf.st_size;
buffer = (unsigned char *) ::malloc(size + 2);
buffer = (utf8_t *) ::malloc(size + 2);
if (!buffer)
{
printf("\tmalloc error, errno = %d\n",errno);
@@ -1075,7 +1077,7 @@ err1:
ref = 0;
size = GetFileSize(h,NULL);
buffer = (unsigned char *) ::malloc(size + 2);
buffer = (utf8_t *) ::malloc(size + 2);
if (!buffer)
goto err2;
@@ -1151,7 +1153,7 @@ int File::mmread()
if (!ref)
mem.free(buffer);
ref = 2;
buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
buffer = (utf8_t *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
if (CloseHandle(hFileMap) != TRUE)
goto Lerr;
if (buffer == NULL) // mapping view failed
@@ -1359,7 +1361,7 @@ int File::exists()
void File::remove()
{
#if POSIX
::remove(this->name->toChars());
int dummy = ::remove(this->name->toChars());
#elif _WIN32
DeleteFileA(this->name->toChars());
#else
@@ -1469,7 +1471,7 @@ OutBuffer::OutBuffer()
doindent = 0;
level = 0;
linehead = 1;
notlinehead = 0;
}
OutBuffer::~OutBuffer()
@@ -1499,7 +1501,8 @@ void OutBuffer::reserve(size_t nbytes)
if (size - offset < nbytes)
{
size = (offset + nbytes) * 2;
data = (unsigned char *)mem.realloc(data, size);
size = (size + 15) & ~15;
data = (utf8_t *)mem.realloc(data, size);
}
}
@@ -1515,7 +1518,7 @@ void OutBuffer::setsize(size_t size)
void OutBuffer::write(const void *data, size_t nbytes)
{
if (doindent && linehead)
if (doindent && !notlinehead)
{
if (level)
{
@@ -1526,14 +1529,14 @@ void OutBuffer::write(const void *data, size_t nbytes)
offset++;
}
}
linehead = 0;
notlinehead = 1;
}
reserve(nbytes);
memcpy(this->data + offset, data, nbytes);
offset += nbytes;
}
void OutBuffer::writebstring(unsigned char *string)
void OutBuffer::writebstring(utf8_t *string)
{
write(string,*string + 1);
}
@@ -1560,12 +1563,12 @@ void OutBuffer::writenl()
writeByte('\n');
#endif
if (doindent)
linehead = 1;
notlinehead = 0;
}
void OutBuffer::writeByte(unsigned b)
{
if (doindent && linehead
if (doindent && !notlinehead
&& b != '\n')
{
if (level)
@@ -1577,7 +1580,7 @@ void OutBuffer::writeByte(unsigned b)
offset++;
}
}
linehead = 0;
notlinehead = 1;
}
reserve(1);
this->data[offset] = (unsigned char)b;
@@ -1655,12 +1658,13 @@ void OutBuffer::writewchar(unsigned w)
void OutBuffer::writeword(unsigned w)
{
if (doindent && linehead
#if _WIN32
&& w != 0x0A0D)
unsigned newline = 0x0A0D;
#else
&& w != '\n')
unsigned newline = '\n';
#endif
if (doindent && !notlinehead
&& w != newline)
{
if (level)
{
@@ -1671,7 +1675,7 @@ void OutBuffer::writeword(unsigned w)
offset++;
}
}
linehead = 0;
notlinehead = 1;
}
reserve(2);
*(unsigned short *)(this->data + offset) = (unsigned short)w;
@@ -1698,12 +1702,12 @@ void OutBuffer::writeUTF16(unsigned w)
void OutBuffer::write4(unsigned w)
{
if (doindent && linehead
#if _WIN32
&& w != 0x000A000D)
bool notnewline = w != 0x000A000D;
#else
)
bool notnewline = true;
#endif
if (doindent && !notlinehead && notnewline)
{
if (level)
{
@@ -1714,7 +1718,7 @@ void OutBuffer::write4(unsigned w)
offset++;
}
}
linehead = 0;
notlinehead = 1;
}
reserve(4);
*(unsigned *)(this->data + offset) = w;
@@ -1730,7 +1734,7 @@ void OutBuffer::write(OutBuffer *buf)
}
}
void OutBuffer::write(Object *obj)
void OutBuffer::write(RootObject *obj)
{
if (obj)
{

View File

@@ -12,10 +12,10 @@
#include <stdlib.h>
#include <stdarg.h>
#ifdef DEBUG
#include <string.h>
#include <assert.h>
#endif
#include "port.h"
#include "rmem.h"
#if __DMC__
#pragma once
@@ -30,17 +30,18 @@ typedef size_t hash_t;
struct OutBuffer;
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct ArrayBase;
typedef ArrayBase<struct File> Files;
typedef ArrayBase<char> Strings;
template <typename TYPE> struct Array;
typedef Array<class File> Files;
typedef Array<char> Strings;
struct Object
class RootObject
{
Object() { }
virtual ~Object() { }
public:
RootObject() { }
virtual ~RootObject() { }
virtual int equals(Object *o);
virtual bool equals(RootObject *o);
/**
* Returns a hash code, useful for things like building hash tables of Objects.
@@ -51,7 +52,7 @@ struct Object
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
* Useful for sorting Objects.
*/
virtual int compare(Object *obj);
virtual int compare(RootObject *obj);
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
@@ -74,8 +75,9 @@ struct Object
void mark();
};
struct String : Object
class String : public RootObject
{
public:
const char *str; // the string itself
String(const char *str);
@@ -85,20 +87,21 @@ struct String : Object
static hash_t calcHash(const char *str);
hash_t hashCode();
size_t len();
int equals(Object *obj);
int compare(Object *obj);
bool equals(RootObject *obj);
int compare(RootObject *obj);
char *toChars();
void print();
void mark();
};
struct FileName : String
class FileName : public String
{
public:
FileName(const char *str);
hash_t hashCode();
int equals(Object *obj);
bool equals(RootObject *obj);
static int equals(const char *name1, const char *name2);
int compare(Object *obj);
int compare(RootObject *obj);
static int compare(const char *name1, const char *name2);
static int absolute(const char *name);
static const char *ext(const char *);
@@ -128,8 +131,9 @@ struct FileName : String
static void free(const char *str);
};
struct File : Object
class File : public RootObject
{
public:
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
size_t len; // amount of data in buffer[]
@@ -233,13 +237,15 @@ struct File : Object
void remove(); // delete file
};
struct OutBuffer : Object
struct OutBuffer
{
unsigned char *data;
size_t offset;
size_t size;
int doindent, level, linehead;
int doindent;
int level;
int notlinehead;
OutBuffer();
~OutBuffer();
@@ -263,7 +269,7 @@ struct OutBuffer : Object
void writeUTF16(unsigned w);
void write4(unsigned w);
void write(OutBuffer *buf);
void write(Object *obj);
void write(RootObject *obj);
void fill0(size_t nbytes);
void align(size_t size);
void vprintf(const char *format, va_list args);
@@ -277,45 +283,178 @@ struct OutBuffer : Object
char *extractString();
};
template <typename TYPE>
struct Array
{
size_t dim;
void **data;
TYPE **data;
private:
size_t allocdim;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
TYPE *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
public:
Array();
~Array();
//Array(const Array&);
void mark();
char *toChars();
Array()
{
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
dim = 0;
allocdim = SMALLARRAYCAP;
}
void reserve(size_t nentries);
void setDim(size_t newdim);
void fixDim();
void push(void *ptr);
void *pop();
void shift(void *ptr);
void insert(size_t index, void *ptr);
void insert(size_t index, Array *a);
void append(Array *a);
void remove(size_t i);
void zero();
void *tos();
void sort();
Array *copy();
};
~Array()
{
if (data != &smallarray[0])
mem.free(data);
}
void mark()
{
mem.mark(data);
for (size_t u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
char *toChars()
{
char **buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
size_t len = 2;
for (size_t u = 0; u < dim; u++)
{
buf[u] = ((RootObject *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
char *str = (char *)mem.malloc(len);
str[0] = '[';
char *p = str + 1;
for (size_t u = 0; u < dim; u++)
{
if (u)
*p++ = ',';
len = strlen(buf[u]);
memcpy(p,buf[u],len);
p += len;
}
*p++ = ']';
*p = 0;
free(buf);
return str;
}
void reserve(size_t nentries)
{
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
if (allocdim - dim < nentries)
{
if (allocdim == 0)
{ // Not properly initialized, someone memset it to zero
if (nentries <= SMALLARRAYCAP)
{ allocdim = SMALLARRAYCAP;
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
}
else
{ allocdim = nentries;
data = (TYPE **)mem.malloc(allocdim * sizeof(*data));
}
}
else if (allocdim == SMALLARRAYCAP)
{
allocdim = dim + nentries;
data = (TYPE **)mem.malloc(allocdim * sizeof(*data));
memcpy(data, &smallarray[0], dim * sizeof(*data));
}
else
{ allocdim = dim + nentries;
data = (TYPE **)mem.realloc(data, allocdim * sizeof(*data));
}
}
}
void setDim(size_t newdim)
{
if (dim < newdim)
{
reserve(newdim - dim);
}
dim = newdim;
}
void fixDim()
{
if (dim != allocdim)
{
if (allocdim >= SMALLARRAYCAP)
{
if (dim <= SMALLARRAYCAP)
{
memcpy(&smallarray[0], data, dim * sizeof(*data));
mem.free(data);
}
else
data = (TYPE **)mem.realloc(data, dim * sizeof(*data));
}
allocdim = dim;
}
}
TYPE *pop()
{
return data[--dim];
}
void shift(TYPE *ptr)
{
reserve(1);
memmove(data + 1, data, dim * sizeof(*data));
data[0] = ptr;
dim++;
}
void remove(size_t i)
{
if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
dim--;
}
void zero()
{
memset(data,0,dim * sizeof(data[0]));
}
TYPE *tos()
{
return dim ? data[dim - 1] : NULL;
}
void sort()
{
struct ArraySort
{
static int
#if _WIN32
__cdecl
#endif
Array_sort_compare(const void *x, const void *y)
{
RootObject *ox = *(RootObject **)x;
RootObject *oy = *(RootObject **)y;
return ox->compare(oy);
}
};
if (dim)
{
qsort(data, dim, sizeof(RootObject *), &ArraySort::Array_sort_compare);
}
}
template <typename TYPE>
struct ArrayBase : Array
{
TYPE **tdata()
{
return (TYPE **)data;
return data;
}
TYPE*& operator[] (size_t index)
@@ -323,36 +462,52 @@ struct ArrayBase : Array
#ifdef DEBUG
assert(index < dim);
#endif
return ((TYPE **)data)[index];
return data[index];
}
void insert(size_t index, TYPE *v)
{
Array::insert(index, (void *)v);
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = v;
dim++;
}
void insert(size_t index, ArrayBase *a)
void insert(size_t index, Array *a)
{
Array::insert(index, (Array *)a);
if (a)
{
size_t d = a->dim;
reserve(d);
if (dim != index)
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
memcpy(data + index, a->data, d * sizeof(*data));
dim += d;
}
}
void append(ArrayBase *a)
void append(Array *a)
{
Array::append((Array *)a);
insert(dim, a);
}
void push(TYPE *a)
{
Array::push((void *)a);
reserve(1);
data[dim++] = a;
}
ArrayBase *copy()
Array *copy()
{
return (ArrayBase *)Array::copy();
Array *a = new Array();
a->setDim(dim);
memcpy(a->data, data, dim * sizeof(*data));
return a;
}
typedef int (*ArrayBase_apply_ft_t)(TYPE *, void *);
int apply(ArrayBase_apply_ft_t fp, void *param)
typedef int (*Array_apply_ft_t)(TYPE *, void *);
int apply(Array_apply_ft_t fp, void *param)
{
for (size_t i = 0; i < dim; i++)
{ TYPE *e = (*this)[i];
@@ -368,8 +523,9 @@ struct ArrayBase : Array
};
// TODO: Remove (only used by disabled GC)
struct Bits : Object
class Bits : public RootObject
{
public:
unsigned bitdim;
unsigned allocdim;
unsigned *data;