mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
Added copy of druntime from DMD 2.020 modified for LDC.
This commit is contained in:
4
bin/ldc2.conf
Normal file
4
bin/ldc2.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
[Environment]
|
||||
|
||||
DFLAGS=-I%@P%/../druntime/import -L-L%@P%/../druntime/lib
|
||||
29
druntime/import/ldc/cstdarg.di
Normal file
29
druntime/import/ldc/cstdarg.di
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* vararg support for extern(C) functions
|
||||
*/
|
||||
|
||||
module ldc.cstdarg;
|
||||
|
||||
// Check for the right compiler
|
||||
version(LDC)
|
||||
{
|
||||
// OK
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(false, "This module is only valid for LDC");
|
||||
}
|
||||
|
||||
alias void* va_list;
|
||||
|
||||
pragma(va_start)
|
||||
void va_start(T)(va_list ap, ref T);
|
||||
|
||||
pragma(va_arg)
|
||||
T va_arg(T)(va_list ap);
|
||||
|
||||
pragma(va_end)
|
||||
void va_end(va_list args);
|
||||
|
||||
pragma(va_copy)
|
||||
void va_copy(va_list dst, va_list src);
|
||||
343
druntime/import/ldc/intrinsics.di
Normal file
343
druntime/import/ldc/intrinsics.di
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* This module holds declarations to LLVM intrinsics.
|
||||
*
|
||||
* See the LLVM language reference for more information:
|
||||
*
|
||||
* - http://llvm.org/docs/LangRef.html#intrinsics
|
||||
*
|
||||
*/
|
||||
|
||||
module ldc.intrinsics;
|
||||
|
||||
// Check for the right compiler
|
||||
version(LDC)
|
||||
{
|
||||
// OK
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(false, "This module is only valid for LDC");
|
||||
}
|
||||
|
||||
//
|
||||
// CODE GENERATOR INTRINSICS
|
||||
//
|
||||
|
||||
|
||||
// The 'llvm.returnaddress' intrinsic attempts to compute a target-specific value indicating the return address of the current function or one of its callers.
|
||||
|
||||
pragma(intrinsic, "llvm.returnaddress")
|
||||
void* llvm_returnaddress(uint level);
|
||||
|
||||
|
||||
// The 'llvm.frameaddress' intrinsic attempts to return the target-specific frame pointer value for the specified stack frame.
|
||||
|
||||
pragma(intrinsic, "llvm.frameaddress")
|
||||
void* llvm_frameaddress(uint level);
|
||||
|
||||
|
||||
// The 'llvm.stacksave' intrinsic is used to remember the current state of the function stack, for use with llvm.stackrestore. This is useful for implementing language features like scoped automatic variable sized arrays in C99.
|
||||
|
||||
pragma(intrinsic, "llvm.stacksave")
|
||||
void* llvm_stacksave();
|
||||
|
||||
|
||||
// The 'llvm.stackrestore' intrinsic is used to restore the state of the function stack to the state it was in when the corresponding llvm.stacksave intrinsic executed. This is useful for implementing language features like scoped automatic variable sized arrays in C99.
|
||||
|
||||
pragma(intrinsic, "llvm.stackrestore")
|
||||
void llvm_stackrestore(void* ptr);
|
||||
|
||||
|
||||
// The 'llvm.prefetch' intrinsic is a hint to the code generator to insert a prefetch instruction if supported; otherwise, it is a noop. Prefetches have no effect on the behavior of the program but can change its performance characteristics.
|
||||
|
||||
pragma(intrinsic, "llvm.prefetch")
|
||||
void llvm_prefetch(void* ptr, uint rw, uint locality);
|
||||
|
||||
|
||||
// The 'llvm.pcmarker' intrinsic is a method to export a Program Counter (PC) in a region of code to simulators and other tools. The method is target specific, but it is expected that the marker will use exported symbols to transmit the PC of the marker. The marker makes no guarantees that it will remain with any specific instruction after optimizations. It is possible that the presence of a marker will inhibit optimizations. The intended use is to be inserted after optimizations to allow correlations of simulation runs.
|
||||
|
||||
pragma(intrinsic, "llvm.pcmarker")
|
||||
void llvm_pcmarker(uint id);
|
||||
|
||||
|
||||
// The 'llvm.readcyclecounter' intrinsic provides access to the cycle counter register (or similar low latency, high accuracy clocks) on those targets that support it. On X86, it should map to RDTSC. On Alpha, it should map to RPCC. As the backing counters overflow quickly (on the order of 9 seconds on alpha), this should only be used for small timings.
|
||||
|
||||
pragma(intrinsic, "llvm.readcyclecounter")
|
||||
ulong readcyclecounter();
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// STANDARD C LIBRARY INTRINSICS
|
||||
//
|
||||
|
||||
|
||||
// The 'llvm.memcpy.*' intrinsics copy a block of memory from the source location to the destination location.
|
||||
// Note that, unlike the standard libc function, the llvm.memcpy.* intrinsics do not return a value, and takes an extra alignment argument.
|
||||
|
||||
pragma(intrinsic, "llvm.memcpy.i32")
|
||||
void llvm_memcpy_i32(void* dst, void* src, uint len, uint alignment);
|
||||
pragma(intrinsic, "llvm.memcpy.i64")
|
||||
void llvm_memcpy_i64(void* dst, void* src, ulong len, uint alignment);
|
||||
|
||||
|
||||
// The 'llvm.memmove.*' intrinsics move a block of memory from the source location to the destination location. It is similar to the 'llvm.memcpy' intrinsic but allows the two memory locations to overlap.
|
||||
// Note that, unlike the standard libc function, the llvm.memmove.* intrinsics do not return a value, and takes an extra alignment argument.
|
||||
|
||||
pragma(intrinsic, "llvm.memmove.i32")
|
||||
void llvm_memmove_i32(void* dst, void* src, uint len, uint alignment);
|
||||
pragma(intrinsic, "llvm.memmove.i64")
|
||||
void llvm_memmove_i64(void* dst, void* src, ulong len, int alignment);
|
||||
|
||||
|
||||
// The 'llvm.memset.*' intrinsics fill a block of memory with a particular byte value.
|
||||
// Note that, unlike the standard libc function, the llvm.memset intrinsic does not return a value, and takes an extra alignment argument.
|
||||
|
||||
pragma(intrinsic, "llvm.memset.i32")
|
||||
void llvm_memset_i32(void* dst, ubyte val, uint len, uint alignment);
|
||||
pragma(intrinsic, "llvm.memset.i64")
|
||||
void llvm_memset_i64(void* dst, ubyte val, ulong len, uint alignment);
|
||||
|
||||
|
||||
// The 'llvm.sqrt' intrinsics return the sqrt of the specified operand, returning the same value as the libm 'sqrt' functions would. Unlike sqrt in libm, however, llvm.sqrt has undefined behavior for negative numbers other than -0.0 (which allows for better optimization, because there is no need to worry about errno being set). llvm.sqrt(-0.0) is defined to return -0.0 like IEEE sqrt.
|
||||
|
||||
pragma(intrinsic, "llvm.sqrt.f32")
|
||||
float llvm_sqrt_f32(float val);
|
||||
pragma(intrinsic, "llvm.sqrt.f64")
|
||||
double llvm_sqrt_f64(double val);
|
||||
version(X86)
|
||||
{
|
||||
pragma(intrinsic, "llvm.sqrt.f80")
|
||||
real llvm_sqrt_f80(real val);
|
||||
}
|
||||
|
||||
version(X86_64)
|
||||
{
|
||||
pragma(intrinsic, "llvm.sqrt.f80")
|
||||
real llvm_sqrt_f80(real val);
|
||||
}
|
||||
|
||||
|
||||
// The 'llvm.sin.*' intrinsics return the sine of the operand.
|
||||
|
||||
pragma(intrinsic, "llvm.sin.f32")
|
||||
float llvm_sin_f32(float val);
|
||||
pragma(intrinsic, "llvm.sin.f64")
|
||||
double llvm_sin_f64(double val);
|
||||
version(X86)
|
||||
{
|
||||
pragma(intrinsic, "llvm.sin.f80")
|
||||
real llvm_sin_f80(real val);
|
||||
}
|
||||
|
||||
version(X86_64)
|
||||
{
|
||||
pragma(intrinsic, "llvm.sin.f80")
|
||||
real llvm_sin_f80(real val);
|
||||
}
|
||||
|
||||
|
||||
// The 'llvm.cos.*' intrinsics return the cosine of the operand.
|
||||
|
||||
pragma(intrinsic, "llvm.cos.f32")
|
||||
float llvm_cos_f32(float val);
|
||||
pragma(intrinsic, "llvm.cos.f64")
|
||||
double llvm_cos_f64(double val);
|
||||
version(X86)
|
||||
{
|
||||
pragma(intrinsic, "llvm.cos.f80")
|
||||
real llvm_cos_f80(real val);
|
||||
}
|
||||
|
||||
version(X86_64)
|
||||
{
|
||||
pragma(intrinsic, "llvm.cos.f80")
|
||||
real llvm_cos_f80(real val);
|
||||
}
|
||||
|
||||
|
||||
// The 'llvm.powi.*' intrinsics return the first operand raised to the specified (positive or negative) power. The order of evaluation of multiplications is not defined. When a vector of floating point type is used, the second argument remains a scalar integer value.
|
||||
|
||||
pragma(intrinsic, "llvm.powi.f32")
|
||||
float llvm_powi_f32(float val, int power);
|
||||
|
||||
pragma(intrinsic, "llvm.powi.f64")
|
||||
double llvm_powi_f64(double val, int power);
|
||||
version(X86)
|
||||
{
|
||||
pragma(intrinsic, "llvm.powi.f80")
|
||||
real llvm_powi_f80(real val, int power);
|
||||
}
|
||||
|
||||
version(X86_64)
|
||||
{
|
||||
pragma(intrinsic, "llvm.powi.f80")
|
||||
real llvm_powi_f80(real val, int power);
|
||||
}
|
||||
|
||||
// The 'llvm.pow.*' intrinsics return the first operand raised to the specified (positive or negative) power.
|
||||
|
||||
pragma(intrinsic, "llvm.pow.f32")
|
||||
float llvm_pow_f32(float val, float power);
|
||||
|
||||
pragma(intrinsic, "llvm.pow.f64")
|
||||
double llvm_pow_f64(double val, double power);
|
||||
version(X86)
|
||||
{
|
||||
pragma(intrinsic, "llvm.pow.f80")
|
||||
real llvm_pow_f80(real val, real power);
|
||||
}
|
||||
|
||||
version(X86_64)
|
||||
{
|
||||
pragma(intrinsic, "llvm.pow.f80")
|
||||
real llvm_pow_f80(real val, real power);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// BIT MANIPULATION INTRINSICS
|
||||
//
|
||||
|
||||
// The 'llvm.bswap' family of intrinsics is used to byte swap integer values with an even number of bytes (positive multiple of 16 bits). These are useful for performing operations on data that is not in the target's native byte order.
|
||||
|
||||
pragma(intrinsic, "llvm.bswap.i16.i16")
|
||||
ushort llvm_bswap_i16(ushort val);
|
||||
|
||||
pragma(intrinsic, "llvm.bswap.i32.i32")
|
||||
uint llvm_bswap_i32(uint val);
|
||||
|
||||
pragma(intrinsic, "llvm.bswap.i64.i64")
|
||||
ulong llvm_bswap_i64(ulong val);
|
||||
|
||||
|
||||
// The 'llvm.ctpop' family of intrinsics counts the number of bits set in a value.
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i8")
|
||||
ubyte llvm_ctpop_i8(ubyte src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i16")
|
||||
ushort llvm_ctpop_i16(ushort src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i32")
|
||||
uint llvm_ctpop_i32(uint src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i64")
|
||||
ulong llvm_ctpop_i64(ulong src);
|
||||
|
||||
|
||||
// The 'llvm.ctlz' family of intrinsic functions counts the number of leading zeros in a variable.
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i8")
|
||||
ubyte llvm_ctlz_i8(ubyte src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i16")
|
||||
ushort llvm_ctlz_i16(ushort src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i32")
|
||||
uint llvm_ctlz_i32(uint src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i64")
|
||||
ulong llvm_ctlz_i64(ulong src);
|
||||
|
||||
|
||||
// The 'llvm.cttz' family of intrinsic functions counts the number of trailing zeros.
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i8")
|
||||
ubyte llvm_cttz_i8(ubyte src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i16")
|
||||
ushort llvm_cttz_i16(ushort src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i32")
|
||||
uint llvm_cttz_i32(uint src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i64")
|
||||
ulong llvm_cttz_i64(ulong src);
|
||||
|
||||
|
||||
// The 'llvm.part.select' family of intrinsic functions selects a range of bits from an integer value and returns them in the same bit width as the original value.
|
||||
|
||||
pragma(intrinsic, "llvm.part.select.i8")
|
||||
ubyte llvm_part_select_i(ubyte val, uint loBit, uint hiBit);
|
||||
|
||||
pragma(intrinsic, "llvm.part.select.i16")
|
||||
ushort llvm_part_select_i(ushort val, uint loBit, uint hiBit);
|
||||
|
||||
pragma(intrinsic, "llvm.part.select.i32")
|
||||
uint llvm_part_select_i(uint val, uint loBit, uint hiBit);
|
||||
|
||||
pragma(intrinsic, "llvm.part.select.i64")
|
||||
ulong llvm_part_select_i(ulong val, uint loBit, uint hiBit);
|
||||
|
||||
|
||||
// The 'llvm.part.set' family of intrinsic functions replaces a range of bits in an integer value with another integer value. It returns the integer with the replaced bits.
|
||||
|
||||
// TODO
|
||||
// declare i17 @llvm.part.set.i17.i9 (i17 %val, i9 %repl, i32 %lo, i32 %hi)
|
||||
// declare i29 @llvm.part.set.i29.i9 (i29 %val, i9 %repl, i32 %lo, i32 %hi)
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// ATOMIC OPERATIONS AND SYNCHRONIZATION INTRINSICS
|
||||
//
|
||||
|
||||
// The llvm.memory.barrier intrinsic guarantees ordering between specific pairs of memory access types.
|
||||
|
||||
pragma(intrinsic, "llvm.memory.barrier")
|
||||
void llvm_memory_barrier(bool ll, bool ls, bool sl, bool ss, bool device);
|
||||
|
||||
// This loads a value in memory and compares it to a given value. If they are equal, it stores a new value into the memory.
|
||||
|
||||
pragma(intrinsic, "llvm.atomic.cmp.swap.i#.p0i#")
|
||||
T llvm_atomic_cmp_swap(T)(T* ptr, T cmp, T val);
|
||||
|
||||
// This intrinsic loads the value stored in memory at ptr and yields the value from memory. It then stores the value in val in the memory at ptr.
|
||||
|
||||
pragma(intrinsic, "llvm.atomic.swap.i#.p0i#")
|
||||
T llvm_atomic_swap(T)(T* ptr, T val);
|
||||
|
||||
// This intrinsic adds delta to the value stored in memory at ptr. It yields the original value at ptr.
|
||||
|
||||
pragma(intrinsic, "llvm.atomic.load.add.i#.p0i#")
|
||||
T llvm_atomic_load_add(T)(T* ptr, T val);
|
||||
|
||||
// This intrinsic subtracts delta to the value stored in memory at ptr. It yields the original value at ptr.
|
||||
|
||||
pragma(intrinsic, "llvm.atomic.load.sub.i#.p0i#")
|
||||
T llvm_atomic_load_sub(T)(T* ptr, T val);
|
||||
|
||||
// These intrinsics bitwise the operation (and, nand, or, xor) delta to the value stored in memory at ptr. It yields the original value at ptr.
|
||||
|
||||
pragma(intrinsic, "llvm.atomic.load.and.i#.p0i#")
|
||||
T llvm_atomic_load_and(T)(T* ptr, T val);
|
||||
pragma(intrinsic, "llvm.atomic.load.nand.i#.p0i#")
|
||||
T llvm_atomic_load_nand(T)(T* ptr, T val);
|
||||
pragma(intrinsic, "llvm.atomic.load.or.i#.p0i#")
|
||||
T llvm_atomic_load_or(T)(T* ptr, T val);
|
||||
pragma(intrinsic, "llvm.atomic.load.xor.i#.p0i#")
|
||||
T llvm_atomic_load_xor(T)(T* ptr, T val);
|
||||
|
||||
// These intrinsics takes the signed or unsigned minimum or maximum of delta and the value stored in memory at ptr. It yields the original value at ptr.
|
||||
|
||||
pragma(intrinsic, "llvm.atomic.load.max.i#.p0i#")
|
||||
T llvm_atomic_load_max(T)(T* ptr, T val);
|
||||
pragma(intrinsic, "llvm.atomic.load.min.i#.p0i#")
|
||||
T llvm_atomic_load_min(T)(T* ptr, T val);
|
||||
pragma(intrinsic, "llvm.atomic.load.umax.i#.p0i#")
|
||||
T llvm_atomic_load_umax(T)(T* ptr, T val);
|
||||
pragma(intrinsic, "llvm.atomic.load.umin.i#.p0i#")
|
||||
T llvm_atomic_load_umin(T)(T* ptr, T val);
|
||||
|
||||
//
|
||||
// GENERAL INTRINSICS
|
||||
//
|
||||
|
||||
|
||||
// This intrinsics is lowered to the target dependent trap instruction. If the target does not have a trap instruction, this intrinsic will be lowered to the call of the abort() function.
|
||||
|
||||
pragma(intrinsic, "llvm.trap")
|
||||
void llvm_trap();
|
||||
10
druntime/license.txt
Normal file
10
druntime/license.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Copyright (c) 2008, The D Runtime Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
10
druntime/readme.txt
Normal file
10
druntime/readme.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Druntime
|
||||
|
||||
The source code repository for druntime is: http://dsource.org/projects/druntime
|
||||
|
||||
Druntime is the minimum library required to support the D programming
|
||||
language. It includes the system code required to support the garbage collector,
|
||||
associative arrays, exception handling, array vector operations,
|
||||
startup/shutdown, etc.
|
||||
|
||||
Druntime forms a common layer underlying the Phobos and Tango user libraries.
|
||||
7
druntime/src/build-dmd.bat
Normal file
7
druntime/src/build-dmd.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
set OLDHOME=%HOME%
|
||||
set HOME=%CD%
|
||||
make clean -fdmd-win32.mak
|
||||
make lib install -fdmd-win32.mak
|
||||
make clean -fdmd-win32.mak
|
||||
set HOME=%OLDHOME%
|
||||
19
druntime/src/build-dmd.sh
Normal file
19
druntime/src/build-dmd.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OLDHOME=$HOME
|
||||
export HOME=`pwd`
|
||||
|
||||
goerror(){
|
||||
export HOME=$OLDHOME
|
||||
echo "="
|
||||
echo "= *** Error ***"
|
||||
echo "="
|
||||
exit 1
|
||||
}
|
||||
|
||||
make clean -fdmd-posix.mak || goerror
|
||||
make lib doc install -fdmd-posix.mak || goerror
|
||||
make clean -fdmd-posix.mak || goerror
|
||||
chmod 644 ../import/*.di || goerror
|
||||
|
||||
export HOME=$OLDHOME
|
||||
19
druntime/src/build-ldc.sh
Normal file
19
druntime/src/build-ldc.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OLDHOME=$HOME
|
||||
export HOME=`pwd`
|
||||
|
||||
goerror(){
|
||||
export HOME=$OLDHOME
|
||||
echo "="
|
||||
echo "= *** Error ***"
|
||||
echo "="
|
||||
exit 1
|
||||
}
|
||||
|
||||
make clean -fldc-gcc.mak || goerror
|
||||
make lib doc install -fldc-gcc.mak || goerror
|
||||
make clean -fldc-gcc.mak || goerror
|
||||
chmod 644 ../import/*.di || goerror
|
||||
|
||||
export HOME=$OLDHOME
|
||||
290
druntime/src/common/core/bitmanip.d
Normal file
290
druntime/src/common/core/bitmanip.d
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* This module contains a collection of bit-level operations.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Walter Bright, Don Clugston, Sean Kelly
|
||||
*/
|
||||
module core.bitmanip;
|
||||
|
||||
|
||||
version( DDoc )
|
||||
{
|
||||
/**
|
||||
* Scans the bits in v starting with bit 0, looking
|
||||
* for the first set bit.
|
||||
* Returns:
|
||||
* The bit number of the first bit set.
|
||||
* The return value is undefined if v is zero.
|
||||
*/
|
||||
int bsf( uint v );
|
||||
|
||||
|
||||
/**
|
||||
* Scans the bits in v from the most significant bit
|
||||
* to the least significant bit, looking
|
||||
* for the first set bit.
|
||||
* Returns:
|
||||
* The bit number of the first bit set.
|
||||
* The return value is undefined if v is zero.
|
||||
* Example:
|
||||
* ---
|
||||
* import core.bitmanip;
|
||||
*
|
||||
* int main()
|
||||
* {
|
||||
* uint v;
|
||||
* int x;
|
||||
*
|
||||
* v = 0x21;
|
||||
* x = bsf(v);
|
||||
* printf("bsf(x%x) = %d\n", v, x);
|
||||
* x = bsr(v);
|
||||
* printf("bsr(x%x) = %d\n", v, x);
|
||||
* return 0;
|
||||
* }
|
||||
* ---
|
||||
* Output:
|
||||
* bsf(x21) = 0<br>
|
||||
* bsr(x21) = 5
|
||||
*/
|
||||
int bsr( uint v );
|
||||
|
||||
|
||||
/**
|
||||
* Tests the bit.
|
||||
*/
|
||||
int bt( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* Tests and complements the bit.
|
||||
*/
|
||||
int btc( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* Tests and resets (sets to 0) the bit.
|
||||
*/
|
||||
int btr( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* Tests and sets the bit.
|
||||
* Params:
|
||||
* p = a non-NULL pointer to an array of uints.
|
||||
* index = a bit number, starting with bit 0 of p[0],
|
||||
* and progressing. It addresses bits like the expression:
|
||||
---
|
||||
p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
|
||||
---
|
||||
* Returns:
|
||||
* A non-zero value if the bit was set, and a zero
|
||||
* if it was clear.
|
||||
*
|
||||
* Example:
|
||||
* ---
|
||||
import core.bitmanip;
|
||||
|
||||
int main()
|
||||
{
|
||||
uint array[2];
|
||||
|
||||
array[0] = 2;
|
||||
array[1] = 0x100;
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
* ---
|
||||
* Output:
|
||||
<pre>
|
||||
btc(array, 35) = 0
|
||||
array = [0]:x2, [1]:x108
|
||||
btc(array, 35) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
bts(array, 35) = 0
|
||||
array = [0]:x2, [1]:x108
|
||||
btr(array, 35) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
bt(array, 1) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
</pre>
|
||||
*/
|
||||
int bts( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
|
||||
* byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
|
||||
* becomes byte 0.
|
||||
*/
|
||||
uint bswap( uint v );
|
||||
|
||||
|
||||
/**
|
||||
* Reads I/O port at port_address.
|
||||
*/
|
||||
ubyte inp( uint port_address );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
ushort inpw( uint port_address );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
uint inpl( uint port_address );
|
||||
|
||||
|
||||
/**
|
||||
* Writes and returns value to I/O port at port_address.
|
||||
*/
|
||||
ubyte outp( uint port_address, ubyte value );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
ushort outpw( uint port_address, ushort value );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
uint outpl( uint port_address, uint value );
|
||||
}
|
||||
else version( LDC )
|
||||
{
|
||||
public import ldc.bitmanip;
|
||||
}
|
||||
else
|
||||
{
|
||||
public import std.intrinsic;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the number of set bits in a 32-bit integer.
|
||||
*/
|
||||
int popcnt( uint x )
|
||||
{
|
||||
// Avoid branches, and the potential for cache misses which
|
||||
// could be incurred with a table lookup.
|
||||
|
||||
// We need to mask alternate bits to prevent the
|
||||
// sum from overflowing.
|
||||
// add neighbouring bits. Each bit is 0 or 1.
|
||||
x = x - ((x>>1) & 0x5555_5555);
|
||||
// now each two bits of x is a number 00,01 or 10.
|
||||
// now add neighbouring pairs
|
||||
x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333);
|
||||
// now each nibble holds 0000-0100. Adding them won't
|
||||
// overflow any more, so we don't need to mask any more
|
||||
|
||||
// Now add the nibbles, then the bytes, then the words
|
||||
// We still need to mask to prevent double-counting.
|
||||
// Note that if we used a rotate instead of a shift, we
|
||||
// wouldn't need the masks, and could just divide the sum
|
||||
// by 8 to account for the double-counting.
|
||||
// On some CPUs, it may be faster to perform a multiply.
|
||||
|
||||
x += (x>>4);
|
||||
x &= 0x0F0F_0F0F;
|
||||
x += (x>>8);
|
||||
x &= 0x00FF_00FF;
|
||||
x += (x>>16);
|
||||
x &= 0xFFFF;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
debug( UnitTest )
|
||||
{
|
||||
unittest
|
||||
{
|
||||
assert( popcnt( 0 ) == 0 );
|
||||
assert( popcnt( 7 ) == 3 );
|
||||
assert( popcnt( 0xAA )== 4 );
|
||||
assert( popcnt( 0x8421_1248 ) == 8 );
|
||||
assert( popcnt( 0xFFFF_FFFF ) == 32 );
|
||||
assert( popcnt( 0xCCCC_CCCC ) == 16 );
|
||||
assert( popcnt( 0x7777_7777 ) == 24 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverses the order of bits in a 32-bit integer.
|
||||
*/
|
||||
uint bitswap( uint x )
|
||||
{
|
||||
|
||||
version( D_InlineAsm_X86 )
|
||||
{
|
||||
asm
|
||||
{
|
||||
// Author: Tiago Gasiba.
|
||||
mov EDX, EAX;
|
||||
shr EAX, 1;
|
||||
and EDX, 0x5555_5555;
|
||||
and EAX, 0x5555_5555;
|
||||
shl EDX, 1;
|
||||
or EAX, EDX;
|
||||
mov EDX, EAX;
|
||||
shr EAX, 2;
|
||||
and EDX, 0x3333_3333;
|
||||
and EAX, 0x3333_3333;
|
||||
shl EDX, 2;
|
||||
or EAX, EDX;
|
||||
mov EDX, EAX;
|
||||
shr EAX, 4;
|
||||
and EDX, 0x0f0f_0f0f;
|
||||
and EAX, 0x0f0f_0f0f;
|
||||
shl EDX, 4;
|
||||
or EAX, EDX;
|
||||
bswap EAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// swap odd and even bits
|
||||
x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1);
|
||||
// swap consecutive pairs
|
||||
x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2);
|
||||
// swap nibbles
|
||||
x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4);
|
||||
// swap bytes
|
||||
x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8);
|
||||
// swap 2-byte long pairs
|
||||
x = ( x >> 16 ) | ( x << 16);
|
||||
return x;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
debug( UnitTest )
|
||||
{
|
||||
unittest
|
||||
{
|
||||
assert( bitswap( 0x8000_0100 ) == 0x0080_0001 );
|
||||
}
|
||||
}
|
||||
276
druntime/src/common/core/exception.d
Normal file
276
druntime/src/common/core/exception.d
Normal file
@@ -0,0 +1,276 @@
|
||||
/**
|
||||
* The exception module defines all system-level exceptions and provides a
|
||||
* mechanism to alter system-level error handling.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module core.exception;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
alias void function( string file, size_t line, string msg = null ) assertHandlerType;
|
||||
|
||||
assertHandlerType assertHandler = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on an array bounds error.
|
||||
*/
|
||||
class ArrayBoundsException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "Array index out of bounds", file, line );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on an assert error.
|
||||
*/
|
||||
class AssertException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "Assertion failure", file, line );
|
||||
}
|
||||
|
||||
this( string msg, string file, size_t line )
|
||||
{
|
||||
super( msg, file, line );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on finalize error.
|
||||
*/
|
||||
class FinalizeException : Exception
|
||||
{
|
||||
ClassInfo info;
|
||||
|
||||
this( ClassInfo c, Exception e = null )
|
||||
{
|
||||
super( "Finalization error", e );
|
||||
info = c;
|
||||
}
|
||||
|
||||
override string toString()
|
||||
{
|
||||
return "An exception was thrown while finalizing an instance of class " ~ info.name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on hidden function error.
|
||||
*/
|
||||
class HiddenFuncException : Exception
|
||||
{
|
||||
this( ClassInfo ci )
|
||||
{
|
||||
super( "Hidden method called for " ~ ci.name );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on an out of memory error.
|
||||
*/
|
||||
class OutOfMemoryException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "Memory allocation failed", file, line );
|
||||
}
|
||||
|
||||
override string toString()
|
||||
{
|
||||
return msg ? super.toString() : "Memory allocation failed";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on a switch error.
|
||||
*/
|
||||
class SwitchException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "No appropriate switch clause found", file, line );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on a unicode conversion error.
|
||||
*/
|
||||
class UnicodeException : Exception
|
||||
{
|
||||
size_t idx;
|
||||
|
||||
this( string msg, size_t idx )
|
||||
{
|
||||
super( msg );
|
||||
this.idx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Overrides
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default assert hander with a user-supplied version.
|
||||
*
|
||||
* Params:
|
||||
* h = The new assert handler. Set to null to use the default handler.
|
||||
*/
|
||||
void setAssertHandler( assertHandlerType h )
|
||||
{
|
||||
assertHandler = h;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Overridable Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A callback for assert errors in D. The user-supplied assert handler will
|
||||
* be called if one has been supplied, otherwise an AssertException will be
|
||||
* thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
*/
|
||||
extern (C) void onAssertError( string file, size_t line )
|
||||
{
|
||||
if( assertHandler is null )
|
||||
throw new AssertException( file, line );
|
||||
assertHandler( file, line );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for assert errors in D. The user-supplied assert handler will
|
||||
* be called if one has been supplied, otherwise an AssertException will be
|
||||
* thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
* msg = An error message supplied by the user.
|
||||
*/
|
||||
extern (C) void onAssertErrorMsg( string file, size_t line, string msg )
|
||||
{
|
||||
if( assertHandler is null )
|
||||
throw new AssertException( msg, file, line );
|
||||
assertHandler( file, line, msg );
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Internal Error Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A callback for array bounds errors in D. An ArrayBoundsException will be
|
||||
* thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
*
|
||||
* Throws:
|
||||
* ArrayBoundsException.
|
||||
*/
|
||||
extern (C) void onArrayBoundsError( string file, size_t line )
|
||||
{
|
||||
throw new ArrayBoundsException( file, line );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for finalize errors in D. A FinalizeException will be thrown.
|
||||
*
|
||||
* Params:
|
||||
* e = The exception thrown during finalization.
|
||||
*
|
||||
* Throws:
|
||||
* FinalizeException.
|
||||
*/
|
||||
extern (C) void onFinalizeError( ClassInfo info, Exception ex )
|
||||
{
|
||||
throw new FinalizeException( info, ex );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for hidden function errors in D. A HiddenFuncException will be
|
||||
* thrown.
|
||||
*
|
||||
* Throws:
|
||||
* HiddenFuncException.
|
||||
*/
|
||||
extern (C) void onHiddenFuncError( Object o )
|
||||
{
|
||||
throw new HiddenFuncException( o.classinfo );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for out of memory errors in D. An OutOfMemoryException will be
|
||||
* thrown.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException.
|
||||
*/
|
||||
extern (C) void onOutOfMemoryError()
|
||||
{
|
||||
// NOTE: Since an out of memory condition exists, no allocation must occur
|
||||
// while generating this object.
|
||||
throw cast(OutOfMemoryException) cast(void*) OutOfMemoryException.classinfo.init;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for switch errors in D. A SwitchException will be thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
*
|
||||
* Throws:
|
||||
* SwitchException.
|
||||
*/
|
||||
extern (C) void onSwitchError( string file, size_t line )
|
||||
{
|
||||
throw new SwitchException( file, line );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for unicode errors in D. A UnicodeException will be thrown.
|
||||
*
|
||||
* Params:
|
||||
* msg = Information about the error.
|
||||
* idx = String index where this error was detected.
|
||||
*
|
||||
* Throws:
|
||||
* UnicodeException.
|
||||
*/
|
||||
extern (C) void onUnicodeError( string msg, size_t idx )
|
||||
{
|
||||
throw new UnicodeException( msg, idx );
|
||||
}
|
||||
484
druntime/src/common/core/memory.d
Normal file
484
druntime/src/common/core/memory.d
Normal file
@@ -0,0 +1,484 @@
|
||||
/**
|
||||
* The memory module provides an interface to the garbage collector and to
|
||||
* any other OS or API-level memory management facilities.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module core.memory;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
extern (C) void gc_init();
|
||||
extern (C) void gc_term();
|
||||
|
||||
extern (C) void gc_enable();
|
||||
extern (C) void gc_disable();
|
||||
extern (C) void gc_collect();
|
||||
extern (C) void gc_minimize();
|
||||
|
||||
extern (C) uint gc_getAttr( void* p );
|
||||
extern (C) uint gc_setAttr( void* p, uint a );
|
||||
extern (C) uint gc_clrAttr( void* p, uint a );
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 );
|
||||
extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
|
||||
extern (C) size_t gc_reserve( size_t sz );
|
||||
extern (C) void gc_free( void* p );
|
||||
|
||||
extern (C) void* gc_addrOf( void* p );
|
||||
extern (C) size_t gc_sizeOf( void* p );
|
||||
|
||||
struct BlkInfo_
|
||||
{
|
||||
void* base;
|
||||
size_t size;
|
||||
uint attr;
|
||||
}
|
||||
|
||||
extern (C) BlkInfo_ gc_query( void* p );
|
||||
|
||||
extern (C) void gc_addRoot( void* p );
|
||||
extern (C) void gc_addRange( void* p, size_t sz );
|
||||
|
||||
extern (C) void gc_removeRoot( void* p );
|
||||
extern (C) void gc_removeRange( void* p );
|
||||
|
||||
extern (C) void* gc_getHandle();
|
||||
extern (C) void gc_setHandle( void* p );
|
||||
extern (C) void gc_endHandle();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This struct encapsulates all garbage collection functionality for the D
|
||||
* programming language.
|
||||
*/
|
||||
struct GC
|
||||
{
|
||||
/**
|
||||
* Enables the garbage collector if collections have previously been
|
||||
* suspended by a call to disable. This function is reentrant, and
|
||||
* must be called once for every call to disable before the garbage
|
||||
* collector is enabled.
|
||||
*/
|
||||
static void enable()
|
||||
{
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disables the garbage collector. This function is reentrant, but
|
||||
* enable must be called once for each call to disable.
|
||||
*/
|
||||
static void disable()
|
||||
{
|
||||
gc_disable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begins a full collection. While the meaning of this may change based
|
||||
* on the garbage collector implementation, typical behavior is to scan
|
||||
* all stack segments for roots, mark accessible memory blocks as alive,
|
||||
* and then to reclaim free space. This action may need to suspend all
|
||||
* running threads for at least part of the collection process.
|
||||
*/
|
||||
static void collect()
|
||||
{
|
||||
gc_collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the managed memory space be minimized by returning free
|
||||
* physical memory to the operating system. The amount of free memory
|
||||
* returned depends on the allocator design and on program behavior.
|
||||
*/
|
||||
static void minimize()
|
||||
{
|
||||
gc_minimize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Elements for a bit field representing memory block attributes. These
|
||||
* are manipulated via the getAttr, setAttr, clrAttr functions.
|
||||
*/
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
|
||||
NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect.
|
||||
NO_MOVE = 0b0000_0100 /// Do not move this memory block on collect.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Contains aggregate information about a block of managed memory. The
|
||||
* purpose of this struct is to support a more efficient query style in
|
||||
* instances where detailed information is needed.
|
||||
*
|
||||
* base = A pointer to the base of the block in question.
|
||||
* size = The size of the block, calculated from base.
|
||||
* attr = Attribute bits set on the memory block.
|
||||
*/
|
||||
alias BlkInfo_ BlkInfo;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a bit field representing all block attributes set for the memory
|
||||
* referenced by p. If p references memory not originally allocated by
|
||||
* this garbage collector, points to the interior of a memory block, or if
|
||||
* p is null, zero will be returned.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
*
|
||||
* Returns:
|
||||
* A bit field containing any bits set for the memory block referenced by
|
||||
* p or zero on error.
|
||||
*/
|
||||
static uint getAttr( void* p )
|
||||
{
|
||||
return gc_getAttr( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the specified bits for the memory references by p. If p references
|
||||
* memory not originally allocated by this garbage collector, points to the
|
||||
* interior of a memory block, or if p is null, no action will be
|
||||
* performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* a = A bit field containing any bits to set for this memory block.
|
||||
*
|
||||
* The result of a call to getAttr after the specified bits have been
|
||||
* set.
|
||||
*/
|
||||
static uint setAttr( void* p, uint a )
|
||||
{
|
||||
return gc_setAttr( p, a );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears the specified bits for the memory references by p. If p
|
||||
* references memory not originally allocated by this garbage collector,
|
||||
* points to the interior of a memory block, or if p is null, no action
|
||||
* will be performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* a = A bit field containing any bits to clear for this memory block.
|
||||
*
|
||||
* Returns:
|
||||
* The result of a call to getAttr after the specified bits have been
|
||||
* cleared.
|
||||
*/
|
||||
static uint clrAttr( void* p, uint a )
|
||||
{
|
||||
return gc_clrAttr( p, a );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests an aligned block of managed memory from the garbage collector.
|
||||
* This memory may be deleted at will with a call to free, or it may be
|
||||
* discarded and cleaned up automatically during a collection run. If
|
||||
* allocation fails, this function will call onOutOfMemory which is
|
||||
* expected to throw an OutOfMemoryException.
|
||||
*
|
||||
* Params:
|
||||
* sz = The desired allocation size in bytes.
|
||||
* ba = A bitmask of the attributes to set on this block.
|
||||
*
|
||||
* Returns:
|
||||
* A reference to the allocated memory or null if insufficient memory
|
||||
* is available.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException on allocation failure.
|
||||
*/
|
||||
static void* malloc( size_t sz, uint ba = 0 )
|
||||
{
|
||||
return gc_malloc( sz, ba );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests an aligned block of managed memory from the garbage collector,
|
||||
* which is initialized with all bits set to zero. This memory may be
|
||||
* deleted at will with a call to free, or it may be discarded and cleaned
|
||||
* up automatically during a collection run. If allocation fails, this
|
||||
* function will call onOutOfMemory which is expected to throw an
|
||||
* OutOfMemoryException.
|
||||
*
|
||||
* Params:
|
||||
* sz = The desired allocation size in bytes.
|
||||
* ba = A bitmask of the attributes to set on this block.
|
||||
*
|
||||
* Returns:
|
||||
* A reference to the allocated memory or null if insufficient memory
|
||||
* is available.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException on allocation failure.
|
||||
*/
|
||||
static void* calloc( size_t sz, uint ba = 0 )
|
||||
{
|
||||
return gc_calloc( sz, ba );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If sz is zero, the memory referenced by p will be deallocated as if
|
||||
* by a call to free. A new memory block of size sz will then be
|
||||
* allocated as if by a call to malloc, or the implementation may instead
|
||||
* resize the memory block in place. The contents of the new memory block
|
||||
* will be the same as the contents of the old memory block, up to the
|
||||
* lesser of the new and old sizes. Note that existing memory will only
|
||||
* be freed by realloc if sz is equal to zero. The garbage collector is
|
||||
* otherwise expected to later reclaim the memory block if it is unused.
|
||||
* If allocation fails, this function will call onOutOfMemory which is
|
||||
* expected to throw an OutOfMemoryException. If p references memory not
|
||||
* originally allocated by this garbage collector, or if it points to the
|
||||
* interior of a memory block, no action will be taken. If ba is zero
|
||||
* (the default) and p references the head of a valid, known memory block
|
||||
* then any bits set on the current block will be set on the new block if a
|
||||
* reallocation is required. If ba is not zero and p references the head
|
||||
* of a valid, known memory block then the bits in ba will replace those on
|
||||
* the current memory block and will also be set on the new block if a
|
||||
* reallocation is required.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* sz = The desired allocation size in bytes.
|
||||
* ba = A bitmask of the attributes to set on this block.
|
||||
*
|
||||
* Returns:
|
||||
* A reference to the allocated memory on success or null if sz is
|
||||
* zero. On failure, the original value of p is returned.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException on allocation failure.
|
||||
*/
|
||||
static void* realloc( void* p, size_t sz, uint ba = 0 )
|
||||
{
|
||||
return gc_realloc( p, sz, ba );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests that the managed memory block referenced by p be extended in
|
||||
* place by at least mx bytes, with a desired extension of sz bytes. If an
|
||||
* extension of the required size is not possible, if p references memory
|
||||
* not originally allocated by this garbage collector, or if p points to
|
||||
* the interior of a memory block, no action will be taken.
|
||||
*
|
||||
* Params:
|
||||
* mx = The minimum extension size in bytes.
|
||||
* sz = The desired extension size in bytes.
|
||||
*
|
||||
* Returns:
|
||||
* The size in bytes of the extended memory block referenced by p or zero
|
||||
* if no extension occurred.
|
||||
*/
|
||||
static size_t extend( void* p, size_t mx, size_t sz )
|
||||
{
|
||||
return gc_extend( p, mx, sz );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests that at least sz bytes of memory be obtained from the operating
|
||||
* system and marked as free.
|
||||
*
|
||||
* Params:
|
||||
* sz = The desired size in bytes.
|
||||
*
|
||||
* Returns:
|
||||
* The actual number of bytes reserved or zero on error.
|
||||
*/
|
||||
static size_t reserve( size_t sz )
|
||||
{
|
||||
return gc_reserve( sz );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deallocates the memory referenced by p. If p is null, no action
|
||||
* occurs. If p references memory not originally allocated by this
|
||||
* garbage collector, or if it points to the interior of a memory block,
|
||||
* no action will be taken. The block will not be finalized regardless
|
||||
* of whether the FINALIZE attribute is set. If finalization is desired,
|
||||
* use delete instead.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
*/
|
||||
static void free( void* p )
|
||||
{
|
||||
gc_free( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the base address of the memory block containing p. This value
|
||||
* is useful to determine whether p is an interior pointer, and the result
|
||||
* may be passed to routines such as sizeOf which may otherwise fail. If p
|
||||
* references memory not originally allocated by this garbage collector, if
|
||||
* p is null, or if the garbage collector does not support this operation,
|
||||
* null will be returned.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root or the interior of a valid memory block or to
|
||||
* null.
|
||||
*
|
||||
* Returns:
|
||||
* The base address of the memory block referenced by p or null on error.
|
||||
*/
|
||||
static void* addrOf( void* p )
|
||||
{
|
||||
return gc_addrOf( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the true size of the memory block referenced by p. This value
|
||||
* represents the maximum number of bytes for which a call to realloc may
|
||||
* resize the existing block in place. If p references memory not
|
||||
* originally allocated by this garbage collector, points to the interior
|
||||
* of a memory block, or if p is null, zero will be returned.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
*
|
||||
* Returns:
|
||||
* The size in bytes of the memory block referenced by p or zero on error.
|
||||
*/
|
||||
static size_t sizeOf( void* p )
|
||||
{
|
||||
return gc_sizeOf( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns aggregate information about the memory block containing p. If p
|
||||
* references memory not originally allocated by this garbage collector, if
|
||||
* p is null, or if the garbage collector does not support this operation,
|
||||
* BlkInfo.init will be returned. Typically, support for this operation
|
||||
* is dependent on support for addrOf.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root or the interior of a valid memory block or to
|
||||
* null.
|
||||
*
|
||||
* Returns:
|
||||
* Information regarding the memory block referenced by p or BlkInfo.init
|
||||
* on error.
|
||||
*/
|
||||
static BlkInfo query( void* p )
|
||||
{
|
||||
return gc_query( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the memory address referenced by p to an internal list of roots to
|
||||
* be scanned during a collection. If p is null, no operation is
|
||||
* performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
*/
|
||||
static void addRoot( void* p )
|
||||
{
|
||||
gc_addRoot( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the memory block referenced by p and of size sz to an internal list
|
||||
* of ranges to be scanned during a collection. If p is null, no operation
|
||||
* is performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
* sz = The size in bytes of the block to add. If sz is zero then the
|
||||
* no operation will occur. If p is null then sz must be zero.
|
||||
*/
|
||||
static void addRange( void* p, size_t sz )
|
||||
{
|
||||
gc_addRange( p, sz );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the memory block referenced by p from an internal list of roots
|
||||
* to be scanned during a collection. If p is null or does not represent
|
||||
* a value previously passed to add(void*) then no operation is performed.
|
||||
*
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
*/
|
||||
static void removeRoot( void* p )
|
||||
{
|
||||
gc_removeRoot( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the memory block referenced by p from an internal list of ranges
|
||||
* to be scanned during a collection. If p is null or does not represent
|
||||
* a value previously passed to add(void*, size_t) then no operation is
|
||||
* performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
*/
|
||||
static void removeRange( void* p )
|
||||
{
|
||||
gc_removeRange( p );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get handle to the collector.
|
||||
* The only thing that can be done with this handle is pass it to
|
||||
* setHandle(). getHandle/setHandle/endHandle work together so that
|
||||
* if there are multiple instances of the gc running, only one instance
|
||||
* can be set to run.
|
||||
* The most common case of this is under Windows where a D application
|
||||
* calls functions in a DLL that is implemented in D.
|
||||
*/
|
||||
|
||||
static void* getHandle()
|
||||
{
|
||||
return gc_getHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set handle to the collector.
|
||||
* The handle p is an opaque handle, acquired by a call to
|
||||
* getHandle().
|
||||
*/
|
||||
|
||||
static void setHandle(void* p)
|
||||
{
|
||||
gc_setHandle(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when done using the collector specified by the
|
||||
* call to setHandle().
|
||||
*/
|
||||
|
||||
static void endHandle()
|
||||
{
|
||||
gc_endHandle();
|
||||
}
|
||||
}
|
||||
171
druntime/src/common/core/runtime.d
Normal file
171
druntime/src/common/core/runtime.d
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* The runtime module exposes information specific to the D runtime code.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module core.runtime;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
extern (C) bool rt_isHalting();
|
||||
|
||||
alias bool function() ModuleUnitTester;
|
||||
alias bool function(Object) CollectHandler;
|
||||
alias Exception.TraceInfo function( void* ptr = null ) TraceHandler;
|
||||
|
||||
extern (C) void rt_setCollectHandler( CollectHandler h );
|
||||
extern (C) void rt_setTraceHandler( TraceHandler h );
|
||||
|
||||
alias void delegate( Exception ) ExceptionHandler;
|
||||
extern (C) bool rt_init( ExceptionHandler dg = null );
|
||||
extern (C) bool rt_term( ExceptionHandler dg = null );
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* This struct encapsulates all functionality related to the underlying runtime
|
||||
* module for the calling context.
|
||||
*/
|
||||
struct Runtime
|
||||
{
|
||||
/**
|
||||
* Initializes the runtime. This call is to be used in instances where the
|
||||
* standard program initialization process is not executed. This is most
|
||||
* often in shared libraries or in libraries linked to a C program.
|
||||
*
|
||||
* Params:
|
||||
* dg = A delegate which will receive any exception thrown during the
|
||||
* initialization process or null if such exceptions should be
|
||||
* discarded.
|
||||
*
|
||||
* Returns:
|
||||
* true if initialization succeeds and false if initialization fails.
|
||||
*/
|
||||
static bool initialize( void delegate( Exception ) dg = null )
|
||||
{
|
||||
return rt_init( dg );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Terminates the runtime. This call is to be used in instances where the
|
||||
* standard program termination process will not be not executed. This is
|
||||
* most often in shared libraries or in libraries linked to a C program.
|
||||
*
|
||||
* Params:
|
||||
* dg = A delegate which will receive any exception thrown during the
|
||||
* termination process or null if such exceptions should be
|
||||
* discarded.
|
||||
*
|
||||
* Returns:
|
||||
* true if termination succeeds and false if termination fails.
|
||||
*/
|
||||
static bool terminate( void delegate( Exception ) dg = null )
|
||||
{
|
||||
return rt_term( dg );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the runtime is halting. Under normal circumstances,
|
||||
* this will be set between the time that normal application code has
|
||||
* exited and before module dtors are called.
|
||||
*
|
||||
* Returns:
|
||||
* true if the runtime is halting.
|
||||
*/
|
||||
static bool isHalting()
|
||||
{
|
||||
return rt_isHalting();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default trace mechanism with s user-supplied version. A
|
||||
* trace represents the context from which an exception was thrown, and the
|
||||
* trace handler will be called when this occurs. The pointer supplied to
|
||||
* this routine indicates the base address from which tracing should occur.
|
||||
* If the supplied pointer is null then the trace routine should determine
|
||||
* an appropriate calling context from which to begin the trace.
|
||||
*
|
||||
* Params:
|
||||
* h = The new trace handler. Set to null to use the default handler.
|
||||
*/
|
||||
static void traceHandler( TraceHandler h )
|
||||
{
|
||||
rt_setTraceHandler( h );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default collect hander with a user-supplied version. This
|
||||
* routine will be called for each resource object that is finalized in a
|
||||
* non-deterministic manner--typically during a garbage collection cycle.
|
||||
* If the supplied routine returns true then the object's dtor will called
|
||||
* as normal, but if the routine returns false than the dtor will not be
|
||||
* called. The default behavior is for all object dtors to be called.
|
||||
*
|
||||
* Params:
|
||||
* h = The new collect handler. Set to null to use the default handler.
|
||||
*/
|
||||
static void collectHandler( CollectHandler h )
|
||||
{
|
||||
rt_setCollectHandler( h );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default module unit tester with a user-supplied version.
|
||||
* This routine will be called once on program initialization. The return
|
||||
* value of this routine indicates to the runtime whether the body of the
|
||||
* program will be executed.
|
||||
*
|
||||
* Params:
|
||||
* h = The new unit tester. Set to null to use the default unit tester.
|
||||
*/
|
||||
static void moduleUnitTester( ModuleUnitTester h )
|
||||
{
|
||||
sm_moduleUnitTester = h;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static ModuleUnitTester sm_moduleUnitTester = null;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Overridable Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* This routine is called by the runtime to run module unit tests on startup.
|
||||
* The user-supplied unit tester will be called if one has been supplied,
|
||||
* otherwise all unit tests will be run in sequence.
|
||||
*
|
||||
* Returns:
|
||||
* true if execution should continue after testing is complete and false if
|
||||
* not. Default behavior is to return true.
|
||||
*/
|
||||
extern (C) bool runModuleUnitTests()
|
||||
{
|
||||
if( Runtime.sm_moduleUnitTester is null )
|
||||
{
|
||||
foreach( m; ModuleInfo )
|
||||
{
|
||||
if( m.unitTest )
|
||||
m.unitTest();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return Runtime.sm_moduleUnitTester();
|
||||
}
|
||||
3322
druntime/src/common/core/thread.d
Normal file
3322
druntime/src/common/core/thread.d
Normal file
File diff suppressed because it is too large
Load Diff
139
druntime/src/common/ldc.mak
Normal file
139
druntime/src/common/ldc.mak
Normal file
@@ -0,0 +1,139 @@
|
||||
# Makefile to build the D runtime library core components for Posix
|
||||
# Designed to work with GNU make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the common library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=libdruntime-core.a
|
||||
LIB_MASK=libdruntime-core*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
CFLAGS=-O $(ADD_CFLAGS)
|
||||
#CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=$(AR) -qsv
|
||||
DC=ldc2
|
||||
|
||||
INC_DEST=../../import
|
||||
LIB_DEST=../../lib
|
||||
DOC_DEST=../../doc
|
||||
|
||||
.SUFFIXES: .s .S .c .cpp .d .html .o
|
||||
|
||||
.s.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.o:
|
||||
g++ -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.o:
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
# $(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
core : lib
|
||||
lib : core.lib
|
||||
doc : core.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_CORE= \
|
||||
core/bitmanip.o \
|
||||
core/exception.o \
|
||||
core/memory_.o \
|
||||
core/runtime.o \
|
||||
core/thread.o
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc/errno.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
|
||||
######################################################
|
||||
|
||||
DOC_CORE= \
|
||||
core/bitmanip.html \
|
||||
core/exception.html \
|
||||
core/memory.html \
|
||||
core/runtime.html \
|
||||
core/thread.html
|
||||
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
core.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
core.doc : $(ALL_DOCS)
|
||||
echo Documentation generated.
|
||||
|
||||
######################################################
|
||||
|
||||
### bitmanip
|
||||
|
||||
core/bitmanip.o : core/bitmanip.d
|
||||
$(DC) -c $(DFLAGS) core/bitmanip.d -of$@
|
||||
|
||||
### memory
|
||||
|
||||
core/memory_.o : core/memory.d
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
|
||||
### thread
|
||||
|
||||
core/thread.o : core/thread.d
|
||||
$(DC) -c $(DFLAGS) -d -Hf$*.di core/thread.d -of$@
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
find . -name "$(LIB_MASK)" | xargs $(RM)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)
|
||||
find . -name "*.di" -exec cp -f {} $(INC_DEST)/{} \;
|
||||
$(MD) $(DOC_DEST)
|
||||
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
|
||||
$(MD) $(LIB_DEST)
|
||||
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
|
||||
139
druntime/src/common/posix.mak
Normal file
139
druntime/src/common/posix.mak
Normal file
@@ -0,0 +1,139 @@
|
||||
# Makefile to build the D runtime library core components for Posix
|
||||
# Designed to work with GNU make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the common library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=libdruntime-core.a
|
||||
LIB_MASK=libdruntime-core*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
CFLAGS=-O $(ADD_CFLAGS)
|
||||
#CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=$(AR) -qsv
|
||||
DC=dmd
|
||||
|
||||
INC_DEST=../../import
|
||||
LIB_DEST=../../lib
|
||||
DOC_DEST=../../doc
|
||||
|
||||
.SUFFIXES: .s .S .c .cpp .d .html .o
|
||||
|
||||
.s.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.o:
|
||||
g++ -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.o:
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
# $(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
core : lib
|
||||
lib : core.lib
|
||||
doc : core.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_CORE= \
|
||||
core/bitmanip.o \
|
||||
core/exception.o \
|
||||
core/memory_.o \
|
||||
core/runtime.o \
|
||||
core/thread.o
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc/errno.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
|
||||
######################################################
|
||||
|
||||
DOC_CORE= \
|
||||
core/bitmanip.html \
|
||||
core/exception.html \
|
||||
core/memory.html \
|
||||
core/runtime.html \
|
||||
core/thread.html
|
||||
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
core.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
core.doc : $(ALL_DOCS)
|
||||
echo Documentation generated.
|
||||
|
||||
######################################################
|
||||
|
||||
### bitmanip
|
||||
|
||||
core/bitmanip.o : core/bitmanip.d
|
||||
$(DC) -c $(DFLAGS) core/bitmanip.d -of$@
|
||||
|
||||
### memory
|
||||
|
||||
core/memory_.o : core/memory.d
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
|
||||
### thread
|
||||
|
||||
core/thread.o : core/thread.d
|
||||
$(DC) -c $(DFLAGS) -d -Hf$*.di core/thread.d -of$@
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
find . -name "$(LIB_MASK)" | xargs $(RM)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)
|
||||
find . -name "*.di" -exec cp -f {} $(INC_DEST)/{} \;
|
||||
$(MD) $(DOC_DEST)
|
||||
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
|
||||
$(MD) $(LIB_DEST)
|
||||
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
|
||||
21
druntime/src/common/stdc/errno.c
Normal file
21
druntime/src/common/stdc/errno.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* This file contains wrapper functions for macro-defined C rouines.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
int getErrno()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
int setErrno( int val )
|
||||
{
|
||||
errno = val;
|
||||
return val;
|
||||
}
|
||||
130
druntime/src/common/win32.mak
Normal file
130
druntime/src/common/win32.mak
Normal file
@@ -0,0 +1,130 @@
|
||||
# Makefile to build the D runtime library core components for Win32
|
||||
# Designed to work with DigitalMars make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the common library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=druntime-core.lib
|
||||
LIB_MASK=druntime-core*.lib
|
||||
|
||||
CP=xcopy /y
|
||||
RM=del /f
|
||||
MD=mkdir
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
CFLAGS=-mn -6 -r $(ADD_CFLAGS)
|
||||
#CFLAGS=-g -mn -6 -r $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=dmc
|
||||
LC=lib
|
||||
DC=dmd
|
||||
|
||||
INC_DEST=..\..\import
|
||||
LIB_DEST=..\..\lib
|
||||
DOC_DEST=..\..\doc
|
||||
|
||||
.DEFAULT: .asm .c .cpp .d .html .obj
|
||||
|
||||
.asm.obj:
|
||||
$(CC) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.obj:
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
# $(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
core : lib
|
||||
lib : core.lib
|
||||
doc : core.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_CORE= \
|
||||
core\bitmanip.obj \
|
||||
core\exception.obj \
|
||||
core\memory.obj \
|
||||
core\runtime.obj \
|
||||
core\thread.obj
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc\errno.obj
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
|
||||
######################################################
|
||||
|
||||
DOC_CORE= \
|
||||
core\bitmanip.html \
|
||||
core\exception.html \
|
||||
core\memory.html \
|
||||
core\runtime.html \
|
||||
core\thread.html
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
core.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) -c -n $@ $(ALL_OBJS)
|
||||
|
||||
core.doc : $(ALL_DOCS)
|
||||
@echo Documentation generated.
|
||||
|
||||
######################################################
|
||||
|
||||
### bitmanip
|
||||
|
||||
core\bitmanip.obj : core\bitmanip.d
|
||||
$(DC) -c $(DFLAGS) core\bitmanip.d -of$@
|
||||
|
||||
### thread
|
||||
|
||||
core\thread.obj : core\thread.d
|
||||
$(DC) -c $(DFLAGS) -d -Hf$*.di core\thread.d -of$@
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
$(RM) /s .\*.di
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)\.
|
||||
$(CP) /s *.di $(INC_DEST)\.
|
||||
$(MD) $(DOC_DEST)
|
||||
$(CP) /s *.html $(DOC_DEST)\.
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)\.
|
||||
408
druntime/src/compiler/dmd/aApply.d
Normal file
408
druntime/src/compiler/dmd/aApply.d
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.aApply;
|
||||
|
||||
/* This code handles decoding UTF strings for foreach loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
/**********************************************
|
||||
*/
|
||||
|
||||
// dg is D, but _aApplycd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplycd1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ d = decode(aa, i);
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
d = decode(aa, i);
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
i++;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
// dg is D, but _aApplycd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplycd2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
n = 1;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplydc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
|
||||
foreach (size_t i, dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
auto j = i;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
974
druntime/src/compiler/dmd/aApplyR.d
Normal file
974
druntime/src/compiler/dmd/aApplyR.d
Normal file
@@ -0,0 +1,974 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.aApplyR;
|
||||
|
||||
/* This code handles decoding UTF strings for foreach_reverse loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
/**********************************************/
|
||||
/* 1 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd1.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd1.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw1.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc1.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0;)
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc1.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw1.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* 2 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
|
||||
for (i = len; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd2.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); assert(k == 8); break;
|
||||
case 1: assert(d == '\U00100456'); assert(k == 4); break;
|
||||
case 2: assert(d == '\u1234'); assert(k == 1); break;
|
||||
case 3: assert(d == 'a'); assert(k == 0); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd2.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == '\U00100456'); break;
|
||||
case 2: assert(k == 1); assert(d == '\u1234'); break;
|
||||
case 3: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw2.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 8); assert(d == 'b'); break;
|
||||
case 1: assert(k == 4); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 4); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc2.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc2.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw2.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 2); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
886
druntime/src/compiler/dmd/aaA.d
Normal file
886
druntime/src/compiler/dmd/aaA.d
Normal file
@@ -0,0 +1,886 @@
|
||||
//_ aaA.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Implementation of associative arrays.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2008 by Digital Mars, http://www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.aaA;
|
||||
|
||||
private
|
||||
{
|
||||
import stdc.stdarg;
|
||||
import stdc.string;
|
||||
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001,
|
||||
NO_SCAN = 0b0000_0010,
|
||||
NO_MOVE = 0b0000_0100,
|
||||
ALL_BITS = 0b1111_1111
|
||||
}
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void gc_free( void* p );
|
||||
}
|
||||
|
||||
// Auto-rehash and pre-allocate - Dave Fladebo
|
||||
|
||||
static size_t[] prime_list = [
|
||||
97UL, 389UL,
|
||||
1_543UL, 6_151UL,
|
||||
24_593UL, 98_317UL,
|
||||
393_241UL, 1_572_869UL,
|
||||
6_291_469UL, 25_165_843UL,
|
||||
100_663_319UL, 402_653_189UL,
|
||||
1_610_612_741UL, 4_294_967_291UL,
|
||||
// 8_589_934_513UL, 17_179_869_143UL
|
||||
];
|
||||
|
||||
/* This is the type of the return value for dynamic arrays.
|
||||
* It should be a type that is returned in registers.
|
||||
* Although DMD will return types of Array in registers,
|
||||
* gcc will not, so we instead use a 'long'.
|
||||
*/
|
||||
alias long ArrayRet_t;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
struct aaA
|
||||
{
|
||||
aaA *left;
|
||||
aaA *right;
|
||||
hash_t hash;
|
||||
/* key */
|
||||
/* value */
|
||||
}
|
||||
|
||||
struct BB
|
||||
{
|
||||
aaA*[] b;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
TypeInfo keyti; // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet()
|
||||
}
|
||||
|
||||
/* This is the type actually seen by the programmer, although
|
||||
* it is completely opaque.
|
||||
*/
|
||||
|
||||
struct AA
|
||||
{
|
||||
BB* a;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Align to next pointer boundary, so that
|
||||
* GC won't be faced with misaligned pointers
|
||||
* in value.
|
||||
*/
|
||||
|
||||
size_t aligntsize(size_t tsize)
|
||||
{
|
||||
// Is pointer alignment on the x64 4 bytes or 8?
|
||||
return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
/*************************************************
|
||||
* Invariant for aa.
|
||||
*/
|
||||
|
||||
/+
|
||||
void _aaInvAh(aaA*[] aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa.length; i++)
|
||||
{
|
||||
if (aa[i])
|
||||
_aaInvAh_x(aa[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private int _aaCmpAh_x(aaA *e1, aaA *e2)
|
||||
{ int c;
|
||||
|
||||
c = e1.hash - e2.hash;
|
||||
if (c == 0)
|
||||
{
|
||||
c = e1.key.length - e2.key.length;
|
||||
if (c == 0)
|
||||
c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private void _aaInvAh_x(aaA *e)
|
||||
{
|
||||
hash_t key_hash;
|
||||
aaA *e1;
|
||||
aaA *e2;
|
||||
|
||||
key_hash = getHash(e.key);
|
||||
assert(key_hash == e.hash);
|
||||
|
||||
while (1)
|
||||
{ int c;
|
||||
|
||||
e1 = e.left;
|
||||
if (e1)
|
||||
{
|
||||
_aaInvAh_x(e1); // ordinary recursion
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e1, e);
|
||||
assert(c < 0);
|
||||
e1 = e1.right;
|
||||
} while (e1 != null);
|
||||
}
|
||||
|
||||
e2 = e.right;
|
||||
if (e2)
|
||||
{
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e, e2);
|
||||
assert(c < 0);
|
||||
e2 = e2.left;
|
||||
} while (e2 != null);
|
||||
e = e.right; // tail recursion
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
*/
|
||||
|
||||
size_t _aaLen(AA aa)
|
||||
in
|
||||
{
|
||||
//printf("_aaLen()+\n");
|
||||
//_aaInv(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
void _aaLen_x(aaA* ex)
|
||||
{
|
||||
auto e = ex;
|
||||
len++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (e.right)
|
||||
_aaLen_x(e.right);
|
||||
e = e.left;
|
||||
if (!e)
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaLen_x(e);
|
||||
}
|
||||
}
|
||||
assert(len == result);
|
||||
|
||||
//printf("_aaLen()-\n");
|
||||
}
|
||||
body
|
||||
{
|
||||
return aa.a ? aa.a.nodes : 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Add entry for key if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
|
||||
in
|
||||
{
|
||||
assert(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(result);
|
||||
assert(aa.a);
|
||||
assert(aa.a.b.length);
|
||||
//assert(_aaInAh(*aa.a, key));
|
||||
}
|
||||
body
|
||||
{
|
||||
auto pkey = cast(void *)(&valuesize + 1);
|
||||
size_t i;
|
||||
aaA *e;
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
|
||||
if (!aa.a)
|
||||
aa.a = new BB();
|
||||
aa.a.keyti = keyti;
|
||||
|
||||
if (!aa.a.b.length)
|
||||
{
|
||||
alias aaA *pa;
|
||||
auto len = prime_list[0];
|
||||
|
||||
aa.a.b = new pa[len];
|
||||
}
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % aa.a.b.length;
|
||||
auto pe = &aa.a.b[i];
|
||||
while ((e = *pe) !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
goto Lret;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
size_t size = aaA.sizeof + keysize + valuesize;
|
||||
e = cast(aaA *) gc_calloc(size);
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
|
||||
auto nodes = ++aa.a.nodes;
|
||||
//printf("length = %d, nodes = %d\n", (*aa.a).length, nodes);
|
||||
if (nodes > aa.a.b.length * 4)
|
||||
{
|
||||
_aaRehash(aa,keyti);
|
||||
}
|
||||
|
||||
Lret:
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Returns null if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
|
||||
{
|
||||
//printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
|
||||
if (!aa.a)
|
||||
return null;
|
||||
|
||||
auto pkey = cast(void *)(&valuesize + 1);
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
auto len = aa.a.b.length;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.a.b[i];
|
||||
while (e !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
return null; // not found, caller will throw exception
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Determine if key is in aa.
|
||||
* Returns:
|
||||
* null not in aa
|
||||
* !=null in aa, return pointer to value
|
||||
*/
|
||||
|
||||
void* _aaIn(AA aa, TypeInfo keyti, ...)
|
||||
in
|
||||
{
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//assert(result == 0 || result == 1);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (aa.a)
|
||||
{
|
||||
auto pkey = cast(void *)(&keyti + 1);
|
||||
|
||||
//printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr);
|
||||
auto len = aa.a.b.length;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.a.b[i];
|
||||
while (e !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + aligntsize(keyti.tsize());
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* Delete key entry in aa[].
|
||||
* If key is not in aa[], do nothing.
|
||||
*/
|
||||
|
||||
void _aaDel(AA aa, TypeInfo keyti, ...)
|
||||
{
|
||||
auto pkey = cast(void *)(&keyti + 1);
|
||||
aaA *e;
|
||||
|
||||
if (aa.a && aa.a.b.length)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % aa.a.b.length;
|
||||
auto pe = &aa.a.b[i];
|
||||
while ((e = *pe) !is null) // null means not found
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
{
|
||||
if (!e.left && !e.right)
|
||||
{
|
||||
*pe = null;
|
||||
}
|
||||
else if (e.left && !e.right)
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
}
|
||||
else if (!e.left && e.right)
|
||||
{
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
do
|
||||
pe = &(*pe).right;
|
||||
while (*pe);
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
|
||||
aa.a.nodes--;
|
||||
gc_free(e);
|
||||
break;
|
||||
}
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of values from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
|
||||
in
|
||||
{
|
||||
assert(keysize == aligntsize(keysize));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t resi;
|
||||
Array a;
|
||||
|
||||
void _aaValues_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(a.ptr + resi * valuesize,
|
||||
cast(byte*)e + aaA.sizeof + keysize,
|
||||
valuesize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaValues_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e !is null);
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
a.length = _aaLen(aa);
|
||||
a.ptr = cast(byte*) gc_malloc(a.length * valuesize,
|
||||
valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
|
||||
resi = 0;
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaValues_x(e);
|
||||
}
|
||||
assert(resi == a.length);
|
||||
}
|
||||
return *cast(ArrayRet_t*)(&a);
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Rehash an array.
|
||||
*/
|
||||
|
||||
void* _aaRehash(AA* paa, TypeInfo keyti)
|
||||
in
|
||||
{
|
||||
//_aaInvAh(paa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//_aaInvAh(result);
|
||||
}
|
||||
body
|
||||
{
|
||||
BB newb;
|
||||
|
||||
void _aaRehash_x(aaA* olde)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
auto left = olde.left;
|
||||
auto right = olde.right;
|
||||
olde.left = null;
|
||||
olde.right = null;
|
||||
|
||||
aaA *e;
|
||||
|
||||
//printf("rehash %p\n", olde);
|
||||
auto key_hash = olde.hash;
|
||||
size_t i = key_hash % newb.b.length;
|
||||
auto pe = &newb.b[i];
|
||||
while ((e = *pe) !is null)
|
||||
{
|
||||
//printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
|
||||
assert(e.left != e);
|
||||
assert(e.right != e);
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(olde + 1, e + 1);
|
||||
assert(c != 0);
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
*pe = olde;
|
||||
|
||||
if (right)
|
||||
{
|
||||
if (!left)
|
||||
{ olde = right;
|
||||
continue;
|
||||
}
|
||||
_aaRehash_x(right);
|
||||
}
|
||||
if (!left)
|
||||
break;
|
||||
olde = left;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("Rehash\n");
|
||||
if (paa.a)
|
||||
{
|
||||
auto aa = paa.a;
|
||||
auto len = _aaLen(*paa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaRehash_x(e);
|
||||
}
|
||||
|
||||
newb.nodes = aa.nodes;
|
||||
newb.keyti = aa.keyti;
|
||||
}
|
||||
|
||||
*paa.a = newb;
|
||||
_aaBalance(paa);
|
||||
}
|
||||
return (*paa).a;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Balance an array.
|
||||
*/
|
||||
|
||||
void _aaBalance(AA* paa)
|
||||
{
|
||||
//printf("_aaBalance()\n");
|
||||
if (paa.a)
|
||||
{
|
||||
aaA*[16] tmp;
|
||||
aaA*[] array = tmp;
|
||||
auto aa = paa.a;
|
||||
foreach (j, e; aa.b)
|
||||
{
|
||||
/* Temporarily store contents of bucket in array[]
|
||||
*/
|
||||
size_t k = 0;
|
||||
void addToArray(aaA* e)
|
||||
{
|
||||
while (e)
|
||||
{ addToArray(e.left);
|
||||
if (k == array.length)
|
||||
array.length = array.length * 2;
|
||||
array[k++] = e;
|
||||
e = e.right;
|
||||
}
|
||||
}
|
||||
addToArray(e);
|
||||
/* The contents of the bucket are now sorted into array[].
|
||||
* Rebuild the tree.
|
||||
*/
|
||||
void buildTree(aaA** p, size_t x1, size_t x2)
|
||||
{
|
||||
if (x1 >= x2)
|
||||
*p = null;
|
||||
else
|
||||
{ auto mid = (x1 + x2) >> 1;
|
||||
*p = array[mid];
|
||||
buildTree(&(*p).left, x1, mid);
|
||||
buildTree(&(*p).right, mid + 1, x2);
|
||||
}
|
||||
}
|
||||
auto p = &aa.b[j];
|
||||
buildTree(p, 0, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
/********************************************
|
||||
* Produce array of N byte keys from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaKeys(AA aa, size_t keysize)
|
||||
{
|
||||
byte[] res;
|
||||
size_t resi;
|
||||
|
||||
void _aaKeys_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaKeys_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e !is null);
|
||||
}
|
||||
|
||||
auto len = _aaLen(aa);
|
||||
if (!len)
|
||||
return 0;
|
||||
res = (cast(byte*) gc_malloc(len * keysize,
|
||||
!(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize];
|
||||
resi = 0;
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaKeys_x(e);
|
||||
}
|
||||
assert(resi == len);
|
||||
|
||||
Array a;
|
||||
a.length = len;
|
||||
a.ptr = res.ptr;
|
||||
return *cast(ArrayRet_t*)(&a);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* 'apply' for associative arrays - to support foreach
|
||||
*/
|
||||
|
||||
// dg is D, but _aaApply() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
int _aaApply(AA aa, size_t keysize, dg_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// dg is D, but _aaApply2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
int _aaApply2(AA aa, size_t keysize, dg2_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct an associative array of type ti from
|
||||
* length pairs of key/value pairs.
|
||||
*/
|
||||
|
||||
extern (C)
|
||||
BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
|
||||
{
|
||||
auto valuesize = ti.next.tsize(); // value size
|
||||
auto keyti = ti.key;
|
||||
auto keysize = keyti.tsize(); // key size
|
||||
BB* result;
|
||||
|
||||
//printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
|
||||
//printf("tivalue = %.*s\n", ti.next.classinfo.name);
|
||||
if (length == 0 || valuesize == 0 || keysize == 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
va_list q;
|
||||
va_start!(size_t)(q, length);
|
||||
|
||||
result = new BB();
|
||||
result.keyti = keyti;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (length <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
auto len = prime_list[i];
|
||||
result.b = new aaA*[len];
|
||||
|
||||
size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
|
||||
size_t keytsize = aligntsize(keysize);
|
||||
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{ void* pkey = q;
|
||||
q += keystacksize;
|
||||
void* pvalue = q;
|
||||
q += valuestacksize;
|
||||
aaA* e;
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % len;
|
||||
auto pe = &result.b[i];
|
||||
while (1)
|
||||
{
|
||||
e = *pe;
|
||||
if (!e)
|
||||
{
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
result.nodes++;
|
||||
break;
|
||||
}
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
|
||||
}
|
||||
|
||||
va_end(q);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
625
druntime/src/compiler/dmd/adi.d
Normal file
625
druntime/src/compiler/dmd/adi.d
Normal file
@@ -0,0 +1,625 @@
|
||||
//_ adi.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Dynamic array property support routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.adi;
|
||||
|
||||
//debug=adi; // uncomment to turn on debugging printf's
|
||||
|
||||
private
|
||||
{
|
||||
debug(adi) import stdc.stdio;
|
||||
import stdc.string;
|
||||
import stdc.stdlib;
|
||||
import util.utf;
|
||||
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001,
|
||||
NO_SCAN = 0b0000_0010,
|
||||
NO_MOVE = 0b0000_0100,
|
||||
ALL_BITS = 0b1111_1111
|
||||
}
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void gc_free( void* p );
|
||||
}
|
||||
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of chars.
|
||||
* Handled separately because embedded multibyte encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverseChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
char[6] tmp;
|
||||
char[6] tmplo;
|
||||
char* lo = a.ptr;
|
||||
char* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
|
||||
if (clo <= 0x7F && chi <= 0x7F)
|
||||
{
|
||||
debug(adi) printf("\tascii\n");
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint stridelo = UTF8stride[clo];
|
||||
|
||||
uint stridehi = 1;
|
||||
while ((chi & 0xC0) == 0x80)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
|
||||
if (stridelo == stridehi)
|
||||
{
|
||||
|
||||
memcpy(tmp.ptr, lo, stridelo);
|
||||
memcpy(lo, hi, stridelo);
|
||||
memcpy(hi, tmp.ptr, stridelo);
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi);
|
||||
memcpy(tmplo.ptr, lo, stridelo);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
|
||||
memcpy(lo, tmp.ptr, stridehi);
|
||||
memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
auto a = "abcd"c;
|
||||
|
||||
auto r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\u1235\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234\u1235a");
|
||||
|
||||
a = "ab\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234ba");
|
||||
|
||||
a = "\u3026\u2021\u3061\n";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "\n\u3061\u2021\u3026");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of wchars.
|
||||
* Handled separately because embedded multiword encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverseWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
wchar[2] tmp;
|
||||
wchar* lo = a.ptr;
|
||||
wchar* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
if ((clo < 0xD800 || clo > 0xDFFF) &&
|
||||
(chi < 0xD800 || chi > 0xDFFF))
|
||||
{
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
|
||||
|
||||
int stridehi = 1;
|
||||
if (chi >= 0xDC00 && chi <= 0xDFFF)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
if (stridelo == stridehi)
|
||||
{ int stmp;
|
||||
|
||||
assert(stridelo == 2);
|
||||
assert(stmp.sizeof == 2 * (*lo).sizeof);
|
||||
stmp = *cast(int*)lo;
|
||||
*cast(int*)lo = *cast(int*)hi;
|
||||
*cast(int*)hi = stmp;
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
|
||||
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
|
||||
memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
wstring a = "abcd";
|
||||
|
||||
auto r = a.dup.reverse;
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\U00012356\U00012346c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012346\U00012356a");
|
||||
|
||||
a = "ab\U00012345c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012345ba");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverse(Array a, size_t szelem)
|
||||
out (result)
|
||||
{
|
||||
assert(result is *cast(long*)(&a));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
byte* tmp;
|
||||
byte[16] buffer;
|
||||
|
||||
void* lo = a.ptr;
|
||||
void* hi = a.ptr + (a.length - 1) * szelem;
|
||||
|
||||
tmp = buffer.ptr;
|
||||
if (szelem > 16)
|
||||
{
|
||||
//version (Windows)
|
||||
tmp = cast(byte*) alloca(szelem);
|
||||
//else
|
||||
//tmp = gc_malloc(szelem);
|
||||
}
|
||||
|
||||
for (; lo < hi; lo += szelem, hi -= szelem)
|
||||
{
|
||||
memcpy(tmp, lo, szelem);
|
||||
memcpy(lo, hi, szelem);
|
||||
memcpy(hi, tmp, szelem);
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (szelem > 16)
|
||||
// BUG: bad code is generate for delete pointer, tries
|
||||
// to call delclass.
|
||||
//gc_free(tmp);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse.unittest\n");
|
||||
|
||||
int[] a = new int[5];
|
||||
int[] b;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
a[i] = i;
|
||||
b = a.reverse;
|
||||
assert(b is a);
|
||||
for (i = 0; i < 5; i++)
|
||||
assert(a[i] == 4 - i);
|
||||
|
||||
struct X20
|
||||
{ // More than 16 bytes in size
|
||||
int a;
|
||||
int b, c, d, e;
|
||||
}
|
||||
|
||||
X20[] c = new X20[5];
|
||||
X20[] d;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{ c[i].a = i;
|
||||
c[i].e = 10;
|
||||
}
|
||||
d = c.reverse;
|
||||
assert(d is c);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(c[i].a == 4 - i);
|
||||
assert(c[i].e == 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of chars.
|
||||
*/
|
||||
|
||||
extern (C) long _adSortChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ char[4] buf;
|
||||
auto t = toUTF8(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of wchars.
|
||||
*/
|
||||
|
||||
extern (C) long _adSortWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ wchar[2] buf;
|
||||
auto t = toUTF16(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array equality test.
|
||||
* Returns:
|
||||
* 1 equal
|
||||
* 0 not equal
|
||||
*/
|
||||
|
||||
extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
auto sz = ti.tsize();
|
||||
auto p1 = a1.ptr;
|
||||
auto p2 = a2.ptr;
|
||||
|
||||
if (sz == 1)
|
||||
// We should really have a ti.isPOD() check for this
|
||||
return (memcmp(p1, p2, a1.length) == 0);
|
||||
|
||||
for (size_t i = 0; i < a1.length; i++)
|
||||
{
|
||||
if (!ti.equals(p1 + i * sz, p2 + i * sz))
|
||||
return 0; // not equal
|
||||
}
|
||||
return 1; // equal
|
||||
}
|
||||
|
||||
extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
if (!ti.equals(&a1, &a2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Eq unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
|
||||
assert(a != "hel");
|
||||
assert(a != "helloo");
|
||||
assert(a != "betty");
|
||||
assert(a == "hello");
|
||||
assert(a != "hxxxx");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("adCmp()\n");
|
||||
auto len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
auto sz = ti.tsize();
|
||||
void *p1 = a1.ptr;
|
||||
void *p2 = a2.ptr;
|
||||
|
||||
if (sz == 1)
|
||||
{ // We should really have a ti.isPOD() check for this
|
||||
auto c = memcmp(p1, p2, len);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
auto c = ti.compare(p1 + i * sz, p2 + i * sz);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if (a1.length == a2.length)
|
||||
return 0;
|
||||
return (a1.length > a2.length) ? 1 : -1;
|
||||
}
|
||||
|
||||
extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
return ti.compare(&a1, &a2);
|
||||
}
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Cmp unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmpChar(Array a1, Array a2)
|
||||
{
|
||||
version (X86)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
|
||||
push EDI ;
|
||||
push ESI ;
|
||||
|
||||
mov ESI,a1+4[4+ESP] ;
|
||||
mov EDI,a2+4[4+ESP] ;
|
||||
|
||||
mov ECX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
cmp ECX,EDX ;
|
||||
jb GotLength ;
|
||||
|
||||
mov ECX,EDX ;
|
||||
|
||||
GotLength:
|
||||
cmp ECX,4 ;
|
||||
jb DoBytes ;
|
||||
|
||||
// Do alignment if neither is dword aligned
|
||||
test ESI,3 ;
|
||||
jz Aligned ;
|
||||
|
||||
test EDI,3 ;
|
||||
jz Aligned ;
|
||||
DoAlign:
|
||||
mov AL,[ESI] ; //align ESI to dword bounds
|
||||
mov DL,[EDI] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
inc ESI ;
|
||||
inc EDI ;
|
||||
|
||||
test ESI,3 ;
|
||||
|
||||
lea ECX,[ECX-1] ;
|
||||
jnz DoAlign ;
|
||||
Aligned:
|
||||
mov EAX,ECX ;
|
||||
|
||||
// do multiple of 4 bytes at a time
|
||||
|
||||
shr ECX,2 ;
|
||||
jz TryOdd ;
|
||||
|
||||
repe ;
|
||||
cmpsd ;
|
||||
|
||||
jnz UnequalQuad ;
|
||||
|
||||
TryOdd:
|
||||
mov ECX,EAX ;
|
||||
DoBytes:
|
||||
// if still equal and not end of string, do up to 3 bytes slightly
|
||||
// slower.
|
||||
|
||||
and ECX,3 ;
|
||||
jz Equal ;
|
||||
|
||||
repe ;
|
||||
cmpsb ;
|
||||
|
||||
jnz Unequal ;
|
||||
Equal:
|
||||
mov EAX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
sub EAX,EDX ;
|
||||
pop ESI ;
|
||||
|
||||
pop EDI ;
|
||||
ret ;
|
||||
|
||||
UnequalQuad:
|
||||
mov EDX,[EDI-4] ;
|
||||
mov EAX,[ESI-4] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
jnz Unequal ;
|
||||
|
||||
shr EAX,16 ;
|
||||
|
||||
shr EDX,16 ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
Unequal:
|
||||
sbb EAX,EAX ;
|
||||
pop ESI ;
|
||||
|
||||
or EAX,1 ;
|
||||
pop EDI ;
|
||||
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
int c;
|
||||
|
||||
debug(adi) printf("adCmpChar()\n");
|
||||
len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
|
||||
if (!c)
|
||||
c = cast(int)a1.length - cast(int)a2.length;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpChar unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
110
druntime/src/compiler/dmd/alloca.d
Normal file
110
druntime/src/compiler/dmd/alloca.d
Normal file
@@ -0,0 +1,110 @@
|
||||
/*_ _alloca.d
|
||||
* Copyright (C) 1990-2003 by Digital Mars, www.digitalmars.com
|
||||
* All Rights Reserved
|
||||
* Written by Walter Bright
|
||||
*/
|
||||
|
||||
module rt.alloca;
|
||||
|
||||
/+
|
||||
#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 (Windows)
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
180
druntime/src/compiler/dmd/arrayassign.d
Normal file
180
druntime/src/compiler/dmd/arrayassign.d
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* http://www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
* Placed in the Public Domain
|
||||
*/
|
||||
module rt.arrayassign;
|
||||
|
||||
private
|
||||
{
|
||||
import util.string;
|
||||
import stdc.string;
|
||||
import stdc.stdlib;
|
||||
debug(PRINTF) import stdc.stdio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does array assignment (not construction) from another
|
||||
* array of the same element type.
|
||||
* ti is the element type.
|
||||
* Handles overlapping copies.
|
||||
*/
|
||||
extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
|
||||
{
|
||||
debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
|
||||
|
||||
if (to.length != from.length)
|
||||
{
|
||||
char[10] tmp = void;
|
||||
string msg = "lengths don't match for array copy,"c;
|
||||
msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
/* Need a temporary buffer tmp[] big enough to hold one element
|
||||
*/
|
||||
void[16] buf = void;
|
||||
void[] tmp;
|
||||
if (element_size > buf.sizeof)
|
||||
tmp = alloca(element_size)[0 .. element_size];
|
||||
else
|
||||
tmp = buf;
|
||||
|
||||
|
||||
if (to.ptr <= from.ptr)
|
||||
{
|
||||
foreach (i; 0 .. to.length)
|
||||
{
|
||||
void* pto = to.ptr + i * element_size;
|
||||
void* pfrom = from.ptr + i * element_size;
|
||||
memcpy(tmp.ptr, pto, element_size);
|
||||
memcpy(pto, pfrom, element_size);
|
||||
ti.postblit(pto);
|
||||
ti.destroy(tmp.ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = to.length; i--; )
|
||||
{
|
||||
void* pto = to.ptr + i * element_size;
|
||||
void* pfrom = from.ptr + i * element_size;
|
||||
memcpy(tmp.ptr, pto, element_size);
|
||||
memcpy(pto, pfrom, element_size);
|
||||
ti.postblit(pto);
|
||||
ti.destroy(tmp.ptr);
|
||||
}
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does array initialization (not assignment) from another
|
||||
* array of the same element type.
|
||||
* ti is the element type.
|
||||
*/
|
||||
extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
|
||||
{
|
||||
debug(PRINTF) printf("_d_arrayctor(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
|
||||
|
||||
if (to.length != from.length)
|
||||
{
|
||||
char[10] tmp = void;
|
||||
string msg = "lengths don't match for array initialization,"c;
|
||||
msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
int i;
|
||||
try
|
||||
{
|
||||
for (i = 0; i < to.length; i++)
|
||||
{
|
||||
// Copy construction is defined as bit copy followed by postblit.
|
||||
memcpy(to.ptr + i * element_size, from.ptr + i * element_size, element_size);
|
||||
ti.postblit(to.ptr + i * element_size);
|
||||
}
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
/* Destroy, in reverse order, what we've constructed so far
|
||||
*/
|
||||
while (i--)
|
||||
{
|
||||
ti.destroy(to.ptr + i * element_size);
|
||||
}
|
||||
|
||||
throw o;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do assignment to an array.
|
||||
* p[0 .. count] = value;
|
||||
*/
|
||||
extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
|
||||
{
|
||||
void* pstart = p;
|
||||
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
//Need a temporary buffer tmp[] big enough to hold one element
|
||||
void[16] buf = void;
|
||||
void[] tmp;
|
||||
if (element_size > buf.sizeof)
|
||||
{
|
||||
tmp = alloca(element_size)[0 .. element_size];
|
||||
}
|
||||
else
|
||||
tmp = buf;
|
||||
|
||||
foreach (i; 0 .. count)
|
||||
{
|
||||
memcpy(tmp.ptr, p, element_size);
|
||||
memcpy(p, value, element_size);
|
||||
ti.postblit(p);
|
||||
ti.destroy(tmp.ptr);
|
||||
p += element_size;
|
||||
}
|
||||
return pstart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do construction of an array.
|
||||
* ti[count] p = value;
|
||||
*/
|
||||
extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti)
|
||||
{
|
||||
void* pstart = p;
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (i; 0 .. count)
|
||||
{
|
||||
// Copy construction is defined as bit copy followed by postblit.
|
||||
memcpy(p, value, element_size);
|
||||
ti.postblit(p);
|
||||
p += element_size;
|
||||
}
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
// Destroy, in reverse order, what we've constructed so far
|
||||
while (p > pstart)
|
||||
{
|
||||
p -= element_size;
|
||||
ti.destroy(p);
|
||||
}
|
||||
|
||||
throw o;
|
||||
}
|
||||
return pstart;
|
||||
}
|
||||
1890
druntime/src/compiler/dmd/arraybyte.d
Normal file
1890
druntime/src/compiler/dmd/arraybyte.d
Normal file
File diff suppressed because it is too large
Load Diff
109
druntime/src/compiler/dmd/arraycast.d
Normal file
109
druntime/src/compiler/dmd/arraycast.d
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.arraycast;
|
||||
|
||||
/******************************************
|
||||
* Runtime helper to convert dynamic array of one
|
||||
* type to dynamic array of another.
|
||||
* Adjusts the length of the array.
|
||||
* Throws exception if new length is not aligned.
|
||||
*/
|
||||
|
||||
extern (C)
|
||||
|
||||
void[] _d_arraycast(size_t tsize, size_t fsize, void[] a)
|
||||
{
|
||||
auto length = a.length;
|
||||
|
||||
auto nbytes = length * fsize;
|
||||
if (nbytes % tsize != 0)
|
||||
{
|
||||
throw new Exception("array cast misalignment");
|
||||
}
|
||||
length = nbytes / tsize;
|
||||
*cast(size_t *)&a = length; // jam new length
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
byte[int.sizeof * 3] b;
|
||||
int[] i;
|
||||
short[] s;
|
||||
|
||||
i = cast(int[])b;
|
||||
assert(i.length == 3);
|
||||
|
||||
s = cast(short[])b;
|
||||
assert(s.length == 6);
|
||||
|
||||
s = cast(short[])i;
|
||||
assert(s.length == 6);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Runtime helper to convert dynamic array of bits
|
||||
* dynamic array of another.
|
||||
* Adjusts the length of the array.
|
||||
* Throws exception if new length is not aligned.
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C)
|
||||
|
||||
void[] _d_arraycast_frombit(uint tsize, void[] a)
|
||||
{
|
||||
uint length = a.length;
|
||||
|
||||
if (length & 7)
|
||||
{
|
||||
throw new Exception("bit[] array cast misalignment");
|
||||
}
|
||||
length /= 8 * tsize;
|
||||
*cast(size_t *)&a = length; // jam new length
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
version (D_Bits)
|
||||
{
|
||||
bit[int.sizeof * 3 * 8] b;
|
||||
int[] i;
|
||||
short[] s;
|
||||
|
||||
i = cast(int[])b;
|
||||
assert(i.length == 3);
|
||||
|
||||
s = cast(short[])b;
|
||||
assert(s.length == 6);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
druntime/src/compiler/dmd/arraycat.d
Normal file
61
druntime/src/compiler/dmd/arraycat.d
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.arraycat;
|
||||
|
||||
private
|
||||
{
|
||||
import stdc.string;
|
||||
debug import stdc.stdio;
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
byte[] _d_arraycopy(size_t size, byte[] from, byte[] to)
|
||||
{
|
||||
debug printf("f = %p,%d, t = %p,%d, size = %d\n",
|
||||
from.ptr, from.length, to.ptr, to.length, size);
|
||||
|
||||
if (to.length != from.length)
|
||||
{
|
||||
throw new Exception("lengths don't match for array copy");
|
||||
}
|
||||
else if (to.ptr + to.length * size <= from.ptr ||
|
||||
from.ptr + from.length * size <= to.ptr)
|
||||
{
|
||||
memcpy(to.ptr, from.ptr, to.length * size);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("overlapping array copy");
|
||||
}
|
||||
return to;
|
||||
}
|
||||
1714
druntime/src/compiler/dmd/arraydouble.d
Normal file
1714
druntime/src/compiler/dmd/arraydouble.d
Normal file
File diff suppressed because it is too large
Load Diff
2303
druntime/src/compiler/dmd/arrayfloat.d
Normal file
2303
druntime/src/compiler/dmd/arrayfloat.d
Normal file
File diff suppressed because it is too large
Load Diff
2427
druntime/src/compiler/dmd/arrayint.d
Normal file
2427
druntime/src/compiler/dmd/arrayint.d
Normal file
File diff suppressed because it is too large
Load Diff
234
druntime/src/compiler/dmd/arrayreal.d
Normal file
234
druntime/src/compiler/dmd/arrayreal.d
Normal file
@@ -0,0 +1,234 @@
|
||||
/***************************
|
||||
* D programming language http://www.digitalmars.com/d/
|
||||
* Runtime support for double array operations.
|
||||
* Placed in public domain.
|
||||
*/
|
||||
|
||||
module rt.arrayreal;
|
||||
|
||||
import util.cpuid;
|
||||
|
||||
version (Unittest)
|
||||
{
|
||||
/* This is so unit tests will test every CPU variant
|
||||
*/
|
||||
int cpuid;
|
||||
const int CPUID_MAX = 1;
|
||||
bool mmx() { return cpuid == 1 && util.cpuid.mmx(); }
|
||||
bool sse() { return cpuid == 2 && util.cpuid.sse(); }
|
||||
bool sse2() { return cpuid == 3 && util.cpuid.sse2(); }
|
||||
bool amd3dnow() { return cpuid == 4 && util.cpuid.amd3dnow(); }
|
||||
}
|
||||
else
|
||||
{
|
||||
alias util.cpuid.mmx mmx;
|
||||
alias util.cpuid.sse sse;
|
||||
alias util.cpuid.sse2 sse2;
|
||||
alias util.cpuid.amd3dnow amd3dnow;
|
||||
}
|
||||
|
||||
//version = log;
|
||||
|
||||
bool disjoint(T)(T[] a, T[] b)
|
||||
{
|
||||
return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
|
||||
}
|
||||
|
||||
alias real T;
|
||||
|
||||
extern (C):
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] = b[] + c[]
|
||||
*/
|
||||
|
||||
T[] _arraySliceSliceAddSliceAssign_r(T[] a, T[] c, T[] b)
|
||||
in
|
||||
{
|
||||
assert(a.length == b.length && b.length == c.length);
|
||||
assert(disjoint(a, b));
|
||||
assert(disjoint(a, c));
|
||||
assert(disjoint(b, c));
|
||||
}
|
||||
body
|
||||
{
|
||||
for (int i = 0; i < a.length; i++)
|
||||
a[i] = b[i] + c[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
printf("_arraySliceSliceAddSliceAssign_r unittest\n");
|
||||
for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
|
||||
{
|
||||
version (log) printf(" cpuid %d\n", cpuid);
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
const int dim = 67;
|
||||
T[] a = new T[dim + j]; // aligned on 16 byte boundary
|
||||
a = a[j .. dim + j]; // misalign for second iteration
|
||||
T[] b = new T[dim + j];
|
||||
b = b[j .. dim + j];
|
||||
T[] c = new T[dim + j];
|
||||
c = c[j .. dim + j];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{ a[i] = cast(T)i;
|
||||
b[i] = cast(T)(i + 7);
|
||||
c[i] = cast(T)(i * 2);
|
||||
}
|
||||
|
||||
c[] = a[] + b[];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
if (c[i] != cast(T)(a[i] + b[i]))
|
||||
{
|
||||
printf("[%d]: %Lg != %Lg + %Lg\n", i, c[i], a[i], b[i]);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] = b[] - c[]
|
||||
*/
|
||||
|
||||
T[] _arraySliceSliceMinSliceAssign_r(T[] a, T[] c, T[] b)
|
||||
in
|
||||
{
|
||||
assert(a.length == b.length && b.length == c.length);
|
||||
assert(disjoint(a, b));
|
||||
assert(disjoint(a, c));
|
||||
assert(disjoint(b, c));
|
||||
}
|
||||
body
|
||||
{
|
||||
for (int i = 0; i < a.length; i++)
|
||||
a[i] = b[i] - c[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
printf("_arraySliceSliceMinSliceAssign_r unittest\n");
|
||||
for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
|
||||
{
|
||||
version (log) printf(" cpuid %d\n", cpuid);
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
const int dim = 67;
|
||||
T[] a = new T[dim + j]; // aligned on 16 byte boundary
|
||||
a = a[j .. dim + j]; // misalign for second iteration
|
||||
T[] b = new T[dim + j];
|
||||
b = b[j .. dim + j];
|
||||
T[] c = new T[dim + j];
|
||||
c = c[j .. dim + j];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{ a[i] = cast(T)i;
|
||||
b[i] = cast(T)(i + 7);
|
||||
c[i] = cast(T)(i * 2);
|
||||
}
|
||||
|
||||
c[] = a[] - b[];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
if (c[i] != cast(T)(a[i] - b[i]))
|
||||
{
|
||||
printf("[%d]: %Lg != %Lg - %Lg\n", i, c[i], a[i], b[i]);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] -= b[] * value
|
||||
*/
|
||||
|
||||
T[] _arraySliceExpMulSliceMinass_r(T[] a, T value, T[] b)
|
||||
{
|
||||
return _arraySliceExpMulSliceAddass_r(a, -value, b);
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] += b[] * value
|
||||
*/
|
||||
|
||||
T[] _arraySliceExpMulSliceAddass_r(T[] a, T value, T[] b)
|
||||
in
|
||||
{
|
||||
assert(a.length == b.length);
|
||||
assert(disjoint(a, b));
|
||||
}
|
||||
body
|
||||
{
|
||||
auto aptr = a.ptr;
|
||||
auto aend = aptr + a.length;
|
||||
auto bptr = b.ptr;
|
||||
|
||||
// Handle remainder
|
||||
while (aptr < aend)
|
||||
*aptr++ += *bptr++ * value;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
printf("_arraySliceExpMulSliceAddass_r unittest\n");
|
||||
|
||||
cpuid = 1;
|
||||
{
|
||||
version (log) printf(" cpuid %d\n", cpuid);
|
||||
|
||||
for (int j = 0; j < 1; j++)
|
||||
{
|
||||
const int dim = 67;
|
||||
T[] a = new T[dim + j]; // aligned on 16 byte boundary
|
||||
a = a[j .. dim + j]; // misalign for second iteration
|
||||
T[] b = new T[dim + j];
|
||||
b = b[j .. dim + j];
|
||||
T[] c = new T[dim + j];
|
||||
c = c[j .. dim + j];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{ a[i] = cast(T)i;
|
||||
b[i] = cast(T)(i + 7);
|
||||
c[i] = cast(T)(i * 2);
|
||||
}
|
||||
|
||||
b[] = c[];
|
||||
c[] += a[] * 6;
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
//printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
|
||||
if (c[i] != cast(T)(b[i] + a[i] * 6))
|
||||
{
|
||||
printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2300
druntime/src/compiler/dmd/arrayshort.d
Normal file
2300
druntime/src/compiler/dmd/arrayshort.d
Normal file
File diff suppressed because it is too large
Load Diff
184
druntime/src/compiler/dmd/cast_.d
Normal file
184
druntime/src/compiler/dmd/cast_.d
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.cast_;
|
||||
|
||||
extern (C):
|
||||
|
||||
/******************************************
|
||||
* Given a pointer:
|
||||
* If it is an Object, return that Object.
|
||||
* If it is an interface, return the Object implementing the interface.
|
||||
* If it is null, return null.
|
||||
* Else, undefined crash
|
||||
*/
|
||||
|
||||
Object _d_toObject(void* p)
|
||||
{ Object o;
|
||||
|
||||
if (p)
|
||||
{
|
||||
o = cast(Object)p;
|
||||
ClassInfo oc = o.classinfo;
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
/* Interface.offset lines up with ClassInfo.name.ptr,
|
||||
* so we rely on pointers never being less than 64K,
|
||||
* and Objects never being greater.
|
||||
*/
|
||||
if (pi.offset < 0x10000)
|
||||
{
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Attempts to cast Object o to class c.
|
||||
* Returns o if successful, null if not.
|
||||
*/
|
||||
|
||||
Object _d_interface_cast(void* p, ClassInfo c)
|
||||
{ Object o;
|
||||
|
||||
//printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
|
||||
if (p)
|
||||
{
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
return _d_dynamic_cast(o, c);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
{ ClassInfo oc;
|
||||
size_t offset = 0;
|
||||
|
||||
//printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
|
||||
|
||||
if (o)
|
||||
{
|
||||
oc = o.classinfo;
|
||||
if (_d_isbaseof2(oc, c, offset))
|
||||
{
|
||||
//printf("\toffset = %d\n", offset);
|
||||
o = cast(Object)(cast(void*)o + offset);
|
||||
}
|
||||
else
|
||||
o = null;
|
||||
}
|
||||
//printf("\tresult = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c)
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (_d_isbaseof2(ic, c, offset))
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c || _d_isbaseof(ic, c))
|
||||
return 1;
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* Find the vtbl[] associated with Interface ic.
|
||||
*/
|
||||
|
||||
void *_d_interface_vtbl(ClassInfo ic, Object o)
|
||||
{ int i;
|
||||
ClassInfo oc;
|
||||
|
||||
//printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
|
||||
|
||||
assert(o);
|
||||
|
||||
oc = o.classinfo;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo oic;
|
||||
|
||||
oic = oc.interfaces[i].classinfo;
|
||||
if (oic is ic)
|
||||
{
|
||||
return cast(void *)oc.interfaces[i].vtbl;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
218
druntime/src/compiler/dmd/cmath2.d
Normal file
218
druntime/src/compiler/dmd/cmath2.d
Normal file
@@ -0,0 +1,218 @@
|
||||
|
||||
// Copyright (C) 2001-2003 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// www.digitalmars.com
|
||||
|
||||
// Runtime support for complex arithmetic code generation
|
||||
// (for linux)
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.cmath2;
|
||||
|
||||
private import stdc.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
|
||||
*/
|
||||
|
||||
void _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;
|
||||
+/
|
||||
asm
|
||||
{
|
||||
fld q_re;
|
||||
fld q_im;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************
|
||||
* 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 ;
|
||||
}
|
||||
}
|
||||
36
druntime/src/compiler/dmd/compiler.d
Normal file
36
druntime/src/compiler/dmd/compiler.d
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
/* Written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
* Placed into Public Domain
|
||||
*/
|
||||
|
||||
module rt.compiler;
|
||||
|
||||
// Identify the compiler used and its various features.
|
||||
|
||||
const
|
||||
{
|
||||
// Vendor specific string naming the compiler
|
||||
char[] name = "Digital Mars D";
|
||||
|
||||
// Master list of D compiler vendors
|
||||
enum Vendor
|
||||
{
|
||||
DigitalMars = 1
|
||||
}
|
||||
|
||||
// Which vendor we are
|
||||
Vendor vendor = Vendor.DigitalMars;
|
||||
|
||||
|
||||
// The vendor specific version number, as in
|
||||
// version_major.version_minor
|
||||
uint version_major = 0;
|
||||
uint version_minor = 0;
|
||||
|
||||
|
||||
// The version of the D Programming Language Specification
|
||||
// Supported by the compiler
|
||||
uint D_major = 0;
|
||||
uint D_minor = 0;
|
||||
}
|
||||
107
druntime/src/compiler/dmd/complex.c
Normal file
107
druntime/src/compiler/dmd/complex.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Placed into the public domain.
|
||||
* Written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef struct Complex
|
||||
{
|
||||
long double re;
|
||||
long double im;
|
||||
} Complex;
|
||||
|
||||
Complex _complex_div(Complex x, Complex y)
|
||||
{
|
||||
Complex q;
|
||||
long double r;
|
||||
long double den;
|
||||
|
||||
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;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
Complex _complex_mul(Complex x, Complex y)
|
||||
{
|
||||
Complex p;
|
||||
|
||||
p.re = x.re * y.re - x.im * y.im;
|
||||
p.im = x.im * y.re + x.re * y.im;
|
||||
return p;
|
||||
}
|
||||
|
||||
long double _complex_abs(Complex z)
|
||||
{
|
||||
long double x,y,ans,temp;
|
||||
|
||||
x = fabs(z.re);
|
||||
y = fabs(z.im);
|
||||
if (x == 0)
|
||||
ans = y;
|
||||
else if (y == 0)
|
||||
ans = x;
|
||||
else if (x > y)
|
||||
{
|
||||
temp = y / x;
|
||||
ans = x * sqrt(1 + temp * temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = x / y;
|
||||
ans = y * sqrt(1 + temp * temp);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
Complex _complex_sqrt(Complex z)
|
||||
{
|
||||
Complex c;
|
||||
long double x,y,w,r;
|
||||
|
||||
if (z.re == 0 && z.im == 0)
|
||||
{
|
||||
c.re = 0;
|
||||
c.im = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = fabs(z.re);
|
||||
y = fabs(z.im);
|
||||
if (x >= y)
|
||||
{
|
||||
r = y / x;
|
||||
w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
|
||||
}
|
||||
else
|
||||
{
|
||||
r = x / y;
|
||||
w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
|
||||
}
|
||||
if (z.re >= 0)
|
||||
{
|
||||
c.re = w;
|
||||
c.im = z.im / (w + w);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.im = (z.im >= 0) ? w : -w;
|
||||
c.re = z.im / (c.im + c.im);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
373
druntime/src/compiler/dmd/cover.d
Normal file
373
druntime/src/compiler/dmd/cover.d
Normal file
@@ -0,0 +1,373 @@
|
||||
/**
|
||||
* Code coverage analyzer.
|
||||
*
|
||||
* Bugs:
|
||||
* $(UL
|
||||
* $(LI the execution counters are 32 bits in size, and can overflow)
|
||||
* $(LI inline asm statements are not counted)
|
||||
* )
|
||||
*
|
||||
* Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com. All rights reserved.
|
||||
* License: BSD style: $(LICENSE)
|
||||
* Authors: Walter Bright, Sean Kelly
|
||||
*/
|
||||
|
||||
module rt.cover;
|
||||
|
||||
private
|
||||
{
|
||||
version( Windows )
|
||||
import sys.windows.windows;
|
||||
else version( Posix )
|
||||
{
|
||||
import stdc.posix.fcntl;
|
||||
import stdc.posix.unistd;
|
||||
}
|
||||
import core.bitmanip;
|
||||
import stdc.stdio;
|
||||
import util.utf;
|
||||
|
||||
struct BitArray
|
||||
{
|
||||
size_t len;
|
||||
uint* ptr;
|
||||
|
||||
bool opIndex( size_t i )
|
||||
in
|
||||
{
|
||||
assert( i < len );
|
||||
}
|
||||
body
|
||||
{
|
||||
return cast(bool) bt( ptr, i );
|
||||
}
|
||||
}
|
||||
|
||||
struct Cover
|
||||
{
|
||||
char[] filename;
|
||||
BitArray valid;
|
||||
uint[] data;
|
||||
}
|
||||
|
||||
Cover[] gdata;
|
||||
char[] srcpath;
|
||||
char[] dstpath;
|
||||
bool merge;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set path to where source files are located.
|
||||
*
|
||||
* Params:
|
||||
* pathname = The new path name.
|
||||
*/
|
||||
extern (C) void dmd_coverSourcePath( char[] pathname )
|
||||
{
|
||||
srcpath = pathname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set path to where listing files are to be written.
|
||||
*
|
||||
* Params:
|
||||
* pathname = The new path name.
|
||||
*/
|
||||
extern (C) void dmd_coverDestPath( char[] pathname )
|
||||
{
|
||||
dstpath = pathname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set merge mode.
|
||||
*
|
||||
* Params:
|
||||
* flag = true means new data is summed with existing data in the listing
|
||||
* file; false means a new listing file is always created.
|
||||
*/
|
||||
extern (C) void dmd_coverSetMerge( bool flag )
|
||||
{
|
||||
merge = flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The coverage callback.
|
||||
*
|
||||
* Params:
|
||||
* filename = The name of the coverage file.
|
||||
* valid = ???
|
||||
* data = ???
|
||||
*/
|
||||
extern (C) void _d_cover_register( char[] filename, BitArray valid, uint[] data )
|
||||
{
|
||||
Cover c;
|
||||
|
||||
c.filename = filename;
|
||||
c.valid = valid;
|
||||
c.data = data;
|
||||
gdata ~= c;
|
||||
}
|
||||
|
||||
|
||||
static ~this()
|
||||
{
|
||||
const NUMLINES = 16384 - 1;
|
||||
const NUMCHARS = 16384 * 16 - 1;
|
||||
|
||||
char[] srcbuf = new char[NUMCHARS];
|
||||
char[][] srclines = new char[][NUMLINES];
|
||||
char[] lstbuf = new char[NUMCHARS];
|
||||
char[][] lstlines = new char[][NUMLINES];
|
||||
|
||||
foreach( Cover c; gdata )
|
||||
{
|
||||
if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) )
|
||||
continue;
|
||||
splitLines( srcbuf, srclines );
|
||||
|
||||
if( merge )
|
||||
{
|
||||
if( !readFile( c.filename ~ ".lst", lstbuf ) )
|
||||
break;
|
||||
splitLines( lstbuf, lstlines );
|
||||
|
||||
for( size_t i = 0; i < lstlines.length; ++i )
|
||||
{
|
||||
if( i >= c.data.length )
|
||||
break;
|
||||
|
||||
int count = 0;
|
||||
|
||||
foreach( char c2; lstlines[i] )
|
||||
{
|
||||
switch( c2 )
|
||||
{
|
||||
case ' ':
|
||||
continue;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
count = count * 10 + c2 - '0';
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
c.data[i] += count;
|
||||
}
|
||||
}
|
||||
|
||||
FILE* flst = fopen( (c.filename ~ ".lst").ptr, "wb" );
|
||||
|
||||
if( !flst )
|
||||
continue; //throw new Exception( "Error opening file for write: " ~ lstfn );
|
||||
|
||||
uint nno;
|
||||
uint nyes;
|
||||
|
||||
for( int i = 0; i < c.data.length; i++ )
|
||||
{
|
||||
if( i < srclines.length )
|
||||
{
|
||||
uint n = c.data[i];
|
||||
char[] line = srclines[i];
|
||||
|
||||
line = expandTabs( line );
|
||||
|
||||
if( n == 0 )
|
||||
{
|
||||
if( c.valid[i] )
|
||||
{
|
||||
nno++;
|
||||
fprintf( flst, "0000000|%.*s\n", line );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( flst, " |%.*s\n", line );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nyes++;
|
||||
fprintf( flst, "%7u|%.*s\n", n, line );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( nyes + nno ) // no divide by 0 bugs
|
||||
{
|
||||
fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) );
|
||||
}
|
||||
fclose( flst );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char[] appendFN( char[] path, char[] name )
|
||||
{
|
||||
version( Windows )
|
||||
const char sep = '\\';
|
||||
else
|
||||
const char sep = '/';
|
||||
|
||||
char[] dest = path;
|
||||
|
||||
if( dest && dest[$ - 1] != sep )
|
||||
dest ~= sep;
|
||||
dest ~= name;
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
bool readFile( char[] name, inout char[] buf )
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
auto wnamez = toUTF16z( name );
|
||||
HANDLE file = CreateFileW( wnamez,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
null,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
cast(HANDLE) null );
|
||||
|
||||
delete wnamez;
|
||||
if( file == INVALID_HANDLE_VALUE )
|
||||
return false;
|
||||
scope( exit ) CloseHandle( file );
|
||||
|
||||
DWORD num = 0;
|
||||
DWORD pos = 0;
|
||||
|
||||
buf.length = 4096;
|
||||
while( true )
|
||||
{
|
||||
if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) )
|
||||
return false;
|
||||
if( !num )
|
||||
break;
|
||||
pos += num;
|
||||
buf.length = pos * 2;
|
||||
}
|
||||
buf.length = pos;
|
||||
return true;
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
char[] namez = new char[name.length + 1];
|
||||
namez[0 .. name.length] = name;
|
||||
namez[$ - 1] = 0;
|
||||
int file = open( namez.ptr, O_RDONLY );
|
||||
|
||||
delete namez;
|
||||
if( file == -1 )
|
||||
return false;
|
||||
scope( exit ) close( file );
|
||||
|
||||
int num = 0;
|
||||
uint pos = 0;
|
||||
|
||||
buf.length = 4096;
|
||||
while( true )
|
||||
{
|
||||
num = read( file, &buf[pos], cast(uint)( buf.length - pos ) );
|
||||
if( num == -1 )
|
||||
return false;
|
||||
if( !num )
|
||||
break;
|
||||
pos += num;
|
||||
buf.length = pos * 2;
|
||||
}
|
||||
buf.length = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void splitLines( char[] buf, inout char[][] lines )
|
||||
{
|
||||
size_t beg = 0,
|
||||
pos = 0;
|
||||
|
||||
lines.length = 0;
|
||||
for( ; pos < buf.length; ++pos )
|
||||
{
|
||||
char c = buf[pos];
|
||||
|
||||
switch( buf[pos] )
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
lines ~= buf[beg .. pos];
|
||||
beg = pos + 1;
|
||||
if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' )
|
||||
++pos, ++beg;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( beg != pos )
|
||||
{
|
||||
lines ~= buf[beg .. pos];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char[] expandTabs( char[] string, int tabsize = 8 )
|
||||
{
|
||||
const dchar LS = '\u2028'; // UTF line separator
|
||||
const dchar PS = '\u2029'; // UTF paragraph separator
|
||||
|
||||
bool changes = false;
|
||||
char[] result = string;
|
||||
int column;
|
||||
int nspaces;
|
||||
|
||||
foreach( size_t i, dchar c; string )
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case '\t':
|
||||
nspaces = tabsize - (column % tabsize);
|
||||
if( !changes )
|
||||
{
|
||||
changes = true;
|
||||
result = null;
|
||||
result.length = string.length + nspaces - 1;
|
||||
result.length = i + nspaces;
|
||||
result[0 .. i] = string[0 .. i];
|
||||
result[i .. i + nspaces] = ' ';
|
||||
}
|
||||
else
|
||||
{ int j = result.length;
|
||||
result.length = j + nspaces;
|
||||
result[j .. j + nspaces] = ' ';
|
||||
}
|
||||
column += nspaces;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
case '\n':
|
||||
case PS:
|
||||
case LS:
|
||||
column = 0;
|
||||
goto L1;
|
||||
|
||||
default:
|
||||
column++;
|
||||
L1:
|
||||
if (changes)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
result ~= c;
|
||||
else
|
||||
encode(result, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
159
druntime/src/compiler/dmd/critical.c
Normal file
159
druntime/src/compiler/dmd/critical.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/* ================================= Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.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;
|
||||
CRITICAL_SECTION 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)
|
||||
{
|
||||
EnterCriticalSection(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
InitializeCriticalSection(&dcs->cs);
|
||||
}
|
||||
LeaveCriticalSection(&critical_section.cs);
|
||||
}
|
||||
EnterCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
LeaveCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&critical_section.cs);
|
||||
dcs_list = &critical_section;
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
while (dcs_list)
|
||||
{
|
||||
DeleteCriticalSection(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ================================= linux ============================ */
|
||||
|
||||
#if linux
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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 pthread_mutexattr_t _criticals_attr;
|
||||
|
||||
void _STI_critical_init(void);
|
||||
void _STD_critical_term(void);
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ _STI_critical_init();
|
||||
atexit(_STD_critical_term);
|
||||
}
|
||||
//printf("_d_criticalenter(dcs = x%x)\n", 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, &_criticals_attr);
|
||||
}
|
||||
pthread_mutex_unlock(&critical_section.cs);
|
||||
}
|
||||
pthread_mutex_lock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
//printf("_d_criticalexit(dcs = x%x)\n", dcs);
|
||||
pthread_mutex_unlock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ //printf("_STI_critical_init()\n");
|
||||
pthread_mutexattr_init(&_criticals_attr);
|
||||
pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
|
||||
// The global critical section doesn't need to be recursive
|
||||
pthread_mutex_init(&critical_section.cs, 0);
|
||||
dcs_list = &critical_section;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (dcs_list)
|
||||
{ //printf("_STI_critical_term()\n");
|
||||
while (dcs_list)
|
||||
{
|
||||
//printf("\tlooping... %x\n", dcs_list);
|
||||
pthread_mutex_destroy(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
662
druntime/src/compiler/dmd/deh.c
Normal file
662
druntime/src/compiler/dmd/deh.c
Normal file
@@ -0,0 +1,662 @@
|
||||
//
|
||||
// Copyright (c) 1999-2003 by Digital Mars, www.digitalmars.com
|
||||
// All Rights Reserved
|
||||
// Written by Walter Bright
|
||||
|
||||
// Exception handling support
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ======================== Win32 =============================== */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <excpt.h>
|
||||
#include <windows.h>
|
||||
|
||||
//#include "\sc\src\include\ehsup.h"
|
||||
|
||||
/*** From Digital Mars C runtime library ***/
|
||||
EXCEPTION_DISPOSITION __cdecl _local_except_handler (EXCEPTION_RECORD *ExceptionRecord,
|
||||
void* EstablisherFrame,
|
||||
void *ContextRecord,
|
||||
void *DispatcherContext
|
||||
);
|
||||
void __cdecl _global_unwind(void *frame,EXCEPTION_RECORD *eRecord);
|
||||
#define EXCEPTION_UNWIND 6 // Flag to indicate if the system is unwinding
|
||||
|
||||
extern DWORD _except_list;
|
||||
/*** ***/
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
extern ClassInfo D6object9Throwable7__ClassZ;
|
||||
#define _Class_9Throwable D6object9Throwable7__ClassZ;
|
||||
|
||||
extern ClassInfo D6object5Error7__ClassZ;
|
||||
#define _Class_5Error D6object5Error7__ClassZ
|
||||
|
||||
typedef int (__pascal *fp_t)(); // function pointer in ambient memory model
|
||||
|
||||
// The layout of DEstablisherFrame is the same for C++
|
||||
|
||||
struct DEstablisherFrame
|
||||
{
|
||||
void *prev; // pointer to previous exception list
|
||||
void *handler; // pointer to routine for exception handler
|
||||
DWORD table_index; // current index into handler_info[]
|
||||
DWORD ebp; // this is EBP of routine
|
||||
};
|
||||
|
||||
struct DHandlerInfo
|
||||
{
|
||||
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 is passed in EAX to _d_framehandler()
|
||||
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
// Macro to make our own exception code
|
||||
#define MAKE_EXCEPTION_CODE(severity, facility, exception) \
|
||||
(((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception))
|
||||
|
||||
#define STATUS_DIGITAL_MARS_D_EXCEPTION MAKE_EXCEPTION_CODE(3,'D',1)
|
||||
|
||||
Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record);
|
||||
void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, struct DEstablisherFrame *frame, int stop_index);
|
||||
|
||||
|
||||
/***********************************
|
||||
* The frame handler, this is called for each frame that has been registered
|
||||
* in the OS except_list.
|
||||
* Input:
|
||||
* EAX the handler table for the frame
|
||||
*/
|
||||
|
||||
EXCEPTION_DISPOSITION _d_framehandler(
|
||||
EXCEPTION_RECORD *exception_record,
|
||||
struct DEstablisherFrame *frame,
|
||||
CONTEXT context,
|
||||
void *dispatcher_context)
|
||||
{
|
||||
struct DHandlerTable *handler_table;
|
||||
|
||||
__asm { mov handler_table,EAX }
|
||||
|
||||
if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
|
||||
{
|
||||
// Call all the finally blocks in this frame
|
||||
_d_local_unwind(handler_table, frame, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Jump to catch block if matching one is found
|
||||
|
||||
int ndx,prev_ndx,i;
|
||||
struct DHandlerInfo *phi;
|
||||
struct DCatchInfo *pci;
|
||||
struct DCatchBlock *pcb;
|
||||
unsigned ncatches; // number of catches in the current handler
|
||||
Object *pti;
|
||||
ClassInfo *ci;
|
||||
|
||||
ci = NULL; // only compute it if we need it
|
||||
|
||||
// walk through handler table, checking each handler
|
||||
// with an index smaller than the current table_index
|
||||
for (ndx = frame->table_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)
|
||||
pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
|
||||
ncatches = pci->ncatches;
|
||||
for (i = 0; i < ncatches; i++)
|
||||
{
|
||||
pcb = &pci->catch_block[i];
|
||||
|
||||
if (!ci)
|
||||
{
|
||||
// This code must match the translation code
|
||||
if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION)
|
||||
{
|
||||
//printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]);
|
||||
ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]);
|
||||
}
|
||||
else
|
||||
ci = &_Class_9Throwable;
|
||||
}
|
||||
|
||||
if (_d_isbaseof(ci, pcb->type))
|
||||
{
|
||||
// Matched the catch type, so we've found the handler.
|
||||
int regebp;
|
||||
|
||||
pti = _d_translate_se_to_d_exception(exception_record);
|
||||
|
||||
// Initialize catch variable
|
||||
regebp = (int)&frame->ebp; // EBP for this frame
|
||||
*(void **)(regebp + (pcb->bpoffset)) = pti;
|
||||
|
||||
// Have system call all finally blocks in intervening frames
|
||||
_global_unwind(frame, exception_record);
|
||||
|
||||
// Call all the finally blocks skipped in this frame
|
||||
_d_local_unwind(handler_table, frame, ndx);
|
||||
|
||||
frame->table_index = prev_ndx; // we are out of this handler
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Exception filter for use in __try..__except block
|
||||
* surrounding call to Dmain()
|
||||
*/
|
||||
|
||||
int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs,
|
||||
int retval,
|
||||
Object **exception_object)
|
||||
{
|
||||
*exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Throw a D object.
|
||||
*/
|
||||
|
||||
void __stdcall _d_throw(Object *h)
|
||||
{
|
||||
//printf("_d_throw(h = %p, &h = %p)\n", h, &h);
|
||||
//printf("\tvptr = %p\n", *(void **)h);
|
||||
RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION,
|
||||
EXCEPTION_NONCONTINUABLE,
|
||||
1, (DWORD *)&h);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Create an exception object
|
||||
*/
|
||||
|
||||
Object *_d_create_exception_object(ClassInfo *ci, char *msg)
|
||||
{
|
||||
Throwable *exc;
|
||||
|
||||
exc = (Throwable *)_d_newclass(ci);
|
||||
// BUG: what if _d_newclass() throws an out of memory exception?
|
||||
|
||||
if (msg)
|
||||
{
|
||||
exc->msglen = strlen(msg);
|
||||
exc->msg = msg;
|
||||
}
|
||||
return (Object *)exc;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Converts a Windows Structured Exception code to a D Exception Object.
|
||||
*/
|
||||
|
||||
Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record)
|
||||
{
|
||||
Object *pti;
|
||||
|
||||
switch (exception_record->ExceptionCode) {
|
||||
case STATUS_DIGITAL_MARS_D_EXCEPTION:
|
||||
// Generated D exception
|
||||
pti = (Object *)(exception_record->ExceptionInformation[0]);
|
||||
break;
|
||||
|
||||
case STATUS_INTEGER_DIVIDE_BY_ZERO:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero");
|
||||
break;
|
||||
|
||||
case STATUS_FLOAT_DIVIDE_BY_ZERO:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero");
|
||||
break;
|
||||
|
||||
case STATUS_ACCESS_VIOLATION:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Access Violation");
|
||||
break;
|
||||
|
||||
case STATUS_STACK_OVERFLOW:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow");
|
||||
break;
|
||||
|
||||
// convert all other exception codes into a Win32Exception
|
||||
default:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception");
|
||||
break;
|
||||
}
|
||||
|
||||
return pti;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Call finally blocks in the current stack frame until stop_index.
|
||||
* This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c
|
||||
*/
|
||||
|
||||
void __cdecl _d_local_unwind(struct DHandlerTable *handler_table,
|
||||
struct DEstablisherFrame *frame, int stop_index)
|
||||
{
|
||||
struct DHandlerInfo *phi;
|
||||
struct DCatchInfo *pci;
|
||||
int i;
|
||||
|
||||
// Set up a special exception handler to catch double-fault exceptions.
|
||||
__asm
|
||||
{
|
||||
push dword ptr -1
|
||||
push dword ptr 0
|
||||
push offset _local_except_handler // defined in src\win32\ehsup.c
|
||||
push dword ptr fs:_except_list
|
||||
mov FS:_except_list,ESP
|
||||
}
|
||||
|
||||
for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index)
|
||||
{
|
||||
phi = &handler_table->handler_info[i];
|
||||
if (phi->finally_code)
|
||||
{
|
||||
// Note that it is unnecessary to adjust the ESP, as the finally block
|
||||
// accesses all items on the stack as relative to EBP.
|
||||
|
||||
DWORD *catch_ebp = &frame->ebp;
|
||||
void *blockaddr = phi->finally_code;
|
||||
|
||||
_asm
|
||||
{
|
||||
push EBX
|
||||
mov EBX,blockaddr
|
||||
push EBP
|
||||
mov EBP,catch_ebp
|
||||
call EBX
|
||||
pop EBP
|
||||
pop EBX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_asm
|
||||
{
|
||||
pop FS:_except_list
|
||||
add ESP,12
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* external version of the unwinder
|
||||
*/
|
||||
|
||||
__declspec(naked) void __cdecl _d_local_unwind2()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
jmp _d_local_unwind
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* The frame handler, this is called for each frame that has been registered
|
||||
* in the OS except_list.
|
||||
* Input:
|
||||
* EAX the handler table for the frame
|
||||
*/
|
||||
|
||||
EXCEPTION_DISPOSITION _d_monitor_handler(
|
||||
EXCEPTION_RECORD *exception_record,
|
||||
struct DEstablisherFrame *frame,
|
||||
CONTEXT context,
|
||||
void *dispatcher_context)
|
||||
{
|
||||
if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
|
||||
{
|
||||
_d_monitorexit((Object *)frame->table_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*/
|
||||
|
||||
void _d_monitor_prolog(void *x, void *y, Object *h)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push EAX
|
||||
}
|
||||
//printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h);
|
||||
_d_monitorenter(h);
|
||||
__asm
|
||||
{
|
||||
pop EAX
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*/
|
||||
|
||||
void _d_monitor_epilog(void *x, void *y, Object *h)
|
||||
{
|
||||
//printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h);
|
||||
__asm
|
||||
{
|
||||
push EAX
|
||||
push EDX
|
||||
}
|
||||
_d_monitorexit(h);
|
||||
__asm
|
||||
{
|
||||
pop EDX
|
||||
pop EAX
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ======================== linux =============================== */
|
||||
|
||||
#if linux
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
extern ClassInfo D6object9Throwable7__ClassZ;
|
||||
#define _Class_9Throwable D6object9Throwable7__ClassZ;
|
||||
|
||||
extern ClassInfo D6object5Error7__ClassZ;
|
||||
#define _Class_5Error D6object5Error7__ClassZ
|
||||
|
||||
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
|
||||
308
druntime/src/compiler/dmd/deh2.d
Normal file
308
druntime/src/compiler/dmd/deh2.d
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (C) 1999-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.deh2;
|
||||
|
||||
// Exception handling support for linux
|
||||
|
||||
//debug=1;
|
||||
|
||||
extern (C)
|
||||
{
|
||||
extern void* _deh_beg;
|
||||
extern void* _deh_end;
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c);
|
||||
}
|
||||
|
||||
alias int (*fp_t)(); // function pointer in ambient memory model
|
||||
|
||||
struct DHandlerInfo
|
||||
{
|
||||
uint offset; // offset from function address to start of guarded section
|
||||
uint endoffset; // offset of end of guarded section
|
||||
int prev_index; // previous table index
|
||||
uint 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
|
||||
uint espoffset; // offset of ESP from EBP
|
||||
uint retoffset; // offset from start of function to return code
|
||||
uint nhandlers; // dimension of handler_info[]
|
||||
DHandlerInfo handler_info[1];
|
||||
}
|
||||
|
||||
struct DCatchBlock
|
||||
{
|
||||
ClassInfo type; // catch type
|
||||
uint bpoffset; // EBP offset of catch var
|
||||
void *code; // catch handler code
|
||||
}
|
||||
|
||||
// Create one of these for each try-catch
|
||||
struct DCatchInfo
|
||||
{
|
||||
uint ncatches; // number of catch blocks
|
||||
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
|
||||
DHandlerTable *handlertable; // eh data for this function
|
||||
uint fsize; // size of function in bytes
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
DHandlerTable *__eh_finddata(void *address)
|
||||
{
|
||||
FuncTable *ft;
|
||||
|
||||
// debug printf("__eh_finddata(address = x%x)\n", address);
|
||||
// debug printf("_deh_beg = x%x, _deh_end = x%x\n", &_deh_beg, &_deh_end);
|
||||
for (ft = cast(FuncTable *)&_deh_beg;
|
||||
ft < cast(FuncTable *)&_deh_end;
|
||||
ft++)
|
||||
{
|
||||
// debug printf("\tfptr = x%x, fsize = x%03x, handlertable = x%x\n",
|
||||
// ft.fptr, ft.fsize, ft.handlertable);
|
||||
|
||||
if (ft.fptr <= address &&
|
||||
address < cast(void *)(cast(char *)ft.fptr + ft.fsize))
|
||||
{
|
||||
// debug printf("\tfound handler table\n");
|
||||
return ft.handlertable;
|
||||
}
|
||||
}
|
||||
// debug printf("\tnot found\n");
|
||||
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
|
||||
*/
|
||||
|
||||
uint __eh_find_caller(uint regbp, uint *pretaddr)
|
||||
{
|
||||
uint bp = *cast(uint *)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 = *cast(uint *)(regbp + int.sizeof);
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Throw a D object.
|
||||
*/
|
||||
|
||||
extern (Windows) void _d_throw(Object *h)
|
||||
{
|
||||
uint regebp;
|
||||
|
||||
debug
|
||||
{
|
||||
printf("_d_throw(h = %p, &h = %p)\n", h, &h);
|
||||
printf("\tvptr = %p\n", *cast(void **)h);
|
||||
}
|
||||
|
||||
asm
|
||||
{
|
||||
mov regebp,EBP ;
|
||||
}
|
||||
|
||||
//static uint abc;
|
||||
//if (++abc == 2) *(char *)0=0;
|
||||
|
||||
//int count = 0;
|
||||
while (1) // for each function on the stack
|
||||
{
|
||||
DHandlerTable *handler_table;
|
||||
FuncTable *pfunc;
|
||||
DHandlerInfo *phi;
|
||||
uint retaddr;
|
||||
uint funcoffset;
|
||||
uint spoff;
|
||||
uint retoffset;
|
||||
int index;
|
||||
int dim;
|
||||
int ndx;
|
||||
int prev_ndx;
|
||||
|
||||
regebp = __eh_find_caller(regebp,&retaddr);
|
||||
if (!regebp)
|
||||
{ // if end of call chain
|
||||
debug printf("end of call chain\n");
|
||||
break;
|
||||
}
|
||||
|
||||
debug printf("found caller, EBP = x%x, retaddr = x%x\n", regebp, retaddr);
|
||||
//if (++count == 12) *(char*)0=0;
|
||||
handler_table = __eh_finddata(cast(void *)retaddr); // find static data associated with function
|
||||
if (!handler_table) // if no static data
|
||||
{
|
||||
debug printf("no handler table\n");
|
||||
continue;
|
||||
}
|
||||
funcoffset = cast(uint)handler_table.fptr;
|
||||
spoff = handler_table.espoffset;
|
||||
retoffset = handler_table.retoffset;
|
||||
|
||||
debug
|
||||
{
|
||||
printf("retaddr = x%x\n",cast(uint)retaddr);
|
||||
printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
|
||||
regebp,funcoffset,spoff,retoffset);
|
||||
}
|
||||
|
||||
// Find start index for retaddr in static data
|
||||
dim = handler_table.nhandlers;
|
||||
|
||||
debug
|
||||
{
|
||||
printf("handler_info[]:\n");
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
phi = &handler_table.handler_info[i];
|
||||
printf("\t[%d]: offset = x%04x, endoffset = x%04x, prev_index = %d, cioffset = x%04x, finally_code = %x\n",
|
||||
i, phi.offset, phi.endoffset, phi.prev_index, phi.cioffset, phi.finally_code);
|
||||
}
|
||||
}
|
||||
|
||||
index = -1;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
phi = &handler_table.handler_info[i];
|
||||
|
||||
debug printf("i = %d, phi.offset = %04x\n", i, funcoffset + phi.offset);
|
||||
if (cast(uint)retaddr > funcoffset + phi.offset &&
|
||||
cast(uint)retaddr <= funcoffset + phi.endoffset)
|
||||
index = i;
|
||||
}
|
||||
debug printf("index = %d\n", index);
|
||||
|
||||
// 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)
|
||||
DCatchInfo *pci;
|
||||
int ncatches;
|
||||
int i;
|
||||
|
||||
pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset);
|
||||
ncatches = pci.ncatches;
|
||||
for (i = 0; i < ncatches; i++)
|
||||
{
|
||||
DCatchBlock *pcb;
|
||||
ClassInfo ci = **cast(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
|
||||
*cast(void **)(regebp + (pcb.bpoffset)) = h;
|
||||
|
||||
// Jump to catch block. Does not return.
|
||||
{
|
||||
uint catch_esp;
|
||||
fp_t catch_addr;
|
||||
|
||||
catch_addr = cast(fp_t)(pcb.code);
|
||||
catch_esp = regebp - handler_table.espoffset - fp_t.sizeof;
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
315
druntime/src/compiler/dmd/dmain2.d
Normal file
315
druntime/src/compiler/dmd/dmain2.d
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Placed into the Public Domain.
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.dmain2;
|
||||
|
||||
private
|
||||
{
|
||||
import util.console;
|
||||
import stdc.stddef;
|
||||
import stdc.stdlib;
|
||||
import stdc.string;
|
||||
}
|
||||
|
||||
version(Windows)
|
||||
{
|
||||
extern (Windows) void* LocalFree(void*);
|
||||
extern (Windows) wchar_t* GetCommandLineW();
|
||||
extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*);
|
||||
extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
|
||||
pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
|
||||
}
|
||||
|
||||
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_term();
|
||||
extern (C) void _minit();
|
||||
extern (C) void _moduleCtor();
|
||||
extern (C) void _moduleDtor();
|
||||
extern (C) void thread_joinAll();
|
||||
|
||||
/***********************************
|
||||
* These functions must be defined for any D program linked
|
||||
* against this library.
|
||||
*/
|
||||
extern (C) void onAssertError(string file, size_t line);
|
||||
extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
|
||||
extern (C) void onArrayBoundsError(string file, size_t line);
|
||||
extern (C) void onHiddenFuncError(Object o);
|
||||
extern (C) void onSwitchError(string file, size_t line);
|
||||
extern (C) bool runModuleUnitTests();
|
||||
|
||||
// this function is called from the utf module
|
||||
//extern (C) void onUnicodeError(string msg, size_t idx);
|
||||
|
||||
/***********************************
|
||||
* These are internal callbacks for various language errors.
|
||||
*/
|
||||
extern (C) void _d_assert(string file, uint line)
|
||||
{
|
||||
onAssertError(file, line);
|
||||
}
|
||||
|
||||
extern (C) static void _d_assert_msg(string msg, string file, uint line)
|
||||
{
|
||||
onAssertErrorMsg(file, line, msg);
|
||||
}
|
||||
|
||||
extern (C) void _d_array_bounds(string file, uint line)
|
||||
{
|
||||
onArrayBoundsError(file, line);
|
||||
}
|
||||
|
||||
extern (C) void _d_switch_error(string file, uint line)
|
||||
{
|
||||
onSwitchError(file, line);
|
||||
}
|
||||
|
||||
extern (C) void _d_hidden_func()
|
||||
{
|
||||
Object o;
|
||||
asm
|
||||
{
|
||||
mov o, EAX;
|
||||
}
|
||||
onHiddenFuncError(o);
|
||||
}
|
||||
|
||||
bool _d_isHalting = false;
|
||||
|
||||
extern (C) bool rt_isHalting()
|
||||
{
|
||||
return _d_isHalting;
|
||||
}
|
||||
|
||||
extern (C) bool rt_trapExceptions = true;
|
||||
|
||||
void _d_criticalInit()
|
||||
{
|
||||
version (linux)
|
||||
{
|
||||
_STI_monitor_staticctor();
|
||||
_STI_critical_init();
|
||||
}
|
||||
}
|
||||
|
||||
alias void delegate(Throwable) ExceptionHandler;
|
||||
|
||||
extern (C) bool rt_init(ExceptionHandler dg = null)
|
||||
{
|
||||
_d_criticalInit();
|
||||
|
||||
try
|
||||
{
|
||||
gc_init();
|
||||
version (Windows)
|
||||
_minit();
|
||||
_moduleCtor();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
if (dg)
|
||||
dg(e);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
_d_criticalTerm();
|
||||
return false;
|
||||
}
|
||||
|
||||
void _d_criticalTerm()
|
||||
{
|
||||
version (linux)
|
||||
{
|
||||
_STD_critical_term();
|
||||
_STD_monitor_staticdtor();
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) bool rt_term(ExceptionHandler dg = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
thread_joinAll();
|
||||
_d_isHalting = true;
|
||||
_moduleDtor();
|
||||
gc_term();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
if (dg)
|
||||
dg(e);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
_d_criticalTerm();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* The D main() function supplied by the user's program
|
||||
*/
|
||||
int main(char[][] args);
|
||||
|
||||
/***********************************
|
||||
* Substitutes for the C main() function.
|
||||
* It's purpose is to wrap the call to the D main()
|
||||
* function and catch any unhandled exceptions.
|
||||
*/
|
||||
|
||||
extern (C) int main(int argc, char **argv)
|
||||
{
|
||||
char[][] args;
|
||||
int result;
|
||||
|
||||
version (linux)
|
||||
{
|
||||
_STI_monitor_staticctor();
|
||||
_STI_critical_init();
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
wchar_t* wcbuf = GetCommandLineW();
|
||||
size_t wclen = wcslen(wcbuf);
|
||||
int wargc = 0;
|
||||
wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
|
||||
assert(wargc == argc);
|
||||
|
||||
char* cargp = null;
|
||||
size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
|
||||
|
||||
cargp = cast(char*) alloca(cargl);
|
||||
args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
|
||||
|
||||
for (size_t i = 0, p = 0; i < wargc; i++)
|
||||
{
|
||||
int wlen = wcslen(wargs[i]);
|
||||
int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
|
||||
args[i] = cargp[p .. p+clen];
|
||||
p += clen; assert(p <= cargl);
|
||||
WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
|
||||
}
|
||||
LocalFree(wargs);
|
||||
wargs = null;
|
||||
wargc = 0;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
|
||||
scope(exit) free(am);
|
||||
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
{
|
||||
auto len = strlen(argv[i]);
|
||||
am[i] = argv[i][0 .. len];
|
||||
}
|
||||
args = am[0 .. argc];
|
||||
}
|
||||
|
||||
bool trapExceptions = rt_trapExceptions;
|
||||
|
||||
void tryExec(void delegate() dg)
|
||||
{
|
||||
|
||||
if (trapExceptions)
|
||||
{
|
||||
try
|
||||
{
|
||||
dg();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
while (e)
|
||||
{
|
||||
if (e.file)
|
||||
{
|
||||
// fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
|
||||
console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf(stderr, "%.*s\n", e.toString());
|
||||
console (e.toString)("\n");
|
||||
}
|
||||
if (e.info)
|
||||
{
|
||||
console ("----------------\n");
|
||||
foreach (t; e.info)
|
||||
console (t)("\n");
|
||||
}
|
||||
if (e.next)
|
||||
console ("\n");
|
||||
e = e.next;
|
||||
}
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
// fprintf(stderr, "%.*s\n", o.toString());
|
||||
console (o.toString)("\n");
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dg();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The lifetime of a process is much like the lifetime of an object:
|
||||
// it is initialized, then used, then destroyed. If initialization
|
||||
// fails, the successive two steps are never reached. However, if
|
||||
// initialization succeeds, then cleanup will occur even if the use
|
||||
// step fails in some way. Here, the use phase consists of running
|
||||
// the user's main function. If main terminates with an exception,
|
||||
// the exception is handled and then cleanup begins. An exception
|
||||
// thrown during cleanup, however, will abort the cleanup process.
|
||||
|
||||
void runMain()
|
||||
{
|
||||
result = main(args);
|
||||
}
|
||||
|
||||
void runAll()
|
||||
{
|
||||
gc_init();
|
||||
version (Windows)
|
||||
_minit();
|
||||
_moduleCtor();
|
||||
if (runModuleUnitTests())
|
||||
tryExec(&runMain);
|
||||
thread_joinAll();
|
||||
_d_isHalting = true;
|
||||
_moduleDtor();
|
||||
gc_term();
|
||||
}
|
||||
|
||||
tryExec(&runAll);
|
||||
|
||||
version (linux)
|
||||
{
|
||||
_STD_critical_term();
|
||||
_STD_monitor_staticdtor();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
24
druntime/src/compiler/dmd/invariant.d
Normal file
24
druntime/src/compiler/dmd/invariant.d
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
void _d_invariant(Object o)
|
||||
{ ClassInfo c;
|
||||
|
||||
//printf("__d_invariant(%p)\n", o);
|
||||
|
||||
// BUG: needs to be filename/line of caller, not library routine
|
||||
assert(o !is null); // just do null check, not invariant check
|
||||
|
||||
c = o.classinfo;
|
||||
do
|
||||
{
|
||||
if (c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
}
|
||||
25
druntime/src/compiler/dmd/invariant_.d
Normal file
25
druntime/src/compiler/dmd/invariant_.d
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
module rt.invariant_;
|
||||
|
||||
extern (C) void _d_invariant(Object o)
|
||||
{ ClassInfo c;
|
||||
|
||||
//printf("__d_invariant(%p)\n", o);
|
||||
|
||||
// BUG: needs to be filename/line of caller, not library routine
|
||||
assert(o !is null); // just do null check, not invariant check
|
||||
|
||||
c = o.classinfo;
|
||||
do
|
||||
{
|
||||
if (c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
}
|
||||
1081
druntime/src/compiler/dmd/lifetime.d
Normal file
1081
druntime/src/compiler/dmd/lifetime.d
Normal file
File diff suppressed because it is too large
Load Diff
295
druntime/src/compiler/dmd/llmath.d
Normal file
295
druntime/src/compiler/dmd/llmath.d
Normal file
@@ -0,0 +1,295 @@
|
||||
// llmath.d
|
||||
// Copyright (C) 1993-2003 by Digital Mars, www.digitalmars.com
|
||||
// All Rights Reserved
|
||||
// Written by Walter Bright
|
||||
|
||||
module rt.llmath;
|
||||
|
||||
// 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 ;
|
||||
cdq ; // [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)0x800_0000_0000_0000 * 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 ;
|
||||
}
|
||||
}
|
||||
|
||||
// Same as __U64_LDBL, but return result as double in [EDX,EAX]
|
||||
ulong __ULLNGDBL()
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
call __U64_LDBL ;
|
||||
sub ESP,8 ;
|
||||
fstp double ptr [ESP] ;
|
||||
pop EAX ;
|
||||
pop EDX ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert double to ulong
|
||||
|
||||
private short roundTo0 = 0xFBF;
|
||||
|
||||
ulong __DBLULLNG()
|
||||
{
|
||||
// BUG: should handle NAN's and overflows
|
||||
asm
|
||||
{ naked ;
|
||||
push EDX ;
|
||||
push EAX ;
|
||||
fld double ptr [ESP] ;
|
||||
sub ESP,8 ;
|
||||
fld real ptr adjust ;
|
||||
fcomp ;
|
||||
fstsw AX ;
|
||||
fstcw 8[ESP] ;
|
||||
fldcw roundTo0 ;
|
||||
sahf ;
|
||||
jae L1 ;
|
||||
fld real ptr adjust ;
|
||||
fsubp ST(1), ST ;
|
||||
fistp qword ptr [ESP] ;
|
||||
pop EAX ;
|
||||
pop EDX ;
|
||||
fldcw [ESP] ;
|
||||
add ESP,8 ;
|
||||
add EDX,0x8000_0000 ;
|
||||
ret ;
|
||||
L1: ;
|
||||
fistp qword ptr [ESP] ;
|
||||
pop EAX ;
|
||||
pop EDX ;
|
||||
fldcw [ESP] ;
|
||||
add ESP,8 ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert double in ST0 to uint
|
||||
|
||||
uint __DBLULNG()
|
||||
{
|
||||
// BUG: should handle NAN's and overflows
|
||||
asm
|
||||
{ naked ;
|
||||
sub ESP,16 ;
|
||||
fstcw 8[ESP] ;
|
||||
fldcw roundTo0 ;
|
||||
fistp qword ptr [ESP] ;
|
||||
fldcw 8[ESP] ;
|
||||
pop EAX ;
|
||||
add ESP,12 ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
104
druntime/src/compiler/dmd/mars.h
Normal file
104
druntime/src/compiler/dmd/mars.h
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ClassInfo;
|
||||
struct Vtbl;
|
||||
|
||||
typedef struct Vtbl
|
||||
{
|
||||
size_t len;
|
||||
void **vptr;
|
||||
} Vtbl;
|
||||
|
||||
typedef struct Interface
|
||||
{
|
||||
struct ClassInfo *classinfo;
|
||||
struct Vtbl vtbl;
|
||||
int offset;
|
||||
} Interface;
|
||||
|
||||
typedef struct Object
|
||||
{
|
||||
void **vptr;
|
||||
void *monitor;
|
||||
} Object;
|
||||
|
||||
typedef struct ClassInfo
|
||||
{
|
||||
Object object;
|
||||
|
||||
size_t initlen;
|
||||
void *init;
|
||||
|
||||
size_t namelen;
|
||||
char *name;
|
||||
|
||||
Vtbl vtbl;
|
||||
|
||||
size_t interfacelen;
|
||||
Interface *interfaces;
|
||||
|
||||
struct ClassInfo *baseClass;
|
||||
|
||||
void *destructor;
|
||||
void *invariant;
|
||||
|
||||
int flags;
|
||||
} ClassInfo;
|
||||
|
||||
typedef struct Throwable
|
||||
{
|
||||
Object object;
|
||||
|
||||
size_t msglen;
|
||||
char* msg;
|
||||
|
||||
size_t filelen;
|
||||
char* file;
|
||||
|
||||
size_t line;
|
||||
|
||||
struct Interface *info;
|
||||
struct Throwable *next;
|
||||
} Throwable;
|
||||
|
||||
typedef struct Array
|
||||
{
|
||||
size_t length;
|
||||
void *ptr;
|
||||
} Array;
|
||||
|
||||
typedef struct Delegate
|
||||
{
|
||||
void *thisptr;
|
||||
void (*funcptr)();
|
||||
} Delegate;
|
||||
|
||||
void _d_monitorenter(Object *h);
|
||||
void _d_monitorexit(Object *h);
|
||||
|
||||
int _d_isbaseof(ClassInfo *b, ClassInfo *c);
|
||||
Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
|
||||
|
||||
Object * _d_newclass(ClassInfo *ci);
|
||||
void _d_delclass(Object **p);
|
||||
|
||||
void _d_OutOfMemory();
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
184
druntime/src/compiler/dmd/memory.d
Normal file
184
druntime/src/compiler/dmd/memory.d
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* This module exposes functionality for inspecting and manipulating memory.
|
||||
*
|
||||
* Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
|
||||
* All rights reserved.
|
||||
* License:
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
* Authors: Walter Bright, Sean Kelly
|
||||
*/
|
||||
module rt.memory;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
version( linux )
|
||||
{
|
||||
version = SimpleLibcStackEnd;
|
||||
|
||||
version( SimpleLibcStackEnd )
|
||||
{
|
||||
extern (C) extern void* __libc_stack_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_stackBottom()
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked;
|
||||
mov EAX,FS:4;
|
||||
ret;
|
||||
}
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
version( SimpleLibcStackEnd )
|
||||
{
|
||||
return __libc_stack_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
// See discussion: http://autopackage.org/forums/viewtopic.php?t=22
|
||||
static void** libc_stack_end;
|
||||
|
||||
if( libc_stack_end == libc_stack_end.init )
|
||||
{
|
||||
void* handle = dlopen( null, RTLD_NOW );
|
||||
libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
|
||||
dlclose( handle );
|
||||
}
|
||||
return *libc_stack_end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Operating system not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_stackTop()
|
||||
{
|
||||
version( D_InlineAsm_X86 )
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked;
|
||||
mov EAX, ESP;
|
||||
ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Architecture not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
extern (C)
|
||||
{
|
||||
extern int _xi_a; // &_xi_a just happens to be start of data segment
|
||||
extern int _edata; // &_edata is start of BSS segment
|
||||
extern int _end; // &_end is past end of BSS
|
||||
}
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
extern (C)
|
||||
{
|
||||
extern int _data;
|
||||
extern int __data_start;
|
||||
extern int _end;
|
||||
extern int _data_start__;
|
||||
extern int _data_end__;
|
||||
extern int _bss_start__;
|
||||
extern int _bss_end__;
|
||||
extern int __fini_array_end;
|
||||
}
|
||||
|
||||
alias __data_start Data_Start;
|
||||
alias _end Data_End;
|
||||
}
|
||||
|
||||
alias void delegate( void*, void* ) scanFn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void rt_scanStaticData( scanFn scan )
|
||||
{
|
||||
scan(rt_staticDataBottom(), rt_staticDataTop());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_staticDataBottom()
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
return &_xi_a;
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
return &__data_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Operating system not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_staticDataTop()
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
return &_end;
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
return &_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Operating system not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
120
druntime/src/compiler/dmd/memset.d
Normal file
120
druntime/src/compiler/dmd/memset.d
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
module rt.memset;
|
||||
|
||||
|
||||
extern (C)
|
||||
{
|
||||
// Functions from the C library.
|
||||
void *memcpy(void *, void *, size_t);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
short *_memset16(short *p, short value, size_t count)
|
||||
{
|
||||
short *pstart = p;
|
||||
short *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
int *_memset32(int *p, int value, size_t count)
|
||||
{
|
||||
version (X86)
|
||||
{
|
||||
asm
|
||||
{
|
||||
mov EDI,p ;
|
||||
mov EAX,value ;
|
||||
mov ECX,count ;
|
||||
mov EDX,EDI ;
|
||||
rep ;
|
||||
stosd ;
|
||||
mov EAX,EDX ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int *pstart = p;
|
||||
int *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
}
|
||||
|
||||
long *_memset64(long *p, long value, size_t count)
|
||||
{
|
||||
long *pstart = p;
|
||||
long *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
cdouble *_memset128(cdouble *p, cdouble value, size_t count)
|
||||
{
|
||||
cdouble *pstart = p;
|
||||
cdouble *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
real *_memset80(real *p, real value, size_t count)
|
||||
{
|
||||
real *pstart = p;
|
||||
real *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
creal *_memset160(creal *p, creal value, size_t count)
|
||||
{
|
||||
creal *pstart = p;
|
||||
creal *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
void *_memsetn(void *p, void *value, int count, size_t sizelem)
|
||||
{ void *pstart = p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
memcpy(p, value, sizelem);
|
||||
p = cast(void *)(cast(char *)p + sizelem);
|
||||
}
|
||||
return pstart;
|
||||
}
|
||||
79
druntime/src/compiler/dmd/minit.asm
Normal file
79
druntime/src/compiler/dmd/minit.asm
Normal file
@@ -0,0 +1,79 @@
|
||||
;_ minit.asm
|
||||
; Written by Walter Bright
|
||||
; Digital Mars
|
||||
; http://www.digitalmars.com/d/
|
||||
; Placed into the Public Domain
|
||||
|
||||
include macros.asm
|
||||
|
||||
ifdef _WIN32
|
||||
DATAGRP EQU FLAT
|
||||
else
|
||||
DATAGRP EQU DGROUP
|
||||
endif
|
||||
|
||||
; Provide a default resolution for weak extern records, no way in C
|
||||
; to define an omf symbol with a specific value
|
||||
public __nullext
|
||||
__nullext equ 0
|
||||
|
||||
extrn __moduleinfo_array:near
|
||||
|
||||
; This bit of assembler is needed because, from C or D, one cannot
|
||||
; specify the names of data segments. Why does this matter?
|
||||
; All the ModuleInfo pointers are placed into a segment named 'FM'.
|
||||
; The order in which they are placed in 'FM' is arbitrarily up to the linker.
|
||||
; In order to walk all the pointers, we need to be able to find the
|
||||
; beginning and the end of the 'FM' segment.
|
||||
; This is done by bracketing the 'FM' segment with two other, empty,
|
||||
; segments named 'FMB' and 'FME'. Since this module is the only one that
|
||||
; ever refers to 'FMB' and 'FME', we get to control the order in which
|
||||
; these segments appear relative to 'FM' by using a GROUP statement.
|
||||
; So, we have in memory:
|
||||
; FMB empty segment
|
||||
; FM contains all the pointers
|
||||
; FME empty segment
|
||||
; and finding the limits of FM is as easy as taking the address of FMB
|
||||
; and the address of FME.
|
||||
|
||||
; These segments bracket FM, which contains the list of ModuleInfo pointers
|
||||
FMB segment dword use32 public 'DATA'
|
||||
FMB ends
|
||||
FM segment dword use32 public 'DATA'
|
||||
FM ends
|
||||
FME segment dword use32 public 'DATA'
|
||||
FME ends
|
||||
|
||||
; This leaves room in the _fatexit() list for _moduleDtor()
|
||||
XOB segment dword use32 public 'BSS'
|
||||
XOB ends
|
||||
XO segment dword use32 public 'BSS'
|
||||
dd ?
|
||||
XO ends
|
||||
XOE segment dword use32 public 'BSS'
|
||||
XOE ends
|
||||
|
||||
DGROUP group FMB,FM,FME
|
||||
|
||||
begcode minit
|
||||
|
||||
; extern (C) void _minit();
|
||||
; Converts array of ModuleInfo pointers to a D dynamic array of them,
|
||||
; so they can be accessed via D.
|
||||
; Result is written to:
|
||||
; extern (C) ModuleInfo[] _moduleinfo_array;
|
||||
|
||||
public __minit
|
||||
__minit proc near
|
||||
mov EDX,offset DATAGRP:FMB
|
||||
mov EAX,offset DATAGRP:FME
|
||||
mov dword ptr __moduleinfo_array+4,EDX
|
||||
sub EAX,EDX ; size in bytes of FM segment
|
||||
shr EAX,2 ; convert to array length
|
||||
mov dword ptr __moduleinfo_array,EAX
|
||||
ret
|
||||
__minit endp
|
||||
|
||||
endcode minit
|
||||
|
||||
end
|
||||
BIN
druntime/src/compiler/dmd/minit.obj
Normal file
BIN
druntime/src/compiler/dmd/minit.obj
Normal file
Binary file not shown.
208
druntime/src/compiler/dmd/monitor.c
Normal file
208
druntime/src/compiler/dmd/monitor.c
Normal file
@@ -0,0 +1,208 @@
|
||||
// D programming language runtime library
|
||||
// Public Domain
|
||||
// written by Walter Bright, Digital Mars
|
||||
// www.digitalmars.com
|
||||
|
||||
// This is written in C because nobody has written a pthreads interface
|
||||
// to D yet.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
#elif linux
|
||||
#define USE_PTHREADS 1
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if USE_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
// This is what the monitor reference in Object points to
|
||||
typedef struct Monitor
|
||||
{
|
||||
void* impl; // for user-level monitors
|
||||
Array devt; // for internal monitors
|
||||
|
||||
#if _WIN32
|
||||
CRITICAL_SECTION mon;
|
||||
#endif
|
||||
|
||||
#if USE_PTHREADS
|
||||
pthread_mutex_t mon;
|
||||
#endif
|
||||
} Monitor;
|
||||
|
||||
#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon)
|
||||
|
||||
static volatile int inited;
|
||||
|
||||
/* =============================== Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
static CRITICAL_SECTION _monitor_critsec;
|
||||
|
||||
void _STI_monitor_staticctor()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&_monitor_critsec);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_monitor_staticdtor()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
DeleteCriticalSection(&_monitor_critsec);
|
||||
}
|
||||
}
|
||||
|
||||
void _d_monitor_create(Object *h)
|
||||
{
|
||||
/*
|
||||
* NOTE: Assume this is only called when h->monitor is null prior to the
|
||||
* call. However, please note that another thread may call this function
|
||||
* at the same time, so we can not assert this here. Instead, try and
|
||||
* create a lock, and if one already exists then forget about it.
|
||||
*/
|
||||
|
||||
//printf("+_d_monitor_create(%p)\n", h);
|
||||
assert(h);
|
||||
Monitor *cs = NULL;
|
||||
EnterCriticalSection(&_monitor_critsec);
|
||||
if (!h->monitor)
|
||||
{
|
||||
cs = (Monitor *)calloc(sizeof(Monitor), 1);
|
||||
assert(cs);
|
||||
InitializeCriticalSection(&cs->mon);
|
||||
h->monitor = (void *)cs;
|
||||
cs = NULL;
|
||||
}
|
||||
LeaveCriticalSection(&_monitor_critsec);
|
||||
if (cs)
|
||||
free(cs);
|
||||
//printf("-_d_monitor_create(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_destroy(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_destroy(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
DeleteCriticalSection(MONPTR(h));
|
||||
free((void *)h->monitor);
|
||||
h->monitor = NULL;
|
||||
//printf("-_d_monitor_destroy(%p)\n", h);
|
||||
}
|
||||
|
||||
int _d_monitor_lock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_acquire(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
EnterCriticalSection(MONPTR(h));
|
||||
//printf("-_d_monitor_acquire(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_unlock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_release(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
LeaveCriticalSection(MONPTR(h));
|
||||
//printf("-_d_monitor_release(%p)\n", h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* =============================== linux ============================ */
|
||||
|
||||
#if USE_PTHREADS
|
||||
|
||||
// Includes attribute fixes from David Friedman's GDC port
|
||||
|
||||
static pthread_mutex_t _monitor_critsec;
|
||||
static pthread_mutexattr_t _monitors_attr;
|
||||
|
||||
void _STI_monitor_staticctor()
|
||||
{
|
||||
if (!inited)
|
||||
{
|
||||
pthread_mutexattr_init(&_monitors_attr);
|
||||
pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
pthread_mutex_init(&_monitor_critsec, 0);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_monitor_staticdtor()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
pthread_mutex_destroy(&_monitor_critsec);
|
||||
pthread_mutexattr_destroy(&_monitors_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void _d_monitor_create(Object *h)
|
||||
{
|
||||
/*
|
||||
* NOTE: Assume this is only called when h->monitor is null prior to the
|
||||
* call. However, please note that another thread may call this function
|
||||
* at the same time, so we can not assert this here. Instead, try and
|
||||
* create a lock, and if one already exists then forget about it.
|
||||
*/
|
||||
|
||||
//printf("+_d_monitor_create(%p)\n", h);
|
||||
assert(h);
|
||||
Monitor *cs = NULL;
|
||||
pthread_mutex_lock(&_monitor_critsec);
|
||||
if (!h->monitor)
|
||||
{
|
||||
cs = (Monitor *)calloc(sizeof(Monitor), 1);
|
||||
assert(cs);
|
||||
pthread_mutex_init(&cs->mon, & _monitors_attr);
|
||||
h->monitor = (void *)cs;
|
||||
cs = NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&_monitor_critsec);
|
||||
if (cs)
|
||||
free(cs);
|
||||
//printf("-_d_monitor_create(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_destroy(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_destroy(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_destroy(MONPTR(h));
|
||||
free((void *)h->monitor);
|
||||
h->monitor = NULL;
|
||||
//printf("-_d_monitor_destroy(%p)\n", h);
|
||||
}
|
||||
|
||||
int _d_monitor_lock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_acquire(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_lock(MONPTR(h));
|
||||
//printf("-_d_monitor_acquire(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_unlock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_release(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_unlock(MONPTR(h));
|
||||
//printf("-_d_monitor_release(%p)\n", h);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
druntime/src/compiler/dmd/obj.d
Normal file
27
druntime/src/compiler/dmd/obj.d
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
|
||||
module rt.obj;
|
||||
|
||||
extern (C):
|
||||
|
||||
/********************************
|
||||
* Compiler helper for operator == for class objects.
|
||||
*/
|
||||
|
||||
int _d_obj_eq(Object o1, Object o2)
|
||||
{
|
||||
return o1 is o2 || (o1 && o1.opEquals(o2));
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
* Compiler helper for operator <, <=, >, >= for class objects.
|
||||
*/
|
||||
|
||||
int _d_obj_cmp(Object o1, Object o2)
|
||||
{
|
||||
return o1.opCmp(o2);
|
||||
}
|
||||
1517
druntime/src/compiler/dmd/object_.d
Normal file
1517
druntime/src/compiler/dmd/object_.d
Normal file
File diff suppressed because it is too large
Load Diff
178
druntime/src/compiler/dmd/posix.mak
Normal file
178
druntime/src/compiler/dmd/posix.mak
Normal file
@@ -0,0 +1,178 @@
|
||||
# Makefile to build the compiler runtime D library for Linux
|
||||
# Designed to work with GNU make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the compiler runtime library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=libdruntime-rt-dmd.a
|
||||
LIB_MASK=libdruntime-rt-dmd*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
|
||||
CFLAGS=-O $(ADD_CFLAGS)
|
||||
#CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=$(AR) -qsv
|
||||
DC=dmd
|
||||
|
||||
LIB_DEST=../../../lib
|
||||
|
||||
.SUFFIXES: .s .S .c .cpp .d .html .o
|
||||
|
||||
.s.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.o:
|
||||
g++ -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.o:
|
||||
$(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html dmd.ddoc $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
lib : dmd.lib
|
||||
doc : dmd.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_BASE= \
|
||||
aaA.o \
|
||||
aApply.o \
|
||||
aApplyR.o \
|
||||
adi.o \
|
||||
alloca.o \
|
||||
arrayassign.o \
|
||||
arraybyte.o \
|
||||
arraycast.o \
|
||||
arraycat.o \
|
||||
arraydouble.o \
|
||||
arrayfloat.o \
|
||||
arrayint.o \
|
||||
arrayreal.o \
|
||||
arrayshort.o \
|
||||
cast_.o \
|
||||
cmath2.o \
|
||||
complex.o \
|
||||
cover.o \
|
||||
critical.o \
|
||||
deh2.o \
|
||||
dmain2.o \
|
||||
invariant.o \
|
||||
invariant_.o \
|
||||
lifetime.o \
|
||||
llmath.o \
|
||||
memory.o \
|
||||
memset.o \
|
||||
monitor.o \
|
||||
obj.o \
|
||||
object_.o \
|
||||
qsort.o \
|
||||
switch_.o \
|
||||
trace.o
|
||||
# NOTE: trace.obj and cover.obj are not necessary for a successful build
|
||||
# as both are used for debugging features (profiling and coverage)
|
||||
# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
|
||||
# minit.asm is not used by dmd for linux
|
||||
# NOTE: deh.o is only needed for Win32, linux uses deh2.o
|
||||
|
||||
OBJ_UTIL= \
|
||||
util/console.o \
|
||||
util/cpuid.o \
|
||||
util/ctype.o \
|
||||
util/string.o \
|
||||
util/utf.o
|
||||
|
||||
OBJ_TI= \
|
||||
typeinfo/ti_AC.o \
|
||||
typeinfo/ti_Acdouble.o \
|
||||
typeinfo/ti_Acfloat.o \
|
||||
typeinfo/ti_Acreal.o \
|
||||
typeinfo/ti_Adouble.o \
|
||||
typeinfo/ti_Afloat.o \
|
||||
typeinfo/ti_Ag.o \
|
||||
typeinfo/ti_Aint.o \
|
||||
typeinfo/ti_Along.o \
|
||||
typeinfo/ti_Areal.o \
|
||||
typeinfo/ti_Ashort.o \
|
||||
typeinfo/ti_byte.o \
|
||||
typeinfo/ti_C.o \
|
||||
typeinfo/ti_cdouble.o \
|
||||
typeinfo/ti_cfloat.o \
|
||||
typeinfo/ti_char.o \
|
||||
typeinfo/ti_creal.o \
|
||||
typeinfo/ti_dchar.o \
|
||||
typeinfo/ti_delegate.o \
|
||||
typeinfo/ti_double.o \
|
||||
typeinfo/ti_float.o \
|
||||
typeinfo/ti_idouble.o \
|
||||
typeinfo/ti_ifloat.o \
|
||||
typeinfo/ti_int.o \
|
||||
typeinfo/ti_ireal.o \
|
||||
typeinfo/ti_long.o \
|
||||
typeinfo/ti_ptr.o \
|
||||
typeinfo/ti_real.o \
|
||||
typeinfo/ti_short.o \
|
||||
typeinfo/ti_ubyte.o \
|
||||
typeinfo/ti_uint.o \
|
||||
typeinfo/ti_ulong.o \
|
||||
typeinfo/ti_ushort.o \
|
||||
typeinfo/ti_void.o \
|
||||
typeinfo/ti_wchar.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_BASE) \
|
||||
$(OBJ_UTIL) \
|
||||
$(OBJ_TI)
|
||||
|
||||
######################################################
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
dmd.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
dmd.doc : $(ALL_DOCS)
|
||||
echo No documentation available.
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
|
||||
install :
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)/.
|
||||
158
druntime/src/compiler/dmd/qsort.d
Normal file
158
druntime/src/compiler/dmd/qsort.d
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Portions of this file are:
|
||||
Copyright Prototronics, 1987
|
||||
Totem Lake P.O. 8117
|
||||
Kirkland, Washington 98034
|
||||
(206) 820-1972
|
||||
Licensed to Digital Mars.
|
||||
|
||||
June 11, 1987 from Ray Gardner's
|
||||
Denver, Colorado) public domain version
|
||||
|
||||
Use qsort2.d instead of this file if a redistributable version of
|
||||
_adSort() is required.
|
||||
*/
|
||||
|
||||
module rt.qsort;
|
||||
|
||||
/*
|
||||
** Sorts an array starting at base, of length nbr_elements, each
|
||||
** element of size width_bytes, ordered via compare_function; which
|
||||
** is called as (*comp_fp)(ptr_to_element1, ptr_to_element2)
|
||||
** and returns < 0 if element1 < element2, 0 if element1 = element2,
|
||||
** > 0 if element1 > element2. Most of the refinements are due to
|
||||
** R. Sedgewick. See "Implementing Quicksort Programs", Comm. ACM,
|
||||
** Oct. 1978, and Corrigendum, Comm. ACM, June 1979.
|
||||
*/
|
||||
|
||||
//debug=qsort; // uncomment to turn on debugging printf's
|
||||
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
|
||||
private const int _maxspan = 7; // subarrays of _maxspan or fewer elements
|
||||
// will be sorted by a simple insertion sort
|
||||
|
||||
/* Adjust _maxspan according to relative cost of a swap and a compare. Reduce
|
||||
_maxspan (not less than 1) if a swap is very expensive such as when you have
|
||||
an array of large structures to be sorted, rather than an array of pointers to
|
||||
structures. The default value is optimized for a high cost for compares. */
|
||||
|
||||
|
||||
extern (C) long _adSort(Array a, TypeInfo ti)
|
||||
{
|
||||
byte* base;
|
||||
byte*[40] stack; // stack
|
||||
byte** sp; // stack pointer
|
||||
byte* i, j, limit; // scan and limit pointers
|
||||
uint thresh; // size of _maxspan elements in bytes
|
||||
uint width = ti.tsize();
|
||||
|
||||
base = cast(byte *)a.ptr;
|
||||
thresh = _maxspan * width; // init threshold
|
||||
sp = stack.ptr; // init stack pointer
|
||||
limit = base + a.length * width; // pointer past end of array
|
||||
while (1) // repeat until done then return
|
||||
{
|
||||
while (limit - base > thresh) // if more than _maxspan elements
|
||||
{
|
||||
//swap middle, base
|
||||
ti.swap((cast(uint)(limit - base) >> 1) -
|
||||
(((cast(uint)(limit - base) >> 1)) % width) + base, base);
|
||||
|
||||
i = base + width; // i scans from left to right
|
||||
j = limit - width; // j scans from right to left
|
||||
|
||||
if (ti.compare(i, j) > 0) // Sedgewick's
|
||||
ti.swap(i, j); // three-element sort
|
||||
if (ti.compare(base, j) > 0) // sets things up
|
||||
ti.swap(base, j); // so that
|
||||
if (ti.compare(i, base) > 0) // *i <= *base <= *j
|
||||
ti.swap(i, base); // *base is the pivot element
|
||||
|
||||
while (1)
|
||||
{
|
||||
do // move i right until *i >= pivot
|
||||
i += width;
|
||||
while (ti.compare(i, base) < 0);
|
||||
do // move j left until *j <= pivot
|
||||
j -= width;
|
||||
while (ti.compare(j, base) > 0);
|
||||
if (i > j) // break loop if pointers crossed
|
||||
break;
|
||||
ti.swap(i, j); // else swap elements, keep scanning
|
||||
}
|
||||
ti.swap(base, j); // move pivot into correct place
|
||||
if (j - base > limit - i) // if left subarray is larger...
|
||||
{
|
||||
sp[0] = base; // stack left subarray base
|
||||
sp[1] = j; // and limit
|
||||
base = i; // sort the right subarray
|
||||
}
|
||||
else // else right subarray is larger
|
||||
{
|
||||
sp[0] = i; // stack right subarray base
|
||||
sp[1] = limit; // and limit
|
||||
limit = j; // sort the left subarray
|
||||
}
|
||||
sp += 2; // increment stack pointer
|
||||
assert(sp < cast(byte**)stack + stack.length);
|
||||
}
|
||||
|
||||
// Insertion sort on remaining subarray
|
||||
i = base + width;
|
||||
while (i < limit)
|
||||
{
|
||||
j = i;
|
||||
while (j > base && ti.compare(j - width, j) > 0)
|
||||
{
|
||||
ti.swap(j - width, j);
|
||||
j -= width;
|
||||
}
|
||||
i += width;
|
||||
}
|
||||
|
||||
if (sp > stack.ptr) // if any entries on stack...
|
||||
{
|
||||
sp -= 2; // pop the base and limit
|
||||
base = sp[0];
|
||||
limit = sp[1];
|
||||
}
|
||||
else // else stack empty, all done
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int a[] = new int[10];
|
||||
|
||||
a[0] = 23;
|
||||
a[1] = 1;
|
||||
a[2] = 64;
|
||||
a[3] = 5;
|
||||
a[4] = 6;
|
||||
a[5] = 5;
|
||||
a[6] = 17;
|
||||
a[7] = 3;
|
||||
a[8] = 0;
|
||||
a[9] = -1;
|
||||
|
||||
a.sort;
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
72
druntime/src/compiler/dmd/qsort2.d
Normal file
72
druntime/src/compiler/dmd/qsort2.d
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
/*
|
||||
* Placed into Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*
|
||||
* This is a public domain version of qsort.d.
|
||||
* All it does is call C's qsort(), but runs a little slower since
|
||||
* it needs to synchronize a global variable.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.qsort2;
|
||||
|
||||
//debug=qsort;
|
||||
|
||||
private import stdc.stdlib;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
private TypeInfo tiglobal;
|
||||
|
||||
extern (C) int cmp(void* p1, void* p2)
|
||||
{
|
||||
return tiglobal.compare(p1, p2);
|
||||
}
|
||||
|
||||
extern (C) long _adSort(Array a, TypeInfo ti)
|
||||
{
|
||||
synchronized
|
||||
{
|
||||
tiglobal = ti;
|
||||
qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int a[] = new int[10];
|
||||
|
||||
a[0] = 23;
|
||||
a[1] = 1;
|
||||
a[2] = 64;
|
||||
a[3] = 5;
|
||||
a[4] = 6;
|
||||
a[5] = 5;
|
||||
a[6] = 17;
|
||||
a[7] = 3;
|
||||
a[8] = 0;
|
||||
a[9] = -1;
|
||||
|
||||
a.sort;
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
426
druntime/src/compiler/dmd/switch_.d
Normal file
426
druntime/src/compiler/dmd/switch_.d
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.switch_;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
/******************************************************
|
||||
* Support for switch statements switching on strings.
|
||||
* Input:
|
||||
* table[] sorted array of strings generated by compiler
|
||||
* ca string to look up in table
|
||||
* Output:
|
||||
* result index of match in table[]
|
||||
* -1 if not in table
|
||||
*/
|
||||
|
||||
extern (C):
|
||||
|
||||
int _d_switch_string(char[][] table, char[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_string()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int ci;
|
||||
|
||||
ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
|
||||
assert(ci < 0); // ci==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int cj;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ cj = memcmp(table[i].ptr, ca.ptr, ca.length);
|
||||
assert(cj != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
cj = memcmp(table[i].ptr, ca.ptr, ca.length);
|
||||
if (cj == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_string(%.*s)\n", ca);
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
char[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
version (none)
|
||||
{
|
||||
// Print table
|
||||
printf("ca[] = '%s'\n", cast(char *)ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
}
|
||||
if (high &&
|
||||
ca.length >= table[0].length &&
|
||||
ca.length <= table[high - 1].length)
|
||||
{
|
||||
// Looking for 0 length string, which would only be at the beginning
|
||||
if (ca.length == 0)
|
||||
return 0;
|
||||
|
||||
char c1 = ca[0];
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = cast(ubyte)c1 - cast(ubyte)pca[0];
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(char []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Same thing, but for wide chars.
|
||||
*/
|
||||
|
||||
int _d_switch_ustring(wchar[][] table, wchar[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_ustring()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
|
||||
assert(c < 0); // c==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
|
||||
assert(c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
|
||||
if (c == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_ustring()\n");
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
wchar[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
/*
|
||||
// Print table
|
||||
wprintf("ca[] = '%.*s'\n", ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
*/
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(wchar []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* Same thing, but for wide chars.
|
||||
*/
|
||||
|
||||
int _d_switch_dstring(dchar[][] table, dchar[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_dstring()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
|
||||
assert(c < 0); // c==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
|
||||
assert(c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
|
||||
if (c == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_ustring()\n");
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
dchar[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
/*
|
||||
// Print table
|
||||
wprintf("ca[] = '%.*s'\n", ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
*/
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(dchar []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
867
druntime/src/compiler/dmd/trace.d
Normal file
867
druntime/src/compiler/dmd/trace.d
Normal file
@@ -0,0 +1,867 @@
|
||||
|
||||
/* Trace dynamic profiler.
|
||||
* For use with the Digital Mars DMD compiler.
|
||||
* Copyright (C) 1995-2006 by Digital Mars
|
||||
* All Rights Reserved
|
||||
* Written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.trace;
|
||||
|
||||
private
|
||||
{
|
||||
import util.string;
|
||||
import stdc.ctype;
|
||||
import stdc.stdio;
|
||||
import stdc.string;
|
||||
import stdc.stdlib;
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
char* unmangle_ident(char*); // from DMC++ runtime library
|
||||
|
||||
alias long timer_t;
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
|
||||
struct SymPair
|
||||
{
|
||||
SymPair* next;
|
||||
Symbol* sym; // function that is called
|
||||
uint count; // number of times sym is called
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// A Symbol for each function name.
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
Symbol* Sl, Sr; // left, right children
|
||||
SymPair* Sfanin; // list of calling functions
|
||||
SymPair* Sfanout; // list of called functions
|
||||
timer_t totaltime; // aggregate time
|
||||
timer_t functime; // time excluding subfunction calls
|
||||
ubyte Sflags;
|
||||
char[] Sident; // name of symbol
|
||||
}
|
||||
|
||||
const ubyte SFvisited = 1; // visited
|
||||
|
||||
static Symbol* root; // root of symbol table
|
||||
|
||||
//////////////////////////////////
|
||||
// Build a linked list of these.
|
||||
|
||||
struct Stack
|
||||
{
|
||||
Stack* prev;
|
||||
Symbol* sym;
|
||||
timer_t starttime; // time when function was entered
|
||||
timer_t ohd; // overhead of all the bookkeeping code
|
||||
timer_t subtime; // time used by all subfunctions
|
||||
}
|
||||
|
||||
static Stack* stack_freelist;
|
||||
static Stack* trace_tos; // top of stack
|
||||
static int trace_inited; // !=0 if initialized
|
||||
static timer_t trace_ohd;
|
||||
|
||||
static Symbol** psymbols;
|
||||
static uint nsymbols; // number of symbols
|
||||
|
||||
static string trace_logfilename = "trace.log";
|
||||
static FILE* fplog;
|
||||
|
||||
static string trace_deffilename = "trace.def";
|
||||
static FILE* fpdef;
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Set file name for output.
|
||||
// A file name of "" means write results to stdout.
|
||||
// Returns:
|
||||
// 0 success
|
||||
// !=0 failure
|
||||
|
||||
int trace_setlogfilename(string name)
|
||||
{
|
||||
trace_logfilename = name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Set file name for output.
|
||||
// A file name of "" means write results to stdout.
|
||||
// Returns:
|
||||
// 0 success
|
||||
// !=0 failure
|
||||
|
||||
int trace_setdeffilename(string name)
|
||||
{
|
||||
trace_deffilename = name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Output optimal function link order.
|
||||
|
||||
static void trace_order(Symbol *s)
|
||||
{
|
||||
while (s)
|
||||
{
|
||||
trace_place(s,0);
|
||||
if (s.Sl)
|
||||
trace_order(s.Sl);
|
||||
s = s.Sr;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static Stack* stack_malloc()
|
||||
{ Stack *s;
|
||||
|
||||
if (stack_freelist)
|
||||
{ s = stack_freelist;
|
||||
stack_freelist = s.prev;
|
||||
}
|
||||
else
|
||||
s = cast(Stack *)trace_malloc(Stack.sizeof);
|
||||
return s;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static void stack_free(Stack *s)
|
||||
{
|
||||
s.prev = stack_freelist;
|
||||
stack_freelist = s;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Qsort() comparison routine for array of pointers to SymPair's.
|
||||
|
||||
static int sympair_cmp(in void* e1, in void* e2)
|
||||
{ SymPair** psp1;
|
||||
SymPair** psp2;
|
||||
|
||||
psp1 = cast(SymPair**)e1;
|
||||
psp2 = cast(SymPair**)e2;
|
||||
|
||||
return (*psp2).count - (*psp1).count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Place symbol s, and then place any fan ins or fan outs with
|
||||
// counts greater than count.
|
||||
|
||||
static void trace_place(Symbol *s, uint count)
|
||||
{ SymPair* sp;
|
||||
SymPair** base;
|
||||
|
||||
if (!(s.Sflags & SFvisited))
|
||||
{ size_t num;
|
||||
uint u;
|
||||
|
||||
//printf("\t%.*s\t%u\n", s.Sident, count);
|
||||
fprintf(fpdef,"\t%.*s\n", s.Sident);
|
||||
s.Sflags |= SFvisited;
|
||||
|
||||
// Compute number of items in array
|
||||
num = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
num++;
|
||||
for (sp = s.Sfanout; sp; sp = sp.next)
|
||||
num++;
|
||||
if (!num)
|
||||
return;
|
||||
|
||||
// Allocate and fill array
|
||||
base = cast(SymPair**)trace_malloc(SymPair.sizeof * num);
|
||||
u = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
base[u++] = sp;
|
||||
for (sp = s.Sfanout; sp; sp = sp.next)
|
||||
base[u++] = sp;
|
||||
|
||||
// Sort array
|
||||
qsort(base, num, (SymPair *).sizeof, &sympair_cmp);
|
||||
|
||||
//for (u = 0; u < num; u++)
|
||||
//printf("\t\t%.*s\t%u\n", base[u].sym.Sident, base[u].count);
|
||||
|
||||
// Place symbols
|
||||
for (u = 0; u < num; u++)
|
||||
{
|
||||
if (base[u].count >= count)
|
||||
{ uint u2;
|
||||
uint c2;
|
||||
|
||||
u2 = (u + 1 < num) ? u + 1 : u;
|
||||
c2 = base[u2].count;
|
||||
if (c2 < count)
|
||||
c2 = count;
|
||||
trace_place(base[u].sym,c2);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
trace_free(base);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// Initialize and terminate.
|
||||
|
||||
static this()
|
||||
{
|
||||
trace_init();
|
||||
}
|
||||
|
||||
static ~this()
|
||||
{
|
||||
trace_term();
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// Report results.
|
||||
// Also compute nsymbols.
|
||||
|
||||
static void trace_report(Symbol* s)
|
||||
{ SymPair* sp;
|
||||
uint count;
|
||||
|
||||
//printf("trace_report()\n");
|
||||
while (s)
|
||||
{ nsymbols++;
|
||||
if (s.Sl)
|
||||
trace_report(s.Sl);
|
||||
fprintf(fplog,"------------------\n");
|
||||
count = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
{
|
||||
fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident);
|
||||
count += sp.count;
|
||||
}
|
||||
fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime);
|
||||
for (sp = s.Sfanout; sp; sp = sp.next)
|
||||
{
|
||||
fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident);
|
||||
}
|
||||
s = s.Sr;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Allocate and fill array of symbols.
|
||||
|
||||
static void trace_array(Symbol *s)
|
||||
{ static uint u;
|
||||
|
||||
if (!psymbols)
|
||||
{ u = 0;
|
||||
psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols);
|
||||
}
|
||||
while (s)
|
||||
{
|
||||
psymbols[u++] = s;
|
||||
trace_array(s.Sl);
|
||||
s = s.Sr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// Qsort() comparison routine for array of pointers to Symbol's.
|
||||
|
||||
static int symbol_cmp(in void* e1, in void* e2)
|
||||
{ Symbol** ps1;
|
||||
Symbol** ps2;
|
||||
timer_t diff;
|
||||
|
||||
ps1 = cast(Symbol **)e1;
|
||||
ps2 = cast(Symbol **)e2;
|
||||
|
||||
diff = (*ps2).functime - (*ps1).functime;
|
||||
return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
// Report function timings
|
||||
|
||||
static void trace_times(Symbol* root)
|
||||
{ uint u;
|
||||
timer_t freq;
|
||||
|
||||
// Sort array
|
||||
qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp);
|
||||
|
||||
// Print array
|
||||
QueryPerformanceFrequency(&freq);
|
||||
fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq);
|
||||
fprintf(fplog," Num Tree Func Per\n");
|
||||
fprintf(fplog," Calls Time Time Call\n\n");
|
||||
for (u = 0; u < nsymbols; u++)
|
||||
{ Symbol* s = psymbols[u];
|
||||
timer_t tl,tr;
|
||||
timer_t fl,fr;
|
||||
timer_t pl,pr;
|
||||
timer_t percall;
|
||||
SymPair* sp;
|
||||
uint calls;
|
||||
char[] id;
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
char* p = (s.Sident ~ '\0').ptr;
|
||||
p = unmangle_ident(p);
|
||||
if (p)
|
||||
id = p[0 .. strlen(p)];
|
||||
}
|
||||
if (!id)
|
||||
id = s.Sident;
|
||||
calls = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
calls += sp.count;
|
||||
if (calls == 0)
|
||||
calls = 1;
|
||||
|
||||
version (all)
|
||||
{
|
||||
tl = (s.totaltime * 1000000) / freq;
|
||||
fl = (s.functime * 1000000) / freq;
|
||||
percall = s.functime / calls;
|
||||
pl = (s.functime * 1000000) / calls / freq;
|
||||
|
||||
fprintf(fplog,"%7d%12lld%12lld%12lld %.*s\n",
|
||||
calls,tl,fl,pl,id);
|
||||
}
|
||||
else
|
||||
{
|
||||
tl = s.totaltime / freq;
|
||||
tr = ((s.totaltime - tl * freq) * 10000000) / freq;
|
||||
|
||||
fl = s.functime / freq;
|
||||
fr = ((s.functime - fl * freq) * 10000000) / freq;
|
||||
|
||||
percall = s.functime / calls;
|
||||
pl = percall / freq;
|
||||
pr = ((percall - pl * freq) * 10000000) / freq;
|
||||
|
||||
fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n",
|
||||
calls,tl,tr,fl,fr,pl,pr,id);
|
||||
}
|
||||
if (id !is s.Sident)
|
||||
free(id.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
// Initialize.
|
||||
|
||||
static void trace_init()
|
||||
{
|
||||
if (!trace_inited)
|
||||
{
|
||||
trace_inited = 1;
|
||||
|
||||
{ // See if we can determine the overhead.
|
||||
uint u;
|
||||
timer_t starttime;
|
||||
timer_t endtime;
|
||||
Stack *st;
|
||||
|
||||
st = trace_tos;
|
||||
trace_tos = null;
|
||||
QueryPerformanceCounter(&starttime);
|
||||
for (u = 0; u < 100; u++)
|
||||
{
|
||||
asm
|
||||
{
|
||||
call _trace_pro_n ;
|
||||
db 0 ;
|
||||
call _trace_epi_n ;
|
||||
}
|
||||
}
|
||||
QueryPerformanceCounter(&endtime);
|
||||
trace_ohd = (endtime - starttime) / u;
|
||||
//printf("trace_ohd = %lld\n",trace_ohd);
|
||||
if (trace_ohd > 0)
|
||||
trace_ohd--; // round down
|
||||
trace_tos = st;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Terminate.
|
||||
|
||||
void trace_term()
|
||||
{
|
||||
//printf("trace_term()\n");
|
||||
if (trace_inited == 1)
|
||||
{ Stack *n;
|
||||
|
||||
trace_inited = 2;
|
||||
|
||||
// Free remainder of the stack
|
||||
while (trace_tos)
|
||||
{
|
||||
n = trace_tos.prev;
|
||||
stack_free(trace_tos);
|
||||
trace_tos = n;
|
||||
}
|
||||
|
||||
while (stack_freelist)
|
||||
{
|
||||
n = stack_freelist.prev;
|
||||
stack_free(stack_freelist);
|
||||
stack_freelist = n;
|
||||
}
|
||||
|
||||
// Merge in data from any existing file
|
||||
trace_merge();
|
||||
|
||||
// Report results
|
||||
fplog = fopen(trace_logfilename.ptr, "w");
|
||||
if (fplog)
|
||||
{ nsymbols = 0;
|
||||
trace_report(root);
|
||||
trace_array(root);
|
||||
trace_times(root);
|
||||
fclose(fplog);
|
||||
}
|
||||
|
||||
// Output function link order
|
||||
fpdef = fopen(trace_deffilename.ptr,"w");
|
||||
if (fpdef)
|
||||
{ fprintf(fpdef,"\nFUNCTIONS\n");
|
||||
trace_order(root);
|
||||
fclose(fpdef);
|
||||
}
|
||||
|
||||
trace_free(psymbols);
|
||||
psymbols = null;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Our storage allocator.
|
||||
|
||||
static void *trace_malloc(size_t nbytes)
|
||||
{ void *p;
|
||||
|
||||
p = malloc(nbytes);
|
||||
if (!p)
|
||||
exit(EXIT_FAILURE);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void trace_free(void *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static Symbol* trace_addsym(char[] id)
|
||||
{
|
||||
Symbol** parent;
|
||||
Symbol* rover;
|
||||
Symbol* s;
|
||||
int cmp;
|
||||
char c;
|
||||
|
||||
//printf("trace_addsym('%s',%d)\n",p,len);
|
||||
parent = &root;
|
||||
rover = *parent;
|
||||
while (rover !is null) // while we haven't run out of tree
|
||||
{
|
||||
cmp = dstrcmp(id, rover.Sident);
|
||||
if (cmp == 0)
|
||||
{
|
||||
return rover;
|
||||
}
|
||||
parent = (cmp < 0) ? /* if we go down left side */
|
||||
&(rover.Sl) : /* then get left child */
|
||||
&(rover.Sr); /* else get right child */
|
||||
rover = *parent; /* get child */
|
||||
}
|
||||
/* not in table, so insert into table */
|
||||
s = cast(Symbol *)trace_malloc(Symbol.sizeof);
|
||||
memset(s,0,Symbol.sizeof);
|
||||
s.Sident = id;
|
||||
*parent = s; // link new symbol into tree
|
||||
return s;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Add symbol s with count to SymPair list.
|
||||
*/
|
||||
|
||||
static void trace_sympair_add(SymPair** psp, Symbol* s, uint count)
|
||||
{ SymPair* sp;
|
||||
|
||||
for (; 1; psp = &sp.next)
|
||||
{
|
||||
sp = *psp;
|
||||
if (!sp)
|
||||
{
|
||||
sp = cast(SymPair *)trace_malloc(SymPair.sizeof);
|
||||
sp.sym = s;
|
||||
sp.count = 0;
|
||||
sp.next = null;
|
||||
*psp = sp;
|
||||
break;
|
||||
}
|
||||
else if (sp.sym == s)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
sp.count += count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static void trace_pro(char[] id)
|
||||
{
|
||||
Stack* n;
|
||||
Symbol* s;
|
||||
timer_t starttime;
|
||||
timer_t t;
|
||||
|
||||
QueryPerformanceCounter(&starttime);
|
||||
if (id.length == 0)
|
||||
return;
|
||||
if (!trace_inited)
|
||||
trace_init(); // initialize package
|
||||
n = stack_malloc();
|
||||
n.prev = trace_tos;
|
||||
trace_tos = n;
|
||||
s = trace_addsym(id);
|
||||
trace_tos.sym = s;
|
||||
if (trace_tos.prev)
|
||||
{
|
||||
Symbol* prev;
|
||||
int i;
|
||||
|
||||
// Accumulate Sfanout and Sfanin
|
||||
prev = trace_tos.prev.sym;
|
||||
trace_sympair_add(&prev.Sfanout,s,1);
|
||||
trace_sympair_add(&s.Sfanin,prev,1);
|
||||
}
|
||||
QueryPerformanceCounter(&t);
|
||||
trace_tos.starttime = starttime;
|
||||
trace_tos.ohd = trace_ohd + t - starttime;
|
||||
trace_tos.subtime = 0;
|
||||
//printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n",
|
||||
// trace_tos.ohd,trace_ohd,t,starttime);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
|
||||
static void trace_epi()
|
||||
{ Stack* n;
|
||||
timer_t endtime;
|
||||
timer_t t;
|
||||
timer_t ohd;
|
||||
|
||||
//printf("trace_epi()\n");
|
||||
if (trace_tos)
|
||||
{
|
||||
timer_t starttime;
|
||||
timer_t totaltime;
|
||||
|
||||
QueryPerformanceCounter(&endtime);
|
||||
starttime = trace_tos.starttime;
|
||||
totaltime = endtime - starttime - trace_tos.ohd;
|
||||
if (totaltime < 0)
|
||||
{ //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n",
|
||||
// endtime,starttime,trace_tos.ohd);
|
||||
totaltime = 0; // round off error, just make it 0
|
||||
}
|
||||
|
||||
// totaltime is time spent in this function + all time spent in
|
||||
// subfunctions - bookkeeping overhead.
|
||||
trace_tos.sym.totaltime += totaltime;
|
||||
|
||||
//if (totaltime < trace_tos.subtime)
|
||||
//printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime);
|
||||
trace_tos.sym.functime += totaltime - trace_tos.subtime;
|
||||
ohd = trace_tos.ohd;
|
||||
n = trace_tos.prev;
|
||||
stack_free(trace_tos);
|
||||
trace_tos = n;
|
||||
if (n)
|
||||
{ QueryPerformanceCounter(&t);
|
||||
n.ohd += ohd + t - endtime;
|
||||
n.subtime += totaltime;
|
||||
//printf("n.ohd = %lld\n",n.ohd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////// FILE INTERFACE /////////////////////////
|
||||
|
||||
/////////////////////////////////////
|
||||
// Read line from file fp.
|
||||
// Returns:
|
||||
// trace_malloc'd line buffer
|
||||
// null if end of file
|
||||
|
||||
static char* trace_readline(FILE* fp)
|
||||
{ int c;
|
||||
int dim;
|
||||
int i;
|
||||
char *buf;
|
||||
|
||||
//printf("trace_readline(%p)\n", fp);
|
||||
i = 0;
|
||||
dim = 0;
|
||||
buf = null;
|
||||
while (1)
|
||||
{
|
||||
if (i == dim)
|
||||
{ char *p;
|
||||
|
||||
dim += 80;
|
||||
p = cast(char *)trace_malloc(dim);
|
||||
memcpy(p,buf,i);
|
||||
trace_free(buf);
|
||||
buf = p;
|
||||
}
|
||||
c = fgetc(fp);
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
if (i == 0)
|
||||
{ trace_free(buf);
|
||||
return null;
|
||||
}
|
||||
case '\n':
|
||||
goto L1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
buf[i] = cast(char)c;
|
||||
i++;
|
||||
}
|
||||
L1:
|
||||
buf[i] = 0;
|
||||
//printf("line '%s'\n",buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Skip space
|
||||
|
||||
static char *skipspace(char *p)
|
||||
{
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
return p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Merge in profiling data from existing file.
|
||||
|
||||
static void trace_merge()
|
||||
{ FILE *fp;
|
||||
char *buf;
|
||||
char *p;
|
||||
uint count;
|
||||
Symbol *s;
|
||||
SymPair *sfanin;
|
||||
SymPair **psp;
|
||||
|
||||
if (trace_logfilename && (fp = fopen(trace_logfilename.ptr,"r")) !is null)
|
||||
{
|
||||
buf = null;
|
||||
sfanin = null;
|
||||
psp = &sfanin;
|
||||
while (1)
|
||||
{
|
||||
trace_free(buf);
|
||||
buf = trace_readline(fp);
|
||||
if (!buf)
|
||||
break;
|
||||
switch (*buf)
|
||||
{
|
||||
case '=': // ignore rest of file
|
||||
trace_free(buf);
|
||||
goto L1;
|
||||
case ' ':
|
||||
case '\t': // fan in or fan out line
|
||||
count = strtoul(buf,&p,10);
|
||||
if (p == buf) // if invalid conversion
|
||||
continue;
|
||||
p = skipspace(p);
|
||||
if (!*p)
|
||||
continue;
|
||||
s = trace_addsym(p[0 .. strlen(p)]);
|
||||
trace_sympair_add(psp,s,count);
|
||||
break;
|
||||
default:
|
||||
if (!isalpha(*buf))
|
||||
{
|
||||
if (!sfanin)
|
||||
psp = &sfanin;
|
||||
continue; // regard unrecognized line as separator
|
||||
}
|
||||
case '?':
|
||||
case '_':
|
||||
case '$':
|
||||
case '@':
|
||||
p = buf;
|
||||
while (isgraph(*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
//printf("trace_addsym('%s')\n",buf);
|
||||
s = trace_addsym(buf[0 .. strlen(buf)]);
|
||||
if (s.Sfanin)
|
||||
{ SymPair *sp;
|
||||
|
||||
for (; sfanin; sfanin = sp)
|
||||
{
|
||||
trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count);
|
||||
sp = sfanin.next;
|
||||
trace_free(sfanin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ s.Sfanin = sfanin;
|
||||
}
|
||||
sfanin = null;
|
||||
psp = &s.Sfanout;
|
||||
|
||||
{ timer_t t;
|
||||
|
||||
p++;
|
||||
count = strtoul(p,&p,10);
|
||||
t = cast(long)strtoull(p,&p,10);
|
||||
s.totaltime += t;
|
||||
t = cast(long)strtoull(p,&p,10);
|
||||
s.functime += t;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
L1:
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////// COMPILER INTERFACE /////////////////////
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Function called by trace code in function prolog.
|
||||
|
||||
void _trace_pro_n()
|
||||
{
|
||||
/* Length of string is either:
|
||||
* db length
|
||||
* ascii string
|
||||
* or:
|
||||
* db 0x0FF
|
||||
* db 0
|
||||
* dw length
|
||||
* ascii string
|
||||
*/
|
||||
|
||||
asm
|
||||
{ naked ;
|
||||
pushad ;
|
||||
mov ECX,8*4[ESP] ;
|
||||
xor EAX,EAX ;
|
||||
mov AL,[ECX] ;
|
||||
cmp AL,0xFF ;
|
||||
jne L1 ;
|
||||
cmp byte ptr 1[ECX],0 ;
|
||||
jne L1 ;
|
||||
mov AX,2[ECX] ;
|
||||
add 8*4[ESP],3 ;
|
||||
add ECX,3 ;
|
||||
L1: inc EAX ;
|
||||
inc ECX ;
|
||||
add 8*4[ESP],EAX ;
|
||||
dec EAX ;
|
||||
push ECX ;
|
||||
push EAX ;
|
||||
call trace_pro ;
|
||||
add ESP,8 ;
|
||||
popad ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Function called by trace code in function epilog.
|
||||
|
||||
|
||||
void _trace_epi_n()
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
pushad ;
|
||||
}
|
||||
trace_epi();
|
||||
asm
|
||||
{
|
||||
popad ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
extern (Windows)
|
||||
{
|
||||
export int QueryPerformanceCounter(timer_t *);
|
||||
export int QueryPerformanceFrequency(timer_t *);
|
||||
}
|
||||
}
|
||||
else version (X86)
|
||||
{
|
||||
extern (D)
|
||||
{
|
||||
void QueryPerformanceCounter(timer_t* ctr)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
mov ECX,EAX ;
|
||||
rdtsc ;
|
||||
mov [ECX],EAX ;
|
||||
mov 4[ECX],EDX ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
void QueryPerformanceFrequency(timer_t* freq)
|
||||
{
|
||||
*freq = 3579545;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
95
druntime/src/compiler/dmd/typeinfo/ti_AC.d
Normal file
95
druntime/src/compiler/dmd/typeinfo/ti_AC.d
Normal file
@@ -0,0 +1,95 @@
|
||||
module rt.typeinfo.ti_AC;
|
||||
|
||||
// Object[]
|
||||
|
||||
class TypeInfo_AC : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{ Object[] s = *cast(Object[]*)p;
|
||||
hash_t hash = 0;
|
||||
|
||||
foreach (Object o; s)
|
||||
{
|
||||
if (o)
|
||||
hash += o.toHash();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
Object[] s1 = *cast(Object[]*)p1;
|
||||
Object[] s2 = *cast(Object[]*)p2;
|
||||
|
||||
if (s1.length == s2.length)
|
||||
{
|
||||
for (size_t u = 0; u < s1.length; u++)
|
||||
{ Object o1 = s1[u];
|
||||
Object o2 = s2[u];
|
||||
|
||||
// Do not pass null's to Object.opEquals()
|
||||
if (o1 is o2 ||
|
||||
(!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
Object[] s1 = *cast(Object[]*)p1;
|
||||
Object[] s2 = *cast(Object[]*)p2;
|
||||
ptrdiff_t c;
|
||||
|
||||
c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
|
||||
if (c == 0)
|
||||
{
|
||||
for (size_t u = 0; u < s1.length; u++)
|
||||
{ Object o1 = s1[u];
|
||||
Object o2 = s2[u];
|
||||
|
||||
if (o1 is o2)
|
||||
continue;
|
||||
|
||||
// Regard null references as always being "less than"
|
||||
if (o1)
|
||||
{
|
||||
if (!o2)
|
||||
{ c = 1;
|
||||
break;
|
||||
}
|
||||
c = o1.opCmp(o2);
|
||||
if (c)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ c = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
c = -1;
|
||||
else if (c > 0)
|
||||
c = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (Object[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(Object);
|
||||
}
|
||||
}
|
||||
105
druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d
Normal file
105
druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Acdouble;
|
||||
|
||||
private import typeinfo.ti_cdouble;
|
||||
|
||||
// cdouble[]
|
||||
|
||||
class TypeInfo_Ar : TypeInfo
|
||||
{
|
||||
override string toString() { return "cdouble[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ cdouble[] s = *cast(cdouble[]*)p;
|
||||
size_t len = s.length;
|
||||
cdouble *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(uint *)str)[2];
|
||||
hash += (cast(uint *)str)[3];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
cdouble[] s1 = *cast(cdouble[]*)p1;
|
||||
cdouble[] s2 = *cast(cdouble[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return false;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_r._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
cdouble[] s1 = *cast(cdouble[]*)p1;
|
||||
cdouble[] s2 = *cast(cdouble[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_r._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (cdouble[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(cdouble);
|
||||
}
|
||||
}
|
||||
103
druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d
Normal file
103
druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Acfloat;
|
||||
|
||||
private import typeinfo.ti_cfloat;
|
||||
|
||||
// cfloat[]
|
||||
|
||||
class TypeInfo_Aq : TypeInfo
|
||||
{
|
||||
override string toString() { return "cfloat[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ cfloat[] s = *cast(cfloat[]*)p;
|
||||
size_t len = s.length;
|
||||
cfloat *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
cfloat[] s1 = *cast(cfloat[]*)p1;
|
||||
cfloat[] s2 = *cast(cfloat[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return false;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_q._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
cfloat[] s1 = *cast(cfloat[]*)p1;
|
||||
cfloat[] s2 = *cast(cfloat[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_q._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (cfloat[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(cfloat);
|
||||
}
|
||||
}
|
||||
106
druntime/src/compiler/dmd/typeinfo/ti_Acreal.d
Normal file
106
druntime/src/compiler/dmd/typeinfo/ti_Acreal.d
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Acreal;
|
||||
|
||||
private import typeinfo.ti_creal;
|
||||
|
||||
// creal[]
|
||||
|
||||
class TypeInfo_Ac : TypeInfo
|
||||
{
|
||||
override string toString() { return "creal[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ creal[] s = *cast(creal[]*)p;
|
||||
size_t len = s.length;
|
||||
creal *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(uint *)str)[2];
|
||||
hash += (cast(uint *)str)[3];
|
||||
hash += (cast(uint *)str)[4];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
creal[] s1 = *cast(creal[]*)p1;
|
||||
creal[] s2 = *cast(creal[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_c._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
creal[] s1 = *cast(creal[]*)p1;
|
||||
creal[] s2 = *cast(creal[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_c._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (creal[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(creal);
|
||||
}
|
||||
}
|
||||
115
druntime/src/compiler/dmd/typeinfo/ti_Adouble.d
Normal file
115
druntime/src/compiler/dmd/typeinfo/ti_Adouble.d
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Adouble;
|
||||
|
||||
private import typeinfo.ti_double;
|
||||
|
||||
// double[]
|
||||
|
||||
class TypeInfo_Ad : TypeInfo
|
||||
{
|
||||
override string toString() { return "double[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ double[] s = *cast(double[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
double[] s1 = *cast(double[]*)p1;
|
||||
double[] s2 = *cast(double[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_d._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
double[] s1 = *cast(double[]*)p1;
|
||||
double[] s2 = *cast(double[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_d._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (double[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(double);
|
||||
}
|
||||
}
|
||||
|
||||
// idouble[]
|
||||
|
||||
class TypeInfo_Ap : TypeInfo_Ad
|
||||
{
|
||||
override string toString() { return "idouble[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(idouble);
|
||||
}
|
||||
}
|
||||
114
druntime/src/compiler/dmd/typeinfo/ti_Afloat.d
Normal file
114
druntime/src/compiler/dmd/typeinfo/ti_Afloat.d
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Afloat;
|
||||
|
||||
private import typeinfo.ti_float;
|
||||
|
||||
// float[]
|
||||
|
||||
class TypeInfo_Af : TypeInfo
|
||||
{
|
||||
override string toString() { return "float[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ float[] s = *cast(float[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
float[] s1 = *cast(float[]*)p1;
|
||||
float[] s2 = *cast(float[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_f._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
float[] s1 = *cast(float[]*)p1;
|
||||
float[] s2 = *cast(float[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_f._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (float[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(float);
|
||||
}
|
||||
}
|
||||
|
||||
// ifloat[]
|
||||
|
||||
class TypeInfo_Ao : TypeInfo_Af
|
||||
{
|
||||
override string toString() { return "ifloat[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ifloat);
|
||||
}
|
||||
}
|
||||
204
druntime/src/compiler/dmd/typeinfo/ti_Ag.d
Normal file
204
druntime/src/compiler/dmd/typeinfo/ti_Ag.d
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
module rt.typeinfo.ti_Ag;
|
||||
|
||||
private import util.string;
|
||||
private import stdc.string;
|
||||
|
||||
// byte[]
|
||||
|
||||
class TypeInfo_Ag : TypeInfo
|
||||
{
|
||||
override string toString() { return "byte[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ byte[] s = *cast(byte[]*)p;
|
||||
size_t len = s.length;
|
||||
byte *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ubyte *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 9;
|
||||
hash += (*cast(ushort *)str << 8) +
|
||||
(cast(ubyte *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
byte[] s1 = *cast(byte[]*)p1;
|
||||
byte[] s2 = *cast(byte[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
byte[] s1 = *cast(byte[]*)p1;
|
||||
byte[] s2 = *cast(byte[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (byte[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(byte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ubyte[]
|
||||
|
||||
class TypeInfo_Ah : TypeInfo_Ag
|
||||
{
|
||||
override string toString() { return "ubyte[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
char[] s1 = *cast(char[]*)p1;
|
||||
char[] s2 = *cast(char[]*)p2;
|
||||
|
||||
return dstrcmp(s1, s2);
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ubyte);
|
||||
}
|
||||
}
|
||||
|
||||
// void[]
|
||||
|
||||
class TypeInfo_Av : TypeInfo_Ah
|
||||
{
|
||||
override string toString() { return "void[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(void);
|
||||
}
|
||||
}
|
||||
|
||||
// bool[]
|
||||
|
||||
class TypeInfo_Ab : TypeInfo_Ah
|
||||
{
|
||||
override string toString() { return "bool[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(bool);
|
||||
}
|
||||
}
|
||||
|
||||
// char[]
|
||||
|
||||
class TypeInfo_Aa : TypeInfo_Ag
|
||||
{
|
||||
override string toString() { return "char[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ char[] s = *cast(char[]*)p;
|
||||
hash_t hash = 0;
|
||||
|
||||
version (all)
|
||||
{
|
||||
foreach (char c; s)
|
||||
hash = hash * 11 + c;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = s.length;
|
||||
char *str = s;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ubyte *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 9;
|
||||
hash += (*cast(ushort *)str << 8) +
|
||||
(cast(ubyte *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(char);
|
||||
}
|
||||
}
|
||||
129
druntime/src/compiler/dmd/typeinfo/ti_Aint.d
Normal file
129
druntime/src/compiler/dmd/typeinfo/ti_Aint.d
Normal file
@@ -0,0 +1,129 @@
|
||||
|
||||
module rt.typeinfo.ti_Aint;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
// int[]
|
||||
|
||||
class TypeInfo_Ai : TypeInfo
|
||||
{
|
||||
override string toString() { return "int[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ int[] s = *cast(int[]*)p;
|
||||
auto len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
int[] s1 = *cast(int[]*)p1;
|
||||
int[] s2 = *cast(int[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
int[] s1 = *cast(int[]*)p1;
|
||||
int[] s2 = *cast(int[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (int[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(int);
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
int[][] a = [[5,3,8,7], [2,5,3,8,7]];
|
||||
a.sort;
|
||||
assert(a == [[2,5,3,8,7], [5,3,8,7]]);
|
||||
|
||||
a = [[5,3,8,7], [5,3,8]];
|
||||
a.sort;
|
||||
assert(a == [[5,3,8], [5,3,8,7]]);
|
||||
}
|
||||
|
||||
// uint[]
|
||||
|
||||
class TypeInfo_Ak : TypeInfo_Ai
|
||||
{
|
||||
override string toString() { return "uint[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
uint[] s1 = *cast(uint[]*)p1;
|
||||
uint[] s2 = *cast(uint[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(uint);
|
||||
}
|
||||
}
|
||||
|
||||
// dchar[]
|
||||
|
||||
class TypeInfo_Aw : TypeInfo_Ak
|
||||
{
|
||||
override string toString() { return "dchar[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(dchar);
|
||||
}
|
||||
}
|
||||
109
druntime/src/compiler/dmd/typeinfo/ti_Along.d
Normal file
109
druntime/src/compiler/dmd/typeinfo/ti_Along.d
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
module rt.typeinfo.ti_Along;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
// long[]
|
||||
|
||||
class TypeInfo_Al : TypeInfo
|
||||
{
|
||||
override string toString() { return "long[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ long[] s = *cast(long[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str + *(cast(uint *)str + 1);
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
long[] s1 = *cast(long[]*)p1;
|
||||
long[] s2 = *cast(long[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
long[] s1 = *cast(long[]*)p1;
|
||||
long[] s2 = *cast(long[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (s1[u] < s2[u])
|
||||
return -1;
|
||||
else if (s1[u] > s2[u])
|
||||
return 1;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (long[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(long);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ulong[]
|
||||
|
||||
class TypeInfo_Am : TypeInfo_Al
|
||||
{
|
||||
override string toString() { return "ulong[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
ulong[] s1 = *cast(ulong[]*)p1;
|
||||
ulong[] s2 = *cast(ulong[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (s1[u] < s2[u])
|
||||
return -1;
|
||||
else if (s1[u] > s2[u])
|
||||
return 1;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ulong);
|
||||
}
|
||||
}
|
||||
116
druntime/src/compiler/dmd/typeinfo/ti_Areal.d
Normal file
116
druntime/src/compiler/dmd/typeinfo/ti_Areal.d
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Areal;
|
||||
|
||||
private import typeinfo.ti_real;
|
||||
|
||||
// real[]
|
||||
|
||||
class TypeInfo_Ae : TypeInfo
|
||||
{
|
||||
override string toString() { return "real[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ real[] s = *cast(real[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(ushort *)str)[4];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
real[] s1 = *cast(real[]*)p1;
|
||||
real[] s2 = *cast(real[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return false;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_e._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
real[] s1 = *cast(real[]*)p1;
|
||||
real[] s2 = *cast(real[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_e._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (real[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(real);
|
||||
}
|
||||
}
|
||||
|
||||
// ireal[]
|
||||
|
||||
class TypeInfo_Aj : TypeInfo_Ae
|
||||
{
|
||||
override string toString() { return "ireal[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ireal);
|
||||
}
|
||||
}
|
||||
132
druntime/src/compiler/dmd/typeinfo/ti_Ashort.d
Normal file
132
druntime/src/compiler/dmd/typeinfo/ti_Ashort.d
Normal file
@@ -0,0 +1,132 @@
|
||||
|
||||
module rt.typeinfo.ti_Ashort;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
// short[]
|
||||
|
||||
class TypeInfo_As : TypeInfo
|
||||
{
|
||||
override string toString() { return "short[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ short[] s = *cast(short[]*)p;
|
||||
size_t len = s.length;
|
||||
short *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
short[] s1 = *cast(short[]*)p1;
|
||||
short[] s2 = *cast(short[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
short[] s1 = *cast(short[]*)p1;
|
||||
short[] s2 = *cast(short[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (short[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(short);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ushort[]
|
||||
|
||||
class TypeInfo_At : TypeInfo_As
|
||||
{
|
||||
override string toString() { return "ushort[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
ushort[] s1 = *cast(ushort[]*)p1;
|
||||
ushort[] s2 = *cast(ushort[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ushort);
|
||||
}
|
||||
}
|
||||
|
||||
// wchar[]
|
||||
|
||||
class TypeInfo_Au : TypeInfo_At
|
||||
{
|
||||
override string toString() { return "wchar[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(wchar);
|
||||
}
|
||||
}
|
||||
74
druntime/src/compiler/dmd/typeinfo/ti_C.d
Normal file
74
druntime/src/compiler/dmd/typeinfo/ti_C.d
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_C;
|
||||
|
||||
// Object
|
||||
|
||||
class TypeInfo_C : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
Object o = *cast(Object*)p;
|
||||
return o ? o.toHash() : 0;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
Object o1 = *cast(Object*)p1;
|
||||
Object o2 = *cast(Object*)p2;
|
||||
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
Object o1 = *cast(Object*)p1;
|
||||
Object o2 = *cast(Object*)p2;
|
||||
int c = 0;
|
||||
|
||||
// Regard null references as always being "less than"
|
||||
if (!(o1 is o2))
|
||||
{
|
||||
if (o1)
|
||||
{ if (!o2)
|
||||
c = 1;
|
||||
else
|
||||
c = o1.opCmp(o2);
|
||||
}
|
||||
else
|
||||
c = -1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return Object.sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
38
druntime/src/compiler/dmd/typeinfo/ti_byte.d
Normal file
38
druntime/src/compiler/dmd/typeinfo/ti_byte.d
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// byte
|
||||
|
||||
module rt.typeinfo.ti_byte;
|
||||
|
||||
class TypeInfo_g : TypeInfo
|
||||
{
|
||||
override string toString() { return "byte"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(byte *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return byte.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
}
|
||||
66
druntime/src/compiler/dmd/typeinfo/ti_cdouble.d
Normal file
66
druntime/src/compiler/dmd/typeinfo/ti_cdouble.d
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
// cdouble
|
||||
|
||||
module rt.typeinfo.ti_cdouble;
|
||||
|
||||
class TypeInfo_r : TypeInfo
|
||||
{
|
||||
override string toString() { return "cdouble"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3];
|
||||
}
|
||||
|
||||
static equals_t _equals(cdouble f1, cdouble f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cdouble f1, cdouble f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return cdouble.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
cdouble t;
|
||||
|
||||
t = *cast(cdouble *)p1;
|
||||
*cast(cdouble *)p1 = *cast(cdouble *)p2;
|
||||
*cast(cdouble *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static cdouble r;
|
||||
|
||||
return (cast(cdouble *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
65
druntime/src/compiler/dmd/typeinfo/ti_cfloat.d
Normal file
65
druntime/src/compiler/dmd/typeinfo/ti_cfloat.d
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
// cfloat
|
||||
|
||||
module rt.typeinfo.ti_cfloat;
|
||||
|
||||
class TypeInfo_q : TypeInfo
|
||||
{
|
||||
override string toString() { return "cfloat"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static equals_t _equals(cfloat f1, cfloat f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cfloat f1, cfloat f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return cfloat.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
cfloat t;
|
||||
|
||||
t = *cast(cfloat *)p1;
|
||||
*cast(cfloat *)p1 = *cast(cfloat *)p2;
|
||||
*cast(cfloat *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static cfloat r;
|
||||
|
||||
return (cast(cfloat *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_char.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_char.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
module rt.typeinfo.ti_char;
|
||||
|
||||
class TypeInfo_a : TypeInfo
|
||||
{
|
||||
override string toString() { return "char"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(char *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(char *)p1 == *cast(char *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(char *)p1 - *cast(char *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return char.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
char t;
|
||||
|
||||
t = *cast(char *)p1;
|
||||
*cast(char *)p1 = *cast(char *)p2;
|
||||
*cast(char *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static char c;
|
||||
|
||||
return (cast(char *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
67
druntime/src/compiler/dmd/typeinfo/ti_creal.d
Normal file
67
druntime/src/compiler/dmd/typeinfo/ti_creal.d
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
// creal
|
||||
|
||||
module rt.typeinfo.ti_creal;
|
||||
|
||||
class TypeInfo_c : TypeInfo
|
||||
{
|
||||
override string toString() { return "creal"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3] +
|
||||
(cast(uint *)p)[4];
|
||||
}
|
||||
|
||||
static equals_t _equals(creal f1, creal f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(creal f1, creal f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return creal.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
creal t;
|
||||
|
||||
t = *cast(creal *)p1;
|
||||
*cast(creal *)p1 = *cast(creal *)p2;
|
||||
*cast(creal *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static creal r;
|
||||
|
||||
return (cast(creal *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
44
druntime/src/compiler/dmd/typeinfo/ti_dchar.d
Normal file
44
druntime/src/compiler/dmd/typeinfo/ti_dchar.d
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// dchar
|
||||
|
||||
module rt.typeinfo.ti_dchar;
|
||||
|
||||
class TypeInfo_w : TypeInfo
|
||||
{
|
||||
override string toString() { return "dchar"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(dchar *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(dchar *)p1 == *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(dchar *)p1 - *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return dchar.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
dchar t;
|
||||
|
||||
t = *cast(dchar *)p1;
|
||||
*cast(dchar *)p1 = *cast(dchar *)p2;
|
||||
*cast(dchar *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static dchar c;
|
||||
|
||||
return (cast(dchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
39
druntime/src/compiler/dmd/typeinfo/ti_delegate.d
Normal file
39
druntime/src/compiler/dmd/typeinfo/ti_delegate.d
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
// delegate
|
||||
|
||||
module rt.typeinfo.ti_delegate;
|
||||
|
||||
alias void delegate(int) dg;
|
||||
|
||||
class TypeInfo_D : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{ long l = *cast(long *)p;
|
||||
|
||||
return cast(uint)(l + (l >> 32));
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(dg *)p1 == *cast(dg *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return dg.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
dg t;
|
||||
|
||||
t = *cast(dg *)p1;
|
||||
*cast(dg *)p1 = *cast(dg *)p2;
|
||||
*cast(dg *)p2 = t;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
64
druntime/src/compiler/dmd/typeinfo/ti_double.d
Normal file
64
druntime/src/compiler/dmd/typeinfo/ti_double.d
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// double
|
||||
|
||||
module rt.typeinfo.ti_double;
|
||||
|
||||
class TypeInfo_d : TypeInfo
|
||||
{
|
||||
override string toString() { return "double"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static equals_t _equals(double f1, double f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(f1 !<>= f1 && f2 !<>= f2);
|
||||
}
|
||||
|
||||
static int _compare(double d1, double d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (d1 !<>= d1)
|
||||
{ if (d2 !<>= d2)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return double.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = *cast(double *)p1;
|
||||
*cast(double *)p1 = *cast(double *)p2;
|
||||
*cast(double *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static double r;
|
||||
|
||||
return (cast(double *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
64
druntime/src/compiler/dmd/typeinfo/ti_float.d
Normal file
64
druntime/src/compiler/dmd/typeinfo/ti_float.d
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// float
|
||||
|
||||
module rt.typeinfo.ti_float;
|
||||
|
||||
class TypeInfo_f : TypeInfo
|
||||
{
|
||||
override string toString() { return "float"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
static equals_t _equals(float f1, float f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(f1 !<>= f1 && f2 !<>= f2);
|
||||
}
|
||||
|
||||
static int _compare(float d1, float d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (d1 !<>= d1)
|
||||
{ if (d2 !<>= d2)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return float.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
float t;
|
||||
|
||||
t = *cast(float *)p1;
|
||||
*cast(float *)p1 = *cast(float *)p2;
|
||||
*cast(float *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static float r;
|
||||
|
||||
return (cast(float *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
11
druntime/src/compiler/dmd/typeinfo/ti_idouble.d
Normal file
11
druntime/src/compiler/dmd/typeinfo/ti_idouble.d
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
// idouble
|
||||
|
||||
module rt.typeinfo.ti_idouble;
|
||||
|
||||
private import typeinfo.ti_double;
|
||||
|
||||
class TypeInfo_p : TypeInfo_d
|
||||
{
|
||||
override string toString() { return "idouble"; }
|
||||
}
|
||||
11
druntime/src/compiler/dmd/typeinfo/ti_ifloat.d
Normal file
11
druntime/src/compiler/dmd/typeinfo/ti_ifloat.d
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
// ifloat
|
||||
|
||||
module rt.typeinfo.ti_ifloat;
|
||||
|
||||
private import typeinfo.ti_float;
|
||||
|
||||
class TypeInfo_o : TypeInfo_f
|
||||
{
|
||||
override string toString() { return "ifloat"; }
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_int.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_int.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// int
|
||||
|
||||
module rt.typeinfo.ti_int;
|
||||
|
||||
class TypeInfo_i : TypeInfo
|
||||
{
|
||||
override string toString() { return "int"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(int*) p1 < *cast(int*) p2)
|
||||
return -1;
|
||||
else if (*cast(int*) p1 > *cast(int*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return int.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(int *)p1;
|
||||
*cast(int *)p1 = *cast(int *)p2;
|
||||
*cast(int *)p2 = t;
|
||||
}
|
||||
}
|
||||
11
druntime/src/compiler/dmd/typeinfo/ti_ireal.d
Normal file
11
druntime/src/compiler/dmd/typeinfo/ti_ireal.d
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
// ireal
|
||||
|
||||
module rt.typeinfo.ti_ireal;
|
||||
|
||||
private import typeinfo.ti_real;
|
||||
|
||||
class TypeInfo_j : TypeInfo_e
|
||||
{
|
||||
override string toString() { return "ireal"; }
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_long.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_long.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// long
|
||||
|
||||
module rt.typeinfo.ti_long;
|
||||
|
||||
class TypeInfo_l : TypeInfo
|
||||
{
|
||||
override string toString() { return "long"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(long *)p1 == *cast(long *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(long *)p1 < *cast(long *)p2)
|
||||
return -1;
|
||||
else if (*cast(long *)p1 > *cast(long *)p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return long.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = *cast(long *)p1;
|
||||
*cast(long *)p1 = *cast(long *)p2;
|
||||
*cast(long *)p2 = t;
|
||||
}
|
||||
}
|
||||
46
druntime/src/compiler/dmd/typeinfo/ti_ptr.d
Normal file
46
druntime/src/compiler/dmd/typeinfo/ti_ptr.d
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
// pointer
|
||||
|
||||
module rt.typeinfo.ti_ptr;
|
||||
|
||||
class TypeInfo_P : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return cast(uint)*cast(void* *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(void* *)p1 == *cast(void* *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
auto c = *cast(void* *)p1 - *cast(void* *)p2;
|
||||
if (c < 0)
|
||||
return -1;
|
||||
else if (c > 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (void*).sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
void* t;
|
||||
|
||||
t = *cast(void* *)p1;
|
||||
*cast(void* *)p1 = *cast(void* *)p2;
|
||||
*cast(void* *)p2 = t;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
64
druntime/src/compiler/dmd/typeinfo/ti_real.d
Normal file
64
druntime/src/compiler/dmd/typeinfo/ti_real.d
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// real
|
||||
|
||||
module rt.typeinfo.ti_real;
|
||||
|
||||
class TypeInfo_e : TypeInfo
|
||||
{
|
||||
override string toString() { return "real"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
|
||||
}
|
||||
|
||||
static equals_t _equals(real f1, real f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(f1 !<>= f1 && f2 !<>= f2);
|
||||
}
|
||||
|
||||
static int _compare(real d1, real d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (d1 !<>= d1)
|
||||
{ if (d2 !<>= d2)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(real *)p1, *cast(real *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(real *)p1, *cast(real *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return real.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
real t;
|
||||
|
||||
t = *cast(real *)p1;
|
||||
*cast(real *)p1 = *cast(real *)p2;
|
||||
*cast(real *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static real r;
|
||||
|
||||
return (cast(real *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
38
druntime/src/compiler/dmd/typeinfo/ti_short.d
Normal file
38
druntime/src/compiler/dmd/typeinfo/ti_short.d
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// short
|
||||
|
||||
module rt.typeinfo.ti_short;
|
||||
|
||||
class TypeInfo_s : TypeInfo
|
||||
{
|
||||
override string toString() { return "short"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(short *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(short *)p1 == *cast(short *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(short *)p1 - *cast(short *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return short.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
short t;
|
||||
|
||||
t = *cast(short *)p1;
|
||||
*cast(short *)p1 = *cast(short *)p2;
|
||||
*cast(short *)p2 = t;
|
||||
}
|
||||
}
|
||||
43
druntime/src/compiler/dmd/typeinfo/ti_ubyte.d
Normal file
43
druntime/src/compiler/dmd/typeinfo/ti_ubyte.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// ubyte
|
||||
|
||||
module rt.typeinfo.ti_ubyte;
|
||||
|
||||
class TypeInfo_h : TypeInfo
|
||||
{
|
||||
override string toString() { return "ubyte"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(ubyte *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ubyte *)p1 == *cast(ubyte *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ubyte *)p1 - *cast(ubyte *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return ubyte.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
ubyte t;
|
||||
|
||||
t = *cast(ubyte *)p1;
|
||||
*cast(ubyte *)p1 = *cast(ubyte *)p2;
|
||||
*cast(ubyte *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
class TypeInfo_b : TypeInfo_h
|
||||
{
|
||||
override string toString() { return "bool"; }
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_uint.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_uint.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// uint
|
||||
|
||||
module rt.typeinfo.ti_uint;
|
||||
|
||||
class TypeInfo_k : TypeInfo
|
||||
{
|
||||
override string toString() { return "uint"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(uint*) p1 < *cast(uint*) p2)
|
||||
return -1;
|
||||
else if (*cast(uint*) p1 > *cast(uint*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return uint.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(uint *)p1;
|
||||
*cast(uint *)p1 = *cast(uint *)p2;
|
||||
*cast(uint *)p2 = t;
|
||||
}
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_ulong.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_ulong.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// ulong
|
||||
|
||||
module rt.typeinfo.ti_ulong;
|
||||
|
||||
class TypeInfo_m : TypeInfo
|
||||
{
|
||||
override string toString() { return "ulong"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ulong *)p1 == *cast(ulong *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(ulong *)p1 < *cast(ulong *)p2)
|
||||
return -1;
|
||||
else if (*cast(ulong *)p1 > *cast(ulong *)p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return ulong.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
ulong t;
|
||||
|
||||
t = *cast(ulong *)p1;
|
||||
*cast(ulong *)p1 = *cast(ulong *)p2;
|
||||
*cast(ulong *)p2 = t;
|
||||
}
|
||||
}
|
||||
38
druntime/src/compiler/dmd/typeinfo/ti_ushort.d
Normal file
38
druntime/src/compiler/dmd/typeinfo/ti_ushort.d
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// ushort
|
||||
|
||||
module rt.typeinfo.ti_ushort;
|
||||
|
||||
class TypeInfo_t : TypeInfo
|
||||
{
|
||||
override string toString() { return "ushort"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(ushort *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ushort *)p1 == *cast(ushort *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ushort *)p1 - *cast(ushort *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return ushort.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
ushort t;
|
||||
|
||||
t = *cast(ushort *)p1;
|
||||
*cast(ushort *)p1 = *cast(ushort *)p2;
|
||||
*cast(ushort *)p2 = t;
|
||||
}
|
||||
}
|
||||
43
druntime/src/compiler/dmd/typeinfo/ti_void.d
Normal file
43
druntime/src/compiler/dmd/typeinfo/ti_void.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// void
|
||||
|
||||
module rt.typeinfo.ti_void;
|
||||
|
||||
class TypeInfo_v : TypeInfo
|
||||
{
|
||||
override string toString() { return "void"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return void.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
43
druntime/src/compiler/dmd/typeinfo/ti_wchar.d
Normal file
43
druntime/src/compiler/dmd/typeinfo/ti_wchar.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
module rt.typeinfo.ti_wchar;
|
||||
|
||||
|
||||
class TypeInfo_u : TypeInfo
|
||||
{
|
||||
override string toString() { return "wchar"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(wchar *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(wchar *)p1 == *cast(wchar *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(wchar *)p1 - *cast(wchar *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return wchar.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
wchar t;
|
||||
|
||||
t = *cast(wchar *)p1;
|
||||
*cast(wchar *)p1 = *cast(wchar *)p2;
|
||||
*cast(wchar *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static wchar c;
|
||||
|
||||
return (cast(wchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
49
druntime/src/compiler/dmd/util/console.d
Normal file
49
druntime/src/compiler/dmd/util/console.d
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* The console module contains some simple routines for console output.
|
||||
*
|
||||
* Copyright: Public Domain
|
||||
* License: Public Domain
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module rt.util.console;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
import sys.windows.windows;
|
||||
}
|
||||
else version( Posix )
|
||||
{
|
||||
import stdc.posix.unistd;
|
||||
}
|
||||
import util.string;
|
||||
}
|
||||
|
||||
|
||||
struct Console
|
||||
{
|
||||
Console opCall( in char[] val )
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
uint count = void;
|
||||
WriteFile( GetStdHandle( 0xfffffff5 ), val.ptr, val.length, &count, null );
|
||||
}
|
||||
else version( Posix )
|
||||
{
|
||||
write( 2, val.ptr, val.length );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Console opCall( uint val )
|
||||
{
|
||||
char[10] tmp = void;
|
||||
return opCall( tmp.intToString( val ) );
|
||||
}
|
||||
}
|
||||
|
||||
Console console;
|
||||
464
druntime/src/compiler/dmd/util/cpuid.d
Normal file
464
druntime/src/compiler/dmd/util/cpuid.d
Normal file
@@ -0,0 +1,464 @@
|
||||
/**
|
||||
* Identify the characteristics of the host CPU.
|
||||
*
|
||||
* Implemented according to:
|
||||
|
||||
- AP-485 Intel(C) Processor Identification and the CPUID Instruction
|
||||
$(LINK http://www.intel.com/design/xeon/applnots/241618.htm)
|
||||
|
||||
- Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 2A: Instruction Set Reference, A-M
|
||||
$(LINK http://developer.intel.com/design/pentium4/manuals/index_new.htm)
|
||||
|
||||
- AMD CPUID Specification Publication # 25481
|
||||
$(LINK http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf)
|
||||
|
||||
Example:
|
||||
---
|
||||
import std.cpuid;
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
writefln(std.cpuid.toString());
|
||||
}
|
||||
---
|
||||
|
||||
AUTHORS: Tomas Lindquist Olsen <tomas@famolsen.dk>
|
||||
(slightly altered by Walter Bright)
|
||||
COPYRIGHT: Public Domain
|
||||
|
||||
* BUGS: Only works on x86 CPUs
|
||||
*
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdCpuid
|
||||
* COPYRIGHT = Public Domain
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.util.cpuid;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
version(D_InlineAsm_X86)
|
||||
{
|
||||
/// Returns vendor string
|
||||
char[] vendor() {return vendorStr;}
|
||||
/// Returns processor string
|
||||
string processor() {return processorStr;}
|
||||
|
||||
/// Is MMX supported?
|
||||
bool mmx() {return (flags&MMX_BIT)!=0;}
|
||||
/// Is FXSR supported?
|
||||
bool fxsr() {return (flags&FXSR_BIT)!=0;}
|
||||
/// Is SSE supported?
|
||||
bool sse() {return (flags&SSE_BIT)!=0;}
|
||||
/// Is SSE2 supported?
|
||||
bool sse2() {return (flags&SSE2_BIT)!=0;}
|
||||
/// Is SSE3 supported?
|
||||
bool sse3() {return (misc&SSE3_BIT)!=0;}
|
||||
/// Is SSSE3 supported?
|
||||
bool ssse3() {return (misc&SSSE3_BIT)!=0;}
|
||||
|
||||
/// Is AMD 3DNOW supported?
|
||||
bool amd3dnow() {return (exflags&AMD_3DNOW_BIT)!=0;}
|
||||
/// Is AMD 3DNOW Ext supported?
|
||||
bool amd3dnowExt() {return (exflags&AMD_3DNOW_EXT_BIT)!=0;}
|
||||
/// Is AMD MMX supported?
|
||||
bool amdMmx() {return (exflags&AMD_MMX_BIT)!=0;}
|
||||
|
||||
/// Is this an Intel Architecture IA64?
|
||||
bool ia64() {return (flags&IA64_BIT)!=0;}
|
||||
/// Is this an AMD 64?
|
||||
bool amd64() {return (exflags&AMD64_BIT)!=0;}
|
||||
|
||||
/// Is hyperthreading supported?
|
||||
bool hyperThreading() {return (flags&HTT_BIT)!=0;}
|
||||
/// Returns number of threads per CPU
|
||||
uint threadsPerCPU() {return maxThreads;}
|
||||
/// Returns number of cores in CPU
|
||||
uint coresPerCPU() {return maxCores;}
|
||||
|
||||
/// Is this an Intel processor?
|
||||
bool intel() {return manufac==INTEL;}
|
||||
/// Is this an AMD processor?
|
||||
bool amd() {return manufac==AMD;}
|
||||
|
||||
/// Returns stepping
|
||||
uint stepping() {return _stepping;}
|
||||
/// Returns model
|
||||
uint model() {return _model;}
|
||||
/// Returns family
|
||||
uint family() {return _family;}
|
||||
//uint processorType() {return (signature>>>12)&0x3;}
|
||||
|
||||
static this()
|
||||
{
|
||||
getVendorString();
|
||||
getProcessorString();
|
||||
getFeatureFlags();
|
||||
|
||||
// stepping / family / model
|
||||
_stepping = signature&0xF;
|
||||
uint fbase = (signature>>>8)&0xF;
|
||||
uint fex = (signature>>>20)&0xFF;
|
||||
uint mbase = (signature>>>4)&0xF;
|
||||
uint mex = (signature>>>16)&0xF;
|
||||
|
||||
// vendor specific
|
||||
void function() threadFn;
|
||||
switch(vendorStr)
|
||||
{
|
||||
case "GenuineIntel":
|
||||
manufac = INTEL;
|
||||
threadFn = &getThreadingIntel;
|
||||
if (fbase == 0xF)
|
||||
_family = fbase+fex;
|
||||
else
|
||||
_family = fbase;
|
||||
if (_family == 0x6 || _family == 0xF)
|
||||
_model = mbase+(mex<<4);
|
||||
else
|
||||
_model = mbase;
|
||||
break;
|
||||
|
||||
case "AuthenticAMD":
|
||||
manufac = AMD;
|
||||
threadFn = &getThreadingAMD;
|
||||
if (fbase < 0xF)
|
||||
{
|
||||
_family = fbase;
|
||||
_model = mbase;
|
||||
}
|
||||
else
|
||||
{
|
||||
_family = fbase+fex;
|
||||
_model = mbase+(mex<<4);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
manufac = OTHER;
|
||||
}
|
||||
|
||||
// threading details
|
||||
if (hyperThreading && threadFn !is null)
|
||||
{
|
||||
threadFn();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// feature flags
|
||||
enum : uint
|
||||
{
|
||||
MMX_BIT = 1<<23,
|
||||
FXSR_BIT = 1<<24,
|
||||
SSE_BIT = 1<<25,
|
||||
SSE2_BIT = 1<<26,
|
||||
HTT_BIT = 1<<28,
|
||||
IA64_BIT = 1<<30
|
||||
}
|
||||
// feature flags misc
|
||||
enum : uint
|
||||
{
|
||||
SSE3_BIT = 1,
|
||||
SSSE3_BIT = 1<<9
|
||||
}
|
||||
// extended feature flags
|
||||
enum : uint
|
||||
{
|
||||
AMD_MMX_BIT = 1<<22,
|
||||
AMD64_BIT = 1<<29,
|
||||
AMD_3DNOW_EXT_BIT = 1<<30,
|
||||
AMD_3DNOW_BIT = 1<<31
|
||||
}
|
||||
// manufacturer
|
||||
enum
|
||||
{
|
||||
OTHER,
|
||||
INTEL,
|
||||
AMD
|
||||
}
|
||||
|
||||
uint flags, misc, exflags, apic, signature;
|
||||
uint _stepping, _model, _family;
|
||||
|
||||
char[12] vendorStr = 0;
|
||||
string processorStr = "";
|
||||
|
||||
uint maxThreads=1;
|
||||
uint maxCores=1;
|
||||
uint manufac=OTHER;
|
||||
|
||||
/* **
|
||||
* fetches the cpu vendor string
|
||||
*/
|
||||
private void getVendorString()
|
||||
{
|
||||
char* dst = vendorStr.ptr;
|
||||
// puts the vendor string into dst
|
||||
asm
|
||||
{
|
||||
mov EAX, 0 ;
|
||||
cpuid ;
|
||||
mov EAX, dst ;
|
||||
mov [EAX], EBX ;
|
||||
mov [EAX+4], EDX ;
|
||||
mov [EAX+8], ECX ;
|
||||
}
|
||||
}
|
||||
|
||||
private void getProcessorString()
|
||||
{
|
||||
char[48] buffer;
|
||||
char* dst = buffer.ptr;
|
||||
// puts the processor string into dst
|
||||
asm
|
||||
{
|
||||
mov EAX, 0x8000_0000 ;
|
||||
cpuid ;
|
||||
cmp EAX, 0x8000_0004 ;
|
||||
jb PSLabel ; // no support
|
||||
push EDI ;
|
||||
mov EDI, dst ;
|
||||
mov EAX, 0x8000_0002 ;
|
||||
cpuid ;
|
||||
mov [EDI], EAX ;
|
||||
mov [EDI+4], EBX ;
|
||||
mov [EDI+8], ECX ;
|
||||
mov [EDI+12], EDX ;
|
||||
mov EAX, 0x8000_0003 ;
|
||||
cpuid ;
|
||||
mov [EDI+16], EAX ;
|
||||
mov [EDI+20], EBX ;
|
||||
mov [EDI+24], ECX ;
|
||||
mov [EDI+28], EDX ;
|
||||
mov EAX, 0x8000_0004 ;
|
||||
cpuid ;
|
||||
mov [EDI+32], EAX ;
|
||||
mov [EDI+36], EBX ;
|
||||
mov [EDI+40], ECX ;
|
||||
mov [EDI+44], EDX ;
|
||||
pop EDI ;
|
||||
PSLabel: ;
|
||||
}
|
||||
|
||||
if (buffer[0] == char.init) // no support
|
||||
return;
|
||||
|
||||
// seems many intel processors prepend whitespace
|
||||
processorStr = cast(string)strip(toString(dst)).dup;
|
||||
}
|
||||
|
||||
private void getFeatureFlags()
|
||||
{
|
||||
uint f,m,e,a,s;
|
||||
asm
|
||||
{
|
||||
mov EAX, 0 ;
|
||||
cpuid ;
|
||||
cmp EAX, 1 ;
|
||||
jb FeatLabel ; // no support
|
||||
mov EAX, 1 ;
|
||||
cpuid ;
|
||||
mov f, EDX ;
|
||||
mov m, ECX ;
|
||||
mov a, EBX ;
|
||||
mov s, EAX ;
|
||||
|
||||
FeatLabel: ;
|
||||
mov EAX, 0x8000_0000 ;
|
||||
cpuid ;
|
||||
cmp EAX, 0x8000_0001 ;
|
||||
jb FeatLabel2 ; // no support
|
||||
mov EAX, 0x8000_0001 ;
|
||||
cpuid ;
|
||||
mov e, EDX ;
|
||||
|
||||
FeatLabel2:
|
||||
;
|
||||
}
|
||||
flags = f;
|
||||
misc = m;
|
||||
exflags = e;
|
||||
apic = a;
|
||||
signature = s;
|
||||
}
|
||||
|
||||
private void getThreadingIntel()
|
||||
{
|
||||
uint n;
|
||||
ubyte b = 0;
|
||||
asm
|
||||
{
|
||||
mov EAX, 0 ;
|
||||
cpuid ;
|
||||
cmp EAX, 4 ;
|
||||
jb IntelSingle ;
|
||||
mov EAX, 4 ;
|
||||
mov ECX, 0 ;
|
||||
cpuid ;
|
||||
mov n, EAX ;
|
||||
mov b, 1 ;
|
||||
IntelSingle: ;
|
||||
}
|
||||
if (b != 0)
|
||||
{
|
||||
maxCores = ((n>>>26)&0x3F)+1;
|
||||
maxThreads = (apic>>>16)&0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxCores = maxThreads = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void getThreadingAMD()
|
||||
{
|
||||
ubyte n;
|
||||
ubyte b = 0;
|
||||
asm
|
||||
{
|
||||
mov EAX, 0x8000_0000 ;
|
||||
cpuid ;
|
||||
cmp EAX, 0x8000_0008 ;
|
||||
jb AMDSingle ;
|
||||
mov EAX, 0x8000_0008 ;
|
||||
cpuid ;
|
||||
mov n, CL ;
|
||||
mov b, 1 ;
|
||||
AMDSingle: ;
|
||||
}
|
||||
if (b != 0)
|
||||
{
|
||||
maxCores = n+1;
|
||||
maxThreads = (apic>>>16)&0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxCores = maxThreads = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Support code for above, from std.string and std.ctype
|
||||
***************************************************************************/
|
||||
|
||||
private
|
||||
{
|
||||
enum
|
||||
{
|
||||
_SPC = 8,
|
||||
_CTL = 0x20,
|
||||
_BLK = 0x40,
|
||||
_HEX = 0x80,
|
||||
_UC = 1,
|
||||
_LC = 2,
|
||||
_PNC = 0x10,
|
||||
_DIG = 4,
|
||||
_ALP = _UC|_LC,
|
||||
}
|
||||
|
||||
ubyte _ctype[128] =
|
||||
[
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a space, tab, vertical tab, form feed,
|
||||
* carriage return, or linefeed.
|
||||
*/
|
||||
int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; }
|
||||
|
||||
/*****************************************
|
||||
* Strips leading or trailing whitespace, or both.
|
||||
*/
|
||||
char[] stripl(char[] s)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < s.length; i++)
|
||||
{
|
||||
if (!isspace(s[i]))
|
||||
break;
|
||||
}
|
||||
return s[i .. s.length];
|
||||
}
|
||||
|
||||
char[] stripr(char[] s) /// ditto
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = s.length; i > 0; i--)
|
||||
{
|
||||
if (!isspace(s[i - 1]))
|
||||
break;
|
||||
}
|
||||
return s[0 .. i];
|
||||
}
|
||||
|
||||
char[] strip(char[] s) /// ditto
|
||||
{
|
||||
return stripr(stripl(s));
|
||||
}
|
||||
|
||||
char[] toString(char* s)
|
||||
{
|
||||
return s ? s[0 .. strlen(s)] : null;
|
||||
}
|
||||
|
||||
string toString(invariant(char)* s)
|
||||
{
|
||||
return s ? s[0 .. strlen(s)] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char[] vendor() {return "unknown vendor"; }
|
||||
char[] processor() {return "unknown processor"; }
|
||||
|
||||
bool mmx() {return false; }
|
||||
bool fxsr() {return false; }
|
||||
bool sse() {return false; }
|
||||
bool sse2() {return false; }
|
||||
bool sse3() {return false; }
|
||||
bool ssse3() {return false; }
|
||||
|
||||
bool amd3dnow() {return false; }
|
||||
bool amd3dnowExt() {return false; }
|
||||
bool amdMmx() {return false; }
|
||||
|
||||
bool ia64() {return false; }
|
||||
bool amd64() {return false; }
|
||||
|
||||
bool hyperThreading() {return false; }
|
||||
uint threadsPerCPU() {return 0; }
|
||||
uint coresPerCPU() {return 0; }
|
||||
|
||||
bool intel() {return false; }
|
||||
bool amd() {return false; }
|
||||
|
||||
uint stepping() {return 0; }
|
||||
uint model() {return 0; }
|
||||
uint family() {return 0; }
|
||||
}
|
||||
106
druntime/src/compiler/dmd/util/ctype.d
Normal file
106
druntime/src/compiler/dmd/util/ctype.d
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
// Simple ASCII char classification functions
|
||||
|
||||
module rt.util.ctype;
|
||||
|
||||
int isalnum(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; }
|
||||
int isalpha(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP) : 0; }
|
||||
int iscntrl(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_CTL) : 0; }
|
||||
int isdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_DIG) : 0; }
|
||||
int islower(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_LC) : 0; }
|
||||
int ispunct(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_PNC) : 0; }
|
||||
int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; }
|
||||
int isupper(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_UC) : 0; }
|
||||
int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX) : 0; }
|
||||
int isgraph(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; }
|
||||
int isprint(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; }
|
||||
int isascii(dchar c) { return c <= 0x7F; }
|
||||
|
||||
dchar tolower(dchar c)
|
||||
out (result)
|
||||
{
|
||||
assert(!isupper(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
return isupper(c) ? c + (cast(dchar)'a' - 'A') : c;
|
||||
}
|
||||
|
||||
dchar toupper(dchar c)
|
||||
out (result)
|
||||
{
|
||||
assert(!islower(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
return islower(c) ? c - (cast(dchar)'a' - 'A') : c;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
_SPC = 8,
|
||||
_CTL = 0x20,
|
||||
_BLK = 0x40,
|
||||
_HEX = 0x80,
|
||||
_UC = 1,
|
||||
_LC = 2,
|
||||
_PNC = 0x10,
|
||||
_DIG = 4,
|
||||
_ALP = _UC|_LC,
|
||||
}
|
||||
|
||||
ubyte _ctype[128] =
|
||||
[
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
|
||||
];
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
assert(isspace(' '));
|
||||
assert(!isspace('z'));
|
||||
assert(toupper('a') == 'A');
|
||||
assert(tolower('Q') == 'q');
|
||||
assert(!isxdigit('G'));
|
||||
}
|
||||
35
druntime/src/compiler/dmd/util/string.d
Normal file
35
druntime/src/compiler/dmd/util/string.d
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* The exception module defines all system-level exceptions and provides a
|
||||
* mechanism to alter system-level error handling.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module rt.util.string;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
char[] intToString( char[] buf, uint val )
|
||||
{
|
||||
assert( buf.length > 9 );
|
||||
auto p = buf.ptr + buf.length;
|
||||
|
||||
do
|
||||
{
|
||||
*--p = cast(char)(val % 10 + '0');
|
||||
} while( val /= 10 );
|
||||
|
||||
return buf[p - buf.ptr .. $];
|
||||
}
|
||||
|
||||
|
||||
int dstrcmp( in char[] s1, in char[] s2 )
|
||||
{
|
||||
auto len = s1.length;
|
||||
if( s2.length < len )
|
||||
len = s2.length;
|
||||
if( memcmp( s1.ptr, s2.ptr, len ) == 0 )
|
||||
return 0;
|
||||
return s1.length > s2.length ? 1 : -1;
|
||||
}
|
||||
917
druntime/src/compiler/dmd/util/utf.d
Normal file
917
druntime/src/compiler/dmd/util/utf.d
Normal file
@@ -0,0 +1,917 @@
|
||||
// Written in the D programming language
|
||||
|
||||
/*
|
||||
* Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/********************************************
|
||||
* Encode and decode UTF-8, UTF-16 and UTF-32 strings.
|
||||
*
|
||||
* For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D
|
||||
* wchar type.
|
||||
* For linux systems, the C wchar_t type is UTF-32 and corresponds to
|
||||
* the D utf.dchar type.
|
||||
*
|
||||
* UTF character support is restricted to (\u0000 <= character <= \U0010FFFF).
|
||||
*
|
||||
* See_Also:
|
||||
* $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
|
||||
* $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
|
||||
* $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdUtf
|
||||
*/
|
||||
|
||||
module rt.util.utf;
|
||||
|
||||
|
||||
extern (C) void onUnicodeError( string msg, size_t idx );
|
||||
|
||||
/*******************************
|
||||
* Test if c is a valid UTF-32 character.
|
||||
*
|
||||
* \uFFFE and \uFFFF are considered valid by this function,
|
||||
* as they are permitted for internal use by an application,
|
||||
* but they are not allowed for interchange by the Unicode standard.
|
||||
*
|
||||
* Returns: true if it is, false if not.
|
||||
*/
|
||||
|
||||
bool isValidDchar(dchar c)
|
||||
{
|
||||
/* Note: FFFE and FFFF are specifically permitted by the
|
||||
* Unicode standard for application internal use, but are not
|
||||
* allowed for interchange.
|
||||
* (thanks to Arcane Jill)
|
||||
*/
|
||||
|
||||
return c < 0xD800 ||
|
||||
(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.isValidDchar.unittest\n");
|
||||
assert(isValidDchar(cast(dchar)'a') == true);
|
||||
assert(isValidDchar(cast(dchar)0x1FFFFF) == false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto UTF8stride =
|
||||
[
|
||||
cast(ubyte)
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
|
||||
];
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-8 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns:
|
||||
* The number of bytes in the UTF-8 sequence or
|
||||
* 0xFF meaning s[i] is not the start of of UTF-8 sequence.
|
||||
*/
|
||||
uint stride(in char[] s, size_t i)
|
||||
{
|
||||
return UTF8stride[s[i]];
|
||||
}
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-16 sequence starting at index i
|
||||
* in string s.
|
||||
*/
|
||||
uint stride(in wchar[] s, size_t i)
|
||||
{ uint u = s[i];
|
||||
return 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-32 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns: The return value will always be 1.
|
||||
*/
|
||||
uint stride(in dchar[] s, size_t i)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Given an index i into an array of characters s[],
|
||||
* and assuming that index i is at the start of a UTF character,
|
||||
* determine the number of UCS characters up to that index i.
|
||||
*/
|
||||
|
||||
size_t toUCSindex(in char[] s, size_t i)
|
||||
{
|
||||
size_t n;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < i; )
|
||||
{
|
||||
j += stride(s, j);
|
||||
n++;
|
||||
}
|
||||
if (j > i)
|
||||
{
|
||||
onUnicodeError("invalid UTF-8 sequence", j);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUCSindex(in wchar[] s, size_t i)
|
||||
{
|
||||
size_t n;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < i; )
|
||||
{
|
||||
j += stride(s, j);
|
||||
n++;
|
||||
}
|
||||
if (j > i)
|
||||
{
|
||||
onUnicodeError("invalid UTF-16 sequence", j);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUCSindex(in dchar[] s, size_t i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Given a UCS index n into an array of characters s[], return the UTF index.
|
||||
*/
|
||||
|
||||
size_t toUTFindex(in char[] s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
uint j = UTF8stride[s[i]];
|
||||
if (j == 0xFF)
|
||||
onUnicodeError("invalid UTF-8 sequence", i);
|
||||
i += j;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUTFindex(in wchar[] s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
while (n--)
|
||||
{ wchar u = s[i];
|
||||
|
||||
i += 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUTFindex(in dchar[] s, size_t n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
/* =================== Decode ======================= */
|
||||
|
||||
/***************
|
||||
* Decodes and returns character starting at s[idx]. idx is advanced past the
|
||||
* decoded character. If the character is not well formed, a UtfException is
|
||||
* thrown and idx remains unchanged.
|
||||
*/
|
||||
dchar decode(in char[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(isValidDchar(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t len = s.length;
|
||||
dchar V;
|
||||
size_t i = idx;
|
||||
char u = s[i];
|
||||
|
||||
if (u & 0x80)
|
||||
{ uint n;
|
||||
char u2;
|
||||
|
||||
/* The following encodings are valid, except for the 5 and 6 byte
|
||||
* combinations:
|
||||
* 0xxxxxxx
|
||||
* 110xxxxx 10xxxxxx
|
||||
* 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
for (n = 1; ; n++)
|
||||
{
|
||||
if (n > 4)
|
||||
goto Lerr; // only do the first 4 of 6 encodings
|
||||
if (((u << n) & 0x80) == 0)
|
||||
{
|
||||
if (n == 1)
|
||||
goto Lerr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pick off (7 - n) significant bits of B from first byte of octet
|
||||
V = cast(dchar)(u & ((1 << (7 - n)) - 1));
|
||||
|
||||
if (i + (n - 1) >= len)
|
||||
goto Lerr; // off end of string
|
||||
|
||||
/* The following combinations are overlong, and illegal:
|
||||
* 1100000x (10xxxxxx)
|
||||
* 11100000 100xxxxx (10xxxxxx)
|
||||
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
|
||||
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
*/
|
||||
u2 = s[i + 1];
|
||||
if ((u & 0xFE) == 0xC0 ||
|
||||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
|
||||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
|
||||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
|
||||
(u == 0xFC && (u2 & 0xFC) == 0x80))
|
||||
goto Lerr; // overlong combination
|
||||
|
||||
for (uint j = 1; j != n; j++)
|
||||
{
|
||||
u = s[i + j];
|
||||
if ((u & 0xC0) != 0x80)
|
||||
goto Lerr; // trailing bytes are 10xxxxxx
|
||||
V = (V << 6) | (u & 0x3F);
|
||||
}
|
||||
if (!isValidDchar(V))
|
||||
goto Lerr;
|
||||
i += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
V = cast(dchar) u;
|
||||
i++;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
return V;
|
||||
|
||||
Lerr:
|
||||
onUnicodeError("invalid UTF-8 sequence", i);
|
||||
return V; // dummy return
|
||||
}
|
||||
|
||||
unittest
|
||||
{ size_t i;
|
||||
dchar c;
|
||||
|
||||
debug(utf) printf("utf.decode.unittest\n");
|
||||
|
||||
static s1 = "abcd"c;
|
||||
i = 0;
|
||||
c = decode(s1, i);
|
||||
assert(c == cast(dchar)'a');
|
||||
assert(i == 1);
|
||||
c = decode(s1, i);
|
||||
assert(c == cast(dchar)'b');
|
||||
assert(i == 2);
|
||||
|
||||
static s2 = "\xC2\xA9"c;
|
||||
i = 0;
|
||||
c = decode(s2, i);
|
||||
assert(c == cast(dchar)'\u00A9');
|
||||
assert(i == 2);
|
||||
|
||||
static s3 = "\xE2\x89\xA0"c;
|
||||
i = 0;
|
||||
c = decode(s3, i);
|
||||
assert(c == cast(dchar)'\u2260');
|
||||
assert(i == 3);
|
||||
|
||||
static s4 =
|
||||
[ "\xE2\x89"c, // too short
|
||||
"\xC0\x8A",
|
||||
"\xE0\x80\x8A",
|
||||
"\xF0\x80\x80\x8A",
|
||||
"\xF8\x80\x80\x80\x8A",
|
||||
"\xFC\x80\x80\x80\x80\x8A",
|
||||
];
|
||||
|
||||
for (int j = 0; j < s4.length; j++)
|
||||
{
|
||||
try
|
||||
{
|
||||
i = 0;
|
||||
c = decode(s4[j], i);
|
||||
assert(0);
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
i = 23;
|
||||
}
|
||||
assert(i == 23);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar decode(in wchar[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(isValidDchar(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
string msg;
|
||||
dchar V;
|
||||
size_t i = idx;
|
||||
uint u = s[i];
|
||||
|
||||
if (u & ~0x7F)
|
||||
{ if (u >= 0xD800 && u <= 0xDBFF)
|
||||
{ uint u2;
|
||||
|
||||
if (i + 1 == s.length)
|
||||
{ msg = "surrogate UTF-16 high value past end of string";
|
||||
goto Lerr;
|
||||
}
|
||||
u2 = s[i + 1];
|
||||
if (u2 < 0xDC00 || u2 > 0xDFFF)
|
||||
{ msg = "surrogate UTF-16 low value out of range";
|
||||
goto Lerr;
|
||||
}
|
||||
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
|
||||
i += 2;
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{ msg = "unpaired surrogate UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{ msg = "illegal UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
return cast(dchar)u;
|
||||
|
||||
Lerr:
|
||||
onUnicodeError(msg, i);
|
||||
return cast(dchar)u; // dummy return
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar decode(in dchar[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t i = idx;
|
||||
dchar c = s[i];
|
||||
|
||||
if (!isValidDchar(c))
|
||||
goto Lerr;
|
||||
idx = i + 1;
|
||||
return c;
|
||||
|
||||
Lerr:
|
||||
onUnicodeError("invalid UTF-32 value", i);
|
||||
return c; // dummy return
|
||||
}
|
||||
|
||||
|
||||
/* =================== Encode ======================= */
|
||||
|
||||
/*******************************
|
||||
* Encodes character c and appends it to array s[].
|
||||
*/
|
||||
void encode(inout char[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
char[] r = s;
|
||||
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
r ~= cast(char) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
char[4] buf;
|
||||
uint L;
|
||||
|
||||
if (c <= 0x7FF)
|
||||
{
|
||||
buf[0] = cast(char)(0xC0 | (c >> 6));
|
||||
buf[1] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 2;
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xE0 | (c >> 12));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 3;
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xF0 | (c >> 18));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[3] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
r ~= buf[0 .. L];
|
||||
}
|
||||
s = r;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.encode.unittest\n");
|
||||
|
||||
char[] s = "abcd".dup;
|
||||
encode(s, cast(dchar)'a');
|
||||
assert(s.length == 5);
|
||||
assert(s == "abcda");
|
||||
|
||||
encode(s, cast(dchar)'\u00A9');
|
||||
assert(s.length == 7);
|
||||
assert(s == "abcda\xC2\xA9");
|
||||
//assert(s == "abcda\u00A9"); // BUG: fix compiler
|
||||
|
||||
encode(s, cast(dchar)'\u2260');
|
||||
assert(s.length == 10);
|
||||
assert(s == "abcda\xC2\xA9\xE2\x89\xA0");
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
void encode(inout wchar[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
wchar[] r = s;
|
||||
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
r ~= cast(wchar) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar[2] buf;
|
||||
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
r ~= buf;
|
||||
}
|
||||
s = r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
void encode(inout dchar[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
s ~= c;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the code length of $(D c) in the encoding using $(D C) as a
|
||||
code point. The code is returned in character count, not in bytes.
|
||||
*/
|
||||
|
||||
ubyte codeLength(C)(dchar c)
|
||||
{
|
||||
|
||||
static if (C.sizeof == 1)
|
||||
{
|
||||
return
|
||||
c <= 0x7F ? 1
|
||||
: c <= 0x7FF ? 2
|
||||
: c <= 0xFFFF ? 3
|
||||
: c <= 0x10FFFF ? 4
|
||||
: (assert(false), 6);
|
||||
}
|
||||
|
||||
else static if (C.sizeof == 2)
|
||||
{
|
||||
return c <= 0xFFFF ? 1 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(C.sizeof == 4);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* =================== Validation ======================= */
|
||||
|
||||
/***********************************
|
||||
Checks to see if string is well formed or not. $(D S) can be an array
|
||||
of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException)
|
||||
if it is not. Use to check all untrusted input for correctness.
|
||||
*/
|
||||
void validate(S)(in S s)
|
||||
{
|
||||
auto len = s.length;
|
||||
for (size_t i = 0; i < len; )
|
||||
{
|
||||
decode(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF8 ======================= */
|
||||
|
||||
char[] toUTF8(char[4] buf, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
buf[0] = cast(char) c;
|
||||
return buf[0 .. 1];
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
buf[0] = cast(char)(0xC0 | (c >> 6));
|
||||
buf[1] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 2];
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xE0 | (c >> 12));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 3];
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xF0 | (c >> 18));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[3] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 4];
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Encodes string s into UTF-8 and returns the encoded string.
|
||||
*/
|
||||
string toUTF8(string s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
string toUTF8(in wchar[] s)
|
||||
{
|
||||
char[] r;
|
||||
size_t i;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
|
||||
for (i = 0; i < slen; i++)
|
||||
{ wchar c = s[i];
|
||||
|
||||
if (c <= 0x7F)
|
||||
r[i] = cast(char)c; // fast path for ascii
|
||||
else
|
||||
{
|
||||
r.length = i;
|
||||
foreach (dchar c; s[i .. slen])
|
||||
{
|
||||
encode(r, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cast(string)r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
string toUTF8(in dchar[] s)
|
||||
{
|
||||
char[] r;
|
||||
size_t i;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
|
||||
for (i = 0; i < slen; i++)
|
||||
{ dchar c = s[i];
|
||||
|
||||
if (c <= 0x7F)
|
||||
r[i] = cast(char)c; // fast path for ascii
|
||||
else
|
||||
{
|
||||
r.length = i;
|
||||
foreach (dchar d; s[i .. slen])
|
||||
{
|
||||
encode(r, d);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cast(string)r;
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF16 ======================= */
|
||||
|
||||
wchar[] toUTF16(wchar[2] buf, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(wchar) c;
|
||||
return buf[0 .. 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
return buf[0 .. 2];
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* Encodes string s into UTF-16 and returns the encoded string.
|
||||
* toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take
|
||||
* an LPWSTR or LPCWSTR argument.
|
||||
*/
|
||||
wstring toUTF16(in char[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
i++;
|
||||
r ~= cast(wchar)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = decode(s, i);
|
||||
encode(r, c);
|
||||
}
|
||||
}
|
||||
return cast(wstring)r;
|
||||
}
|
||||
|
||||
alias const(wchar)* wptr;
|
||||
/** ditto */
|
||||
wptr toUTF16z(in char[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen + 1;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
i++;
|
||||
r ~= cast(wchar)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = decode(s, i);
|
||||
encode(r, c);
|
||||
}
|
||||
}
|
||||
r ~= "\000";
|
||||
return r.ptr;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
wstring toUTF16(wstring s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
wstring toUTF16(in dchar[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; i++)
|
||||
{
|
||||
encode(r, s[i]);
|
||||
}
|
||||
return cast(wstring)r;
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF32 ======================= */
|
||||
|
||||
/*****
|
||||
* Encodes string s into UTF-32 and returns the encoded string.
|
||||
*/
|
||||
dstring toUTF32(in char[] s)
|
||||
{
|
||||
dchar[] r;
|
||||
size_t slen = s.length;
|
||||
size_t j = 0;
|
||||
|
||||
r.length = slen; // r[] will never be longer than s[]
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c >= 0x80)
|
||||
c = decode(s, i);
|
||||
else
|
||||
i++; // c is ascii, no need for decode
|
||||
r[j++] = c;
|
||||
}
|
||||
return cast(dstring)r[0 .. j];
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
dstring toUTF32(in wchar[] s)
|
||||
{
|
||||
dchar[] r;
|
||||
size_t slen = s.length;
|
||||
size_t j = 0;
|
||||
|
||||
r.length = slen; // r[] will never be longer than s[]
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c >= 0x80)
|
||||
c = decode(s, i);
|
||||
else
|
||||
i++; // c is ascii, no need for decode
|
||||
r[j++] = c;
|
||||
}
|
||||
return cast(dstring)r[0 .. j];
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
dstring toUTF32(dstring s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ================================ tests ================================== */
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.toUTF.unittest\n");
|
||||
|
||||
auto c = "hello"c;
|
||||
auto w = toUTF16(c);
|
||||
assert(w == "hello");
|
||||
auto d = toUTF32(c);
|
||||
assert(d == "hello");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "hello");
|
||||
d = toUTF32(w);
|
||||
assert(d == "hello");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "hello");
|
||||
w = toUTF16(d);
|
||||
assert(w == "hello");
|
||||
|
||||
|
||||
c = "hel\u1234o";
|
||||
w = toUTF16(c);
|
||||
assert(w == "hel\u1234o");
|
||||
d = toUTF32(c);
|
||||
assert(d == "hel\u1234o");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "hel\u1234o");
|
||||
d = toUTF32(w);
|
||||
assert(d == "hel\u1234o");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "hel\u1234o");
|
||||
w = toUTF16(d);
|
||||
assert(w == "hel\u1234o");
|
||||
|
||||
|
||||
c = "he\U0010AAAAllo";
|
||||
w = toUTF16(c);
|
||||
//foreach (wchar c; w) printf("c = x%x\n", c);
|
||||
//foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c);
|
||||
assert(w == "he\U0010AAAAllo");
|
||||
d = toUTF32(c);
|
||||
assert(d == "he\U0010AAAAllo");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "he\U0010AAAAllo");
|
||||
d = toUTF32(w);
|
||||
assert(d == "he\U0010AAAAllo");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "he\U0010AAAAllo");
|
||||
w = toUTF16(d);
|
||||
assert(w == "he\U0010AAAAllo");
|
||||
}
|
||||
171
druntime/src/compiler/dmd/win32.mak
Normal file
171
druntime/src/compiler/dmd/win32.mak
Normal file
@@ -0,0 +1,171 @@
|
||||
# Makefile to build the compiler runtime D library for Win32
|
||||
# Designed to work with DigitalMars make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the compiler runtime library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=druntime-rt-dmd.lib
|
||||
LIB_MASK=druntime-rt-dmd*.lib
|
||||
|
||||
CP=xcopy /y
|
||||
RM=del /f
|
||||
MD=mkdir
|
||||
|
||||
CFLAGS=-mn -6 -r $(ADD_CFLAGS)
|
||||
#CFLAGS=-g -mn -6 -r $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=dmc
|
||||
LC=lib
|
||||
DC=dmd
|
||||
|
||||
LIB_DEST=..\..\..\lib
|
||||
|
||||
.DEFAULT: .asm .c .cpp .d .html .obj
|
||||
|
||||
.asm.obj:
|
||||
$(CC) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.obj:
|
||||
$(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html dmd.ddoc $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
lib : dmd.lib
|
||||
doc : dmd.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_BASE= \
|
||||
aaA.obj \
|
||||
aApply.obj \
|
||||
aApplyR.obj \
|
||||
adi.obj \
|
||||
arrayassign.obj \
|
||||
arraybyte.obj \
|
||||
arraycast.obj \
|
||||
arraycat.obj \
|
||||
arraydouble.obj \
|
||||
arrayfloat.obj \
|
||||
arrayint.obj \
|
||||
arrayreal.obj \
|
||||
arrayshort.obj \
|
||||
cast_.obj \
|
||||
complex.obj \
|
||||
cover.obj \
|
||||
critical.obj \
|
||||
deh.obj \
|
||||
dmain2.obj \
|
||||
invariant.obj \
|
||||
invariant_.obj \
|
||||
lifetime.obj \
|
||||
memory.obj \
|
||||
memset.obj \
|
||||
monitor.obj \
|
||||
obj.obj \
|
||||
object_.obj \
|
||||
qsort.obj \
|
||||
switch_.obj \
|
||||
trace.obj
|
||||
# NOTE: trace.obj and cover.obj are not necessary for a successful build
|
||||
# as both are used for debugging features (profiling and coverage)
|
||||
# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
|
||||
# minit.asm is not used by dmd for linux
|
||||
|
||||
OBJ_UTIL= \
|
||||
util\console.obj \
|
||||
util\cpuid.obj \
|
||||
util\ctype.obj \
|
||||
util\string.obj \
|
||||
util\utf.obj
|
||||
|
||||
OBJ_TI= \
|
||||
typeinfo\ti_AC.obj \
|
||||
typeinfo\ti_Acdouble.obj \
|
||||
typeinfo\ti_Acfloat.obj \
|
||||
typeinfo\ti_Acreal.obj \
|
||||
typeinfo\ti_Adouble.obj \
|
||||
typeinfo\ti_Afloat.obj \
|
||||
typeinfo\ti_Ag.obj \
|
||||
typeinfo\ti_Aint.obj \
|
||||
typeinfo\ti_Along.obj \
|
||||
typeinfo\ti_Areal.obj \
|
||||
typeinfo\ti_Ashort.obj \
|
||||
typeinfo\ti_byte.obj \
|
||||
typeinfo\ti_C.obj \
|
||||
typeinfo\ti_cdouble.obj \
|
||||
typeinfo\ti_cfloat.obj \
|
||||
typeinfo\ti_char.obj \
|
||||
typeinfo\ti_creal.obj \
|
||||
typeinfo\ti_dchar.obj \
|
||||
typeinfo\ti_delegate.obj \
|
||||
typeinfo\ti_double.obj \
|
||||
typeinfo\ti_float.obj \
|
||||
typeinfo\ti_idouble.obj \
|
||||
typeinfo\ti_ifloat.obj \
|
||||
typeinfo\ti_int.obj \
|
||||
typeinfo\ti_ireal.obj \
|
||||
typeinfo\ti_long.obj \
|
||||
typeinfo\ti_ptr.obj \
|
||||
typeinfo\ti_real.obj \
|
||||
typeinfo\ti_short.obj \
|
||||
typeinfo\ti_ubyte.obj \
|
||||
typeinfo\ti_uint.obj \
|
||||
typeinfo\ti_ulong.obj \
|
||||
typeinfo\ti_ushort.obj \
|
||||
typeinfo\ti_void.obj \
|
||||
typeinfo\ti_wchar.obj
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_BASE) \
|
||||
$(OBJ_UTIL) \
|
||||
$(OBJ_TI)
|
||||
|
||||
######################################################
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
dmd.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) -c -n $@ $(ALL_OBJS) minit.obj
|
||||
|
||||
dmd.doc : $(ALL_DOCS)
|
||||
@echo No documentation available.
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
$(RM) /s *.di
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
|
||||
install :
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)\.
|
||||
414
druntime/src/compiler/ldc/aApply.d
Normal file
414
druntime/src/compiler/ldc/aApply.d
Normal file
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
/* This code handles decoding UTF strings for foreach loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
//debug = apply;
|
||||
debug(apply)
|
||||
{
|
||||
extern(C) int printf(char*, ...);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
*/
|
||||
|
||||
// dg is D, but _aApplycd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplycd1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ d = decode(aa, i);
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
d = decode(aa, i);
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
i++;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
// dg is D, but _aApplycd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplycd2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
n = 1;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplydc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
d = aa[i];
|
||||
debug(apply) printf("d = %u\n", d);
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
debug(apply) printf("c2 = %d\n", c2);
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
|
||||
foreach (size_t i, dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
auto j = i;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
975
druntime/src/compiler/ldc/aApplyR.d
Normal file
975
druntime/src/compiler/ldc/aApplyR.d
Normal file
@@ -0,0 +1,975 @@
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
/* This code handles decoding UTF strings for foreach_reverse loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
/**********************************************/
|
||||
/* 1 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd1.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd1.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw1.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc1.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0;)
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc1.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw1.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* 2 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
|
||||
for (i = len; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd2.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); assert(k == 8); break;
|
||||
case 1: assert(d == '\U00100456'); assert(k == 4); break;
|
||||
case 2: assert(d == '\u1234'); assert(k == 1); break;
|
||||
case 3: assert(d == 'a'); assert(k == 0); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd2.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == '\U00100456'); break;
|
||||
case 2: assert(k == 1); assert(d == '\u1234'); break;
|
||||
case 3: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw2.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 8); assert(d == 'b'); break;
|
||||
case 1: assert(k == 4); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 4); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc2.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc2.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw2.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 2); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user