Merge dmd-1.074 into ldc.

This commit is contained in:
kai
2012-04-13 21:07:31 +02:00
parent f1998a6110
commit 1c6ff32d50
54 changed files with 5533 additions and 4034 deletions

View File

@@ -1,188 +1,188 @@
/**
* Implementation of associative arrays.
*
*/
#include <stdio.h>
#include <string.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,
};
struct aaA
{
aaA *next;
Key key;
Value value;
};
struct AA
{
aaA* *b;
size_t b_length;
size_t nodes; // total number of aaA nodes
aaA* binit[4]; // initial value of b[]
};
static const AA bbinit = { NULL, };
/****************************************************
* Determine number of entries in associative array.
*/
size_t _aaLen(AA* aa)
{
return aa ? aa->nodes : 0;
}
/*************************************************
* Get pointer to value in associative array indexed by key.
* Add entry for key if it is not already there.
*/
Value* _aaGet(AA** paa, Key key)
{
//printf("paa = %p\n", paa);
if (!*paa)
{ AA *a = new AA();
*a = bbinit;
a->b = a->binit;
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
*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;
aaA** pe = &(*paa)->b[i];
aaA *e;
while ((e = *pe) != NULL)
{
if (key == e->key)
return &e->value;
pe = &e->next;
}
// Not found, create new elem
//printf("create new one\n");
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("rehash\n");
_aaRehash(paa);
}
return &e->value;
}
/*************************************************
* Get value in associative array indexed by key.
* Returns NULL if it is not already there.
*/
Value _aaGetRvalue(AA* aa, Key key)
{
//printf("_aaGetRvalue(key = %p)\n", key);
if (!aa)
return NULL;
size_t len = aa->b_length;
if (len)
{
size_t i = (size_t)key % len;
aaA* e = aa->b[i];
while (e)
{
if (key == e->key)
return e->value;
e = e->next;
}
}
return NULL; // not found
}
/********************************************
* Rehash an array.
*/
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;
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;
e = enext;
}
}
if (aa->b != aa->binit)
delete[] aa->b;
newb.nodes = aa->nodes;
}
**paa = newb;
}
}
#if UNITTEST
void unittest_aa()
{
AA* aa = NULL;
Value v = _aaGetRvalue(aa, NULL);
assert(!v);
Value *pv = _aaGet(&aa, NULL);
assert(pv);
*pv = (void *)3;
v = _aaGetRvalue(aa, NULL);
assert(v == (void *)3);
}
#endif
/**
* Implementation of associative arrays.
*
*/
#include <stdio.h>
#include <string.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,
};
struct aaA
{
aaA *next;
Key key;
Value value;
};
struct AA
{
aaA* *b;
size_t b_length;
size_t nodes; // total number of aaA nodes
aaA* binit[4]; // initial value of b[]
};
static const AA bbinit = { NULL, };
/****************************************************
* Determine number of entries in associative array.
*/
size_t _aaLen(AA* aa)
{
return aa ? aa->nodes : 0;
}
/*************************************************
* Get pointer to value in associative array indexed by key.
* Add entry for key if it is not already there.
*/
Value* _aaGet(AA** paa, Key key)
{
//printf("paa = %p\n", paa);
if (!*paa)
{ AA *a = new AA();
*a = bbinit;
a->b = a->binit;
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
*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;
aaA** pe = &(*paa)->b[i];
aaA *e;
while ((e = *pe) != NULL)
{
if (key == e->key)
return &e->value;
pe = &e->next;
}
// Not found, create new elem
//printf("create new one\n");
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("rehash\n");
_aaRehash(paa);
}
return &e->value;
}
/*************************************************
* Get value in associative array indexed by key.
* Returns NULL if it is not already there.
*/
Value _aaGetRvalue(AA* aa, Key key)
{
//printf("_aaGetRvalue(key = %p)\n", key);
if (!aa)
return NULL;
size_t len = aa->b_length;
if (len)
{
size_t i = (size_t)key % len;
aaA* e = aa->b[i];
while (e)
{
if (key == e->key)
return e->value;
e = e->next;
}
}
return NULL; // not found
}
/********************************************
* Rehash an array.
*/
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;
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;
e = enext;
}
}
if (aa->b != aa->binit)
delete[] aa->b;
newb.nodes = aa->nodes;
}
**paa = newb;
}
}
#if UNITTEST
void unittest_aa()
{
AA* aa = NULL;
Value v = _aaGetRvalue(aa, NULL);
assert(!v);
Value *pv = _aaGet(&aa, NULL);
assert(pv);
*pv = (void *)3;
v = _aaGetRvalue(aa, NULL);
assert(v == (void *)3);
}
#endif

View File

@@ -1,11 +1,11 @@
typedef void* Value;
typedef void* Key;
struct AA;
size_t _aaLen(AA* aa);
Value* _aaGet(AA** aa, Key key);
Value _aaGetRvalue(AA* aa, Key key);
void _aaRehash(AA** paa);
typedef void* Value;
typedef void* Key;
struct AA;
size_t _aaLen(AA* aa);
Value* _aaGet(AA** aa, Key key);
Value _aaGetRvalue(AA* aa, Key key);
void _aaRehash(AA** paa);

View File

@@ -1,257 +1,257 @@
// Copyright (c) 1999-2010 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 <stdarg.h>
#include <string.h>
#include <assert.h>
#if (defined (__SVR4) && defined (__sun))
#include <alloca.h>
#endif
#if _MSC_VER || __MINGW32__
#include <malloc.h>
#endif
#if IN_GCC
#include "gdc_alloca.h"
#endif
#if _WIN32
#include <windows.h>
#endif
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <utime.h>
#endif
#include "port.h"
#include "root.h"
#include "dchar.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()
{ unsigned u;
mem.mark(data);
for (u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
void Array::reserve(unsigned nentries)
{
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, 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(unsigned 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(unsigned index, void *ptr)
{
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = ptr;
dim++;
}
void Array::insert(unsigned index, Array *a)
{
if (a)
{ unsigned d;
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(unsigned i)
{
if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
dim--;
}
char *Array::toChars()
{
unsigned len;
unsigned u;
char **buf;
char *str;
char *p;
buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
len = 2;
for (u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
str = (char *)mem.malloc(len);
str[0] = '[';
p = str + 1;
for (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;
}
// Copyright (c) 1999-2010 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 <stdarg.h>
#include <string.h>
#include <assert.h>
#if (defined (__SVR4) && defined (__sun))
#include <alloca.h>
#endif
#if _MSC_VER || __MINGW32__
#include <malloc.h>
#endif
#if IN_GCC
#include "gdc_alloca.h"
#endif
#if _WIN32
#include <windows.h>
#endif
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <utime.h>
#endif
#include "port.h"
#include "root.h"
#include "dchar.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()
{ unsigned u;
mem.mark(data);
for (u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
void Array::reserve(unsigned nentries)
{
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, 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(unsigned 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(unsigned index, void *ptr)
{
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = ptr;
dim++;
}
void Array::insert(unsigned index, Array *a)
{
if (a)
{ unsigned d;
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(unsigned i)
{
if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
dim--;
}
char *Array::toChars()
{
unsigned len;
unsigned u;
char **buf;
char *str;
char *p;
buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
len = 2;
for (u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
str = (char *)mem.malloc(len);
str[0] = '[';
p = str + 1;
for (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

@@ -1,325 +1,325 @@
#define _MT 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#include <errno.h>
#include <process.h>
#include "root.h"
static unsigned __stdcall startthread(void *p);
struct FileData
{
File *file;
int result;
HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
}
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
WaitForSingleObject(f->event, INFINITE);
Sleep(0); // give up time slice
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
free(aw);
}
unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
SetEvent(f->event);
}
_endthreadex(EXIT_SUCCESS);
return EXIT_SUCCESS; // if skidding
}
#elif linux // Posix
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include "root.h"
void *startthread(void *arg);
void err_abort(int status, const char *msg)
{
fprintf(stderr, "fatal error = %d, %s\n", status, msg);
exit(EXIT_FAILURE);
}
struct FileData
{
File *file;
int result;
pthread_mutex_t mutex;
pthread_cond_t cond;
int value;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
FileData *f = &files[filesdim];
f->file = file;
int status = pthread_mutex_init(&f->mutex, NULL);
if (status != 0)
err_abort(status, "init mutex");
status = pthread_cond_init(&f->cond, NULL);
if (status != 0)
err_abort(status, "init cond");
filesdim++;
}
void AsyncRead::start()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
pthread_t thread_id;
int status = pthread_create(&thread_id,
NULL,
&startthread,
this);
if (status != 0)
err_abort(status, "create thread");
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
// Wait for the event
int status = pthread_mutex_lock(&f->mutex);
if (status != 0)
err_abort(status, "lock mutex");
while (f->value == 0)
{
status = pthread_cond_wait(&f->cond, &f->mutex);
if (status != 0)
err_abort(status, "wait on condition");
}
status = pthread_mutex_unlock(&f->mutex);
if (status != 0)
err_abort(status, "unlock mutex");
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
//printf("AsyncRead::dispose()\n");
for (int i = 0; i < aw->filesdim; i++)
{
FileData *f = &aw->files[i];
int status = pthread_cond_destroy(&f->cond);
if (status != 0)
err_abort(status, "cond destroy");
status = pthread_mutex_destroy(&f->mutex);
if (status != 0)
err_abort(status, "mutex destroy");
}
free(aw);
}
void *startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
size_t dim = aw->filesdim;
for (size_t i = 0; i < dim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
// Set event
int status = pthread_mutex_lock(&f->mutex);
if (status != 0)
err_abort(status, "lock mutex");
f->value = 1;
status = pthread_cond_signal(&f->cond);
if (status != 0)
err_abort(status, "signal condition");
status = pthread_mutex_unlock(&f->mutex);
if (status != 0)
err_abort(status, "unlock mutex");
}
return NULL; // end thread
}
#else
#include <stdio.h>
#include <errno.h>
#include "root.h"
struct FileData
{
File *file;
int result;
//HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
//HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
//ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
f->result = f->file->read();
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
free(aw);
}
#endif
#define _MT 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#include <errno.h>
#include <process.h>
#include "root.h"
static unsigned __stdcall startthread(void *p);
struct FileData
{
File *file;
int result;
HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
}
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
WaitForSingleObject(f->event, INFINITE);
Sleep(0); // give up time slice
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
free(aw);
}
unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
SetEvent(f->event);
}
_endthreadex(EXIT_SUCCESS);
return EXIT_SUCCESS; // if skidding
}
#elif linux // Posix
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include "root.h"
void *startthread(void *arg);
void err_abort(int status, const char *msg)
{
fprintf(stderr, "fatal error = %d, %s\n", status, msg);
exit(EXIT_FAILURE);
}
struct FileData
{
File *file;
int result;
pthread_mutex_t mutex;
pthread_cond_t cond;
int value;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
FileData *f = &files[filesdim];
f->file = file;
int status = pthread_mutex_init(&f->mutex, NULL);
if (status != 0)
err_abort(status, "init mutex");
status = pthread_cond_init(&f->cond, NULL);
if (status != 0)
err_abort(status, "init cond");
filesdim++;
}
void AsyncRead::start()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
pthread_t thread_id;
int status = pthread_create(&thread_id,
NULL,
&startthread,
this);
if (status != 0)
err_abort(status, "create thread");
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
// Wait for the event
int status = pthread_mutex_lock(&f->mutex);
if (status != 0)
err_abort(status, "lock mutex");
while (f->value == 0)
{
status = pthread_cond_wait(&f->cond, &f->mutex);
if (status != 0)
err_abort(status, "wait on condition");
}
status = pthread_mutex_unlock(&f->mutex);
if (status != 0)
err_abort(status, "unlock mutex");
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
//printf("AsyncRead::dispose()\n");
for (int i = 0; i < aw->filesdim; i++)
{
FileData *f = &aw->files[i];
int status = pthread_cond_destroy(&f->cond);
if (status != 0)
err_abort(status, "cond destroy");
status = pthread_mutex_destroy(&f->mutex);
if (status != 0)
err_abort(status, "mutex destroy");
}
free(aw);
}
void *startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
size_t dim = aw->filesdim;
for (size_t i = 0; i < dim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
// Set event
int status = pthread_mutex_lock(&f->mutex);
if (status != 0)
err_abort(status, "lock mutex");
f->value = 1;
status = pthread_cond_signal(&f->cond);
if (status != 0)
err_abort(status, "signal condition");
status = pthread_mutex_unlock(&f->mutex);
if (status != 0)
err_abort(status, "unlock mutex");
}
return NULL; // end thread
}
#else
#include <stdio.h>
#include <errno.h>
#include "root.h"
struct FileData
{
File *file;
int result;
//HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
//HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
//ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
f->result = f->file->read();
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
free(aw);
}
#endif

View File

@@ -1,33 +1,33 @@
// Copyright (c) 2009-2009 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.
#ifndef ASYNC_H
#define ASYNC_H
#if __DMC__
#pragma once
#endif
/*******************
* Simple interface to read files asynchronously in another
* thread.
*/
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
};
#endif
// Copyright (c) 2009-2009 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.
#ifndef ASYNC_H
#define ASYNC_H
#if __DMC__
#pragma once
#endif
/*******************
* Simple interface to read files asynchronously in another
* thread.
*/
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
};
#endif

View File

@@ -1,482 +1,482 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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 <stdint.h>
#include <assert.h>
#include "dchar.h"
#include "rmem.h"
#if M_UNICODE
// Converts a char string to Unicode
dchar *Dchar::dup(char *p)
{
dchar *s;
size_t len;
if (!p)
return NULL;
len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++)
{
s[i] = (dchar)(p[i] & 0xFF);
}
s[len] = 0;
return s;
}
dchar *Dchar::memchr(dchar *p, int c, int count)
{
int u;
for (u = 0; u < count; u++)
{
if (p[u] == c)
return p + u;
}
return NULL;
}
#if _WIN32 && __DMC__
__declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len)
{
__asm
{
mov ECX,4[ESP]
mov EDX,8[ESP]
xor EAX,EAX
test EDX,EDX
je L92
LC8: cmp EDX,1
je L98
cmp EDX,2
je LAE
add EAX,[ECX]
// imul EAX,EAX,025h
lea EAX,[EAX][EAX*8]
add ECX,4
sub EDX,2
jmp LC8
L98: mov DX,[ECX]
and EDX,0FFFFh
add EAX,EDX
ret
LAE: add EAX,[ECX]
L92: ret
}
}
#else
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
unsigned hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str;
return hash;
case 2:
hash += *(const uint32_t *)str;
return hash;
default:
hash += *(const uint32_t *)str;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#endif
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str | 0x20;
return hash;
case 2:
hash += *(const uint32_t *)str | 0x200020;
return hash;
default:
hash += *(const uint32_t *)str | 0x200020;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
#elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
};
dchar *Dchar::dec(dchar *pstart, dchar *p)
{
while ((p[-1] & 0xC0) == 0x80)
p--;
return p;
}
int Dchar::get(dchar *p)
{
unsigned c;
unsigned char *q = (unsigned char *)p;
c = q[0];
switch (mblen[c])
{
case 2:
c = ((c - 0xC0) << 6) |
(q[1] - 0x80);
break;
case 3:
c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) |
(q[2] - 0x80);
break;
case 4:
c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) |
(q[3] - 0x80);
break;
case 5:
c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) |
(q[4] - 0x80);
break;
case 6:
c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) |
(q[5] - 0x80);
break;
}
return c;
}
dchar *Dchar::put(dchar *p, unsigned c)
{
if (c <= 0x7F)
{
*p++ = c;
}
else if (c <= 0x7FF)
{
p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F);
p += 2;
}
else if (c <= 0xFFFF)
{
p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F);
p += 3;
}
else if (c <= 0x1FFFFF)
{
p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F);
p += 4;
}
else if (c <= 0x3FFFFFF)
{
p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F);
p += 5;
}
else if (c <= 0x7FFFFFFF)
{
p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F);
p += 6;
}
else
assert(0); // not a UCS-4 character
return p;
}
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
#else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020;
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str | 0x20202020;
str += 4;
len -= 4;
break;
}
}
}
#endif
#if 0
#include <stdio.h>
void main()
{
// Print out values to hardcode into Dchar::mblen[]
int c;
int s;
for (c = 0; c < 256; c++)
{
s = 1;
if (c >= 0xC0 && c <= 0xDF)
s = 2;
if (c >= 0xE0 && c <= 0xEF)
s = 3;
if (c >= 0xF0 && c <= 0xF7)
s = 4;
if (c >= 0xF8 && c <= 0xFB)
s = 5;
if (c >= 0xFC && c <= 0xFD)
s = 6;
printf("%d", s);
if ((c & 15) == 15)
printf(",\n");
else
printf(",");
}
}
#endif
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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 <stdint.h>
#include <assert.h>
#include "dchar.h"
#include "rmem.h"
#if M_UNICODE
// Converts a char string to Unicode
dchar *Dchar::dup(char *p)
{
dchar *s;
size_t len;
if (!p)
return NULL;
len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++)
{
s[i] = (dchar)(p[i] & 0xFF);
}
s[len] = 0;
return s;
}
dchar *Dchar::memchr(dchar *p, int c, int count)
{
int u;
for (u = 0; u < count; u++)
{
if (p[u] == c)
return p + u;
}
return NULL;
}
#if _WIN32 && __DMC__
__declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len)
{
__asm
{
mov ECX,4[ESP]
mov EDX,8[ESP]
xor EAX,EAX
test EDX,EDX
je L92
LC8: cmp EDX,1
je L98
cmp EDX,2
je LAE
add EAX,[ECX]
// imul EAX,EAX,025h
lea EAX,[EAX][EAX*8]
add ECX,4
sub EDX,2
jmp LC8
L98: mov DX,[ECX]
and EDX,0FFFFh
add EAX,EDX
ret
LAE: add EAX,[ECX]
L92: ret
}
}
#else
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
unsigned hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str;
return hash;
case 2:
hash += *(const uint32_t *)str;
return hash;
default:
hash += *(const uint32_t *)str;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#endif
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str | 0x20;
return hash;
case 2:
hash += *(const uint32_t *)str | 0x200020;
return hash;
default:
hash += *(const uint32_t *)str | 0x200020;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
#elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
};
dchar *Dchar::dec(dchar *pstart, dchar *p)
{
while ((p[-1] & 0xC0) == 0x80)
p--;
return p;
}
int Dchar::get(dchar *p)
{
unsigned c;
unsigned char *q = (unsigned char *)p;
c = q[0];
switch (mblen[c])
{
case 2:
c = ((c - 0xC0) << 6) |
(q[1] - 0x80);
break;
case 3:
c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) |
(q[2] - 0x80);
break;
case 4:
c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) |
(q[3] - 0x80);
break;
case 5:
c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) |
(q[4] - 0x80);
break;
case 6:
c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) |
(q[5] - 0x80);
break;
}
return c;
}
dchar *Dchar::put(dchar *p, unsigned c)
{
if (c <= 0x7F)
{
*p++ = c;
}
else if (c <= 0x7FF)
{
p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F);
p += 2;
}
else if (c <= 0xFFFF)
{
p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F);
p += 3;
}
else if (c <= 0x1FFFFF)
{
p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F);
p += 4;
}
else if (c <= 0x3FFFFFF)
{
p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F);
p += 5;
}
else if (c <= 0x7FFFFFFF)
{
p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F);
p += 6;
}
else
assert(0); // not a UCS-4 character
return p;
}
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
#else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020;
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str | 0x20202020;
str += 4;
len -= 4;
break;
}
}
}
#endif
#if 0
#include <stdio.h>
void main()
{
// Print out values to hardcode into Dchar::mblen[]
int c;
int s;
for (c = 0; c < 256; c++)
{
s = 1;
if (c >= 0xC0 && c <= 0xDF)
s = 2;
if (c >= 0xE0 && c <= 0xEF)
s = 3;
if (c >= 0xF0 && c <= 0xF7)
s = 4;
if (c >= 0xF8 && c <= 0xFB)
s = 5;
if (c >= 0xFC && c <= 0xFD)
s = 6;
printf("%d", s);
if ((c & 15) == 15)
printf(",\n");
else
printf(",");
}
}
#endif

View File

@@ -1,194 +1,194 @@
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#ifndef DCHAR_H
#define DCHAR_H
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif
//#include "root.h"
typedef size_t hash_t;
#undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE
#include <string.h>
#include <wchar.h>
typedef wchar_t dchar;
#define TEXT(x) L##x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2)
{
#if __DMC__
if (!*s1 && !*s2) // wcscmp is broken
return 0;
#endif
return wcscmp(s1, s2);
#if 0
return (*s1 == *s2)
? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2);
#endif
}
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#elif MCBS
#include <limits.h>
#include <mbstring.h>
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX
#elif UTF8
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 6
struct Dchar
{
static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
};
#else
#include <string.h>
#ifndef GCC_SAFE_DMD
#include <ctype.h>
#endif
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
static int isUpper(dchar c) { return isupper((unsigned char)c); }
static int isLower(dchar c) { return islower((unsigned char)c); }
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
#ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#endif
#endif
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#ifndef DCHAR_H
#define DCHAR_H
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif
//#include "root.h"
typedef size_t hash_t;
#undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE
#include <string.h>
#include <wchar.h>
typedef wchar_t dchar;
#define TEXT(x) L##x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2)
{
#if __DMC__
if (!*s1 && !*s2) // wcscmp is broken
return 0;
#endif
return wcscmp(s1, s2);
#if 0
return (*s1 == *s2)
? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2);
#endif
}
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#elif MCBS
#include <limits.h>
#include <mbstring.h>
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX
#elif UTF8
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 6
struct Dchar
{
static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
};
#else
#include <string.h>
#ifndef GCC_SAFE_DMD
#include <ctype.h>
#endif
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; }
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
static int isUpper(dchar c) { return isupper((unsigned char)c); }
static int isLower(dchar c) { return islower((unsigned char)c); }
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
#ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#endif
#endif

636
dmd/root/longdouble.c Normal file
View File

@@ -0,0 +1,636 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Rainer Schuetze
// 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.
// 80 bit floating point value implementation for Microsoft compiler
#if _MSC_VER
#include "longdouble.h"
#include "assert.h"
#include <float.h>
#include <stdio.h>
#include <string.h>
extern "C"
{
// implemented in ldfpu.asm for _WIN64
int ld_initfpu(int bits, int mask);
void ld_expl(longdouble* ld, int exp);
longdouble ld_add(longdouble ld1, longdouble ld2);
longdouble ld_sub(longdouble ld1, longdouble ld2);
longdouble ld_mul(longdouble ld1, longdouble ld2);
longdouble ld_div(longdouble ld1, longdouble ld2);
longdouble ld_mod(longdouble ld1, longdouble ld2);
bool ld_cmpb(longdouble ld1, longdouble ld2);
bool ld_cmpbe(longdouble ld1, longdouble ld2);
bool ld_cmpa(longdouble ld1, longdouble ld2);
bool ld_cmpae(longdouble ld1, longdouble ld2);
bool ld_cmpe(longdouble ld1, longdouble ld2);
bool ld_cmpne(longdouble ld1, longdouble ld2);
longdouble ld_sqrt(longdouble ld1);
longdouble ld_sin(longdouble ld1);
longdouble ld_cos(longdouble ld1);
longdouble ld_tan(longdouble ld1);
}
bool initFPU()
{
#ifdef _WIN64
// int old_cw = ld_initfpu(_RC_NEAR);
int old_cw = ld_initfpu(0x300 /*_PC_64 | _RC_NEAR*/, // #defines NOT identical to CPU FPU control word!
0xF00 /*_MCW_PC | _MCW_RC*/);
#else
int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR,
_MCW_EM | _MCW_PC | _MCW_RC);
#endif
return true;
}
static bool doInitFPU = initFPU();
#ifndef _WIN64
extern "C"
{
double ld_read(const longdouble* pthis)
{
double res;
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fstp res
}
return res;
}
long long ld_readll(const longdouble* pthis)
{
#if 1
return ld_readull(pthis);
#elif defined _WIN64
return ld_readll(this);
#else
longdouble* pthis = this;
long long res;
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fistp qword ptr res
}
return res;
#endif
}
unsigned long long ld_readull(const longdouble* pthis)
{
#if 1
// somehow the FPU does not respect the CHOP mode of the rounding control
// in 64-bit mode
// so we roll our own conversion (it also allows the usual C wrap-around
// instead of the "invalid value" created by the FPU)
int expo = pthis->exponent - 0x3fff;
unsigned long long u;
if(expo < 0 || expo > 127)
return 0;
if(expo < 64)
u = pthis->mantissa >> (63 - expo);
else
u = pthis->mantissa << (expo - 63);
if(pthis->sign)
u = ~u + 1;
return u;
#else
longdouble* pthis = this;
long long res; // cannot use unsigned, VC will not generate "fistp qword"
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fld tbyte ptr twoPow63
fsubp ST(1),ST(0) // move it into signed range
lea eax, res
fistp qword ptr [eax]
}
res ^= (1LL << 63);
return res;
#endif
}
void ld_set(longdouble* pthis, double d)
{
__asm
{
mov eax, pthis
fld d
fstp tbyte ptr [eax]
}
}
void ld_setll(longdouble* pthis, long long d)
{
__asm
{
fild qword ptr d
mov eax, pthis
fstp tbyte ptr [eax]
}
}
void ld_setull(longdouble* pthis, unsigned long long d)
{
d ^= (1LL << 63);
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
__asm
{
fild qword ptr d
fld tbyte ptr twoPow63
faddp ST(1),ST(0)
mov eax, pthis
fstp tbyte ptr [eax]
}
}
} // extern "C"
#endif // !_WIN64
longdouble ldexpl(longdouble ld, int exp)
{
#ifdef _WIN64
ld_expl(&ld, exp);
#else
__asm
{
fild dword ptr exp
fld tbyte ptr ld
fscale // ST(0) = ST(0) * (2**ST(1))
fstp ST(1)
fstp tbyte ptr ld
}
#endif
return ld;
}
///////////////////////////////////////////////////////////////////////
longdouble operator+(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_add(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fadd
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble operator-(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_sub(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fsub
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble operator*(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_mul(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fmul
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble operator/(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_div(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fdiv
fstp tbyte ptr res;
}
return res;
#endif
}
bool operator< (longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpb(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setb AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator<=(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpbe(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setbe AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator> (longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpa(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
seta AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator>=(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpae(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setae AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator==(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpe(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
sete AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator!=(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpne(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setne AL
setp AH
or AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
int _isnan(longdouble ld)
{
return (ld.exponent == 0x7fff && ld.mantissa != 0);
}
longdouble fabsl(longdouble ld)
{
ld.sign = 0;
return ld;
}
longdouble sqrtl(longdouble ld)
{
#ifdef _WIN64
return ld_sqrt(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fsqrt;
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble sinl (longdouble ld)
{
#ifdef _WIN64
return ld_sin(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fsin; // exact for |x|<=PI/4
fstp tbyte ptr res
}
return res;
#endif
}
longdouble cosl (longdouble ld)
{
#ifdef _WIN64
return ld_cos(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fcos; // exact for |x|<=PI/4
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble tanl (longdouble ld)
{
#ifdef _WIN64
return ld_tan(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fptan;
fstp ST(0); // always 1
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble fmodl(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_mod(x, y);
#else
short sw;
longdouble res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
FM1: // We don't use fprem1 because for some inexplicable
// reason we get -5 when we do _modulo(15, 10)
fprem // ST = ST % ST1
fstsw word ptr sw
fwait
mov AH,byte ptr sw+1 // get msb of status word in AH
sahf // transfer to flags
jp FM1 // continue till ST < ST1
fstp ST(1) // leave remainder on stack
fstp tbyte ptr res;
}
return res;
#endif
}
//////////////////////////////////////////////////////////////
longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 };
longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 };
longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 };
longdouble ld_zero = { 0, 0, 0 };
longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 };
longdouble ld_pi = { 0xc90fdaa22168c235ULL, 0x4000, 0 };
longdouble ld_log2t = { 0xd49a784bcd1b8afeULL, 0x4000, 0 };
longdouble ld_log2e = { 0xb8aa3b295c17f0bcULL, 0x3fff, 0 };
longdouble ld_log2 = { 0x9a209a84fbcff799ULL, 0x3ffd, 0 };
longdouble ld_ln2 = { 0xb17217f7d1cf79acULL, 0x3ffe, 0 };
longdouble ld_pi2 = ld_pi*2;
longdouble ld_piOver2 = ld_pi*0.5;
longdouble ld_piOver4 = ld_pi*0.25;
//////////////////////////////////////////////////////////////
#define LD_TYPE_OTHER 0
#define LD_TYPE_ZERO 1
#define LD_TYPE_INFINITE 2
#define LD_TYPE_SNAN 3
#define LD_TYPE_QNAN 4
int ld_type(longdouble x)
{
if(x.exponent == 0)
return x.mantissa == 0 ? LD_TYPE_ZERO : LD_TYPE_OTHER; // dnormal if not zero
if(x.exponent != 0x7fff)
return LD_TYPE_OTHER;
if(x.mantissa == 0)
return LD_TYPE_INFINITE;
if(x.mantissa & (1LL << 63))
return LD_TYPE_QNAN;
return LD_TYPE_SNAN;
}
int ld_sprint(char* str, int fmt, longdouble x)
{
// fmt is 'a','A','f' or 'g'
if(fmt != 'a' && fmt != 'A')
{
char format[] = { '%', fmt, 0 };
return sprintf(str, format, ld_read(&x));
}
unsigned short exp = x.exponent;
unsigned long long mantissa = x.mantissa;
switch(ld_type(x))
{
case LD_TYPE_ZERO:
return sprintf(str, "0x0.0L");
case LD_TYPE_QNAN:
case LD_TYPE_SNAN:
return sprintf(str, "NAN");
case LD_TYPE_INFINITE:
return sprintf(str, x.sign ? "-INF" : "INF");
}
int len = 0;
if(x.sign)
str[len++] = '-';
len += sprintf(str + len, mantissa & (1LL << 63) ? "0x1." : "0x0.");
mantissa = mantissa << 1;
while(mantissa)
{
int dig = (mantissa >> 60) & 0xf;
dig += dig < 10 ? '0' : fmt - 10;
str[len++] = dig;
mantissa = mantissa << 4;
}
str[len++] = 'p';
if(exp < 0x3fff)
{
str[len++] = '-';
exp = 0x3fff - exp;
}
else
{
str[len++] = '+';
exp = exp - 0x3fff;
}
int exppos = len;
for(int i = 12; i >= 0; i -= 4)
{
int dig = (exp >> i) & 0xf;
if(dig != 0 || len > exppos || i == 0)
str[len++] = dig + (dig < 10 ? '0' : fmt - 10);
}
str[len] = 0;
return len;
}
//////////////////////////////////////////////////////////////
#if UNITTEST
static bool unittest()
{
char buffer[32];
ld_sprint(buffer, 'a', ld_pi);
assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0);
longdouble ldb = ldouble(0.4);
long long b = ldb;
assert(b == 0);
b = ldouble(0.9);
assert(b == 0);
long long x = 0x12345678abcdef78LL;
longdouble ldx = ldouble(x);
assert(ldx > 0);
long long y = ldx;
assert(x == y);
x = -0x12345678abcdef78LL;
ldx = ldouble(x);
assert(ldx < 0);
y = ldx;
assert(x == y);
unsigned long long u = 0x12345678abcdef78LL;
longdouble ldu = ldouble(u);
assert(ldu > 0);
unsigned long long v = ldu;
assert(u == v);
u = 0xf234567812345678ULL;
ldu = ldouble(u);
assert(ldu > 0);
v = ldu;
assert(u == v);
u = 0xf2345678;
ldu = ldouble(u);
ldu = ldu * ldu;
ldu = sqrt(ldu);
v = ldu;
assert(u == v);
u = 0x123456789A;
ldu = ldouble(u);
ldu = ldu * (1LL << 23);
v = ldu;
u = u * (1LL << 23);
assert(u == v);
return true;
}
static bool runUnittest = unittest();
#endif // UNITTEST
#endif // _MSC_VER

254
dmd/root/longdouble.h Normal file
View File

@@ -0,0 +1,254 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Rainer Schuetze
// 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.
// 80 bit floating point value implementation for Microsoft compiler
#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 int 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
#include <stdio.h>
typedef long double longdouble;
typedef volatile long double volatile_longdouble;
// also used from within C code, so use a #define rather than a template
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
#define ldouble(x) ((longdouble)(x))
inline int ld_sprint(char* str, int fmt, longdouble x)
{
char sfmt[4] = "%Lg";
sfmt[2] = fmt;
return sprintf(str, sfmt, x);
}
#else
#include <float.h>
#include <limits>
struct longdouble;
extern "C"
{
// implemented in ldfpu.asm for _WIN64
double ld_read(const longdouble* ld);
long long ld_readll(const longdouble* ld);
unsigned long long ld_readull(const longdouble* ld);
void ld_set(longdouble* ld, double d);
void ld_setll(longdouble* ld, long long d);
void ld_setull(longdouble* ld, unsigned long long d);
}
struct longdouble
{
unsigned long long mantissa;
unsigned short exponent:15; // bias 0x3fff
unsigned short sign:1;
unsigned short fill:16; // for 12 byte alignment
// no constructor to be able to use this class in a union
// use ldouble() to explicitely create a longdouble value
template<typename T> longdouble& operator=(T x) { set(x); return *this; }
void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; }
// we need to list all basic types to avoid ambiguities
void set(float d) { ld_set(this, d); }
void set(double d) { ld_set(this, d); }
void set(long double d) { ld_set(this, d); }
void set(signed char d) { ld_set(this, d); }
void set(short d) { ld_set(this, d); }
void set(int d) { ld_set(this, d); }
void set(long d) { ld_set(this, d); }
void set(long long d) { ld_setll(this, d); }
void set(unsigned char d) { ld_set(this, d); }
void set(unsigned short d) { ld_set(this, d); }
void set(unsigned int d) { ld_set(this, d); }
void set(unsigned long d) { ld_set(this, d); }
void set(unsigned long long d) { ld_setull(this, d); }
void set(bool d) { ld_set(this, d); }
operator float () { return ld_read(this); }
operator double () { return ld_read(this); }
operator signed char () { return ld_read(this); }
operator short () { return ld_read(this); }
operator int () { return ld_read(this); }
operator long () { return ld_read(this); }
operator long long () { return ld_readll(this); }
operator unsigned char () { return ld_read(this); }
operator unsigned short () { return ld_read(this); }
operator unsigned int () { return ld_read(this); }
operator unsigned long () { return ld_read(this); }
operator unsigned long long() { return ld_readull(this); }
operator bool () { return mantissa != 0 || exponent != 0; } // correct?
};
// some optimizations are avoided by adding volatile to the longdouble
// type, but this introduces bad ambiguities when using the class implementation above
// as we are going through asm these optimizations won't kick in anyway, so "volatile"
// is not required.
typedef longdouble volatile_longdouble;
inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
{
longdouble d;
d.mantissa = mantissa;
d.exponent = exp;
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; }
longdouble operator+(longdouble ld1, longdouble ld2);
longdouble operator-(longdouble ld1, longdouble ld2);
longdouble operator*(longdouble ld1, longdouble ld2);
longdouble operator/(longdouble ld1, longdouble ld2);
bool operator< (longdouble ld1, longdouble ld2);
bool operator<=(longdouble ld1, longdouble ld2);
bool operator> (longdouble ld1, longdouble ld2);
bool operator>=(longdouble ld1, longdouble ld2);
bool operator==(longdouble ld1, longdouble ld2);
bool operator!=(longdouble ld1, longdouble ld2);
inline longdouble operator-(longdouble ld1) { ld1.sign ^= 1; return ld1; }
inline longdouble operator+(longdouble ld1) { return ld1; }
template<typename T> inline longdouble operator+(longdouble ld, T x) { return ld + ldouble(x); }
template<typename T> inline longdouble operator-(longdouble ld, T x) { return ld - ldouble(x); }
template<typename T> inline longdouble operator*(longdouble ld, T x) { return ld * ldouble(x); }
template<typename T> inline longdouble operator/(longdouble ld, T x) { return ld / ldouble(x); }
template<typename T> inline longdouble operator+(T x, longdouble ld) { return ldouble(x) + ld; }
template<typename T> inline longdouble operator-(T x, longdouble ld) { return ldouble(x) - ld; }
template<typename T> inline longdouble operator*(T x, longdouble ld) { return ldouble(x) * ld; }
template<typename T> inline longdouble operator/(T x, longdouble ld) { return ldouble(x) / ld; }
template<typename T> inline longdouble& operator+=(longdouble& ld, T x) { return ld = ld + x; }
template<typename T> inline longdouble& operator-=(longdouble& ld, T x) { return ld = ld - x; }
template<typename T> inline longdouble& operator*=(longdouble& ld, T x) { return ld = ld * x; }
template<typename T> inline longdouble& operator/=(longdouble& ld, T x) { return ld = ld / x; }
template<typename T> inline bool operator< (longdouble ld, T x) { return ld < ldouble(x); }
template<typename T> inline bool operator<=(longdouble ld, T x) { return ld <= ldouble(x); }
template<typename T> inline bool operator> (longdouble ld, T x) { return ld > ldouble(x); }
template<typename T> inline bool operator>=(longdouble ld, T x) { return ld >= ldouble(x); }
template<typename T> inline bool operator==(longdouble ld, T x) { return ld == ldouble(x); }
template<typename T> inline bool operator!=(longdouble ld, T x) { return ld != ldouble(x); }
template<typename T> inline bool operator< (T x, longdouble ld) { return ldouble(x) < ld; }
template<typename T> inline bool operator<=(T x, longdouble ld) { return ldouble(x) <= ld; }
template<typename T> inline bool operator> (T x, longdouble ld) { return ldouble(x) > ld; }
template<typename T> inline bool operator>=(T x, longdouble ld) { return ldouble(x) >= ld; }
template<typename T> inline bool operator==(T x, longdouble ld) { return ldouble(x) == ld; }
template<typename T> inline bool operator!=(T x, longdouble ld) { return ldouble(x) != ld; }
int _isnan(longdouble ld);
longdouble fabsl(longdouble ld);
longdouble sqrtl(longdouble ld);
longdouble sinl (longdouble ld);
longdouble cosl (longdouble ld);
longdouble tanl (longdouble ld);
longdouble fmodl(longdouble x, longdouble y);
longdouble ldexpl(longdouble ldval, int exp); // see strtold
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
#undef LDBL_DIG
#undef LDBL_MAX
#undef LDBL_MIN
#undef LDBL_EPSILON
#undef LDBL_MANT_DIG
#undef LDBL_MAX_EXP
#undef LDBL_MIN_EXP
#undef LDBL_MAX_10_EXP
#undef LDBL_MIN_10_EXP
#define LDBL_DIG 18
#define LDBL_MAX ldouble(0xffffffffffffffffULL, 0x7ffe)
#define LDBL_MIN ldouble(0x8000000000000000ULL, 1)
#define LDBL_EPSILON ldouble(0x8000000000000000ULL, 0x3fff - 63) // allow denormal?
#define LDBL_MANT_DIG 64
#define LDBL_MAX_EXP 16384
#define LDBL_MIN_EXP (-16381)
#define LDBL_MAX_10_EXP 4932
#define LDBL_MIN_10_EXP (-4932)
extern longdouble ld_zero;
extern longdouble ld_one;
extern longdouble ld_pi;
extern longdouble ld_log2t;
extern longdouble ld_log2e;
extern longdouble ld_log2;
extern longdouble ld_ln2;
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)
int ld_sprint(char* str, int fmt, longdouble x);
#endif // !_MSC_VER
#endif // __LONG_DOUBLE_H__

View File

@@ -1,63 +1,63 @@
// lstring.c
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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 <stdlib.h>
#include "dchar.h"
#include "rmem.h"
#include "lstring.h"
#ifdef _MSC_VER // prevent compiler internal crash
Lstring Lstring::zero;
#else
Lstring Lstring::zero = LSTRING_EMPTY();
#endif
Lstring *Lstring::ctor(const dchar *p, unsigned length)
{
Lstring *s;
s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar));
return s;
}
Lstring *Lstring::alloc(unsigned length)
{
Lstring *s;
s = (Lstring *)mem.malloc(size(length));
s->length = length;
s->string[length] = 0;
return s;
}
Lstring *Lstring::append(const Lstring *s)
{
Lstring *t;
if (!s->length)
return this;
t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t;
}
Lstring *Lstring::substring(int start, int end)
{
Lstring *t;
if (start == end)
return &zero;
t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t;
}
// lstring.c
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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 <stdlib.h>
#include "dchar.h"
#include "rmem.h"
#include "lstring.h"
#ifdef _MSC_VER // prevent compiler internal crash
Lstring Lstring::zero;
#else
Lstring Lstring::zero = LSTRING_EMPTY();
#endif
Lstring *Lstring::ctor(const dchar *p, unsigned length)
{
Lstring *s;
s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar));
return s;
}
Lstring *Lstring::alloc(unsigned length)
{
Lstring *s;
s = (Lstring *)mem.malloc(size(length));
s->length = length;
s->string[length] = 0;
return s;
}
Lstring *Lstring::append(const Lstring *s)
{
Lstring *t;
if (!s->length)
return this;
t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t;
}
Lstring *Lstring::substring(int start, int end)
{
Lstring *t;
if (start == end)
return &zero;
t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t;
}

View File

@@ -1,72 +1,74 @@
// lstring.h
// length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#ifndef LSTRING_H
#define LSTRING_H 1
#include "dchar.h"
struct Lstring
{
unsigned length;
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
dchar string[];
static Lstring zero; // 0 length string
// No constructors because we want to be able to statically
// initialize Lstring's, and Lstrings are of variable size.
#if M_UNICODE
#define LSTRING(p,length) { length, L##p }
#else
#define LSTRING(p,length) { length, p }
#endif
#if __GNUC__
#define LSTRING_EMPTY() { 0 }
#else
#define LSTRING_EMPTY() LSTRING("", 0)
#endif
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
Lstring *clone();
unsigned len() { return length; }
dchar *toDchars() { return string; }
hash_t hash() { return Dchar::calcHash(string, length); }
hash_t ihash() { return Dchar::icalcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
}
static int icmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
}
Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
};
#endif
// lstring.h
// length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#ifndef LSTRING_H
#define LSTRING_H 1
#include "dchar.h"
struct Lstring
{
unsigned length;
#ifndef IN_GCC
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
#endif
dchar string[];
static Lstring zero; // 0 length string
// No constructors because we want to be able to statically
// initialize Lstring's, and Lstrings are of variable size.
#if M_UNICODE
#define LSTRING(p,length) { length, L##p }
#else
#define LSTRING(p,length) { length, p }
#endif
#if __GNUC__
#define LSTRING_EMPTY() { 0 }
#else
#define LSTRING_EMPTY() LSTRING("", 0)
#endif
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
Lstring *clone();
unsigned len() { return length; }
dchar *toDchars() { return string; }
hash_t hash() { return Dchar::calcHash(string, length); }
hash_t ihash() { return Dchar::icalcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
}
static int icmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
}
Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
};
#endif

View File

@@ -1,100 +1,100 @@
// Compiler implementation of the D programming language
// Copyright (c) 2008-2009 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 <string.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#pragma comment(lib,"shell32.lib")
void browse(const char *url)
{
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
}
#endif
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void browse(const char *url)
{
pid_t childpid;
const char *args[3];
const char *browser = getenv("BROWSER");
if (browser)
browser = strdup(browser);
else
browser = "x-www-browser";
args[0] = browser;
args[1] = url;
args[2] = NULL;
childpid = fork();
if (childpid == 0)
{
execvp(args[0], (char**)args);
perror(args[0]); // failed to execute
return;
}
}
#endif
#if __APPLE__
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void browse(const char *url)
{
pid_t childpid;
const char *args[5];
char *browser = getenv("BROWSER");
if (browser)
{ browser = strdup(browser);
args[0] = browser;
args[1] = url;
args[2] = NULL;
}
else
{
//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
args[0] = "open";
args[1] = "-a";
args[2] = "/Applications/Safari.app";
args[3] = url;
args[4] = NULL;
}
childpid = fork();
if (childpid == 0)
{
execvp(args[0], (char**)args);
perror(args[0]); // failed to execute
return;
}
}
#endif
// Compiler implementation of the D programming language
// Copyright (c) 2008-2009 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 <string.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#pragma comment(lib,"shell32.lib")
void browse(const char *url)
{
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
}
#endif
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void browse(const char *url)
{
pid_t childpid;
const char *args[3];
const char *browser = getenv("BROWSER");
if (browser)
browser = strdup(browser);
else
browser = "x-www-browser";
args[0] = browser;
args[1] = url;
args[2] = NULL;
childpid = fork();
if (childpid == 0)
{
execvp(args[0], (char**)args);
perror(args[0]); // failed to execute
return;
}
}
#endif
#if __APPLE__
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void browse(const char *url)
{
pid_t childpid;
const char *args[5];
char *browser = getenv("BROWSER");
if (browser)
{ browser = strdup(browser);
args[0] = browser;
args[1] = url;
args[2] = NULL;
}
else
{
//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
args[0] = "open";
args[1] = "-a";
args[2] = "/Applications/Safari.app";
args[3] = url;
args[4] = NULL;
}
childpid = fork();
if (childpid == 0)
{
execvp(args[0], (char**)args);
perror(args[0]); // failed to execute
return;
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,81 +1,83 @@
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#ifndef PORT_H
#define PORT_H
// Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code.
#ifndef TYPEDEFS
#define TYPEDEFS
#include <wchar.h>
#if _MSC_VER
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
// According to VC 8.0 docs, long double is the same as double
#define strtold strtod
#define strtof strtod
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
typedef double d_time;
struct Port
{
static double nan;
static double infinity;
static double dbl_max;
static double dbl_min;
static long double ldbl_max;
#if __OpenBSD__
#elif __GNUC__ && !defined __HAIKU__
// These conflict with macros in math.h, should rename them
#undef isnan
#undef isfinite
#undef isinfinity
#undef signbit
#endif
static int isNan(double);
static int isNan(long double);
static int isSignallingNan(double);
static int isSignallingNan(long double);
static int isFinite(double);
static int isInfinity(double);
static int Signbit(double);
static double floor(double);
static double pow(double x, double y);
static long double fmodl(long double x, long double 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 char *strupr(char *);
};
#endif
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#ifndef PORT_H
#define PORT_H
// Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code.
#include "longdouble.h"
#ifndef TYPEDEFS
#define TYPEDEFS
#include <wchar.h>
#if _MSC_VER
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
// According to VC 8.0 docs, long double is the same as double
longdouble strtold(const char *p,char **endp);
#define strtof strtod
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
typedef double d_time;
struct Port
{
static double nan;
static double infinity;
static double dbl_max;
static double dbl_min;
static longdouble ldbl_max;
#if __OpenBSD__
#elif __GNUC__ && !defined __HAIKU__
// These conflict with macros in math.h, should rename them
#undef isnan
#undef isfinite
#undef isinfinity
#undef signbit
#endif
static int isNan(double);
static int isNan(longdouble);
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 char *strupr(char *);
};
#endif

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -8,7 +8,7 @@
// See the included readme.txt for details.
#ifndef POSIX
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
#endif
#include <stdio.h>
@@ -35,7 +35,7 @@
#endif
#ifdef __HAIKU__
#include <iostream>
#include <iostream>
#endif
#if POSIX
@@ -364,21 +364,21 @@ FileName::FileName(char *path, char *name)
}
// Split a path into an Array of paths
Strings *FileName::splitPath(const char *path)
Strings *FileName::splitPath(const char *path)
{
char c = 0; // unnecessary initializer is for VC /W4
const char *p;
OutBuffer buf;
Strings *array;
Strings *array;
array = new Strings();
array = new Strings();
if (path)
{
p = path;
do
{ char instring = 0;
while (isspace((unsigned char)*p)) // skip leading whitespace
while (isspace((unsigned char)*p)) // skip leading whitespace
p++;
buf.reserve(strlen(p) + 1); // guess size of path
// LDC remember first character
@@ -799,7 +799,7 @@ void FileName::CopyTo(FileName *to)
* cwd if !=0, search current directory before searching path
*/
char *FileName::searchPath(Strings *path, const char *name, int cwd)
char *FileName::searchPath(Strings *path, const char *name, int cwd)
{
if (absolute(name))
{
@@ -815,7 +815,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
for (i = 0; i < path->dim; i++)
{
char *p = path->tdata()[i];
char *p = path->tdata()[i];
char *n = combine(p, name);
if (exists(n))
@@ -839,7 +839,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
* !=NULL mem.malloc'd file name
*/
char *FileName::safeSearchPath(Strings *path, const char *name)
char *FileName::safeSearchPath(Strings *path, const char *name)
{
#if _WIN32
/* Disallow % / \ : and .. in name characters
@@ -876,7 +876,7 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
for (i = 0; i < path->dim; i++)
{
char *cname = NULL;
char *cpath = canonicalName(path->tdata()[i]);
char *cpath = canonicalName(path->tdata()[i]);
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
// name, (char *)path->data[i], cpath);
if (cpath == NULL)
@@ -966,7 +966,7 @@ void FileName::ensurePathExists(const char *path)
{
//printf("mkdir(%s)\n", path);
#if _WIN32
if (_mkdir(path))
if (_mkdir(path))
#endif
#if POSIX
if (mkdir(path, 0777))
@@ -1088,13 +1088,13 @@ int File::read()
//printf("File::read('%s')\n",name);
fd = open(name, O_RDONLY);
if (fd == -1)
{
{
//printf("\topen error, errno = %d\n",errno);
goto err1;
}
if (!ref)
::free(buffer);
::free(buffer);
ref = 0; // we own the buffer now
//printf("\tfile opened\n");
@@ -1104,7 +1104,7 @@ int File::read()
goto err2;
}
size = buf.st_size;
buffer = (unsigned char *) ::malloc(size + 2);
buffer = (unsigned char *) ::malloc(size + 2);
if (!buffer)
{
printf("\tmalloc error, errno = %d\n",errno);
@@ -1137,7 +1137,7 @@ int File::read()
err2:
close(fd);
err:
::free(buffer);
::free(buffer);
buffer = NULL;
len = 0;
@@ -1158,11 +1158,11 @@ err1:
goto err1;
if (!ref)
::free(buffer);
::free(buffer);
ref = 0;
size = GetFileSize(h,NULL);
buffer = (unsigned char *) ::malloc(size + 2);
buffer = (unsigned char *) ::malloc(size + 2);
if (!buffer)
goto err2;
@@ -1191,7 +1191,7 @@ err1:
err2:
CloseHandle(h);
err:
::free(buffer);
::free(buffer);
buffer = NULL;
len = 0;
@@ -1454,23 +1454,23 @@ void File::remove()
#endif
}
Files *File::match(char *n)
Files *File::match(char *n)
{
return match(new FileName(n, 0));
}
Files *File::match(FileName *n)
Files *File::match(FileName *n)
{
#if POSIX
return NULL;
#elif _WIN32
HANDLE h;
WIN32_FIND_DATAA fileinfo;
Files *a;
Files *a;
char *c;
char *name;
a = new Files();
a = new Files();
c = n->toChars();
name = n->name();
h = FindFirstFileA(c,&fileinfo);
@@ -1540,7 +1540,7 @@ void File::stat()
void File::checkoffset(size_t offset, size_t nbytes)
{
if (offset > len || offset + nbytes > len)
error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset);
}
char *File::toChars()
@@ -1563,11 +1563,11 @@ OutBuffer::~OutBuffer()
mem.free(data);
}
char *OutBuffer::extractData()
char *OutBuffer::extractData()
{
char *p;
char *p;
p = (char *)data;
p = (char *)data;
data = NULL;
offset = 0;
size = 0;
@@ -1813,7 +1813,7 @@ void OutBuffer::align(unsigned size)
// The compiler shipped with Visual Studio 2005 (and possible
// other versions) does not support C99 printf format specfiers
// such as %z and %j
#if _MSC_VER || __MINGW32__
#if 0 && _MSC_VER
using std::string;
using std::wstring;
@@ -1832,7 +1832,7 @@ search_and_replace(S& str, const S& what, const S& replacement)
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
S tmp = f; \
search_and_replace(fmt, S("%z"), S("%l")); \
search_and_replace(fmt, S("%j"), S("%i")); \
search_and_replace(fmt, S("%j"), S("%l")); \
f = tmp.c_str();
#else
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)

View File

@@ -1,425 +1,428 @@
// Copyright (c) 1999-2011 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.
#ifndef ROOT_H
#define ROOT_H
#include <stdlib.h>
#include <stdarg.h>
#ifdef DEBUG
#include <assert.h>
#endif
#if __DMC__
#pragma once
#endif
#ifndef IS_PRINTF
# ifdef __GNUC__
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
# else
# define IS_PRINTF(FMTARG)
# endif
#endif
typedef size_t hash_t;
#include "dchar.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *);
char *wchar2ascii(wchar_t *, unsigned len);
int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b);
void error(const char *format, ...) IS_PRINTF(1);
void error(const wchar_t *format, ...);
void warning(const char *format, ...) IS_PRINTF(1);
#ifndef TYPEDEFS
#define TYPEDEFS
#if _MSC_VER
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double
#define strtold strtod
#define strtof strtod
#define isnan _isnan
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
longlong randomx();
/*
* Root of our class library.
*/
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;
struct Object
{
Object() { }
virtual ~Object() { }
virtual int equals(Object *o);
/**
* Returns a hash code, useful for things like building hash tables of Objects.
*/
virtual hash_t hashCode();
/**
* 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);
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
*/
virtual void print();
virtual char *toChars();
virtual dchar *toDchars();
virtual void toBuffer(OutBuffer *buf);
/**
* Used as a replacement for dynamic_cast. Returns a unique number
* defined by the library user. For Object, the return value is 0.
*/
virtual int dyncast();
/**
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
*/
/*virtual*/ // not used, disable for now
void mark();
};
struct String : Object
{
int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself
String(char *str, int ref = 1);
~String();
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str);
hash_t hashCode();
unsigned len();
int equals(Object *obj);
int compare(Object *obj);
char *toChars();
void print();
void mark();
};
struct FileName : String
{
FileName(char *str, int ref);
FileName(char *path, char *name);
hash_t hashCode();
int equals(Object *obj);
static int equals(const char *name1, const char *name2);
int compare(Object *obj);
static int compare(const char *name1, const char *name2);
static int absolute(const char *name);
static char *ext(const char *);
char *ext();
static char *removeExt(const char *str);
static char *name(const char *);
char *name();
static char *path(const char *);
static const char *replaceName(const char *path, const char *name);
static char *combine(const char *path, const char *name);
static Strings *splitPath(const char *path);
static FileName *defaultExt(const char *name, const char *ext);
static FileName *forceExt(const char *name, const char *ext);
int equalsExt(const char *ext);
void CopyTo(FileName *to);
static char *searchPath(Strings *path, const char *name, int cwd);
static char *safeSearchPath(Strings *path, const char *name);
static int exists(const char *name);
static void ensurePathExists(const char *path);
static char *canonicalName(const char *name);
};
struct File : Object
{
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
unsigned len; // amount of data in buffer[]
void *touchtime; // system time to use for file
FileName *name; // name of our file
File(char *);
File(FileName *);
~File();
void mark();
char *toChars();
/* Read file, return !=0 if error
*/
int read();
/* Write file, either succeed or fail
* with error message & exit.
*/
void readv();
/* Read file, return !=0 if error
*/
int mmread();
/* Write file, either succeed or fail
* with error message & exit.
*/
void mmreadv();
/* Write file, return !=0 if error
*/
int write();
/* Write file, either succeed or fail
* with error message & exit.
*/
void writev();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
/* Append to file, return !=0 if error
*/
int append();
/* Append to file, either succeed or fail
* with error message & exit.
*/
void appendv();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
int exists();
/* Given wildcard filespec, return an array of
* matching File's.
*/
static Files *match(char *);
static Files *match(FileName *);
// Compare file times.
// Return <0 this < f
// =0 this == f
// >0 this > f
int compareTime(File *f);
// Read system file statistics
void stat();
/* Set buffer
*/
void setbuffer(void *buffer, unsigned len)
{
this->buffer = (unsigned char *)buffer;
this->len = len;
}
void checkoffset(size_t offset, size_t nbytes);
void remove(); // delete file
};
struct OutBuffer : Object
{
unsigned char *data;
unsigned offset;
unsigned size;
OutBuffer();
~OutBuffer();
char *extractData();
void mark();
void reserve(unsigned nbytes);
void setsize(unsigned size);
void reset();
void write(const void *data, unsigned nbytes);
void writebstring(unsigned char *string);
void writestring(const char *string);
void writedstring(const char *string);
void writedstring(const wchar_t *string);
void prependstring(const char *string);
void writenl(); // write newline
void writeByte(unsigned b);
void writebyte(unsigned b) { writeByte(b); }
void writeUTF8(unsigned b);
void writedchar(unsigned b);
void prependbyte(unsigned b);
void writeword(unsigned w);
void writeUTF16(unsigned w);
void write4(unsigned w);
void write(OutBuffer *buf);
void write(Object *obj);
void fill0(unsigned nbytes);
void align(unsigned size);
void vprintf(const char *format, va_list args);
void printf(const char *format, ...) IS_PRINTF(2);
#if M_UNICODE
void vprintf(const unsigned short *format, va_list args);
void printf(const unsigned short *format, ...);
#endif
void bracket(char left, char right);
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
void spread(unsigned offset, unsigned nbytes);
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
void remove(unsigned offset, unsigned nbytes);
char *toChars();
char *extractString();
};
struct Array : Object
{
unsigned dim;
void **data;
private:
unsigned allocdim;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
public:
Array();
~Array();
//Array(const Array&);
void mark();
char *toChars();
void reserve(unsigned nentries);
void setDim(unsigned newdim);
void fixDim();
void push(void *ptr);
void *pop();
void shift(void *ptr);
void insert(unsigned index, void *ptr);
void insert(unsigned index, Array *a);
void append(Array *a);
void remove(unsigned i);
void zero();
void *tos();
void sort();
Array *copy();
};
template <typename TYPE>
struct ArrayBase : Array
{
TYPE **tdata()
{
return (TYPE **)data;
}
TYPE*& operator[] (size_t index)
{
#ifdef DEBUG
assert(index < dim);
#endif
return ((TYPE **)data)[index];
}
void insert(size_t index, TYPE *v)
{
Array::insert(index, (void *)v);
}
void insert(size_t index, ArrayBase *a)
{
Array::insert(index, (Array *)a);
}
void append(ArrayBase *a)
{
Array::append((Array *)a);
}
void push(TYPE *a)
{
Array::push((void *)a);
}
ArrayBase *copy()
{
return (ArrayBase *)Array::copy();
}
};
struct Bits : Object
{
unsigned bitdim;
unsigned allocdim;
unsigned *data;
Bits();
~Bits();
void mark();
void resize(unsigned bitdim);
void set(unsigned bitnum);
void clear(unsigned bitnum);
int test(unsigned bitnum);
void set();
void clear();
void copy(Bits *from);
Bits *clone();
void sub(Bits *b);
};
#endif
// Copyright (c) 1999-2011 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.
#ifndef ROOT_H
#define ROOT_H
#include <stdlib.h>
#include <stdarg.h>
#ifdef DEBUG
#include <assert.h>
#endif
#if __DMC__
#pragma once
#endif
#ifndef IS_PRINTF
# ifdef __GNUC__
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
# else
# define IS_PRINTF(FMTARG)
# endif
#endif
typedef size_t hash_t;
#include "longdouble.h"
#include "dchar.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *);
char *wchar2ascii(wchar_t *, unsigned len);
int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b);
void error(const char *format, ...) IS_PRINTF(1);
#if M_UNICODE
void error(const dchar *format, ...);
#endif
void warning(const char *format, ...) IS_PRINTF(1);
#ifndef TYPEDEFS
#define TYPEDEFS
#if _MSC_VER
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double
longdouble strtold(const char *p,char **endp);
#define strtof strtod
#define isnan _isnan
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
longlong randomx();
/*
* Root of our class library.
*/
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;
struct Object
{
Object() { }
virtual ~Object() { }
virtual int equals(Object *o);
/**
* Returns a hash code, useful for things like building hash tables of Objects.
*/
virtual hash_t hashCode();
/**
* 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);
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
*/
virtual void print();
virtual char *toChars();
virtual dchar *toDchars();
virtual void toBuffer(OutBuffer *buf);
/**
* Used as a replacement for dynamic_cast. Returns a unique number
* defined by the library user. For Object, the return value is 0.
*/
virtual int dyncast();
/**
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
*/
/*virtual*/ // not used, disable for now
void mark();
};
struct String : Object
{
int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself
String(char *str, int ref = 1);
~String();
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str);
hash_t hashCode();
unsigned len();
int equals(Object *obj);
int compare(Object *obj);
char *toChars();
void print();
void mark();
};
struct FileName : String
{
FileName(char *str, int ref);
FileName(char *path, char *name);
hash_t hashCode();
int equals(Object *obj);
static int equals(const char *name1, const char *name2);
int compare(Object *obj);
static int compare(const char *name1, const char *name2);
static int absolute(const char *name);
static char *ext(const char *);
char *ext();
static char *removeExt(const char *str);
static char *name(const char *);
char *name();
static char *path(const char *);
static const char *replaceName(const char *path, const char *name);
static char *combine(const char *path, const char *name);
static Strings *splitPath(const char *path);
static FileName *defaultExt(const char *name, const char *ext);
static FileName *forceExt(const char *name, const char *ext);
int equalsExt(const char *ext);
void CopyTo(FileName *to);
static char *searchPath(Strings *path, const char *name, int cwd);
static char *safeSearchPath(Strings *path, const char *name);
static int exists(const char *name);
static void ensurePathExists(const char *path);
static char *canonicalName(const char *name);
};
struct File : Object
{
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
unsigned len; // amount of data in buffer[]
void *touchtime; // system time to use for file
FileName *name; // name of our file
File(char *);
File(FileName *);
~File();
void mark();
char *toChars();
/* Read file, return !=0 if error
*/
int read();
/* Write file, either succeed or fail
* with error message & exit.
*/
void readv();
/* Read file, return !=0 if error
*/
int mmread();
/* Write file, either succeed or fail
* with error message & exit.
*/
void mmreadv();
/* Write file, return !=0 if error
*/
int write();
/* Write file, either succeed or fail
* with error message & exit.
*/
void writev();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
/* Append to file, return !=0 if error
*/
int append();
/* Append to file, either succeed or fail
* with error message & exit.
*/
void appendv();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
int exists();
/* Given wildcard filespec, return an array of
* matching File's.
*/
static Files *match(char *);
static Files *match(FileName *);
// Compare file times.
// Return <0 this < f
// =0 this == f
// >0 this > f
int compareTime(File *f);
// Read system file statistics
void stat();
/* Set buffer
*/
void setbuffer(void *buffer, unsigned len)
{
this->buffer = (unsigned char *)buffer;
this->len = len;
}
void checkoffset(size_t offset, size_t nbytes);
void remove(); // delete file
};
struct OutBuffer : Object
{
unsigned char *data;
unsigned offset;
unsigned size;
OutBuffer();
~OutBuffer();
char *extractData();
void mark();
void reserve(unsigned nbytes);
void setsize(unsigned size);
void reset();
void write(const void *data, unsigned nbytes);
void writebstring(unsigned char *string);
void writestring(const char *string);
void writedstring(const char *string);
void writedstring(const wchar_t *string);
void prependstring(const char *string);
void writenl(); // write newline
void writeByte(unsigned b);
void writebyte(unsigned b) { writeByte(b); }
void writeUTF8(unsigned b);
void writedchar(unsigned b);
void prependbyte(unsigned b);
void writeword(unsigned w);
void writeUTF16(unsigned w);
void write4(unsigned w);
void write(OutBuffer *buf);
void write(Object *obj);
void fill0(unsigned nbytes);
void align(unsigned size);
void vprintf(const char *format, va_list args);
void printf(const char *format, ...) IS_PRINTF(2);
#if M_UNICODE
void vprintf(const unsigned short *format, va_list args);
void printf(const unsigned short *format, ...);
#endif
void bracket(char left, char right);
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
void spread(unsigned offset, unsigned nbytes);
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
void remove(unsigned offset, unsigned nbytes);
char *toChars();
char *extractString();
};
struct Array : Object
{
unsigned dim;
void **data;
private:
unsigned allocdim;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
public:
Array();
~Array();
//Array(const Array&);
void mark();
char *toChars();
void reserve(unsigned nentries);
void setDim(unsigned newdim);
void fixDim();
void push(void *ptr);
void *pop();
void shift(void *ptr);
void insert(unsigned index, void *ptr);
void insert(unsigned index, Array *a);
void append(Array *a);
void remove(unsigned i);
void zero();
void *tos();
void sort();
Array *copy();
};
template <typename TYPE>
struct ArrayBase : Array
{
TYPE **tdata()
{
return (TYPE **)data;
}
TYPE*& operator[] (size_t index)
{
#ifdef DEBUG
assert(index < dim);
#endif
return ((TYPE **)data)[index];
}
void insert(size_t index, TYPE *v)
{
Array::insert(index, (void *)v);
}
void insert(size_t index, ArrayBase *a)
{
Array::insert(index, (Array *)a);
}
void append(ArrayBase *a)
{
Array::append((Array *)a);
}
void push(TYPE *a)
{
Array::push((void *)a);
}
ArrayBase *copy()
{
return (ArrayBase *)Array::copy();
}
};
struct Bits : Object
{
unsigned bitdim;
unsigned allocdim;
unsigned *data;
Bits();
~Bits();
void mark();
void resize(unsigned bitdim);
void set(unsigned bitnum);
void clear(unsigned bitnum);
int test(unsigned bitnum);
void set();
void clear();
void copy(Bits *from);
Bits *clone();
void sub(Bits *b);
};
#endif

View File

@@ -1,139 +1,139 @@
// Copyright (c) 1999-2011 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 <string.h>
#include <stdlib.h>
#include "root.h"
#include "rmem.h"
#include "dchar.h"
#include "lstring.h"
#include "stringtable.h"
void StringTable::init(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;
count = 0;
}
StringTable::~StringTable()
{
unsigned i;
// Zero out dangling pointers to help garbage collector.
// Should zero out StringEntry's too.
for (i = 0; i < count; i++)
table[i] = NULL;
mem.free(table);
table = NULL;
}
struct StringEntry
{
StringEntry *left;
StringEntry *right;
hash_t hash;
StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len);
};
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
{
StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
return se;
}
void **StringTable::search(const dchar *s, unsigned len)
{
hash_t hash;
unsigned u;
int cmp;
StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len);
u = hash % tabledim;
se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u);
while (*se)
{
cmp = (*se)->hash - hash;
if (cmp == 0)
{
cmp = (*se)->value.lstring.len() - len;
if (cmp == 0)
{
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
if (cmp == 0)
break;
}
}
if (cmp < 0)
se = &(*se)->left;
else
se = &(*se)->right;
}
//printf("\treturn %p, %p\n",se, (*se));
return (void **)se;
}
StringValue *StringTable::lookup(const dchar *s, unsigned len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
if (se)
return &se->value;
else
return NULL;
}
StringValue *StringTable::update(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (!se) // not in table: so create new entry
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}
StringValue *StringTable::insert(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (se)
return NULL; // error: already in table
else
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}
// Copyright (c) 1999-2011 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 <string.h>
#include <stdlib.h>
#include "root.h"
#include "rmem.h"
#include "dchar.h"
#include "lstring.h"
#include "stringtable.h"
void StringTable::init(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;
count = 0;
}
StringTable::~StringTable()
{
unsigned i;
// Zero out dangling pointers to help garbage collector.
// Should zero out StringEntry's too.
for (i = 0; i < count; i++)
table[i] = NULL;
mem.free(table);
table = NULL;
}
struct StringEntry
{
StringEntry *left;
StringEntry *right;
hash_t hash;
StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len);
};
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
{
StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
return se;
}
void **StringTable::search(const dchar *s, unsigned len)
{
hash_t hash;
unsigned u;
int cmp;
StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len);
u = hash % tabledim;
se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u);
while (*se)
{
cmp = (*se)->hash - hash;
if (cmp == 0)
{
cmp = (*se)->value.lstring.len() - len;
if (cmp == 0)
{
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
if (cmp == 0)
break;
}
}
if (cmp < 0)
se = &(*se)->left;
else
se = &(*se)->right;
}
//printf("\treturn %p, %p\n",se, (*se));
return (void **)se;
}
StringValue *StringTable::lookup(const dchar *s, unsigned len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
if (se)
return &se->value;
else
return NULL;
}
StringValue *StringTable::update(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (!se) // not in table: so create new entry
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}
StringValue *StringTable::insert(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (se)
return NULL; // error: already in table
else
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}

View File

@@ -1,48 +1,48 @@
// Copyright (c) 1999-2011 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.
#ifndef STRINGTABLE_H
#define STRINGTABLE_H
#if __SC__
#pragma once
#endif
#include "root.h"
#include "dchar.h"
#include "lstring.h"
struct StringValue
{
union
{ int intvalue;
void *ptrvalue;
dchar *string;
};
Lstring lstring;
};
struct StringTable
{
void **table;
unsigned count;
unsigned tabledim;
void init(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len);
private:
void **search(const dchar *s, unsigned len);
};
#endif
// Copyright (c) 1999-2011 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.
#ifndef STRINGTABLE_H
#define STRINGTABLE_H
#if __SC__
#pragma once
#endif
#include "root.h"
#include "dchar.h"
#include "lstring.h"
struct StringValue
{
union
{ int intvalue;
void *ptrvalue;
dchar *string;
};
Lstring lstring;
};
struct StringTable
{
void **table;
unsigned count;
unsigned tabledim;
void init(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len);
private:
void **search(const dchar *s, unsigned len);
};
#endif