mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 13:40:20 +03:00
phobos 0.65
This commit is contained in:
parent
dba8d9bcaa
commit
c7ea30e9a0
31 changed files with 2923 additions and 162 deletions
18
adi.d
18
adi.d
|
@ -42,7 +42,12 @@ extern (C) Array _adReverse(Array a, int szelem)
|
||||||
|
|
||||||
tmp = buffer;
|
tmp = buffer;
|
||||||
if (szelem > 16)
|
if (szelem > 16)
|
||||||
tmp = (byte*) alloca(szelem);
|
{
|
||||||
|
//version (Win32)
|
||||||
|
tmp = (byte*) alloca(szelem);
|
||||||
|
//else
|
||||||
|
//tmp = new byte[szelem];
|
||||||
|
}
|
||||||
|
|
||||||
for (; lo < hi; lo += szelem, hi -= szelem)
|
for (; lo < hi; lo += szelem, hi -= szelem)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +55,17 @@ extern (C) Array _adReverse(Array a, int szelem)
|
||||||
memcpy(lo, hi, szelem);
|
memcpy(lo, hi, szelem);
|
||||||
memcpy(hi, tmp, szelem);
|
memcpy(hi, tmp, szelem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if (szelem > 16)
|
||||||
|
// BUG: bad code is generate for delete pointer, tries
|
||||||
|
// to call delclass.
|
||||||
|
//delete tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
130
alloca.d
Normal file
130
alloca.d
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*_ _alloca.d
|
||||||
|
* Copyright (C) 1990-2003 by Digital Mars, www.digitalmars.com
|
||||||
|
* All Rights Reserved
|
||||||
|
* Written by Walter Bright
|
||||||
|
*/
|
||||||
|
|
||||||
|
/+
|
||||||
|
#if DOS386
|
||||||
|
extern size_t _x386_break;
|
||||||
|
#else
|
||||||
|
extern size_t _pastdata;
|
||||||
|
#endif
|
||||||
|
+/
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
|
* Allocate data from the caller's stack frame.
|
||||||
|
* This is a 'magic' function that needs help from the compiler to
|
||||||
|
* work right, do not change its name, do not call it from other compilers.
|
||||||
|
* Input:
|
||||||
|
* nbytes number of bytes to allocate
|
||||||
|
* ECX address of variable with # of bytes in locals
|
||||||
|
* This is adjusted upon return to reflect the additional
|
||||||
|
* size of the stack frame.
|
||||||
|
* Returns:
|
||||||
|
* EAX allocated data, null if stack overflows
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern (C) void* __alloca(int nbytes)
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
naked ;
|
||||||
|
mov EDX,ECX ;
|
||||||
|
mov EAX,4[ESP] ; // get nbytes
|
||||||
|
push EBX ;
|
||||||
|
push EDI ;
|
||||||
|
push ESI ;
|
||||||
|
add EAX,3 ;
|
||||||
|
and EAX,0xFFFFFFFC ; // round up to dword
|
||||||
|
jnz Abegin ;
|
||||||
|
mov EAX,4 ; // allow zero bytes allocation, 0 rounded to dword is 4..
|
||||||
|
Abegin:
|
||||||
|
mov ESI,EAX ; // ESI = nbytes
|
||||||
|
neg EAX ;
|
||||||
|
add EAX,ESP ; // EAX is now what the new ESP will be.
|
||||||
|
jae Aoverflow ;
|
||||||
|
}
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
// We need to be careful about the guard page
|
||||||
|
// Thus, for every 4k page, touch it to cause the OS to load it in.
|
||||||
|
mov ECX,EAX ; // ECX is new location for stack
|
||||||
|
mov EBX,ESI ; // EBX is size to "grow" stack
|
||||||
|
L1:
|
||||||
|
test [ECX+EBX],EBX ; // bring in page
|
||||||
|
sub EBX,0x1000 ; // next 4K page down
|
||||||
|
jae L1 ; // if more pages
|
||||||
|
test [ECX],EBX ; // bring in last page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version (DOS386)
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
// is ESP off bottom?
|
||||||
|
cmp EAX,_x386_break ;
|
||||||
|
jbe Aoverflow ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version (Unix)
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
cmp EAX,_pastdata ;
|
||||||
|
jbe Aoverflow ; // Unlikely - ~2 Gbytes under UNIX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
// Copy down to [ESP] the temps on the stack.
|
||||||
|
// The number of temps is (EBP - ESP - locals).
|
||||||
|
mov ECX,EBP ;
|
||||||
|
sub ECX,ESP ;
|
||||||
|
sub ECX,[EDX] ; // ECX = number of temps (bytes) to move.
|
||||||
|
add [EDX],ESI ; // adjust locals by nbytes for next call to alloca()
|
||||||
|
mov ESP,EAX ; // Set up new stack pointer.
|
||||||
|
add EAX,ECX ; // Return value = ESP + temps.
|
||||||
|
mov EDI,ESP ; // Destination of copy of temps.
|
||||||
|
add ESI,ESP ; // Source of copy.
|
||||||
|
shr ECX,2 ; // ECX to count of dwords in temps
|
||||||
|
// Always at least 4 (nbytes, EIP, ESI,and EDI).
|
||||||
|
rep ;
|
||||||
|
movsd ;
|
||||||
|
jmp done ;
|
||||||
|
|
||||||
|
Aoverflow:
|
||||||
|
// Overflowed the stack. Return null
|
||||||
|
xor EAX,EAX ;
|
||||||
|
|
||||||
|
done:
|
||||||
|
pop ESI ;
|
||||||
|
pop EDI ;
|
||||||
|
pop EBX ;
|
||||||
|
ret ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
206
cmath.d
Normal file
206
cmath.d
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
|
||||||
|
// Copyright (C) 2001-2003 by Digital Mars
|
||||||
|
// All Rights Reserved
|
||||||
|
// www.digitalmars.com
|
||||||
|
|
||||||
|
// Runtime support for complex arithmetic code generation
|
||||||
|
|
||||||
|
import math;
|
||||||
|
|
||||||
|
extern (C):
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
* Multiply two complex floating point numbers, x and y.
|
||||||
|
* Input:
|
||||||
|
* x.re ST3
|
||||||
|
* x.im ST2
|
||||||
|
* y.re ST1
|
||||||
|
* y.im ST0
|
||||||
|
* Output:
|
||||||
|
* ST1 real part
|
||||||
|
* ST0 imaginary part
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _Cmul()
|
||||||
|
{
|
||||||
|
// p.re = x.re * y.re - x.im * y.im;
|
||||||
|
// p.im = x.im * y.re + x.re * y.im;
|
||||||
|
asm
|
||||||
|
{ naked ;
|
||||||
|
fld ST(1) ; // x.re
|
||||||
|
fmul ST,ST(4) ; // ST0 = x.re * y.re
|
||||||
|
|
||||||
|
fld ST(1) ; // y.im
|
||||||
|
fmul ST,ST(4) ; // ST0 = x.im * y.im
|
||||||
|
|
||||||
|
fsubp ST(1),ST ; // ST0 = x.re * y.re - x.im * y.im
|
||||||
|
|
||||||
|
fld ST(3) ; // x.im
|
||||||
|
fmul ST,ST(3) ; // ST0 = x.im * y.re
|
||||||
|
|
||||||
|
fld ST(5) ; // x.re
|
||||||
|
fmul ST,ST(3) ; // ST0 = x.re * y.im
|
||||||
|
|
||||||
|
faddp ST(1),ST ; // ST0 = x.im * y.re + x.re * y.im
|
||||||
|
|
||||||
|
fxch ST(4),ST ;
|
||||||
|
fstp ST(0) ;
|
||||||
|
fxch ST(4),ST ;
|
||||||
|
fstp ST(0) ;
|
||||||
|
fstp ST(0) ;
|
||||||
|
fstp ST(0) ;
|
||||||
|
|
||||||
|
ret ;
|
||||||
|
}
|
||||||
|
/+
|
||||||
|
if (isnan(x) && isnan(y))
|
||||||
|
{
|
||||||
|
// Recover infinities that computed as NaN+ iNaN ...
|
||||||
|
int recalc = 0;
|
||||||
|
if ( isinf( a) || isinf( b) )
|
||||||
|
{ // z is infinite
|
||||||
|
// "Box" the infinity and change NaNs in the other factor to 0
|
||||||
|
a = copysignl( isinf( a) ? 1.0 : 0.0, a);
|
||||||
|
b = copysignl( isinf( b) ? 1.0 : 0.0, b);
|
||||||
|
if (isnan( c)) c = copysignl( 0.0, c);
|
||||||
|
if (isnan( d)) d = copysignl( 0.0, d);
|
||||||
|
recalc = 1;
|
||||||
|
}
|
||||||
|
if (isinf(c) || isinf(d))
|
||||||
|
{ // w is infinite
|
||||||
|
// "Box" the infinity and change NaNs in the other factor to 0
|
||||||
|
c = copysignl( isinf( c) ? 1.0 : 0.0, c);
|
||||||
|
d = copysignl( isinf( d) ? 1.0 : 0.0, d);
|
||||||
|
if (isnan( a)) a = copysignl( 0.0, a);
|
||||||
|
if (isnan( b)) b = copysignl( 0.0, b);
|
||||||
|
recalc = 1;
|
||||||
|
}
|
||||||
|
if (!recalc && (isinf(ac) || isinf(bd) ||
|
||||||
|
isinf(ad) || isinf(bc)))
|
||||||
|
{
|
||||||
|
// Recover infinities from overflow by changing NaNs to 0 ...
|
||||||
|
if (isnan( a)) a = copysignl( 0.0, a);
|
||||||
|
if (isnan( b)) b = copysignl( 0.0, b);
|
||||||
|
if (isnan( c)) c = copysignl( 0.0, c);
|
||||||
|
if (isnan( d)) d = copysignl( 0.0, d);
|
||||||
|
recalc = 1;
|
||||||
|
}
|
||||||
|
if (recalc)
|
||||||
|
{
|
||||||
|
x = INFINITY * (a * c - b * d);
|
||||||
|
y = INFINITY * (a * d + b * c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+/
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
* Divide two complex floating point numbers, x / y.
|
||||||
|
* Input:
|
||||||
|
* x.re ST3
|
||||||
|
* x.im ST2
|
||||||
|
* y.re ST1
|
||||||
|
* y.im ST0
|
||||||
|
* Output:
|
||||||
|
* ST1 real part
|
||||||
|
* ST0 imaginary part
|
||||||
|
*/
|
||||||
|
|
||||||
|
creal _Cdiv()
|
||||||
|
{
|
||||||
|
real x_re, x_im;
|
||||||
|
real y_re, y_im;
|
||||||
|
real q_re, q_im;
|
||||||
|
real r;
|
||||||
|
real den;
|
||||||
|
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
fstp y_im ;
|
||||||
|
fstp y_re ;
|
||||||
|
fstp x_im ;
|
||||||
|
fstp x_re ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabs(y_re) < fabs(y_im))
|
||||||
|
{
|
||||||
|
r = y_re / y_im;
|
||||||
|
den = y_im + r * y_re;
|
||||||
|
q_re = (x_re * r + x_im) / den;
|
||||||
|
q_im = (x_im * r - x_re) / den;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = y_im / y_re;
|
||||||
|
den = y_re + r * y_im;
|
||||||
|
q_re = (x_re + r * x_im) / den;
|
||||||
|
q_im = (x_im - r * x_re) / den;
|
||||||
|
}
|
||||||
|
//printf("q.re = %g, q.im = %g\n", (double)q_re, (double)q_im);
|
||||||
|
/+
|
||||||
|
if (isnan(q_re) && isnan(q_im))
|
||||||
|
{
|
||||||
|
real denom = y_re * y_re + y_im * y_im;
|
||||||
|
|
||||||
|
// non-zero / zero
|
||||||
|
if (denom == 0.0 && (!isnan(x_re) || !isnan(x_im)))
|
||||||
|
{
|
||||||
|
q_re = copysignl(INFINITY, y_re) * x_re;
|
||||||
|
q_im = copysignl(INFINITY, y_re) * x_im;
|
||||||
|
}
|
||||||
|
// infinite / finite
|
||||||
|
else if ((isinf(x_re) || isinf(x_im)) && isfinite(y_re) && isfinite(y_im))
|
||||||
|
{
|
||||||
|
x_re = copysignl(isinf(x_re) ? 1.0 : 0.0, x_re);
|
||||||
|
x_im = copysignl(isinf(x_im) ? 1.0 : 0.0, x_im);
|
||||||
|
q_re = INFINITY * (x_re * y_re + x_im * y_im);
|
||||||
|
q_im = INFINITY * (x_im * y_re - x_re * y_im);
|
||||||
|
}
|
||||||
|
// finite / infinite
|
||||||
|
else if (isinf(logbw) && isfinite(x_re) && isfinite(x_im))
|
||||||
|
{
|
||||||
|
y_re = copysignl(isinf(y_re) ? 1.0 : 0.0, y_re);
|
||||||
|
y_im = copysignl(isinf(y_im) ? 1.0 : 0.0, y_im);
|
||||||
|
q_re = 0.0 * (x_re * y_re + x_im * y_im);
|
||||||
|
q_im = 0.0 * (x_im * y_re - x_re * y_im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+/
|
||||||
|
return q_re + q_im * 1.0i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
* Compare two complex floating point numbers, x and y.
|
||||||
|
* Input:
|
||||||
|
* x.re ST3
|
||||||
|
* x.im ST2
|
||||||
|
* y.re ST1
|
||||||
|
* y.im ST0
|
||||||
|
* Output:
|
||||||
|
* 8087 stack is cleared
|
||||||
|
* flags set
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _Ccmp()
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{ naked ;
|
||||||
|
fucomp ST(2) ; // compare x.im and y.im
|
||||||
|
fstsw AX ;
|
||||||
|
sahf ;
|
||||||
|
jne L1 ;
|
||||||
|
jp L1 ; // jmp if NAN
|
||||||
|
fucomp ST(2) ; // compare x.re and y.re
|
||||||
|
fstsw AX ;
|
||||||
|
sahf ;
|
||||||
|
fstp ST(0) ; // pop
|
||||||
|
fstp ST(0) ; // pop
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
L1:
|
||||||
|
fstp ST(0) ; // pop
|
||||||
|
fstp ST(0) ; // pop
|
||||||
|
fstp ST(0) ; // pop
|
||||||
|
ret ;
|
||||||
|
}
|
||||||
|
}
|
79
critical.c
79
critical.c
|
@ -1,7 +1,11 @@
|
||||||
// Copyright (C) 2000 by Digital Mars
|
// Copyright (C) 2000-2003 by Digital Mars, www.digitalmars.com
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// Written by Walter Bright
|
// Written by Walter Bright
|
||||||
|
|
||||||
|
/* ================================= Win32 ============================ */
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
|
@ -65,3 +69,76 @@ void _STD_critical_term()
|
||||||
DeleteCriticalSection(&critical_section.cs);
|
DeleteCriticalSection(&critical_section.cs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ================================= linux ============================ */
|
||||||
|
|
||||||
|
#if linux
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
* Enter/exit critical section.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We don't initialize critical sections unless we actually need them.
|
||||||
|
* So keep a linked list of the ones we do use, and in the static destructor
|
||||||
|
* code, walk the list and release them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct D_CRITICAL_SECTION
|
||||||
|
{
|
||||||
|
struct D_CRITICAL_SECTION *next;
|
||||||
|
pthread_mutex_t cs;
|
||||||
|
} D_CRITICAL_SECTION;
|
||||||
|
|
||||||
|
static D_CRITICAL_SECTION *dcs_list;
|
||||||
|
static D_CRITICAL_SECTION critical_section;
|
||||||
|
static volatile int inited;
|
||||||
|
|
||||||
|
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||||
|
{
|
||||||
|
if (!dcs->next)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&critical_section.cs);
|
||||||
|
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||||
|
{
|
||||||
|
dcs->next = dcs_list;
|
||||||
|
dcs_list = dcs;
|
||||||
|
pthread_mutex_init(&dcs->cs, 0);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&critical_section.cs);
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&dcs->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&dcs->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _STI_critical_init()
|
||||||
|
{
|
||||||
|
if (!inited)
|
||||||
|
{ pthread_mutex_init(&critical_section.cs, 0);
|
||||||
|
dcs_list = &critical_section;
|
||||||
|
inited = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _STD_critical_term()
|
||||||
|
{
|
||||||
|
if (inited)
|
||||||
|
{ inited = 0;
|
||||||
|
while (dcs_list)
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&dcs_list->cs);
|
||||||
|
dcs_list = dcs_list->next;
|
||||||
|
}
|
||||||
|
pthread_mutex_destroy(&critical_section.cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
17
date.d
17
date.d
|
@ -635,15 +635,14 @@ version (Win32)
|
||||||
version (linux)
|
version (linux)
|
||||||
{
|
{
|
||||||
|
|
||||||
import c.time;
|
import linux;
|
||||||
import c.sys.time;
|
|
||||||
|
|
||||||
d_time getUTCtime()
|
d_time getUTCtime()
|
||||||
{ timeval tv;
|
{ timeval tv;
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL))
|
if (gettimeofday(&tv, null))
|
||||||
{ // Some error happened - try time() instead
|
{ // Some error happened - try time() instead
|
||||||
return c.time.time(null) * TicksPerSecond;
|
return time(null) * TicksPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tv.tv_sec * TicksPerSecond + (tv.tv_usec / (1000000 / TicksPerSecond));
|
return tv.tv_sec * TicksPerSecond + (tv.tv_usec / (1000000 / TicksPerSecond));
|
||||||
|
@ -651,9 +650,9 @@ version (linux)
|
||||||
|
|
||||||
d_time getLocalTZA()
|
d_time getLocalTZA()
|
||||||
{
|
{
|
||||||
time_t t;
|
int t;
|
||||||
|
|
||||||
c.time.time(&t);
|
time(&t);
|
||||||
localtime(&t); // this will set timezone
|
localtime(&t); // this will set timezone
|
||||||
return -(timezone * TicksPerSecond);
|
return -(timezone * TicksPerSecond);
|
||||||
}
|
}
|
||||||
|
@ -664,10 +663,10 @@ version (linux)
|
||||||
|
|
||||||
int DaylightSavingTA(d_time dt)
|
int DaylightSavingTA(d_time dt)
|
||||||
{
|
{
|
||||||
struct tm *tmp;
|
tm *tmp;
|
||||||
time_t t;
|
int t;
|
||||||
|
|
||||||
t = (time_t) (dt / TicksPerSecond); // BUG: need range check
|
t = (int) (dt / TicksPerSecond); // BUG: need range check
|
||||||
tmp = localtime(&t);
|
tmp = localtime(&t);
|
||||||
if (tmp.tm_isdst > 0)
|
if (tmp.tm_isdst > 0)
|
||||||
// BUG: Assume daylight savings time is plus one hour.
|
// BUG: Assume daylight savings time is plus one hour.
|
||||||
|
|
14
dateparse.d
14
dateparse.d
|
@ -24,7 +24,10 @@ struct DateParse
|
||||||
{
|
{
|
||||||
*this = DateParse.init;
|
*this = DateParse.init;
|
||||||
|
|
||||||
buffer = ((char *)alloca(s.length))[0 .. s.length];
|
//version (Win32)
|
||||||
|
buffer = ((char *)alloca(s.length))[0 .. s.length];
|
||||||
|
//else
|
||||||
|
//buffer = new char[s.length];
|
||||||
|
|
||||||
debug(log) printf("DateParse.parse('%.*s')\n", s);
|
debug(log) printf("DateParse.parse('%.*s')\n", s);
|
||||||
if (!parseString(s))
|
if (!parseString(s))
|
||||||
|
@ -132,13 +135,15 @@ private:
|
||||||
int bi;
|
int bi;
|
||||||
DP result = DP.err;
|
DP result = DP.err;
|
||||||
|
|
||||||
//message(DTEXT("DateParse::nextToken()\n"));
|
//printf("DateParse::nextToken()\n");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
//message(DTEXT("\t*p = '%c'\n"), *p);
|
|
||||||
assert(si <= s.length);
|
assert(si <= s.length);
|
||||||
if (si == s.length)
|
if (si == s.length)
|
||||||
return DP.end;
|
{ result = DP.end;
|
||||||
|
goto Lret;
|
||||||
|
}
|
||||||
|
//printf("\ts[%d] = '%c'\n", si, s[si]);
|
||||||
switch (s[si])
|
switch (s[si])
|
||||||
{
|
{
|
||||||
case ':': result = DP.colon; goto ret_inc;
|
case ':': result = DP.colon; goto ret_inc;
|
||||||
|
@ -233,6 +238,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Lret:
|
Lret:
|
||||||
|
//printf("-DateParse::nextToken()\n");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
257
deh.c
257
deh.c
|
@ -1,9 +1,19 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 1999-2003 by Digital Mars, www.digitalmars.com
|
||||||
|
// All Rights Reserved
|
||||||
|
// Written by Walter Bright
|
||||||
|
|
||||||
|
// Exception handling support
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* ======================== Win32 =============================== */
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
|
||||||
#include <excpt.h>
|
#include <excpt.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
@ -393,4 +403,251 @@ void _d_monitor_epilog(void *x, void *y, Object *h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ======================== linux =============================== */
|
||||||
|
|
||||||
|
#if linux
|
||||||
|
|
||||||
|
#include "mars.h"
|
||||||
|
|
||||||
|
extern ClassInfo _Class_Exception;
|
||||||
|
|
||||||
|
typedef int (*fp_t)(); // function pointer in ambient memory model
|
||||||
|
|
||||||
|
struct DHandlerInfo
|
||||||
|
{
|
||||||
|
unsigned offset; // offset from function address to start of guarded section
|
||||||
|
int prev_index; // previous table index
|
||||||
|
unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch)
|
||||||
|
void *finally_code; // pointer to finally code to execute
|
||||||
|
// (!=0 if try-finally)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Address of DHandlerTable, searched for by eh_finddata()
|
||||||
|
|
||||||
|
struct DHandlerTable
|
||||||
|
{
|
||||||
|
void *fptr; // pointer to start of function
|
||||||
|
unsigned espoffset; // offset of ESP from EBP
|
||||||
|
unsigned retoffset; // offset from start of function to return code
|
||||||
|
unsigned nhandlers; // dimension of handler_info[]
|
||||||
|
struct DHandlerInfo handler_info[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DCatchBlock
|
||||||
|
{
|
||||||
|
ClassInfo *type; // catch type
|
||||||
|
unsigned bpoffset; // EBP offset of catch var
|
||||||
|
void *code; // catch handler code
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create one of these for each try-catch
|
||||||
|
struct DCatchInfo
|
||||||
|
{
|
||||||
|
unsigned ncatches; // number of catch blocks
|
||||||
|
struct DCatchBlock catch_block[1]; // data for each catch block
|
||||||
|
};
|
||||||
|
|
||||||
|
// One of these is generated for each function with try-catch or try-finally
|
||||||
|
|
||||||
|
struct FuncTable
|
||||||
|
{
|
||||||
|
void *fptr; // pointer to start of function
|
||||||
|
struct DHandlerTable *handlertable; // eh data for this function
|
||||||
|
unsigned size; // size of function in bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct FuncTable *table_start;
|
||||||
|
extern struct FuncTable *table_end;
|
||||||
|
|
||||||
|
void terminate()
|
||||||
|
{
|
||||||
|
// _asm
|
||||||
|
// {
|
||||||
|
// hlt
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
|
* Given address that is inside a function,
|
||||||
|
* figure out which function it is in.
|
||||||
|
* Return DHandlerTable if there is one, NULL if not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct DHandlerTable *__eh_finddata(void *address)
|
||||||
|
{
|
||||||
|
struct FuncTable *ft;
|
||||||
|
|
||||||
|
for (ft = (struct FuncTable *)table_start;
|
||||||
|
ft < (struct FuncTable *)table_end;
|
||||||
|
ft++)
|
||||||
|
{
|
||||||
|
if (ft->fptr <= address &&
|
||||||
|
address < (void *)((char *)ft->fptr + ft->size))
|
||||||
|
{
|
||||||
|
return ft->handlertable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* Given EBP, find return address to caller, and caller's EBP.
|
||||||
|
* Input:
|
||||||
|
* regbp Value of EBP for current function
|
||||||
|
* *pretaddr Return address
|
||||||
|
* Output:
|
||||||
|
* *pretaddr return address to caller
|
||||||
|
* Returns:
|
||||||
|
* caller's EBP
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr)
|
||||||
|
{
|
||||||
|
unsigned bp = *(unsigned *)regbp;
|
||||||
|
|
||||||
|
if (bp) // if not end of call chain
|
||||||
|
{
|
||||||
|
// Perform sanity checks on new EBP.
|
||||||
|
// If it is screwed up, terminate() hopefully before we do more damage.
|
||||||
|
if (bp <= regbp)
|
||||||
|
// stack should grow to smaller values
|
||||||
|
terminate();
|
||||||
|
|
||||||
|
*pretaddr = *(unsigned *)(regbp + sizeof(int));
|
||||||
|
}
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Throw a D object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void __stdcall _d_throw(Object *h)
|
||||||
|
{
|
||||||
|
unsigned regebp;
|
||||||
|
|
||||||
|
//printf("_d_throw(h = %p, &h = %p)\n", h, &h);
|
||||||
|
//printf("\tvptr = %p\n", *(void **)h);
|
||||||
|
|
||||||
|
regebp = _EBP;
|
||||||
|
|
||||||
|
while (1) // for each function on the stack
|
||||||
|
{
|
||||||
|
struct DHandlerTable *handler_table;
|
||||||
|
struct FuncTable *pfunc;
|
||||||
|
struct DHandlerInfo *phi;
|
||||||
|
unsigned retaddr;
|
||||||
|
unsigned funcoffset;
|
||||||
|
unsigned spoff;
|
||||||
|
unsigned retoffset;
|
||||||
|
int index;
|
||||||
|
int dim;
|
||||||
|
int ndx;
|
||||||
|
int prev_ndx;
|
||||||
|
|
||||||
|
regebp = __eh_find_caller(regebp,&retaddr);
|
||||||
|
if (!regebp)
|
||||||
|
// if end of call chain
|
||||||
|
break;
|
||||||
|
|
||||||
|
handler_table = __eh_finddata((void *)retaddr); // find static data associated with function
|
||||||
|
if (!handler_table) // if no static data
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
funcoffset = (unsigned)handler_table->fptr;
|
||||||
|
spoff = handler_table->espoffset;
|
||||||
|
retoffset = handler_table->retoffset;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("retaddr = x%x\n",(unsigned)retaddr);
|
||||||
|
printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
|
||||||
|
regebp,funcoffset,spoff,retoffset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Find start index for retaddr in static data
|
||||||
|
dim = handler_table->nhandlers;
|
||||||
|
index = -1;
|
||||||
|
for (int i = 0; i < dim; i++)
|
||||||
|
{
|
||||||
|
phi = &handler_table->handler_info[i];
|
||||||
|
|
||||||
|
if ((unsigned)retaddr >= funcoffset + phi->offset)
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk through handler table, checking each handler
|
||||||
|
// with an index smaller than the current table_index
|
||||||
|
for (ndx = index; ndx != -1; ndx = prev_ndx)
|
||||||
|
{
|
||||||
|
phi = &handler_table->handler_info[ndx];
|
||||||
|
prev_ndx = phi->prev_index;
|
||||||
|
if (phi->cioffset)
|
||||||
|
{
|
||||||
|
// this is a catch handler (no finally)
|
||||||
|
struct DCatchInfo *pci;
|
||||||
|
int ncatches;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
|
||||||
|
ncatches = pci->ncatches;
|
||||||
|
for (i = 0; i < ncatches; i++)
|
||||||
|
{
|
||||||
|
struct DCatchBlock *pcb;
|
||||||
|
ClassInfo *ci = **(ClassInfo ***)h;
|
||||||
|
|
||||||
|
pcb = &pci->catch_block[i];
|
||||||
|
|
||||||
|
if (_d_isbaseof(ci, pcb->type))
|
||||||
|
{ // Matched the catch type, so we've found the handler.
|
||||||
|
|
||||||
|
// Initialize catch variable
|
||||||
|
*(void **)(regebp + (pcb->bpoffset)) = h;
|
||||||
|
|
||||||
|
// Jump to catch block. Does not return.
|
||||||
|
{
|
||||||
|
unsigned catch_esp;
|
||||||
|
fp_t catch_addr;
|
||||||
|
|
||||||
|
catch_addr = (fp_t)(pcb->code);
|
||||||
|
catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
mov EAX,catch_esp
|
||||||
|
mov ECX,catch_addr
|
||||||
|
mov [EAX],ECX
|
||||||
|
mov EBP,regebp
|
||||||
|
mov ESP,EAX // reset stack
|
||||||
|
ret // jump to catch block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (phi->finally_code)
|
||||||
|
{ // Call finally block
|
||||||
|
// Note that it is unnecessary to adjust the ESP, as the finally block
|
||||||
|
// accesses all items on the stack as relative to EBP.
|
||||||
|
|
||||||
|
void *blockaddr = phi->finally_code;
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
push EBX
|
||||||
|
mov EBX,blockaddr
|
||||||
|
push EBP
|
||||||
|
mov EBP,regebp
|
||||||
|
call EBX
|
||||||
|
pop EBP
|
||||||
|
pop EBX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
31
dmain2.d
31
dmain2.d
|
@ -4,10 +4,15 @@ import c.stdio;
|
||||||
import c.stdlib;
|
import c.stdlib;
|
||||||
import string;
|
import string;
|
||||||
|
|
||||||
|
extern (C) void _STI_monitor_staticctor();
|
||||||
|
extern (C) void _STD_monitor_staticdtor();
|
||||||
|
extern (C) void _STI_critical_init();
|
||||||
|
extern (C) void _STD_critical_term();
|
||||||
extern (C) void gc_init();
|
extern (C) void gc_init();
|
||||||
extern (C) void gc_term();
|
extern (C) void gc_term();
|
||||||
extern (C) void _minit();
|
extern (C) void _minit();
|
||||||
extern (C) void _moduleCtor();
|
extern (C) void _moduleCtor();
|
||||||
|
extern (C) void _moduleDtor();
|
||||||
extern (C) void _moduleUnitTests();
|
extern (C) void _moduleUnitTests();
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
|
@ -16,7 +21,7 @@ extern (C) void _moduleUnitTests();
|
||||||
int main(char[][] args);
|
int main(char[][] args);
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* Called by the C main() function in main.c.
|
* Substitutes for the C main() function.
|
||||||
* It's purpose is to wrap the call to the D main()
|
* It's purpose is to wrap the call to the D main()
|
||||||
* function and catch any unhandled exceptions.
|
* function and catch any unhandled exceptions.
|
||||||
*/
|
*/
|
||||||
|
@ -28,9 +33,20 @@ extern (C) int main(int argc, char **argv)
|
||||||
int i;
|
int i;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
gc_init();
|
version (linux)
|
||||||
_minit();
|
{
|
||||||
am = (char[] *) alloca(argc * (char[]).size);
|
_STI_monitor_staticctor();
|
||||||
|
_STI_critical_init();
|
||||||
|
gc_init();
|
||||||
|
//am = (char[] *) malloc(argc * (char[]).size);
|
||||||
|
am = (char[] *) alloca(argc * (char[]).size);
|
||||||
|
}
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
gc_init();
|
||||||
|
_minit();
|
||||||
|
am = (char[] *) alloca(argc * (char[]).size);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -55,7 +71,14 @@ extern (C) int main(int argc, char **argv)
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_moduleDtor();
|
||||||
gc_term();
|
gc_term();
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
//free(am);
|
||||||
|
_STD_critical_term();
|
||||||
|
_STD_monitor_staticdtor();
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
217
file.d
217
file.d
|
@ -36,6 +36,11 @@ class FileError : Error
|
||||||
* Basic File operations.
|
* Basic File operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* =========================== Win32 ======================= */
|
||||||
|
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
|
||||||
import windows;
|
import windows;
|
||||||
|
|
||||||
/********************************************
|
/********************************************
|
||||||
|
@ -208,3 +213,215 @@ uint getAttributes(char[] name)
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================== linux ======================= */
|
||||||
|
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
|
||||||
|
import linux;
|
||||||
|
|
||||||
|
/********************************************
|
||||||
|
* Read a file.
|
||||||
|
* Returns:
|
||||||
|
* array of bytes read
|
||||||
|
*/
|
||||||
|
|
||||||
|
byte[] read(char[] name)
|
||||||
|
{
|
||||||
|
uint size;
|
||||||
|
uint numread;
|
||||||
|
int fd;
|
||||||
|
stat statbuf;
|
||||||
|
byte[] buf;
|
||||||
|
char *namez;
|
||||||
|
|
||||||
|
namez = toStringz(name);
|
||||||
|
//printf("file.read('%s')\n",namez);
|
||||||
|
fd = linux.open(namez, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
//printf("\topen error, errno = %d\n",getErrno());
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("\tfile opened\n");
|
||||||
|
if (linux.fstat(fd, &statbuf))
|
||||||
|
{
|
||||||
|
//printf("\tfstat error, errno = %d\n",getErrno());
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
size = statbuf.st_size;
|
||||||
|
buf = new byte[size];
|
||||||
|
|
||||||
|
numread = linux.read(fd, (char*)buf, size);
|
||||||
|
if (numread != size)
|
||||||
|
{
|
||||||
|
//printf("\tread error, errno = %d\n",getErrno());
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linux.close(fd) == -1)
|
||||||
|
{
|
||||||
|
//printf("\tclose error, errno = %d\n",getErrno());
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
linux.close(fd);
|
||||||
|
err:
|
||||||
|
delete buf;
|
||||||
|
|
||||||
|
err1:
|
||||||
|
throw new FileError(name, getErrno());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* Write a file.
|
||||||
|
* Returns:
|
||||||
|
* 0 success
|
||||||
|
*/
|
||||||
|
|
||||||
|
void write(char[] name, byte[] buffer)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int numwritten;
|
||||||
|
int len;
|
||||||
|
char *namez;
|
||||||
|
|
||||||
|
namez = toStringz(name);
|
||||||
|
fd = linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660);
|
||||||
|
if (fd == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
numwritten = linux.write(fd, buffer, len);
|
||||||
|
if (len != numwritten)
|
||||||
|
goto err2;
|
||||||
|
|
||||||
|
if (linux.close(fd) == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
linux.close(fd);
|
||||||
|
err:
|
||||||
|
throw new FileError(name, getErrno());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* Append to a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void append(char[] name, byte[] buffer)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int numwritten;
|
||||||
|
int len;
|
||||||
|
char *namez;
|
||||||
|
|
||||||
|
namez = toStringz(name);
|
||||||
|
fd = linux.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660);
|
||||||
|
if (fd == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
numwritten = linux.write(fd, buffer, len);
|
||||||
|
if (len != numwritten)
|
||||||
|
goto err2;
|
||||||
|
|
||||||
|
if (linux.close(fd) == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
linux.close(fd);
|
||||||
|
err:
|
||||||
|
throw new FileError(name, getErrno());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
* Rename a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rename(char[] from, char[] to)
|
||||||
|
{
|
||||||
|
char *fromz = toStringz(from);
|
||||||
|
char *toz = toStringz(to);
|
||||||
|
|
||||||
|
if (c.stdio.rename(fromz, toz) == -1)
|
||||||
|
throw new FileError(to, getErrno());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
* Delete a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void remove(char[] name)
|
||||||
|
{
|
||||||
|
if (c.stdio.remove(toStringz(name)) == -1)
|
||||||
|
throw new FileError(name, getErrno());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
* Get file size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint getSize(char[] name)
|
||||||
|
{
|
||||||
|
uint size;
|
||||||
|
int fd;
|
||||||
|
stat statbuf;
|
||||||
|
char *namez;
|
||||||
|
|
||||||
|
namez = toStringz(name);
|
||||||
|
//printf("file.getSize('%s')\n",namez);
|
||||||
|
fd = linux.open(namez, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
//printf("\topen error, errno = %d\n",getErrno());
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("\tfile opened\n");
|
||||||
|
if (linux.fstat(fd, &statbuf))
|
||||||
|
{
|
||||||
|
//printf("\tfstat error, errno = %d\n",getErrno());
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
size = statbuf.st_size;
|
||||||
|
|
||||||
|
if (linux.close(fd) == -1)
|
||||||
|
{
|
||||||
|
//printf("\tclose error, errno = %d\n",getErrno());
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
linux.close(fd);
|
||||||
|
err:
|
||||||
|
err1:
|
||||||
|
throw new FileError(name, getErrno());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
* Get file attributes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint getAttributes(char[] name)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
89
gc2/gclinux.d
Normal file
89
gc2/gclinux.d
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
// Copyright (C) 2001-2003 by Digital Mars, www.digitalmars.com
|
||||||
|
// All Rights Reserved
|
||||||
|
// Written by Walter Bright
|
||||||
|
|
||||||
|
import linuxextern;
|
||||||
|
|
||||||
|
extern (C)
|
||||||
|
{
|
||||||
|
// from <sys/mman.h>
|
||||||
|
void* mmap(void* addr, uint len, int prot, int flags, int fd, uint offset);
|
||||||
|
int munmap(void* addr, uint len);
|
||||||
|
const void* MAP_FAILED = (void*)-1;
|
||||||
|
|
||||||
|
// from <bits/mman.h>
|
||||||
|
enum { PROT_NONE = 0, PROT_READ = 1, PROT_WRITE = 2, PROT_EXEC = 4 }
|
||||||
|
enum { MAP_SHARED = 1, MAP_PRIVATE = 2, MAP_TYPE = 0x0F,
|
||||||
|
MAP_FIXED = 0x10, MAP_FILE = 0, MAP_ANON = 0x20 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Map memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *os_mem_map(uint nbytes)
|
||||||
|
{ void *p;
|
||||||
|
|
||||||
|
//errno = 0;
|
||||||
|
p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
|
return (p == MAP_FAILED) ? null : p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Commit memory.
|
||||||
|
* Returns:
|
||||||
|
* 0 success
|
||||||
|
* !=0 failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
int os_mem_commit(void *base, uint offset, uint nbytes)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Decommit memory.
|
||||||
|
* Returns:
|
||||||
|
* 0 success
|
||||||
|
* !=0 failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
int os_mem_decommit(void *base, uint offset, uint nbytes)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Unmap memory allocated with os_mem_map().
|
||||||
|
* Returns:
|
||||||
|
* 0 success
|
||||||
|
* !=0 failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
int os_mem_unmap(void *base, uint nbytes)
|
||||||
|
{
|
||||||
|
return munmap(base, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************
|
||||||
|
* Determine "bottom" of stack (actually the top on x86 systems).
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *os_query_stackBottom()
|
||||||
|
{
|
||||||
|
return __libc_stack_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************
|
||||||
|
* Determine base address and size of static data segment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void os_query_staticdataseg(void **base, uint *nbytes)
|
||||||
|
{
|
||||||
|
*base = (void *)&__data_start;
|
||||||
|
*nbytes = &_end - &__data_start;
|
||||||
|
}
|
68
gc2/gcx.d
68
gc2/gcx.d
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Copyright (C) 2001-2002 by Digital Mars
|
// Copyright (C) 2001-2003 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// Written by Walter Bright
|
// Written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
|
@ -31,11 +31,21 @@ debug (PRINTF) import c.stdio;
|
||||||
|
|
||||||
import c.stdlib;
|
import c.stdlib;
|
||||||
import gcbits;
|
import gcbits;
|
||||||
import win32;
|
|
||||||
import outofmemory;
|
import outofmemory;
|
||||||
import gc;
|
import gc;
|
||||||
import gcstats;
|
import gcstats;
|
||||||
|
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
import win32;
|
||||||
|
}
|
||||||
|
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
import gclinux;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
version (MULTI_THREADED)
|
version (MULTI_THREADED)
|
||||||
{
|
{
|
||||||
import thread;
|
import thread;
|
||||||
|
@ -158,7 +168,14 @@ struct GC
|
||||||
gcLock = GCLock.classinfo;
|
gcLock = GCLock.classinfo;
|
||||||
gcx = (Gcx *)c.stdlib.calloc(1, Gcx.size);
|
gcx = (Gcx *)c.stdlib.calloc(1, Gcx.size);
|
||||||
gcx.init();
|
gcx.init();
|
||||||
setStackBottom(win32.os_query_stackBottom());
|
version (Win32)
|
||||||
|
{
|
||||||
|
setStackBottom(win32.os_query_stackBottom());
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
setStackBottom(gclinux.os_query_stackBottom());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -488,9 +505,11 @@ struct GC
|
||||||
void *ptop;
|
void *ptop;
|
||||||
uint nbytes;
|
uint nbytes;
|
||||||
|
|
||||||
|
//debug(PRINTF) printf("+GC.scanStaticData()\n");
|
||||||
os_query_staticdataseg(&pbot, &nbytes);
|
os_query_staticdataseg(&pbot, &nbytes);
|
||||||
ptop = pbot + nbytes;
|
ptop = pbot + nbytes;
|
||||||
addRange(pbot, ptop);
|
addRange(pbot, ptop);
|
||||||
|
//debug(PRINTF) printf("-GC.scanStaticData()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -512,10 +531,12 @@ struct GC
|
||||||
|
|
||||||
void addRange(void *pbot, void *ptop) // add range to scan for roots
|
void addRange(void *pbot, void *ptop) // add range to scan for roots
|
||||||
{
|
{
|
||||||
|
//debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop);
|
||||||
synchronized (gcLock)
|
synchronized (gcLock)
|
||||||
{
|
{
|
||||||
gcx.addRange(pbot, ptop);
|
gcx.addRange(pbot, ptop);
|
||||||
}
|
}
|
||||||
|
//debug(PRINTF) printf("-GC.addRange()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeRange(void *pbot) // remove range
|
void removeRange(void *pbot) // remove range
|
||||||
|
@ -874,8 +895,8 @@ struct Gcx
|
||||||
|
|
||||||
void addRange(void *pbot, void *ptop)
|
void addRange(void *pbot, void *ptop)
|
||||||
{
|
{
|
||||||
//debug(PRINTF) printf("Thread %x ", pthread_self());
|
debug(PRINTF) printf("Thread %x ", pthread_self());
|
||||||
//debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges);
|
debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges);
|
||||||
if (nranges == rangedim)
|
if (nranges == rangedim)
|
||||||
{
|
{
|
||||||
uint newdim = rangedim * 2 + 16;
|
uint newdim = rangedim * 2 + 16;
|
||||||
|
@ -898,8 +919,8 @@ struct Gcx
|
||||||
|
|
||||||
void removeRange(void *pbot)
|
void removeRange(void *pbot)
|
||||||
{
|
{
|
||||||
//debug(PRINTF) printf("Thread %x ", pthread_self());
|
debug(PRINTF) printf("Thread %x ", pthread_self());
|
||||||
//debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges);
|
debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges);
|
||||||
for (uint i = nranges; i--;)
|
for (uint i = nranges; i--;)
|
||||||
{
|
{
|
||||||
if (ranges[i].pbot == pbot)
|
if (ranges[i].pbot == pbot)
|
||||||
|
@ -909,7 +930,7 @@ struct Gcx
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//debug(PRINTF) printf("Wrong thread\n");
|
debug(PRINTF) printf("Wrong thread\n");
|
||||||
|
|
||||||
// This is a fatal error, but ignore it.
|
// This is a fatal error, but ignore it.
|
||||||
// The problem is that we can get a Close() call on a thread
|
// The problem is that we can get a Close() call on a thread
|
||||||
|
@ -1353,19 +1374,34 @@ struct Gcx
|
||||||
|
|
||||||
if (t && t.getState() == Thread.TS.RUNNING)
|
if (t && t.getState() == Thread.TS.RUNNING)
|
||||||
{
|
{
|
||||||
CONTEXT context;
|
|
||||||
|
|
||||||
if (noStack && threads.length == 1)
|
if (noStack && threads.length == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
|
version (Win32)
|
||||||
if (!GetThreadContext(t.hdl, &context))
|
|
||||||
{
|
{
|
||||||
assert(0);
|
CONTEXT context;
|
||||||
|
|
||||||
|
context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
|
||||||
|
if (!GetThreadContext(t.hdl, &context))
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
debug (PRINTF) printf("mt scan stack bot = %x, top = %x\n", context.Esp, t.stackBottom);
|
||||||
|
mark((void *)context.Esp, t.stackBottom);
|
||||||
|
mark(&context.Edi, &context.Eip);
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
// The registers are already stored in the stack
|
||||||
|
//printf("foo x%x, x%x, isSelf = %d\n", Thread.getESP(), t.stackBottom, t.isSelf());
|
||||||
|
if (t.isSelf())
|
||||||
|
t.stackTop = Thread.getESP();
|
||||||
|
|
||||||
|
version (STACKGROWSDOWN)
|
||||||
|
mark(t.stackTop, t.stackBottom);
|
||||||
|
else
|
||||||
|
mark(t.stackBottom, t.stackTop);
|
||||||
}
|
}
|
||||||
debug (PRINTF) printf("mt scan stack bot = %x, top = %x\n", context.Esp, t.stackBottom);
|
|
||||||
mark((void *)context.Esp, t.stackBottom);
|
|
||||||
mark(&context.Edi, &context.Eip);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
50
gc2/linux.mak
Normal file
50
gc2/linux.mak
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
# makefile to build linux D garbage collector
|
||||||
|
|
||||||
|
DMD=../../dmd
|
||||||
|
#DMD=/dmd/bin/dmd
|
||||||
|
CFLAGS=-g
|
||||||
|
#DFLAGS=-unittest -g -release
|
||||||
|
DFLAGS=-release -O -inline -I..
|
||||||
|
#DFLAGS=-release -inline -O
|
||||||
|
CC=gcc
|
||||||
|
|
||||||
|
OBJS= gc.o gcx.o gcbits.o gclinux.o
|
||||||
|
|
||||||
|
SRC= gc.d gcx.d gcbits.d win32.d gclinux.d testgc.d win32.mak linux.mak
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) $*
|
||||||
|
|
||||||
|
.d.o:
|
||||||
|
$(DMD) -c $(DFLAGS) $*
|
||||||
|
|
||||||
|
targets : testgc dmgc.a
|
||||||
|
|
||||||
|
testgc : testgc.o $(OBJS) linux.mak ../phobos.a
|
||||||
|
$(CC) -o $@ testgc.o $(OBJS) ../phobos.a -lpthread -lm -g -Xlinker -M
|
||||||
|
|
||||||
|
testgc.o : testgc.d
|
||||||
|
$(DMD) -c $(DFLAGS) testgc.d
|
||||||
|
|
||||||
|
dmgc.a : $(OBJS) linux.mak
|
||||||
|
ar -r $@ $(OBJS)
|
||||||
|
|
||||||
|
gc.o : gc.d
|
||||||
|
$(DMD) -c $(DFLAGS) gc.d
|
||||||
|
|
||||||
|
gcx.o : gcx.d
|
||||||
|
$(DMD) -c $(DFLAGS) gcx.d
|
||||||
|
|
||||||
|
gcbits.o : gcbits.d
|
||||||
|
$(DMD) -c $(DFLAGS) gcbits.d
|
||||||
|
|
||||||
|
gclinux.o : gclinux.d
|
||||||
|
$(DMD) -c $(DFLAGS) gclinux.d
|
||||||
|
|
||||||
|
zip : $(SRC)
|
||||||
|
rm dmgc.zip
|
||||||
|
zip dmgc $(SRC)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm $(OBJS) dmgc.a testgc
|
16
gc2/testgc.d
16
gc2/testgc.d
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
// Copyright (C) 2001-2002 by Digital Mars
|
// Copyright (C) 2001-2003 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// Written by Walter Bright
|
// Written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
|
@ -68,10 +68,12 @@ void smoke()
|
||||||
|
|
||||||
gc = newGC();
|
gc = newGC();
|
||||||
deleteGC(gc);
|
deleteGC(gc);
|
||||||
|
printf("smoke.1\n");
|
||||||
|
|
||||||
gc = newGC();
|
gc = newGC();
|
||||||
gc.init();
|
gc.init();
|
||||||
deleteGC(gc);
|
deleteGC(gc);
|
||||||
|
printf("smoke.2\n");
|
||||||
|
|
||||||
gc = newGC();
|
gc = newGC();
|
||||||
gc.init();
|
gc.init();
|
||||||
|
@ -157,11 +159,11 @@ void smoke3()
|
||||||
// for (i = 0; i < 1000000; i++)
|
// for (i = 0; i < 1000000; i++)
|
||||||
for (i = 0; i < 1000; i++)
|
for (i = 0; i < 1000; i++)
|
||||||
{
|
{
|
||||||
uint size = rand() % 2048;
|
uint size = random.rand() % 2048;
|
||||||
p = (int *)gc.malloc(size);
|
p = (int *)gc.malloc(size);
|
||||||
memset(p, i, size);
|
memset(p, i, size);
|
||||||
|
|
||||||
size = rand() % 2048;
|
size = random.rand() % 2048;
|
||||||
p = (int *)gc.realloc(p, size);
|
p = (int *)gc.realloc(p, size);
|
||||||
memset(p, i + 1, size);
|
memset(p, i + 1, size);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +195,7 @@ void smoke4()
|
||||||
p = (int *)gc.malloc(size);
|
p = (int *)gc.malloc(size);
|
||||||
memset(p, i, size);
|
memset(p, i, size);
|
||||||
|
|
||||||
size = rand() % 2048;
|
size = random.rand() % 2048;
|
||||||
gc.check(p);
|
gc.check(p);
|
||||||
p = (int *)gc.realloc(p, size);
|
p = (int *)gc.realloc(p, size);
|
||||||
memset(p, i + 1, size);
|
memset(p, i + 1, size);
|
||||||
|
@ -226,8 +228,8 @@ void smoke5(GC *gc)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 2000 /*4000*/; i++)
|
for (i = 0; i < 2000 /*4000*/; i++)
|
||||||
{
|
{
|
||||||
uint size = (rand() % 2048) + 1;
|
uint size = (random.rand() % 2048) + 1;
|
||||||
uint index = rand() % SMOKE5_SIZE;
|
uint index = random.rand() % SMOKE5_SIZE;
|
||||||
|
|
||||||
//printf("index = %d, size = %d\n", index, size);
|
//printf("index = %d, size = %d\n", index, size);
|
||||||
p = array[index] - offset[index];
|
p = array[index] - offset[index];
|
||||||
|
@ -243,7 +245,7 @@ void smoke5(GC *gc)
|
||||||
}
|
}
|
||||||
array[index] = p;
|
array[index] = p;
|
||||||
fill(p, index, size);
|
fill(p, index, size);
|
||||||
offset[index] = rand() % size;
|
offset[index] = random.rand() % size;
|
||||||
array[index] += offset[index];
|
array[index] += offset[index];
|
||||||
|
|
||||||
//printf("p[0] = %d\n", p[0]);
|
//printf("p[0] = %d\n", p[0]);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
# makefile to build D garbage collector under win32
|
||||||
|
|
||||||
DMD=..\..\dmd
|
DMD=..\..\dmd
|
||||||
#DMD=\dmd\bin\dmd
|
#DMD=\dmd\bin\dmd
|
||||||
CFLAGS=-g -mn -6 -r -Igc
|
CFLAGS=-g -mn -6 -r -Igc
|
||||||
|
@ -28,7 +30,7 @@ testgc.obj : testgc.d
|
||||||
|
|
||||||
OBJS= gc.obj gcx.obj gcbits.obj win32.obj
|
OBJS= gc.obj gcx.obj gcbits.obj win32.obj
|
||||||
|
|
||||||
SRC= gc.d gcx.d gcbits.d win32.d testgc.d
|
SRC= gc.d gcx.d gcbits.d win32.d gclinux.d testgc.d win32.mak linux.mak
|
||||||
|
|
||||||
dmgc.lib : $(OBJS) makefile
|
dmgc.lib : $(OBJS) makefile
|
||||||
del dmgc.lib
|
del dmgc.lib
|
||||||
|
@ -39,8 +41,9 @@ gcx.obj : gcx.d
|
||||||
gcbits.obj : gcbits.d
|
gcbits.obj : gcbits.d
|
||||||
win32.obj : win32.d
|
win32.obj : win32.d
|
||||||
|
|
||||||
zip : makefile $(SRC)
|
zip : $(SRC)
|
||||||
zip32 -u dmgc makefile $(SRC)
|
del dmgc.zip
|
||||||
|
zip32 dmgc $(SRC)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
del $(OBJS)
|
del $(OBJS)
|
120
linux.d
Normal file
120
linux.d
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
|
||||||
|
import linuxextern;
|
||||||
|
|
||||||
|
enum : int
|
||||||
|
{
|
||||||
|
SIGHUP = 1,
|
||||||
|
SIGINT = 2,
|
||||||
|
SIGQUIT = 3,
|
||||||
|
SIGILL = 4,
|
||||||
|
SIGTRAP = 5,
|
||||||
|
SIGABRT = 6,
|
||||||
|
SIGIOT = 6,
|
||||||
|
SIGBUS = 7,
|
||||||
|
SIGFPE = 8,
|
||||||
|
SIGKILL = 9,
|
||||||
|
SIGUSR1 = 10,
|
||||||
|
SIGSEGV = 11,
|
||||||
|
SIGUSR2 = 12,
|
||||||
|
SIGPIPE = 13,
|
||||||
|
SIGALRM = 14,
|
||||||
|
SIGTERM = 15,
|
||||||
|
SIGSTKFLT = 16,
|
||||||
|
SIGCHLD = 17,
|
||||||
|
SIGCONT = 18,
|
||||||
|
SIGSTOP = 19,
|
||||||
|
SIGTSTP = 20,
|
||||||
|
SIGTTIN = 21,
|
||||||
|
SIGTTOU = 22,
|
||||||
|
SIGURG = 23,
|
||||||
|
SIGXCPU = 24,
|
||||||
|
SIGXFSZ = 25,
|
||||||
|
SIGVTALRM = 26,
|
||||||
|
SIGPROF = 27,
|
||||||
|
SIGWINCH = 28,
|
||||||
|
SIGPOLL = 29,
|
||||||
|
SIGIO = 29,
|
||||||
|
SIGPWR = 30,
|
||||||
|
SIGSYS = 31,
|
||||||
|
SIGUNUSED = 31,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
O_RDONLY = 0,
|
||||||
|
O_WRONLY = 1,
|
||||||
|
O_RDWR = 2,
|
||||||
|
O_CREAT = 0100,
|
||||||
|
O_EXCL = 0200,
|
||||||
|
O_TRUNC = 01000,
|
||||||
|
O_APPEND = 02000,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat
|
||||||
|
{
|
||||||
|
ulong st_dev;
|
||||||
|
ushort __pad1;
|
||||||
|
uint st_ino;
|
||||||
|
uint st_mode;
|
||||||
|
uint st_nlink;
|
||||||
|
uint st_uid;
|
||||||
|
uint st_gid;
|
||||||
|
ulong st_rdev;
|
||||||
|
ushort __pad2;
|
||||||
|
int st_size;
|
||||||
|
int st_blksize;
|
||||||
|
int st_blocks;
|
||||||
|
int st_atime;
|
||||||
|
uint __unused1;
|
||||||
|
int st_mtime;
|
||||||
|
uint __unused2;
|
||||||
|
int st_ctime;
|
||||||
|
uint __unused3;
|
||||||
|
uint __unused4;
|
||||||
|
uint __unused5;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
assert(stat.size == 88);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern (C)
|
||||||
|
{
|
||||||
|
int open(char*, int, ...);
|
||||||
|
int read(int, void*, int);
|
||||||
|
int write(int, void*, int);
|
||||||
|
int close(int);
|
||||||
|
int lseek(int, int, int);
|
||||||
|
int fstat(int, stat*);
|
||||||
|
int getErrno();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval
|
||||||
|
{
|
||||||
|
int tv_sec;
|
||||||
|
int tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tm
|
||||||
|
{
|
||||||
|
int tm_sec;
|
||||||
|
int tm_min;
|
||||||
|
int tm_hour;
|
||||||
|
int tm_mday;
|
||||||
|
int tm_mon;
|
||||||
|
int tm_year;
|
||||||
|
int tm_wday;
|
||||||
|
int tm_yday;
|
||||||
|
int tm_isdst;
|
||||||
|
int tm_gmtoff;
|
||||||
|
int tm_zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern (C)
|
||||||
|
{
|
||||||
|
int gettimeofday(timeval*, void*);
|
||||||
|
int time(int*);
|
||||||
|
tm *localtime(int*);
|
||||||
|
}
|
305
linux.mak
Normal file
305
linux.mak
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
# Makefile to build linux D runtime library libphobos.a.
|
||||||
|
# Targets:
|
||||||
|
# make
|
||||||
|
# Same as make unittest
|
||||||
|
# make libphobos.a
|
||||||
|
# Build libphobos.a
|
||||||
|
# make clean
|
||||||
|
# Delete unneeded files created by build process
|
||||||
|
# make unittest
|
||||||
|
# Build libphobos.a, build and run unit tests
|
||||||
|
|
||||||
|
CFLAGS=-O
|
||||||
|
#CFLAGS=-g
|
||||||
|
DFLAGS=-O -release
|
||||||
|
#DFLAGS=-unittest
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
#DMD=/dmd/bin/dmd
|
||||||
|
DMD=../dmd
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) $*.c
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
g++ -c $(CFLAGS) $*.cpp
|
||||||
|
|
||||||
|
.d.o:
|
||||||
|
$(DMD) -c $(DFLAGS) $*.d
|
||||||
|
|
||||||
|
.asm.o:
|
||||||
|
$(CC) -c $*.asm
|
||||||
|
|
||||||
|
targets : unittest
|
||||||
|
|
||||||
|
test.o : test.d
|
||||||
|
$(DMD) -c test -g
|
||||||
|
|
||||||
|
test : test.o libphobos.a
|
||||||
|
$(CC) -o $@ test.o libphobos.a -g
|
||||||
|
|
||||||
|
unittest : unittest.o libphobos.a
|
||||||
|
$(CC) -o $@ unittest.o libphobos.a -lpthread -lm -g
|
||||||
|
|
||||||
|
unittest.o : unittest.d
|
||||||
|
$(DMD) -c unittest
|
||||||
|
|
||||||
|
OBJS= assert.o deh2.o switch.o complex.o gcstats.o \
|
||||||
|
critical.o object.o monitor.o arraycat.o invariant.o \
|
||||||
|
dmain2.o outofmemory.o achar.o aaA.o adi.o file.o \
|
||||||
|
compiler.o system.o moduleinit.o \
|
||||||
|
cast.o syserror.o path.o string.o memset.o math.o \
|
||||||
|
outbuffer.o ctype.o regexp.o random.o linux.o \
|
||||||
|
stream.o switcherr.o array.o gc.o adi.o \
|
||||||
|
qsort.o thread.o obj.o \
|
||||||
|
crc32.o conv.o arraycast.o errno.o alloca.o cmath.o \
|
||||||
|
ti_Aa.o ti_Ag.o ti_C.o ti_int.o ti_char.o \
|
||||||
|
ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \
|
||||||
|
ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \
|
||||||
|
ti_float.o ti_double.o ti_real.o ti_delegate.o \
|
||||||
|
date.o dateparse.o llmath.o math2.o \
|
||||||
|
ti_creal.o ti_ireal.o \
|
||||||
|
ti_cfloat.o ti_ifloat.o \
|
||||||
|
ti_cdouble.o ti_idouble.o
|
||||||
|
|
||||||
|
HDR=mars.h
|
||||||
|
|
||||||
|
SRC= mars.h switch.d complex.c critical.c minit.asm \
|
||||||
|
deh.c object.d gc.d math.d c/stdio.d c/stdlib.d time.d monitor.c \
|
||||||
|
arraycat.d string.d windows.d path.d linuxextern.d \
|
||||||
|
invariant.d assert.d regexp.d dmain2.d dateparse.d \
|
||||||
|
outofmemory.d syserror.d \
|
||||||
|
ctype.d achar.d aaA.d adi.d file.d compiler.d system.d \
|
||||||
|
moduleinit.d cast.d math.d qsort.d \
|
||||||
|
outbuffer.d unittest.d stream.d ctype.d random.d adi.d \
|
||||||
|
math2.d thread.d obj.d iunknown.d intrinsic.d time.d memset.d \
|
||||||
|
array.d switcherr.d arraycast.d errno.c alloca.d cmath.d \
|
||||||
|
ti_wchar.d ti_uint.d ti_short.d ti_ushort.d \
|
||||||
|
ti_byte.d ti_ubyte.d ti_long.d ti_ulong.d ti_ptr.d \
|
||||||
|
ti_float.d ti_double.d ti_real.d ti_delegate.d \
|
||||||
|
ti_creal.d ti_ireal.d ti_cfloat.d ti_ifloat.d \
|
||||||
|
ti_cdouble.d ti_idouble.d \
|
||||||
|
ti_Aa.d ti_Ag.d ti_C.d ti_int.d ti_char.d \
|
||||||
|
crc32.d stdint.d conv.d gcstats.d linux.d deh2.d date.d llmath.d \
|
||||||
|
win32.mak linux.mak
|
||||||
|
|
||||||
|
libphobos.a : $(OBJS) gc2/dmgc.a linux.mak
|
||||||
|
ar -r $@ $(OBJS) gc2/gc.o gc2/gcx.o gc2/gcbits.o gc2/gclinux.o
|
||||||
|
|
||||||
|
aaA.o : aaA.d
|
||||||
|
$(DMD) -c $(DFLAGS) aaA.d
|
||||||
|
|
||||||
|
achar.o : achar.d
|
||||||
|
$(DMD) -c $(DFLAGS) achar.d
|
||||||
|
|
||||||
|
adi.o : adi.d
|
||||||
|
$(DMD) -c $(DFLAGS) adi.d
|
||||||
|
|
||||||
|
alloca.o : alloca.d
|
||||||
|
$(DMD) -c $(DFLAGS) alloca.d
|
||||||
|
|
||||||
|
array.o : array.d
|
||||||
|
$(DMD) -c $(DFLAGS) array.d
|
||||||
|
|
||||||
|
arraycast.o : arraycast.d
|
||||||
|
$(DMD) -c $(DFLAGS) arraycast.d
|
||||||
|
|
||||||
|
arraycat.o : arraycat.d
|
||||||
|
$(DMD) -c $(DFLAGS) arraycat.d
|
||||||
|
|
||||||
|
assert.o : assert.d
|
||||||
|
$(DMD) -c $(DFLAGS) assert.d
|
||||||
|
|
||||||
|
cast.o : cast.d
|
||||||
|
$(DMD) -c $(DFLAGS) cast.d
|
||||||
|
|
||||||
|
cmath.o : cmath.d
|
||||||
|
$(DMD) -c $(DFLAGS) cmath.d
|
||||||
|
|
||||||
|
compiler.o : compiler.d
|
||||||
|
$(DMD) -c $(DFLAGS) compiler.d
|
||||||
|
|
||||||
|
complex.o : mars.h complex.c
|
||||||
|
|
||||||
|
conv.o : conv.d
|
||||||
|
$(DMD) -c $(DFLAGS) conv.d
|
||||||
|
|
||||||
|
crc32.o : crc32.d
|
||||||
|
$(DMD) -c $(DFLAGS) crc32.d
|
||||||
|
|
||||||
|
critical.o : mars.h critical.c
|
||||||
|
|
||||||
|
ctype.o : ctype.d
|
||||||
|
$(DMD) -c $(DFLAGS) ctype.d
|
||||||
|
|
||||||
|
dassert.o : mars.h dassert.c
|
||||||
|
|
||||||
|
date.o : dateparse.d date.d
|
||||||
|
$(DMD) -c $(DFLAGS) date.d
|
||||||
|
|
||||||
|
dateparse.o : dateparse.d date.d
|
||||||
|
$(DMD) -c $(DFLAGS) dateparse.d
|
||||||
|
|
||||||
|
deh2.o : deh2.d
|
||||||
|
$(DMD) -c $(DFLAGS) deh2.d
|
||||||
|
|
||||||
|
dmain2.o : dmain2.d
|
||||||
|
$(DMD) -c $(DFLAGS) dmain2.d
|
||||||
|
|
||||||
|
errno.o : errno.c
|
||||||
|
|
||||||
|
file.o : file.d
|
||||||
|
$(DMD) -c $(DFLAGS) file.d
|
||||||
|
|
||||||
|
gc.o : gc.d
|
||||||
|
$(DMD) -c $(DFLAGS) gc.d
|
||||||
|
|
||||||
|
gcstats.o : gcstats.d
|
||||||
|
$(DMD) -c $(DFLAGS) gcstats.d
|
||||||
|
|
||||||
|
invariant.o : invariant.d
|
||||||
|
$(DMD) -c $(DFLAGS) invariant.d
|
||||||
|
|
||||||
|
linux.o : linux.d
|
||||||
|
$(DMD) -c $(DFLAGS) linux.d
|
||||||
|
|
||||||
|
llmath.o : llmath.d
|
||||||
|
$(DMD) -c $(DFLAGS) llmath.d
|
||||||
|
|
||||||
|
math.o : math.d
|
||||||
|
$(DMD) -c $(DFLAGS) math.d
|
||||||
|
|
||||||
|
math2.o : math2.d
|
||||||
|
$(DMD) -c $(DFLAGS) math2.d
|
||||||
|
|
||||||
|
memset.o : memset.d
|
||||||
|
$(DMD) -c $(DFLAGS) memset.d
|
||||||
|
|
||||||
|
moduleinit.o : moduleinit.d
|
||||||
|
$(DMD) -c $(DFLAGS) moduleinit.d
|
||||||
|
|
||||||
|
monitor.o : mars.h monitor.c
|
||||||
|
|
||||||
|
obj.o : obj.d
|
||||||
|
$(DMD) -c $(DFLAGS) obj.d
|
||||||
|
|
||||||
|
object.o : object.d
|
||||||
|
$(DMD) -c $(DFLAGS) object.d
|
||||||
|
|
||||||
|
outbuffer.o : outbuffer.d
|
||||||
|
$(DMD) -c $(DFLAGS) outbuffer.d
|
||||||
|
|
||||||
|
outofmemory.o : outofmemory.d
|
||||||
|
$(DMD) -c $(DFLAGS) outofmemory.d
|
||||||
|
|
||||||
|
path.o : path.d
|
||||||
|
$(DMD) -c $(DFLAGS) path.d
|
||||||
|
|
||||||
|
qsort.o : qsort.d
|
||||||
|
$(DMD) -c $(DFLAGS) qsort.d
|
||||||
|
|
||||||
|
random.o : random.d
|
||||||
|
$(DMD) -c $(DFLAGS) random.d
|
||||||
|
|
||||||
|
regexp.o : regexp.d
|
||||||
|
$(DMD) -c $(DFLAGS) regexp.d
|
||||||
|
|
||||||
|
stream.o : stream.d
|
||||||
|
$(DMD) -c $(DFLAGS) stream.d
|
||||||
|
|
||||||
|
string.o : string.d
|
||||||
|
$(DMD) -c $(DFLAGS) string.d
|
||||||
|
|
||||||
|
switch.o : switch.d
|
||||||
|
$(DMD) -c $(DFLAGS) switch.d
|
||||||
|
|
||||||
|
switcherr.o : switcherr.d
|
||||||
|
$(DMD) -c $(DFLAGS) switcherr.d
|
||||||
|
|
||||||
|
syserror.o : syserror.d
|
||||||
|
$(DMD) -c $(DFLAGS) syserror.d
|
||||||
|
|
||||||
|
system.o : system.d
|
||||||
|
$(DMD) -c $(DFLAGS) system.d
|
||||||
|
|
||||||
|
thread.o : thread.d
|
||||||
|
$(DMD) -c $(DFLAGS) thread.d
|
||||||
|
|
||||||
|
ti_wchar.o : ti_wchar.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_wchar.d
|
||||||
|
|
||||||
|
ti_uint.o : ti_uint.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_uint.d
|
||||||
|
|
||||||
|
ti_short.o : ti_short.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_short.d
|
||||||
|
|
||||||
|
ti_ushort.o : ti_ushort.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_ushort.d
|
||||||
|
|
||||||
|
ti_byte.o : ti_byte.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_byte.d
|
||||||
|
|
||||||
|
ti_ubyte.o : ti_ubyte.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_ubyte.d
|
||||||
|
|
||||||
|
ti_long.o : ti_long.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_long.d
|
||||||
|
|
||||||
|
ti_ulong.o : ti_ulong.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_ulong.d
|
||||||
|
|
||||||
|
ti_ptr.o : ti_ptr.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_ptr.d
|
||||||
|
|
||||||
|
ti_float.o : ti_float.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_float.d
|
||||||
|
|
||||||
|
ti_double.o : ti_double.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_double.d
|
||||||
|
|
||||||
|
ti_real.o : ti_real.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_real.d
|
||||||
|
|
||||||
|
ti_delegate.o : ti_delegate.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_delegate.d
|
||||||
|
|
||||||
|
ti_creal.o : ti_creal.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_creal.d
|
||||||
|
|
||||||
|
ti_ireal.o : ti_ireal.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_ireal.d
|
||||||
|
|
||||||
|
ti_cfloat.o : ti_cfloat.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_cfloat.d
|
||||||
|
|
||||||
|
ti_ifloat.o : ti_ifloat.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_ifloat.d
|
||||||
|
|
||||||
|
ti_cdouble.o : ti_cdouble.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_cdouble.d
|
||||||
|
|
||||||
|
ti_idouble.o : ti_idouble.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_idouble.d
|
||||||
|
|
||||||
|
ti_Aa.o : ti_Aa.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_Aa.d
|
||||||
|
|
||||||
|
ti_Ag.o : ti_Ag.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_Ag.d
|
||||||
|
|
||||||
|
ti_C.o : ti_C.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_C.d
|
||||||
|
|
||||||
|
ti_char.o : ti_char.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_char.d
|
||||||
|
|
||||||
|
ti_int.o : ti_int.d
|
||||||
|
$(DMD) -c $(DFLAGS) ti_int.d
|
||||||
|
|
||||||
|
zip : $(SRC)
|
||||||
|
rm phobos.zip
|
||||||
|
zip phobos $(SRC)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm $(OBJS)
|
20
linuxextern.d
Normal file
20
linuxextern.d
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
// Copyright (C) 2003 by Digital Mars, www.digitalmars.com
|
||||||
|
// All Rights Reserved
|
||||||
|
// Written by Walter Bright
|
||||||
|
|
||||||
|
/* These are all the globals defined by the linux C runtime library.
|
||||||
|
* Put them separate so they'll be externed - do not link in linuxextern.o
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern (C)
|
||||||
|
{
|
||||||
|
void* __libc_stack_end;
|
||||||
|
int __data_start;
|
||||||
|
int _end;
|
||||||
|
int timezone;
|
||||||
|
|
||||||
|
void *_deh_beg;
|
||||||
|
void *_deh_end;
|
||||||
|
}
|
||||||
|
|
224
llmath.d
Normal file
224
llmath.d
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
// llmath.d
|
||||||
|
// Copyright (C) 1993-2003 by Digital Mars, www.digitalmars.com
|
||||||
|
// All Rights Reserved
|
||||||
|
// Written by Walter Bright
|
||||||
|
|
||||||
|
// Compiler runtime support for 64 bit longs
|
||||||
|
|
||||||
|
extern (C):
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* Unsigned long divide.
|
||||||
|
* Input:
|
||||||
|
* [EDX,EAX],[ECX,EBX]
|
||||||
|
* Output:
|
||||||
|
* [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
|
||||||
|
* [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
|
||||||
|
* ESI,EDI destroyed
|
||||||
|
*/
|
||||||
|
|
||||||
|
void __ULDIV__()
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
naked ;
|
||||||
|
test ECX,ECX ;
|
||||||
|
jz uldiv ;
|
||||||
|
|
||||||
|
push EBP ;
|
||||||
|
|
||||||
|
// left justify [ECX,EBX] and leave count of shifts + 1 in EBP
|
||||||
|
|
||||||
|
mov EBP,1 ; // at least 1 shift
|
||||||
|
test ECX,ECX ; // left justified?
|
||||||
|
js L1 ; // yes
|
||||||
|
jnz L2 ;
|
||||||
|
add EBP,8 ;
|
||||||
|
mov CH,CL ;
|
||||||
|
mov CL,BH ;
|
||||||
|
mov BH,BL ;
|
||||||
|
xor BL,BL ; // [ECX,EBX] <<= 8
|
||||||
|
test ECX,ECX ;
|
||||||
|
js L1 ;
|
||||||
|
even ;
|
||||||
|
L2: inc EBP ; // another shift
|
||||||
|
shl EBX,1 ;
|
||||||
|
rcl ECX,1 ; // [ECX,EBX] <<= 1
|
||||||
|
jno L2 ; // not left justified yet
|
||||||
|
|
||||||
|
L1: mov ESI,ECX ;
|
||||||
|
mov EDI,EBX ; // [ESI,EDI] = divisor
|
||||||
|
|
||||||
|
mov ECX,EDX ;
|
||||||
|
mov EBX,EAX ; // [ECX,EBX] = [EDX,EAX]
|
||||||
|
xor EAX,EAX ;
|
||||||
|
cwd ; // [EDX,EAX] = 0
|
||||||
|
even ;
|
||||||
|
L4: cmp ESI,ECX ; // is [ECX,EBX] > [ESI,EDI]?
|
||||||
|
ja L3 ; // yes
|
||||||
|
jb L5 ; // definitely less than
|
||||||
|
cmp EDI,EBX ; // check low order word
|
||||||
|
ja L3 ;
|
||||||
|
L5: sub EBX,EDI ;
|
||||||
|
sbb ECX,ESI ; // [ECX,EBX] -= [ESI,EDI]
|
||||||
|
stc ; // rotate in a 1
|
||||||
|
L3: rcl EAX,1 ;
|
||||||
|
rcl EDX,1 ; // [EDX,EAX] = ([EDX,EAX] << 1) + C
|
||||||
|
shr ESI,1 ;
|
||||||
|
rcr EDI,1 ; // [ESI,EDI] >>= 1
|
||||||
|
dec EBP ; // control count
|
||||||
|
jne L4 ;
|
||||||
|
pop EBP ;
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
div0: mov EAX,-1 ;
|
||||||
|
cwd ; // quotient is -1
|
||||||
|
// xor ECX,ECX ;
|
||||||
|
// mov EBX,ECX ; // remainder is 0 (ECX and EBX already 0)
|
||||||
|
pop EBP ;
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
uldiv: test EDX,EDX ;
|
||||||
|
jnz D3 ;
|
||||||
|
// Both high words are 0, we can use the DIV instruction
|
||||||
|
div EBX ;
|
||||||
|
mov EBX,EDX ;
|
||||||
|
mov EDX,ECX ; // EDX = ECX = 0
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
even ;
|
||||||
|
D3: // Divide [EDX,EAX] by EBX
|
||||||
|
mov ECX,EAX ;
|
||||||
|
mov EAX,EDX ;
|
||||||
|
xor EDX,EDX ;
|
||||||
|
div EBX ;
|
||||||
|
xchg ECX,EAX ;
|
||||||
|
div EBX ;
|
||||||
|
// ECX,EAX = result
|
||||||
|
// EDX = remainder
|
||||||
|
mov EBX,EDX ;
|
||||||
|
mov EDX,ECX ;
|
||||||
|
xor ECX,ECX ;
|
||||||
|
ret ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* Signed long divide.
|
||||||
|
* Input:
|
||||||
|
* [EDX,EAX],[ECX,EBX]
|
||||||
|
* Output:
|
||||||
|
* [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
|
||||||
|
* [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
|
||||||
|
* ESI,EDI destroyed
|
||||||
|
*/
|
||||||
|
|
||||||
|
void __LDIV__()
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
naked ;
|
||||||
|
test EDX,EDX ; // [EDX,EAX] negative?
|
||||||
|
jns L10 ; // no
|
||||||
|
//neg64 EDX,EAX ; // [EDX,EAX] = -[EDX,EAX]
|
||||||
|
neg EDX ;
|
||||||
|
neg EAX ;
|
||||||
|
sbb EDX,0 ;
|
||||||
|
test ECX,ECX ; // [ECX,EBX] negative?
|
||||||
|
jns L11 ; // no
|
||||||
|
//neg64 ECX,EBX ;
|
||||||
|
neg ECX ;
|
||||||
|
neg EBX ;
|
||||||
|
sbb ECX,0 ;
|
||||||
|
call __ULDIV__ ;
|
||||||
|
//neg64 ECX,EBX ; // remainder same sign as dividend
|
||||||
|
neg ECX ;
|
||||||
|
neg EBX ;
|
||||||
|
sbb ECX,0 ;
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
L11: call __ULDIV__ ;
|
||||||
|
//neg64 ECX,EBX ; // remainder same sign as dividend
|
||||||
|
neg ECX ;
|
||||||
|
neg EBX ;
|
||||||
|
sbb ECX,0 ;
|
||||||
|
//neg64 EDX,EAX ; // quotient is negative
|
||||||
|
neg EDX ;
|
||||||
|
neg EAX ;
|
||||||
|
sbb EDX,0 ;
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
L10: test ECX,ECX ; // [ECX,EBX] negative?
|
||||||
|
jns L12 ; // no (all is positive)
|
||||||
|
//neg64 ECX,EBX ;
|
||||||
|
neg ECX ;
|
||||||
|
neg EBX ;
|
||||||
|
sbb ECX,0 ;
|
||||||
|
call __ULDIV__ ;
|
||||||
|
//neg64 EDX,EAX ; // quotient is negative
|
||||||
|
neg EDX ;
|
||||||
|
neg EAX ;
|
||||||
|
sbb EDX,0 ;
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
L12: jmp __ULDIV__ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* Compare [EDX,EAX] with [ECX,EBX]
|
||||||
|
* Signed
|
||||||
|
* Returns result in flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
void __LCMP__()
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
naked ;
|
||||||
|
cmp EDX,ECX ;
|
||||||
|
jne C1 ;
|
||||||
|
push EDX ;
|
||||||
|
xor EDX,EDX ;
|
||||||
|
cmp EAX,EBX ;
|
||||||
|
jz C2 ;
|
||||||
|
ja C3 ;
|
||||||
|
dec EDX ;
|
||||||
|
pop EDX ;
|
||||||
|
ret ;
|
||||||
|
|
||||||
|
C3: inc EDX ;
|
||||||
|
C2: pop EDX ;
|
||||||
|
C1: ret ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Convert ulong to real
|
||||||
|
|
||||||
|
private real adjust = cast(real)0x800000000000000 * 0x10;
|
||||||
|
|
||||||
|
real __U64_LDBL()
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{ naked ;
|
||||||
|
push EDX ;
|
||||||
|
push EAX ;
|
||||||
|
and dword ptr 4[ESP], 0x7FFFFFFF ;
|
||||||
|
fild qword ptr [ESP] ;
|
||||||
|
test EDX,EDX ;
|
||||||
|
jns L1 ;
|
||||||
|
fld real ptr adjust ;
|
||||||
|
faddp ST(1), ST ;
|
||||||
|
L1: ;
|
||||||
|
add ESP, 8 ;
|
||||||
|
ret ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
9
math2.d
9
math2.d
|
@ -1319,6 +1319,7 @@ unittest
|
||||||
|
|
||||||
char[] toString(real x)
|
char[] toString(real x)
|
||||||
{
|
{
|
||||||
|
// BUG: this code is broken, returning a pointer into the stack
|
||||||
char[1024] buffer;
|
char[1024] buffer;
|
||||||
char* p = buffer;
|
char* p = buffer;
|
||||||
uint psize = buffer.length;
|
uint psize = buffer.length;
|
||||||
|
@ -1331,6 +1332,7 @@ char[] toString(real x)
|
||||||
if (count != -1)
|
if (count != -1)
|
||||||
break;
|
break;
|
||||||
psize *= 2;
|
psize *= 2;
|
||||||
|
p = cast(char*) alloca(psize);
|
||||||
}
|
}
|
||||||
else version(linux)
|
else version(linux)
|
||||||
{
|
{
|
||||||
|
@ -1341,8 +1343,13 @@ char[] toString(real x)
|
||||||
psize = count + 1;
|
psize = count + 1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
/+
|
||||||
|
if (p != buffer)
|
||||||
|
c.stdlib.free(p);
|
||||||
|
p = cast(char*) c.stdlib.malloc(psize);
|
||||||
|
+/
|
||||||
|
p = cast(char*) alloca(psize);
|
||||||
}
|
}
|
||||||
p = cast(char*) alloca(psize);
|
|
||||||
}
|
}
|
||||||
return p[0 .. count];
|
return p[0 .. count];
|
||||||
}
|
}
|
||||||
|
|
62
moduleinit.d
62
moduleinit.d
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
//debug = 1;
|
||||||
|
|
||||||
import object;
|
import object;
|
||||||
import c.stdio;
|
import c.stdio;
|
||||||
import c.stdlib;
|
import c.stdlib;
|
||||||
|
@ -6,7 +8,7 @@ import string;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{ MIctorstart = 1, // we've started constructing it
|
{ MIctorstart = 1, // we've started constructing it
|
||||||
MIctordone = 2, // finished construction
|
MIctordone = 2, // finished construction
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModuleInfo
|
class ModuleInfo
|
||||||
|
@ -30,9 +32,24 @@ class ModuleCtorError : Exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This gets initialized by minit.asm
|
|
||||||
|
// Win32: this gets initialized by minit.asm
|
||||||
|
// linux: this gets initialized in _moduleCtor()
|
||||||
extern (C) ModuleInfo[] _moduleinfo_array;
|
extern (C) ModuleInfo[] _moduleinfo_array;
|
||||||
|
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
// This linked list is created by a compiler generated function inserted
|
||||||
|
// into the .ctor list by the compiler.
|
||||||
|
struct ModuleReference
|
||||||
|
{
|
||||||
|
ModuleReference* next;
|
||||||
|
ModuleInfo mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern (C) ModuleReference *_Dmodule_ref; // start of linked list
|
||||||
|
}
|
||||||
|
|
||||||
ModuleInfo[] _moduleinfo_dtors;
|
ModuleInfo[] _moduleinfo_dtors;
|
||||||
uint _moduleinfo_dtors_i;
|
uint _moduleinfo_dtors_i;
|
||||||
|
|
||||||
|
@ -45,23 +62,43 @@ extern (C) int _fatexit(void *);
|
||||||
|
|
||||||
extern (C) void _moduleCtor()
|
extern (C) void _moduleCtor()
|
||||||
{
|
{
|
||||||
// Ensure module destructors also get called on program termination
|
version (linux)
|
||||||
_fatexit(&_moduleDtor);
|
{
|
||||||
|
int length = 0;
|
||||||
|
ModuleReference *mr;
|
||||||
|
|
||||||
|
for (mr = _Dmodule_ref; mr; mr = mr.next)
|
||||||
|
length++;
|
||||||
|
_moduleinfo_array = new ModuleInfo[length];
|
||||||
|
length = 0;
|
||||||
|
for (mr = _Dmodule_ref; mr; mr = mr.next)
|
||||||
|
{ _moduleinfo_array[length] = mr.mod;
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
// Ensure module destructors also get called on program termination
|
||||||
|
//_fatexit(&_STD_moduleDtor);
|
||||||
|
}
|
||||||
|
|
||||||
_moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
|
_moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
|
||||||
|
//printf("_moduleinfo_dtors = x%x\n", (void *)_moduleinfo_dtors);
|
||||||
_moduleCtor2(_moduleinfo_array, 0);
|
_moduleCtor2(_moduleinfo_array, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _moduleCtor2(ModuleInfo[] mi, int skip)
|
void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||||
{
|
{
|
||||||
//printf("_moduleCtor2(): %d modules\n", mi.length);
|
debug printf("_moduleCtor2(): %d modules\n", mi.length);
|
||||||
for (uint i = 0; i < mi.length; i++)
|
for (uint i = 0; i < mi.length; i++)
|
||||||
{
|
{
|
||||||
ModuleInfo m = mi[i];
|
ModuleInfo m = mi[i];
|
||||||
|
|
||||||
|
// debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
||||||
if (m.flags & MIctordone)
|
if (m.flags & MIctordone)
|
||||||
continue;
|
continue;
|
||||||
//printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
debug printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
|
||||||
|
|
||||||
if (m.ctor || m.dtor)
|
if (m.ctor || m.dtor)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +116,7 @@ void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||||
m.flags |= MIctordone;
|
m.flags |= MIctordone;
|
||||||
|
|
||||||
// Now that construction is done, register the destructor
|
// Now that construction is done, register the destructor
|
||||||
|
//printf("\tadding module dtor x%x\n", m);
|
||||||
assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
|
assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
|
||||||
_moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
|
_moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
|
||||||
}
|
}
|
||||||
|
@ -95,19 +133,23 @@ void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||||
* Destruct the modules.
|
* Destruct the modules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Starting the name with "_STD" means under linux a pointer to the
|
||||||
|
// function gets put in the .dtors segment.
|
||||||
|
|
||||||
extern (C) void _moduleDtor()
|
extern (C) void _moduleDtor()
|
||||||
{
|
{
|
||||||
//printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors.length);
|
debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
|
||||||
for (uint i = _moduleinfo_dtors_i; i-- != 0;)
|
for (uint i = _moduleinfo_dtors_i; i-- != 0;)
|
||||||
{
|
{
|
||||||
ModuleInfo m = _moduleinfo_dtors[i];
|
ModuleInfo m = _moduleinfo_dtors[i];
|
||||||
|
|
||||||
//printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
|
||||||
if (m.dtor)
|
if (m.dtor)
|
||||||
{
|
{
|
||||||
(*m.dtor)();
|
(*m.dtor)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debug printf("_moduleDtor() done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
|
@ -116,12 +158,12 @@ extern (C) void _moduleDtor()
|
||||||
|
|
||||||
extern (C) void _moduleUnitTests()
|
extern (C) void _moduleUnitTests()
|
||||||
{
|
{
|
||||||
//printf("_moduleUnitTests()\n");
|
debug printf("_moduleUnitTests()\n");
|
||||||
for (uint i = 0; i < _moduleinfo_array.length; i++)
|
for (uint i = 0; i < _moduleinfo_array.length; i++)
|
||||||
{
|
{
|
||||||
ModuleInfo m = _moduleinfo_array[i];
|
ModuleInfo m = _moduleinfo_array[i];
|
||||||
|
|
||||||
//printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
||||||
if (m.unitTest)
|
if (m.unitTest)
|
||||||
{
|
{
|
||||||
(*m.unitTest)();
|
(*m.unitTest)();
|
||||||
|
|
86
monitor.c
86
monitor.c
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
// Copyright (c) 2000-2002 by Digital Mars
|
// Copyright (c) 2000-2003 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
|
@ -10,6 +10,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
/* =============================== Win32 ============================ */
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
|
@ -79,3 +84,82 @@ void _d_monitorrelease(Object *h)
|
||||||
h->monitor = 0;
|
h->monitor = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* =============================== linux ============================ */
|
||||||
|
|
||||||
|
#if linux
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "mars.h"
|
||||||
|
|
||||||
|
static pthread_mutex_t _monitor_critsec;
|
||||||
|
static volatile int inited;
|
||||||
|
|
||||||
|
void _STI_monitor_staticctor()
|
||||||
|
{
|
||||||
|
if (!inited)
|
||||||
|
{ pthread_mutex_init(&_monitor_critsec, 0);
|
||||||
|
inited = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _STD_monitor_staticdtor()
|
||||||
|
{
|
||||||
|
if (inited)
|
||||||
|
{ inited = 0;
|
||||||
|
pthread_mutex_destroy(&_monitor_critsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _d_monitorenter(Object *h)
|
||||||
|
{
|
||||||
|
//printf("_d_monitorenter(%p), %p\n", h, h->monitor);
|
||||||
|
if (!h->monitor)
|
||||||
|
{ pthread_mutex_t *cs;
|
||||||
|
|
||||||
|
cs = (pthread_mutex_t *)calloc(sizeof(pthread_mutex_t), 1);
|
||||||
|
assert(cs);
|
||||||
|
pthread_mutex_lock(&_monitor_critsec);
|
||||||
|
if (!h->monitor) // if, in the meantime, another thread didn't set it
|
||||||
|
{
|
||||||
|
h->monitor = (unsigned)cs;
|
||||||
|
pthread_mutex_init(cs, 0);
|
||||||
|
cs = NULL;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&_monitor_critsec);
|
||||||
|
if (cs) // if we didn't use it
|
||||||
|
free(cs);
|
||||||
|
}
|
||||||
|
//printf("-_d_monitorenter(%p)\n", h);
|
||||||
|
pthread_mutex_lock((pthread_mutex_t *)h->monitor);
|
||||||
|
//printf("-_d_monitorenter(%p)\n", h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _d_monitorexit(Object *h)
|
||||||
|
{
|
||||||
|
//printf("+_d_monitorexit(%p)\n", h);
|
||||||
|
assert(h->monitor);
|
||||||
|
pthread_mutex_unlock((pthread_mutex_t *)h->monitor);
|
||||||
|
//printf("-_d_monitorexit(%p)\n", h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* Called by garbage collector when Object is free'd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _d_monitorrelease(Object *h)
|
||||||
|
{
|
||||||
|
if (h->monitor)
|
||||||
|
{ pthread_mutex_destroy((pthread_mutex_t *)h->monitor);
|
||||||
|
|
||||||
|
// We can improve this by making a free list of monitors
|
||||||
|
free((void *)h->monitor);
|
||||||
|
|
||||||
|
h->monitor = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
15
outbuffer.d
15
outbuffer.d
|
@ -217,6 +217,7 @@ class OutBuffer
|
||||||
if (count != -1)
|
if (count != -1)
|
||||||
break;
|
break;
|
||||||
psize *= 2;
|
psize *= 2;
|
||||||
|
p = (char *) alloca(psize); // buffer too small, try again with larger size
|
||||||
}
|
}
|
||||||
version(linux)
|
version(linux)
|
||||||
{
|
{
|
||||||
|
@ -227,10 +228,22 @@ class OutBuffer
|
||||||
psize = count + 1;
|
psize = count + 1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
/+
|
||||||
|
if (p != buffer)
|
||||||
|
c.stdlib.free(p);
|
||||||
|
p = (char *) c.stdlib.malloc(psize); // buffer too small, try again with larger size
|
||||||
|
+/
|
||||||
|
p = (char *) alloca(psize); // buffer too small, try again with larger size
|
||||||
}
|
}
|
||||||
p = (char *) alloca(psize); // buffer too small, try again with larger size
|
|
||||||
}
|
}
|
||||||
write(p[0 .. count]);
|
write(p[0 .. count]);
|
||||||
|
/+
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
if (p != buffer)
|
||||||
|
c.stdlib.free(p);
|
||||||
|
}
|
||||||
|
+/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************
|
/*****************************************
|
||||||
|
|
|
@ -10,7 +10,7 @@ class OutOfMemory : Object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern (C) static void _d_OutOfMemory()
|
extern (C) void _d_OutOfMemory()
|
||||||
{
|
{
|
||||||
throw (OutOfMemory)(void *)OutOfMemory.classinfo.init;
|
throw (OutOfMemory)(void *)OutOfMemory.classinfo.init;
|
||||||
}
|
}
|
||||||
|
|
90
path.d
90
path.d
|
@ -68,19 +68,32 @@ unittest
|
||||||
int i;
|
int i;
|
||||||
char[] result;
|
char[] result;
|
||||||
|
|
||||||
result = getExt('d:\path\foo.bat');
|
version (Win32)
|
||||||
|
result = getExt('d:\path\foo.bat');
|
||||||
|
version (linux)
|
||||||
|
result = getExt('/path/foo.bat');
|
||||||
i = cmp(result, "bat");
|
i = cmp(result, "bat");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
result = getExt('d:\path\foo.');
|
version (Win32)
|
||||||
|
result = getExt('d:\path\foo.');
|
||||||
|
version (linux)
|
||||||
|
result = getExt('d/path/foo.');
|
||||||
i = cmp(result, "");
|
i = cmp(result, "");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
result = getExt('d:\path\foo');
|
version (Win32)
|
||||||
|
result = getExt('d:\path\foo');
|
||||||
|
version (linux)
|
||||||
|
result = getExt('d/path/foo');
|
||||||
i = cmp(result, "");
|
i = cmp(result, "");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
result = getExt('d:\path.bar\foo');
|
version (Win32)
|
||||||
|
result = getExt('d:\path.bar\foo');
|
||||||
|
version (linux)
|
||||||
|
result = getExt('/path.bar/foo');
|
||||||
|
|
||||||
i = cmp(result, "");
|
i = cmp(result, "");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
|
@ -125,12 +138,18 @@ unittest
|
||||||
int i;
|
int i;
|
||||||
char[] result;
|
char[] result;
|
||||||
|
|
||||||
result = getBaseName('d:\path\foo.bat');
|
version (Win32)
|
||||||
|
result = getBaseName('d:\path\foo.bat');
|
||||||
|
version (linux)
|
||||||
|
result = getBaseName('/path/foo.bat');
|
||||||
//printf("result = '%.*s'\n", result);
|
//printf("result = '%.*s'\n", result);
|
||||||
i = cmp(result, "foo.bat");
|
i = cmp(result, "foo.bat");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
result = getBaseName('a\b');
|
version (Win32)
|
||||||
|
result = getBaseName('a\b');
|
||||||
|
version (linux)
|
||||||
|
result = getBaseName('a/b');
|
||||||
i = cmp(result, "b");
|
i = cmp(result, "b");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
}
|
}
|
||||||
|
@ -332,19 +351,40 @@ unittest
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p = join("foo", "bar");
|
p = join("foo", "bar");
|
||||||
i = cmp(p, 'foo\bar');
|
version (Win32)
|
||||||
|
i = cmp(p, 'foo\bar');
|
||||||
|
version (linux)
|
||||||
|
i = cmp(p, 'foo/bar');
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
p = join('foo\', 'bar');
|
version (Win32)
|
||||||
i = cmp(p, 'foo\bar');
|
{ p = join('foo\', 'bar');
|
||||||
|
i = cmp(p, 'foo\bar');
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{ p = join('foo/', 'bar');
|
||||||
|
i = cmp(p, 'foo/bar');
|
||||||
|
}
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
p = join('foo', '\bar');
|
version (Win32)
|
||||||
i = cmp(p, '\bar');
|
{ p = join('foo', '\bar');
|
||||||
|
i = cmp(p, '\bar');
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{ p = join('foo', '/bar');
|
||||||
|
i = cmp(p, '/bar');
|
||||||
|
}
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
p = join('foo\', '\bar');
|
version (Win32)
|
||||||
i = cmp(p, '\bar');
|
{ p = join('foo\', '\bar');
|
||||||
|
i = cmp(p, '\bar');
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{ p = join('foo/', '/bar');
|
||||||
|
i = cmp(p, '/bar');
|
||||||
|
}
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
version(Win32)
|
version(Win32)
|
||||||
|
@ -391,15 +431,22 @@ unittest
|
||||||
|
|
||||||
int fncharmatch(char c1, char c2)
|
int fncharmatch(char c1, char c2)
|
||||||
{
|
{
|
||||||
if (c1 != c2)
|
version (Win32)
|
||||||
|
{
|
||||||
|
if (c1 != c2)
|
||||||
|
{
|
||||||
|
if ('A' <= c1 && c1 <= 'Z')
|
||||||
|
c1 += cast(char)'a' - 'A';
|
||||||
|
if ('A' <= c2 && c2 <= 'Z')
|
||||||
|
c2 += cast(char)'a' - 'A';
|
||||||
|
return c1 == c2;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
{
|
{
|
||||||
if ('A' <= c1 && c1 <= 'Z')
|
|
||||||
c1 += cast(char)'a' - 'A';
|
|
||||||
if ('A' <= c2 && c2 <= 'Z')
|
|
||||||
c2 += cast(char)'a' - 'A';
|
|
||||||
return c1 == c2;
|
return c1 == c2;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
|
@ -523,7 +570,10 @@ unittest
|
||||||
{
|
{
|
||||||
debug(path) printf("path.fnmatch.unittest\n");
|
debug(path) printf("path.fnmatch.unittest\n");
|
||||||
|
|
||||||
assert(fnmatch("foo", "Foo"));
|
version (Win32)
|
||||||
|
assert(fnmatch("foo", "Foo"));
|
||||||
|
version (linux)
|
||||||
|
assert(!fnmatch("foo", "Foo"));
|
||||||
assert(fnmatch("foo", "*"));
|
assert(fnmatch("foo", "*"));
|
||||||
assert(fnmatch("foo.bar", "*"));
|
assert(fnmatch("foo.bar", "*"));
|
||||||
assert(fnmatch("foo.bar", "*.*"));
|
assert(fnmatch("foo.bar", "*.*"));
|
||||||
|
|
7
random.d
7
random.d
|
@ -11,6 +11,11 @@ version (Win32)
|
||||||
extern(Windows) int QueryPerformanceCounter(ulong *count);
|
extern(Windows) int QueryPerformanceCounter(ulong *count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
import linux;
|
||||||
|
}
|
||||||
|
|
||||||
/* ===================== Random ========================= */
|
/* ===================== Random ========================= */
|
||||||
|
|
||||||
// BUG: not multithreaded
|
// BUG: not multithreaded
|
||||||
|
@ -75,7 +80,7 @@ static this()
|
||||||
// time.h
|
// time.h
|
||||||
// sys/time.h
|
// sys/time.h
|
||||||
|
|
||||||
struct timeval tv;
|
timeval tv;
|
||||||
|
|
||||||
if (gettimeofday(&tv, null))
|
if (gettimeofday(&tv, null))
|
||||||
{ // Some error happened - try time() instead
|
{ // Some error happened - try time() instead
|
||||||
|
|
11
regexp.d
11
regexp.d
|
@ -606,6 +606,7 @@ void printProgram(ubyte[] prog)
|
||||||
{
|
{
|
||||||
printf("%3d: ", pc);
|
printf("%3d: ", pc);
|
||||||
|
|
||||||
|
//printf("prog[pc] = %d, REchar = %d, REnmq = %d\n", prog[pc], REchar, REnmq);
|
||||||
switch (prog[pc])
|
switch (prog[pc])
|
||||||
{
|
{
|
||||||
case REchar:
|
case REchar:
|
||||||
|
@ -712,7 +713,9 @@ void printProgram(ubyte[] prog)
|
||||||
len = puint[0];
|
len = puint[0];
|
||||||
n = puint[1];
|
n = puint[1];
|
||||||
m = puint[2];
|
m = puint[2];
|
||||||
printf("\tREnm%s len=%d, n=%u, m=%u, pc=>%d\n", (prog[pc] == REnmq) ? "q" : " ", len, n, m, pc + 1 + uint.size * 3 + len);
|
printf("\tREnm%.*s len=%d, n=%u, m=%u, pc=>%d\n",
|
||||||
|
(prog[pc] == REnmq) ? "q" : " ",
|
||||||
|
len, n, m, pc + 1 + uint.size * 3 + len);
|
||||||
pc += 1 + uint.size * 3;
|
pc += 1 + uint.size * 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1085,7 +1088,10 @@ int trymatch(int pc, int pcend)
|
||||||
}
|
}
|
||||||
if (!psave && count < m)
|
if (!psave && count < m)
|
||||||
{
|
{
|
||||||
psave = (regmatch_t *)alloca((re_nsub + 1) * regmatch_t.size);
|
//version (Win32)
|
||||||
|
psave = (regmatch_t *)alloca((re_nsub + 1) * regmatch_t.size);
|
||||||
|
//else
|
||||||
|
//psave = new regmatch_t[re_nsub + 1];
|
||||||
}
|
}
|
||||||
if (program[pc] == REnmq) // if minimal munch
|
if (program[pc] == REnmq) // if minimal munch
|
||||||
{
|
{
|
||||||
|
@ -2007,6 +2013,7 @@ void optimize()
|
||||||
prog = buf.toBytes();
|
prog = buf.toBytes();
|
||||||
for (i = 0; 1;)
|
for (i = 0; 1;)
|
||||||
{
|
{
|
||||||
|
//printf("\tprog[%d] = %d, %d\n", i, prog[i], REstring);
|
||||||
switch (prog[i])
|
switch (prog[i])
|
||||||
{
|
{
|
||||||
case REend:
|
case REend:
|
||||||
|
|
226
stream.d
226
stream.d
|
@ -132,25 +132,25 @@ class Stream
|
||||||
char[] result;
|
char[] result;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
char c = getc();
|
char ch = getc();
|
||||||
while (readable)
|
while (readable)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case "\r":
|
case "\r":
|
||||||
{
|
{
|
||||||
c = getc();
|
ch = getc();
|
||||||
if (c != "\n")
|
if (ch != "\n")
|
||||||
ungetc(c);
|
ungetc(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
case "\n":
|
case "\n":
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result ~= c;
|
result ~= ch;
|
||||||
}
|
}
|
||||||
c = getc();
|
ch = getc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ReadError e)
|
catch (ReadError e)
|
||||||
|
@ -678,7 +678,7 @@ nws:
|
||||||
else version (Mac)
|
else version (Mac)
|
||||||
writeString("\r");
|
writeString("\r");
|
||||||
+/
|
+/
|
||||||
else // probably *NIX
|
else
|
||||||
writeString("\n");
|
writeString("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,26 +723,38 @@ nws:
|
||||||
{
|
{
|
||||||
version (Win32)
|
version (Win32)
|
||||||
{
|
{
|
||||||
count = _vsnprintf(p, psize, f, args);
|
count = _vsnprintf(p, psize, f, args);
|
||||||
if (count != -1)
|
if (count != -1)
|
||||||
break;
|
break;
|
||||||
psize *= 2;
|
psize *= 2;
|
||||||
|
p = cast(char*) alloca(psize);
|
||||||
}
|
}
|
||||||
else version (linux)
|
else version (linux)
|
||||||
{
|
{
|
||||||
count = vsnprintf(p, psize, f, args);
|
count = vsnprintf(p, psize, f, args);
|
||||||
if (count == -1)
|
if (count == -1)
|
||||||
psize *= 2;
|
psize *= 2;
|
||||||
else if (count >= psize)
|
else if (count >= psize)
|
||||||
psize = count + 1;
|
psize = count + 1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
/+if (p != buffer)
|
||||||
|
c.stdlib.free(p);
|
||||||
|
p = (char *) c.stdlib.malloc(psize); // buffer too small, try again with larger size
|
||||||
|
+/
|
||||||
|
p = cast(char*) alloca(psize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new Error("unsupported platform");
|
throw new Error("unsupported platform");
|
||||||
p = cast(char*) alloca(psize);
|
|
||||||
}
|
}
|
||||||
writeString(p[0 .. count]);
|
writeString(p[0 .. count]);
|
||||||
|
/+
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
if (p != buffer)
|
||||||
|
c.stdlib.free(p);
|
||||||
|
}
|
||||||
|
+/
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,7 +879,17 @@ enum FileMode
|
||||||
// just a file on disk
|
// just a file on disk
|
||||||
class File: Stream
|
class File: Stream
|
||||||
{
|
{
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
import windows;
|
import windows;
|
||||||
|
private HANDLE hFile;
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
import linux;
|
||||||
|
alias int HANDLE;
|
||||||
|
private HANDLE hFile = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// for compatibility with old versions...
|
// for compatibility with old versions...
|
||||||
deprecated enum: FileMode
|
deprecated enum: FileMode
|
||||||
|
@ -876,9 +898,17 @@ class File: Stream
|
||||||
towrite = FileMode.Out
|
towrite = FileMode.Out
|
||||||
}
|
}
|
||||||
|
|
||||||
private HANDLE hFile;
|
this()
|
||||||
|
{
|
||||||
this() { hFile = null; }
|
version (Win32)
|
||||||
|
{
|
||||||
|
hFile = null;
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
hFile = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// opens existing handle; use with care!
|
// opens existing handle; use with care!
|
||||||
this(HANDLE hFile, FileMode mode)
|
this(HANDLE hFile, FileMode mode)
|
||||||
|
@ -903,8 +933,10 @@ class File: Stream
|
||||||
// opens file in requested mode
|
// opens file in requested mode
|
||||||
void open(char[] filename, FileMode mode)
|
void open(char[] filename, FileMode mode)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
int access = 0, share = 0;
|
int access = 0, share = 0;
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
if (mode & FileMode.In)
|
if (mode & FileMode.In)
|
||||||
{
|
{
|
||||||
readable = true;
|
readable = true;
|
||||||
|
@ -921,6 +953,26 @@ class File: Stream
|
||||||
null, OPEN_EXISTING, 0, null);
|
null, OPEN_EXISTING, 0, null);
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
throw new OpenError("file '" ~ filename ~ "' not found");
|
throw new OpenError("file '" ~ filename ~ "' not found");
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
if (mode & FileMode.In)
|
||||||
|
{
|
||||||
|
readable = true;
|
||||||
|
access = O_RDONLY;
|
||||||
|
share = 0660;
|
||||||
|
}
|
||||||
|
if (mode & FileMode.Out)
|
||||||
|
{
|
||||||
|
writeable = true;
|
||||||
|
access = O_CREAT | O_WRONLY;
|
||||||
|
share = 0660;
|
||||||
|
}
|
||||||
|
seekable = true;
|
||||||
|
hFile = linux.open(toStringz(filename), access, share);
|
||||||
|
if (hFile == -1)
|
||||||
|
throw new OpenError("file '" ~ filename ~ "' not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates file for writing
|
// creates file for writing
|
||||||
|
@ -929,8 +981,10 @@ class File: Stream
|
||||||
// creates file in requested mode
|
// creates file in requested mode
|
||||||
void create(char[] filename, FileMode mode)
|
void create(char[] filename, FileMode mode)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
int access = 0, share = 0;
|
int access = 0, share = 0;
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
if (mode & FileMode.In)
|
if (mode & FileMode.In)
|
||||||
{
|
{
|
||||||
access |= GENERIC_READ;
|
access |= GENERIC_READ;
|
||||||
|
@ -947,6 +1001,26 @@ class File: Stream
|
||||||
writeable = cast(bit)(mode & FileMode.Out);
|
writeable = cast(bit)(mode & FileMode.Out);
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
throw new CreateError("unable to create file '" ~ filename ~ "'");
|
throw new CreateError("unable to create file '" ~ filename ~ "'");
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
if (mode & FileMode.In)
|
||||||
|
{
|
||||||
|
readable = true;
|
||||||
|
access = O_RDONLY;
|
||||||
|
share = 0660;
|
||||||
|
}
|
||||||
|
if (mode & FileMode.Out)
|
||||||
|
{
|
||||||
|
writeable = true;
|
||||||
|
access = O_CREAT | O_WRONLY | O_TRUNC;
|
||||||
|
share = 0660;
|
||||||
|
}
|
||||||
|
seekable = true;
|
||||||
|
hFile = linux.open(toStringz(filename), access, share);
|
||||||
|
if (hFile == -1)
|
||||||
|
throw new OpenError("file '" ~ filename ~ "' not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// closes file, if it is open; otherwise, does nothing
|
// closes file, if it is open; otherwise, does nothing
|
||||||
|
@ -954,9 +1028,17 @@ class File: Stream
|
||||||
{
|
{
|
||||||
if (hFile)
|
if (hFile)
|
||||||
{
|
{
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
hFile = null;
|
hFile = null;
|
||||||
readable = writeable = seekable = false;
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
linux.close(hFile);
|
||||||
|
hFile = -1;
|
||||||
|
}
|
||||||
|
readable = writeable = seekable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -968,8 +1050,15 @@ class File: Stream
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
ReadFile(hFile, buffer, size, &size, null);
|
ReadFile(hFile, buffer, size, &size, null);
|
||||||
return size;
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
size = linux.read(hFile, buffer, size);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
override uint writeBlock(void* buffer, uint size)
|
override uint writeBlock(void* buffer, uint size)
|
||||||
|
@ -980,8 +1069,15 @@ class File: Stream
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
WriteFile(hFile, buffer, size, &size, null);
|
WriteFile(hFile, buffer, size, &size, null);
|
||||||
return size;
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
size = linux.write(hFile, buffer, size);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
override ulong seek(long offset, SeekPos rel)
|
override ulong seek(long offset, SeekPos rel)
|
||||||
|
@ -992,10 +1088,19 @@ class File: Stream
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
uint result = SetFilePointer(hFile, offset, null, rel);
|
uint result = SetFilePointer(hFile, offset, null, rel);
|
||||||
if (result == 0xFFFFFFFF)
|
if (result == 0xFFFFFFFF)
|
||||||
throw new SeekError("unable to move file pointer");
|
throw new SeekError("unable to move file pointer");
|
||||||
return result;
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
uint result = lseek(hFile, offset, rel);
|
||||||
|
if (result == 0xFFFFFFFF)
|
||||||
|
throw new SeekError("unable to move file pointer");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OS-specific property, just in case somebody wants
|
// OS-specific property, just in case somebody wants
|
||||||
|
@ -1014,7 +1119,10 @@ class File: Stream
|
||||||
file.writeString("Hello, world!");
|
file.writeString("Hello, world!");
|
||||||
file.write(i);
|
file.write(i);
|
||||||
// string#1 + string#2 + int should give exacly that
|
// string#1 + string#2 + int should give exacly that
|
||||||
assert(file.position() == 19 + 13 + 4);
|
version (Win32)
|
||||||
|
assert(file.position() == 19 + 13 + 4);
|
||||||
|
version (linux)
|
||||||
|
assert(file.position() == 18 + 13 + 4);
|
||||||
// we must be at the end of file
|
// we must be at the end of file
|
||||||
assert(file.eof());
|
assert(file.eof());
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -1026,12 +1134,18 @@ class File: Stream
|
||||||
assert(!string.cmp(file.readLine(), "Testing stream.d:"));
|
assert(!string.cmp(file.readLine(), "Testing stream.d:"));
|
||||||
// jump over "Hello, "
|
// jump over "Hello, "
|
||||||
file.seek(7, SeekPos.Current);
|
file.seek(7, SeekPos.Current);
|
||||||
assert(file.position() == 19 + 7);
|
version (Win32)
|
||||||
|
assert(file.position() == 19 + 7);
|
||||||
|
version (linux)
|
||||||
|
assert(file.position() == 18 + 7);
|
||||||
assert(!string.cmp(file.readString(6), "world!"));
|
assert(!string.cmp(file.readString(6), "world!"));
|
||||||
i = 0; file.read(i);
|
i = 0; file.read(i);
|
||||||
assert(i == 666);
|
assert(i == 666);
|
||||||
// string#1 + string#2 + int should give exacly that
|
// string#1 + string#2 + int should give exacly that
|
||||||
assert(file.position() == 19 + 13 + 4);
|
version (Win32)
|
||||||
|
assert(file.position() == 19 + 13 + 4);
|
||||||
|
version (linux)
|
||||||
|
assert(file.position() == 18 + 13 + 4);
|
||||||
// we must be at the end of file
|
// we must be at the end of file
|
||||||
assert(file.eof());
|
assert(file.eof());
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -1105,7 +1219,7 @@ class MemoryStream: Stream
|
||||||
cur += size;
|
cur += size;
|
||||||
if (cur > len)
|
if (cur > len)
|
||||||
len = cur;
|
len = cur;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
override ulong seek(long offset, SeekPos rel)
|
override ulong seek(long offset, SeekPos rel)
|
||||||
|
@ -1309,7 +1423,7 @@ class SliceStream : Stream
|
||||||
MemoryStream m;
|
MemoryStream m;
|
||||||
SliceStream s;
|
SliceStream s;
|
||||||
|
|
||||||
m = new MemoryStream ("Hello, world");
|
m = new MemoryStream ((cast(char[])"Hello, world").dup);
|
||||||
s = new SliceStream (m, 4, 8);
|
s = new SliceStream (m, 4, 8);
|
||||||
assert (s.size () == 4);
|
assert (s.size () == 4);
|
||||||
assert (s.writeBlock ((char *) "Vroom", 5) == 4);
|
assert (s.writeBlock ((char *) "Vroom", 5) == 4);
|
||||||
|
@ -1348,22 +1462,36 @@ private bit ishexdigit(char c)
|
||||||
return isdigit(c) || (c >= "A" && c <= "F") || (c >= "a" && c <= "f");
|
return isdigit(c) || (c >= "A" && c <= "F") || (c >= "a" && c <= "f");
|
||||||
}
|
}
|
||||||
|
|
||||||
// API imports
|
|
||||||
private extern(Windows)
|
|
||||||
{
|
|
||||||
private import windows;
|
|
||||||
HANDLE GetStdHandle(DWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// standard IO devices
|
// standard IO devices
|
||||||
File stdin, stdout, stderr;
|
File stdin, stdout, stderr;
|
||||||
|
|
||||||
static this()
|
version (Win32)
|
||||||
{
|
{
|
||||||
// open standard I/O devices
|
// API imports
|
||||||
stdin = new File(GetStdHandle(-10), FileMode.In);
|
private extern(Windows)
|
||||||
stdout = new File(GetStdHandle(-11), FileMode.Out);
|
{
|
||||||
stderr = new File(GetStdHandle(-12), FileMode.Out);
|
private import windows;
|
||||||
|
HANDLE GetStdHandle(DWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
// open standard I/O devices
|
||||||
|
stdin = new File(GetStdHandle(-10), FileMode.In);
|
||||||
|
stdout = new File(GetStdHandle(-11), FileMode.Out);
|
||||||
|
stderr = new File(GetStdHandle(-12), FileMode.Out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
// open standard I/O devices
|
||||||
|
stdin = new File(0, FileMode.In);
|
||||||
|
stdout = new File(1, FileMode.Out);
|
||||||
|
stderr = new File(2, FileMode.Out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import string;
|
import string;
|
||||||
|
|
193
string.d
193
string.d
|
@ -124,7 +124,29 @@ int icmp(char[] s1, char[] s2)
|
||||||
|
|
||||||
if (s2.length < len)
|
if (s2.length < len)
|
||||||
len = s2.length;
|
len = s2.length;
|
||||||
result = memicmp(s1, s2, len);
|
version (Win32)
|
||||||
|
{
|
||||||
|
result = memicmp(s1, s2, len);
|
||||||
|
}
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (s1[i] != s2[i])
|
||||||
|
{
|
||||||
|
char c1 = s1[i];
|
||||||
|
char c2 = s2[i];
|
||||||
|
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
|
c1 += (int)'a' - (int)'A';
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
|
c2 += (int)'a' - (int)'A';
|
||||||
|
result = (int)c1 - (int)c2;
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
result = cast(int)s1.length - cast(int)s2.length;
|
result = cast(int)s1.length - cast(int)s2.length;
|
||||||
return result;
|
return result;
|
||||||
|
@ -303,34 +325,60 @@ int find(char[] s, char[] sub)
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
int imax;
|
int sublength = sub.length;
|
||||||
char c;
|
|
||||||
|
|
||||||
if (sub.length == 0)
|
if (sublength == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (sub.length == 1)
|
|
||||||
|
char c = sub[0];
|
||||||
|
if (sublength == 1)
|
||||||
{
|
{
|
||||||
char *p = memchr(s, sub[0], s.length);
|
char *p = memchr(s, c, s.length);
|
||||||
if (p)
|
if (p)
|
||||||
return p - &s[0];
|
return p - &s[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imax = s.length - sub.length + 1;
|
int imax = s.length - sublength + 1;
|
||||||
c = sub[0];
|
|
||||||
|
// Remainder of sub[]
|
||||||
|
char *q = &sub[1];
|
||||||
|
sublength--;
|
||||||
|
|
||||||
for (int i = 0; i < imax; i++)
|
for (int i = 0; i < imax; i++)
|
||||||
{
|
{
|
||||||
if (s[i] == c)
|
char *p = memchr(&s[i], c, imax - i);
|
||||||
{
|
if (!p)
|
||||||
if (memcmp(&s[i + 1], &sub[1], sub.length - 1) == 0)
|
break;
|
||||||
return i;
|
i = p - &s[0];
|
||||||
}
|
if (memcmp(p + 1, q, sublength) == 0)
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
debug(string) printf("string.find.unittest\n");
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = find(null, cast(char[])'a');
|
||||||
|
assert(i == -1);
|
||||||
|
i = find("def", cast(char[])'a');
|
||||||
|
assert(i == -1);
|
||||||
|
i = find("abba", cast(char[])'a');
|
||||||
|
assert(i == 0);
|
||||||
|
i = find("def", cast(char[])'f');
|
||||||
|
assert(i == 2);
|
||||||
|
i = find("dfefffg", 'fff');
|
||||||
|
assert(i == 3);
|
||||||
|
i = find("dfeffgfff", 'fff');
|
||||||
|
assert(i == 6);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
* Find last occurrance of sub in string s.
|
* Find last occurrance of sub in string s.
|
||||||
* Return index in s where it is found.
|
* Return index in s where it is found.
|
||||||
|
@ -710,21 +758,87 @@ char[][] split(char[] s, char[] delim)
|
||||||
i = 0;
|
i = 0;
|
||||||
if (s.length)
|
if (s.length)
|
||||||
{
|
{
|
||||||
while (true)
|
if (delim.length == 1)
|
||||||
{
|
{ char c = delim[0];
|
||||||
j = find(s[i .. s.length], delim);
|
uint nwords = 0;
|
||||||
if (j == -1)
|
char *p = &s[0];
|
||||||
|
char *pend = p + s.length;
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
words ~= s[i .. s.length];
|
nwords++;
|
||||||
break;
|
p = memchr(p, c, pend - p);
|
||||||
|
if (!p)
|
||||||
|
break;
|
||||||
|
p++;
|
||||||
|
if (p == pend)
|
||||||
|
{ nwords++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
words ~= s[i .. i + j];
|
words.length = nwords;
|
||||||
i += j + delim.length;
|
|
||||||
if (i == s.length)
|
int wordi = 0;
|
||||||
|
i = 0;
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
words ~= "";
|
p = memchr(&s[i], c, s.length - i);
|
||||||
break;
|
if (!p)
|
||||||
|
{
|
||||||
|
words[wordi] = s[i .. s.length];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j = p - &s[0];
|
||||||
|
words[wordi] = s[i .. j];
|
||||||
|
wordi++;
|
||||||
|
i = j + 1;
|
||||||
|
if (i == s.length)
|
||||||
|
{
|
||||||
|
words[wordi] = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
assert(wordi + 1 == nwords);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ uint nwords = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
nwords++;
|
||||||
|
j = find(s[i .. s.length], delim);
|
||||||
|
if (j == -1)
|
||||||
|
break;
|
||||||
|
i += j + delim.length;
|
||||||
|
if (i == s.length)
|
||||||
|
{ nwords++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(i < s.length);
|
||||||
|
}
|
||||||
|
words.length = nwords;
|
||||||
|
|
||||||
|
int wordi = 0;
|
||||||
|
i = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
j = find(s[i .. s.length], delim);
|
||||||
|
if (j == -1)
|
||||||
|
{
|
||||||
|
words[wordi] = s[i .. s.length];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
words[wordi] = s[i .. i + j];
|
||||||
|
wordi++;
|
||||||
|
i += j + delim.length;
|
||||||
|
if (i == s.length)
|
||||||
|
{
|
||||||
|
words[wordi] = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(i < s.length);
|
||||||
|
}
|
||||||
|
assert(wordi + 1 == nwords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return words;
|
return words;
|
||||||
|
@ -762,6 +876,34 @@ unittest
|
||||||
assert(words.length == 3);
|
assert(words.length == 3);
|
||||||
i = cmp(words[0], "peter");
|
i = cmp(words[0], "peter");
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
|
char[] s2 = ",,peter,,paul,,jerry,,";
|
||||||
|
|
||||||
|
words = split(s2, ",,");
|
||||||
|
//printf("words.length = %d\n", words.length);
|
||||||
|
assert(words.length == 5);
|
||||||
|
i = cmp(words[0], "");
|
||||||
|
assert(i == 0);
|
||||||
|
i = cmp(words[1], "peter");
|
||||||
|
assert(i == 0);
|
||||||
|
i = cmp(words[2], "paul");
|
||||||
|
assert(i == 0);
|
||||||
|
i = cmp(words[3], "jerry");
|
||||||
|
assert(i == 0);
|
||||||
|
i = cmp(words[4], "");
|
||||||
|
assert(i == 0);
|
||||||
|
|
||||||
|
s2 = s2[0 .. s2.length - 2]; // lop off trailing ',,'
|
||||||
|
words = split(s2, ",,");
|
||||||
|
assert(words.length == 4);
|
||||||
|
i = cmp(words[3], "jerry");
|
||||||
|
assert(i == 0);
|
||||||
|
|
||||||
|
s2 = s2[2 .. s2.length]; // lop off leading ',,'
|
||||||
|
words = split(s2, ",,");
|
||||||
|
assert(words.length == 3);
|
||||||
|
i = cmp(words[0], "peter");
|
||||||
|
assert(i == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1244,13 +1386,16 @@ char[] translate(char[] s, char[] transtab, char[] delchars)
|
||||||
|
|
||||||
deltab[] = false;
|
deltab[] = false;
|
||||||
for (i = 0; i < delchars.length; i++)
|
for (i = 0; i < delchars.length; i++)
|
||||||
|
{
|
||||||
deltab[delchars[i]] = true;
|
deltab[delchars[i]] = true;
|
||||||
|
}
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for (i = 0; i < s.length; i++)
|
for (i = 0; i < s.length; i++)
|
||||||
{
|
{
|
||||||
if (!deltab[s[i]])
|
if (!deltab[s[i]])
|
||||||
count++;
|
count++;
|
||||||
|
//printf("s[%d] = '%c', count = %d\n", i, s[i], count);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = new char[count];
|
r = new char[count];
|
||||||
|
|
499
thread.d
499
thread.d
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
//debug=thread;
|
//debug=thread;
|
||||||
|
|
||||||
|
/* ================================ Win32 ================================= */
|
||||||
|
|
||||||
|
version (Win32)
|
||||||
|
{
|
||||||
|
|
||||||
import windows;
|
import windows;
|
||||||
|
|
||||||
extern (Windows) alias uint (*stdfp)(void *);
|
extern (Windows) alias uint (*stdfp)(void *);
|
||||||
|
@ -324,4 +329,498 @@ void *os_query_stackBottom()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================ linux ================================= */
|
||||||
|
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
|
||||||
|
import linux;
|
||||||
|
import linuxextern;
|
||||||
|
|
||||||
|
alias uint pthread_t;
|
||||||
|
extern (C) alias void (*__sighandler_t)(int);
|
||||||
|
|
||||||
|
struct sigset_t
|
||||||
|
{
|
||||||
|
uint __val[1024 / (8 * uint.size)];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sigaction_t
|
||||||
|
{
|
||||||
|
__sighandler_t sa_handler;
|
||||||
|
sigset_t sa_mask;
|
||||||
|
int sa_flags;
|
||||||
|
void (*sa_restorer)();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _pthread_fastlock
|
||||||
|
{
|
||||||
|
int __status;
|
||||||
|
int __spinlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sem_t
|
||||||
|
{
|
||||||
|
_pthread_fastlock __sem_lock;
|
||||||
|
int __sem_value;
|
||||||
|
void* __sem_waiting;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
assert(sigset_t.size == 128);
|
||||||
|
assert(sigaction_t.size == 140);
|
||||||
|
assert(sem_t.size == 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern (C)
|
||||||
|
{
|
||||||
|
int pthread_create(pthread_t*, void*, void* (*)(void*), void*);
|
||||||
|
int pthread_join(pthread_t, void**);
|
||||||
|
int pthread_kill(pthread_t, int);
|
||||||
|
pthread_t pthread_self();
|
||||||
|
int pthread_equal(pthread_t, pthread_t);
|
||||||
|
int sem_wait(sem_t*);
|
||||||
|
int sem_init(sem_t*, int, uint);
|
||||||
|
int sem_post(sem_t*);
|
||||||
|
int sched_yield();
|
||||||
|
int sigfillset(sigset_t*);
|
||||||
|
int sigdelset(sigset_t*, int);
|
||||||
|
int sigaction(int, sigaction_t*, sigaction_t*);
|
||||||
|
int sigsuspend(sigset_t*);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreadError : Error
|
||||||
|
{
|
||||||
|
this(char[] s)
|
||||||
|
{
|
||||||
|
super("Thread error: " ~ s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Thread
|
||||||
|
{
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
this(int (*fp)(void *), void *arg)
|
||||||
|
{
|
||||||
|
this.fp = fp;
|
||||||
|
this.arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
this(int delegate() dg)
|
||||||
|
{
|
||||||
|
this.dg = dg;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t id;
|
||||||
|
void* stackBottom;
|
||||||
|
void* stackTop;
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
if (state != TS.INITIAL)
|
||||||
|
error("already started");
|
||||||
|
|
||||||
|
synchronized (threadLock)
|
||||||
|
{
|
||||||
|
for (int i = 0; 1; i++)
|
||||||
|
{
|
||||||
|
if (i == allThreads.length)
|
||||||
|
error("too many threads");
|
||||||
|
if (!allThreads[i])
|
||||||
|
{ allThreads[i] = this;
|
||||||
|
idx = i;
|
||||||
|
if (i >= allThreadsDim)
|
||||||
|
allThreadsDim = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nthreads++;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = TS.RUNNING;
|
||||||
|
int result;
|
||||||
|
//printf("creating thread x%x\n", this);
|
||||||
|
result = pthread_create(&id, null, &threadstart, this);
|
||||||
|
if (result)
|
||||||
|
{ state = TS.TERMINATED;
|
||||||
|
allThreads[idx] = null;
|
||||||
|
idx = -1;
|
||||||
|
error("failed to start"); // BUG: should report errno
|
||||||
|
}
|
||||||
|
//printf("t = x%x, id = %d\n", this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run()
|
||||||
|
{
|
||||||
|
if (fp)
|
||||||
|
return fp(arg);
|
||||||
|
else if (dg)
|
||||||
|
return dg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
if (this === getThis())
|
||||||
|
error("wait on self");
|
||||||
|
if (state == TS.RUNNING)
|
||||||
|
{ int result;
|
||||||
|
void *value;
|
||||||
|
|
||||||
|
result = pthread_join(id, &value);
|
||||||
|
if (result)
|
||||||
|
error("failed to wait");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait(uint milliseconds)
|
||||||
|
{
|
||||||
|
wait();
|
||||||
|
/+ not implemented
|
||||||
|
if (this === getThis())
|
||||||
|
error("wait on self");
|
||||||
|
if (state == TS.RUNNING)
|
||||||
|
{ DWORD dw;
|
||||||
|
|
||||||
|
dw = WaitForSingleObject(hdl, milliseconds);
|
||||||
|
}
|
||||||
|
+/
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TS
|
||||||
|
{
|
||||||
|
INITIAL,
|
||||||
|
RUNNING,
|
||||||
|
TERMINATED
|
||||||
|
}
|
||||||
|
|
||||||
|
TS getState()
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PRIORITY
|
||||||
|
{
|
||||||
|
INCREASE,
|
||||||
|
DECREASE,
|
||||||
|
IDLE,
|
||||||
|
CRITICAL
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPriority(PRIORITY p)
|
||||||
|
{
|
||||||
|
/+ not implemented
|
||||||
|
int nPriority;
|
||||||
|
|
||||||
|
switch (p)
|
||||||
|
{
|
||||||
|
case PRIORITY.INCREASE:
|
||||||
|
nPriority = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||||
|
break;
|
||||||
|
case PRIORITY.DECREASE:
|
||||||
|
nPriority = THREAD_PRIORITY_BELOW_NORMAL;
|
||||||
|
break;
|
||||||
|
case PRIORITY.IDLE:
|
||||||
|
nPriority = THREAD_PRIORITY_IDLE;
|
||||||
|
break;
|
||||||
|
case PRIORITY.CRITICAL:
|
||||||
|
nPriority = THREAD_PRIORITY_TIME_CRITICAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SetThreadPriority(hdl, nPriority) == THREAD_PRIORITY_ERROR_RETURN)
|
||||||
|
error("set priority");
|
||||||
|
+/
|
||||||
|
}
|
||||||
|
|
||||||
|
int isSelf()
|
||||||
|
{
|
||||||
|
//printf("id = %d, self = %d\n", id, pthread_self());
|
||||||
|
return pthread_equal(pthread_self(), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Thread getThis()
|
||||||
|
{
|
||||||
|
pthread_t id;
|
||||||
|
Thread result;
|
||||||
|
|
||||||
|
//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
|
||||||
|
synchronized (threadLock)
|
||||||
|
{
|
||||||
|
id = pthread_self();
|
||||||
|
//printf("id = %d\n", id);
|
||||||
|
for (int i = 0; i < allThreadsDim; i++)
|
||||||
|
{
|
||||||
|
Thread t = allThreads[i];
|
||||||
|
//printf("allThreads[%d] = x%x, id = %d\n", i, t, (t ? t.id : 0));
|
||||||
|
if (t && pthread_equal(id, t.id))
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("didn't find it\n");
|
||||||
|
assert(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Thread[] getAll()
|
||||||
|
{
|
||||||
|
return allThreads[0 .. allThreadsDim];
|
||||||
|
}
|
||||||
|
|
||||||
|
void pause()
|
||||||
|
{
|
||||||
|
if (state == TS.RUNNING)
|
||||||
|
{ int result;
|
||||||
|
|
||||||
|
result = pthread_kill(id, SIGUSR1);
|
||||||
|
if (result)
|
||||||
|
error("cannot pause");
|
||||||
|
else
|
||||||
|
sem_wait(&flagSuspend); // wait for acknowledgement
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("cannot pause");
|
||||||
|
}
|
||||||
|
|
||||||
|
void resume()
|
||||||
|
{
|
||||||
|
if (state == TS.RUNNING)
|
||||||
|
{ int result;
|
||||||
|
|
||||||
|
result = pthread_kill(id, SIGUSR2);
|
||||||
|
if (result)
|
||||||
|
error("cannot resume");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("cannot resume");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pauseAll()
|
||||||
|
{
|
||||||
|
if (nthreads > 1)
|
||||||
|
{
|
||||||
|
Thread tthis = getThis();
|
||||||
|
int npause = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < allThreadsDim; i++)
|
||||||
|
{ Thread t;
|
||||||
|
|
||||||
|
t = allThreads[i];
|
||||||
|
if (t && t !== tthis && t.state == TS.RUNNING)
|
||||||
|
{ int result;
|
||||||
|
|
||||||
|
result = pthread_kill(t.id, SIGUSR1);
|
||||||
|
if (result)
|
||||||
|
getThis().error("cannot pause");
|
||||||
|
else
|
||||||
|
npause++; // count of paused threads
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for each paused thread to acknowledge
|
||||||
|
while (npause--)
|
||||||
|
{
|
||||||
|
sem_wait(&flagSuspend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resumeAll()
|
||||||
|
{
|
||||||
|
if (nthreads > 1)
|
||||||
|
{
|
||||||
|
Thread tthis = getThis();
|
||||||
|
|
||||||
|
for (int i = 0; i < allThreadsDim; i++)
|
||||||
|
{ Thread t;
|
||||||
|
|
||||||
|
t = allThreads[i];
|
||||||
|
if (t && t !== tthis && t.state == TS.RUNNING)
|
||||||
|
t.resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void yield()
|
||||||
|
{
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint nthreads = 1;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static uint allThreadsDim;
|
||||||
|
static Object threadLock;
|
||||||
|
static Thread[/*_POSIX_THREAD_THREADS_MAX*/ 100] allThreads;
|
||||||
|
static sem_t flagSuspend;
|
||||||
|
|
||||||
|
TS state;
|
||||||
|
int idx = -1; // index into allThreads[]
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
int (*fp)(void *);
|
||||||
|
void *arg;
|
||||||
|
|
||||||
|
int delegate() dg;
|
||||||
|
|
||||||
|
void error(char[] msg)
|
||||||
|
{
|
||||||
|
throw new ThreadError(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* This is just a wrapper to interface between C rtl and Thread.run().
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern (C) static void *threadstart(void *p)
|
||||||
|
{
|
||||||
|
Thread t = cast(Thread)p;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
debug (thread) printf("Starting thread x%x (%d)\n", t, t.idx);
|
||||||
|
|
||||||
|
// Need to set t.id here, because thread is off and running
|
||||||
|
// before pthread_create() sets it.
|
||||||
|
t.id = pthread_self();
|
||||||
|
|
||||||
|
t.stackBottom = getESP();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = t.run();
|
||||||
|
}
|
||||||
|
catch (Object o)
|
||||||
|
{
|
||||||
|
printf("Error: ");
|
||||||
|
o.print();
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug (thread) printf("Ending thread %d\n", t.idx);
|
||||||
|
t.state = TS.TERMINATED;
|
||||||
|
allThreads[t.idx] = null;
|
||||||
|
t.idx = -1;
|
||||||
|
nthreads--;
|
||||||
|
return (void*)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Create a Thread for global main().
|
||||||
|
*/
|
||||||
|
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
threadLock = new Object();
|
||||||
|
|
||||||
|
Thread t = new Thread();
|
||||||
|
|
||||||
|
t.state = TS.RUNNING;
|
||||||
|
t.id = pthread_self();
|
||||||
|
t.stackBottom = (void*)__libc_stack_end;
|
||||||
|
synchronized (threadLock)
|
||||||
|
{
|
||||||
|
assert(!allThreads[0]);
|
||||||
|
allThreads[0] = t;
|
||||||
|
allThreadsDim = 1;
|
||||||
|
t.idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install signal handlers so we can suspend/resume threads
|
||||||
|
*/
|
||||||
|
|
||||||
|
int result;
|
||||||
|
sigaction_t sigact;
|
||||||
|
result = sigfillset(&sigact.sa_mask);
|
||||||
|
if (result)
|
||||||
|
goto Lfail;
|
||||||
|
sigact.sa_handler = pauseHandler;
|
||||||
|
result = sigaction(SIGUSR1, &sigact, null);
|
||||||
|
if (result)
|
||||||
|
goto Lfail;
|
||||||
|
sigact.sa_handler = resumeHandler;
|
||||||
|
result = sigaction(SIGUSR2, &sigact, null);
|
||||||
|
if (result)
|
||||||
|
goto Lfail;
|
||||||
|
|
||||||
|
result = sem_init(&flagSuspend, 0, 0);
|
||||||
|
if (result)
|
||||||
|
goto Lfail;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
Lfail:
|
||||||
|
getThis().error("cannot initialize threads");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************
|
||||||
|
* This gets called when a thread gets SIGUSR1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern (C) static void pauseHandler(int sig)
|
||||||
|
{ int result;
|
||||||
|
|
||||||
|
// Save all registers on the stack so they'll be scanned by the GC
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
pusha ;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sig == SIGUSR1);
|
||||||
|
sem_post(&flagSuspend);
|
||||||
|
|
||||||
|
sigset_t sigmask;
|
||||||
|
result = sigfillset(&sigmask);
|
||||||
|
assert(result == 0);
|
||||||
|
result = sigdelset(&sigmask, SIGUSR2);
|
||||||
|
assert(result == 0);
|
||||||
|
|
||||||
|
Thread t = getThis();
|
||||||
|
t.stackTop = getESP();
|
||||||
|
t.flags &= ~1;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
sigsuspend(&sigmask); // suspend until SIGUSR2
|
||||||
|
if (t.flags & 1) // ensure it was resumeHandler()
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore all registers
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
popa ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************
|
||||||
|
* This gets called when a thread gets SIGUSR2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern (C) static void resumeHandler(int sig)
|
||||||
|
{
|
||||||
|
Thread t = getThis();
|
||||||
|
|
||||||
|
t.flags |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* getESP()
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{ naked ;
|
||||||
|
mov EAX,ESP ;
|
||||||
|
ret ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,5 +45,6 @@ int main(char[][] args)
|
||||||
printf("args.length = %d\n", args.length);
|
printf("args.length = %d\n", args.length);
|
||||||
for (int i = 0; i < args.length; i++)
|
for (int i = 0; i < args.length; i++)
|
||||||
printf("args[%d] = '%s'\n", i, (char *)args[i]);
|
printf("args[%d] = '%s'\n", i, (char *)args[i]);
|
||||||
|
printf("Success\n!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile to build D runtime library phobos.lib.
|
# Makefile to build D runtime library phobos.lib for Win32
|
||||||
# Designed to work with \dm\bin\make.exe
|
# Designed to work with \dm\bin\make.exe
|
||||||
# Targets:
|
# Targets:
|
||||||
# make
|
# make
|
||||||
|
@ -68,8 +68,8 @@ OBJS= assert.obj deh.obj switch.obj complex.obj gcstats.obj \
|
||||||
|
|
||||||
HDR=mars.h
|
HDR=mars.h
|
||||||
|
|
||||||
SRC= switch.d complex.c critical.c fpu.d \
|
SRC= switch.d complex.c critical.c errno.c alloca.d cmath.d \
|
||||||
aa.c vaa.c interface.c minit.asm
|
minit.asm linux.d deh2.d date.d linuxextern.d llmath.d
|
||||||
|
|
||||||
SRC2=deh.c object.d gc.d math.d c\stdio.d c\stdlib.d time.d monitor.c arraycat.d \
|
SRC2=deh.c object.d gc.d math.d c\stdio.d c\stdlib.d time.d monitor.c arraycat.d \
|
||||||
string.d windows.d path.d
|
string.d windows.d path.d
|
||||||
|
@ -77,7 +77,7 @@ SRC2=deh.c object.d gc.d math.d c\stdio.d c\stdlib.d time.d monitor.c arraycat.d
|
||||||
SRC3=invariant.d assert.d RegExp.d dmain2.d dateparse.d \
|
SRC3=invariant.d assert.d RegExp.d dmain2.d dateparse.d \
|
||||||
outofmemory.d syserror.d
|
outofmemory.d syserror.d
|
||||||
|
|
||||||
SRC4=dchar.d ctype.d achar.d aaA.d adi.d file.d compiler.d system.d \
|
SRC4= ctype.d achar.d aaA.d adi.d file.d compiler.d system.d \
|
||||||
moduleinit.d cast.d math.d qsort.d
|
moduleinit.d cast.d math.d qsort.d
|
||||||
|
|
||||||
SRC5=outbuffer.d unittest.d stream.d ctype.d regexp.d random.d adi.d \
|
SRC5=outbuffer.d unittest.d stream.d ctype.d regexp.d random.d adi.d \
|
||||||
|
@ -94,7 +94,7 @@ SRC7=ti_wchar.d ti_uint.d ti_short.d ti_ushort.d \
|
||||||
|
|
||||||
SRC8=crc32.d stdint.d conv.d gcstats.d
|
SRC8=crc32.d stdint.d conv.d gcstats.d
|
||||||
|
|
||||||
phobos.lib : $(OBJS) minit.obj gc2\dmgc.lib makefile
|
phobos.lib : $(OBJS) minit.obj gc2\dmgc.lib win32.mak
|
||||||
lib -c phobos.lib $(OBJS) minit.obj gc2\dmgc.lib
|
lib -c phobos.lib $(OBJS) minit.obj gc2\dmgc.lib
|
||||||
|
|
||||||
aaA.obj : aaA.d
|
aaA.obj : aaA.d
|
||||||
|
@ -131,9 +131,9 @@ ti_C.obj : ti_C.d
|
||||||
ti_char.obj : ti_char.d
|
ti_char.obj : ti_char.d
|
||||||
ti_int.obj : ti_int.d
|
ti_int.obj : ti_int.d
|
||||||
|
|
||||||
zip : makefile $(HDR) $(SRC) $(SRC2) $(SRC3) $(SRC4) $(SRC5) $(SRC6) $(SRC7) \
|
zip : win32.mak linux.mak $(HDR) $(SRC) $(SRC2) $(SRC3) $(SRC4) $(SRC5) $(SRC6) $(SRC7) \
|
||||||
$(SRC8)
|
$(SRC8)
|
||||||
zip32 -u phobos makefile $(HDR)
|
zip32 -u phobos win32.mak linux.mak $(HDR)
|
||||||
zip32 -u phobos $(SRC)
|
zip32 -u phobos $(SRC)
|
||||||
zip32 -u phobos $(SRC2)
|
zip32 -u phobos $(SRC2)
|
||||||
zip32 -u phobos $(SRC3)
|
zip32 -u phobos $(SRC3)
|
Loading…
Add table
Add a link
Reference in a new issue