 |
Changeset 5652
- Timestamp:
- 05/09/11 11:08:40
(1 year ago)
- Author:
- Marenz
- Message:
Merged branch dmd-1.067 into trunk
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r5561 |
r5652 |
|
| 8 | 8 | |
|---|
| 9 | 9 | EXE=runUnittests_$DC |
|---|
| 10 | | DL="-L-ldl" |
|---|
| | 10 | DL="-L-ldl " |
|---|
| 11 | 11 | UNAME=`uname` |
|---|
| 12 | | OPTIONS="-debug -debug=UnitTest" |
|---|
| | 12 | OPTIONS="-debug -gc -debug=utf -debug=UnitTest" # :w -debug=PRINTF" |
|---|
| 13 | 13 | |
|---|
| 14 | 14 | error () { |
|---|
| … | … | |
| 31 | 31 | if [ $DC == "ldc" ] |
|---|
| 32 | 32 | then |
|---|
| 33 | | OPTIONS="-oq -d-debug -d-debug=UnitTest" |
|---|
| | 33 | OPTIONS="-oq -d-debug -d-debug=UnitTest -gc" |
|---|
| | 34 | DL="-L-ldl " |
|---|
| 34 | 35 | fi |
|---|
| 35 | 36 | |
|---|
| 36 | | build/bin/$PLATFORM$ARCH/bob -v -r=$DC -c=$DC -p=$PLATFORM -l=libtango-$DC-tst -o="-g -unittest $OPTIONS" . |
|---|
| | 37 | if [ $DC == "gdc" ] |
|---|
| | 38 | then |
|---|
| | 39 | OPTIONS="-fdebug -fdebug=UnitTest -funittest -g -nophoboslib" |
|---|
| | 40 | DL="-ldl -L. -ltango-$DC-tst -lz -lbz2 -o $EXE" |
|---|
| | 41 | fi |
|---|
| | 42 | |
|---|
| | 43 | echo build/bin/${PLATFORM}32/bob -r=$DC -m=$ARCH -c=$DC -p=$PLATFORM -l=libtango-$DC-tst -o=\"-m$ARCH -unittest $OPTIONS\" . |
|---|
| | 44 | build/bin/${PLATFORM}32/bob -r=$DC -m=$ARCH -c=$DC -p=$PLATFORM -l=libtango-$DC-tst -o="-m$ARCH -unittest $OPTIONS" . |
|---|
| | 45 | |
|---|
| | 46 | |
|---|
| | 47 | echo "Compiled Library" |
|---|
| 37 | 48 | |
|---|
| 38 | 49 | if ! which $DC >& /dev/null |
|---|
| … | … | |
| 60 | 71 | import tango.core.tools.TraceExceptions; |
|---|
| 61 | 72 | |
|---|
| | 73 | import tango.stdc.stdio : printf; |
|---|
| | 74 | |
|---|
| 62 | 75 | bool tangoUnitTester() |
|---|
| 63 | 76 | { |
|---|
| 64 | 77 | uint countFailed = 0; |
|---|
| 65 | 78 | uint countTotal = 1; |
|---|
| | 79 | |
|---|
| 66 | 80 | Stdout ("NOTE: This is still fairly rudimentary, and will only report the").newline; |
|---|
| 67 | 81 | Stdout (" first error per module.").newline; |
|---|
| … | … | |
| 92 | 106 | } |
|---|
| 93 | 107 | |
|---|
| 94 | | void main() {} |
|---|
| | 108 | void main() { } // assert ( 0 == 1, "Main .. "); } |
|---|
| 95 | 109 | EOF |
|---|
| 96 | 110 | |
|---|
| … | … | |
| 100 | 114 | fi |
|---|
| 101 | 115 | |
|---|
| 102 | | echo "$DC $EXE.d $DFILES -g $OPTIONS -unittest -L-L. -L-ltango-$DC-tst $DL -L-lz -L-lbz2" |
|---|
| 103 | | $DC $EXE.d $DFILES -g $OPTIONS -unittest -L-L. -L-ltango-$DC-tst $DL -L-lz -L-lbz2 && rm $EXE.d && rm libtango-$DC-tst.a |
|---|
| | 116 | echo "$DC $EXE.d $DFILES $OPTIONS -m$ARCH -unittest -L-L. -L-ltango-$DC-tst $DL -L-lz -L-lbz2" |
|---|
| | 117 | $DC $EXE.d $DFILES $OPTIONS -m$ARCH -Itango/core/vendor -unittest -L-L. -L-ltango-$DC-tst $DL -L-lz -L-lbz2 #&& rm $EXE.d && rm libtango-$DC-tst.a |
|---|
| 104 | 118 | |
|---|
| 105 | 119 | ./runUnittests_$DC |
|---|
| r5622 |
r5652 |
|
| 39 | 39 | new Solaris (args); |
|---|
| 40 | 40 | new Windows (args); |
|---|
| 41 | | stdout.formatln ("{} files", FileFilter.builder(args.os, args.compiler)()); |
|---|
| | 41 | Stdout.formatln ("{} files", FileFilter.builder(args.os, args.compiler)()); |
|---|
| 42 | 42 | } |
|---|
| 43 | 43 | } |
|---|
| … | … | |
| 158 | 158 | private auto gcc = "gcc -c -o"; |
|---|
| 159 | 159 | private auto gcc32 = "gcc -c -m32 -o"; |
|---|
| | 160 | private auto gcc64 = "gcc -c -m64 -o"; |
|---|
| 160 | 161 | |
|---|
| 161 | 162 | int dmd () |
|---|
| 162 | 163 | { |
|---|
| 163 | | auto dmd = "dmd -c -I"~args.root~"/tango/core -I"~args.root~" -I"~args.root~"/tango/core/vendor "~args.flags~" -of"; |
|---|
| | 164 | char[] gcc, march; |
|---|
| | 165 | |
|---|
| | 166 | if (args.march.length) |
|---|
| | 167 | { |
|---|
| | 168 | march = " -m" ~ args.march; |
|---|
| | 169 | gcc = args.march == "64" ? gcc64 : gcc32; |
|---|
| | 170 | } |
|---|
| | 171 | |
|---|
| | 172 | auto dmd = "dmd -c -I"~args.root~"/tango/core -I"~args.root ~ |
|---|
| | 173 | march~" -I"~args.root~"/tango/core/vendor "~args.flags~" -of"; |
|---|
| 164 | 174 | exclude ("tango/core/rt/compiler/dmd/windows"); |
|---|
| 165 | 175 | exclude ("tango/core/rt/compiler/dmd/darwin"); |
|---|
| … | … | |
| 171 | 181 | if (args.core) { |
|---|
| 172 | 182 | foreach (file; scan(".c")) { |
|---|
| 173 | | auto obj = compile (file, gcc32); |
|---|
| 174 | | addToLib(obj); |
|---|
| 175 | | } |
|---|
| 176 | | |
|---|
| 177 | | foreach (file; scan(".S")) { |
|---|
| 178 | | auto obj = compile (file, gcc32); |
|---|
| 179 | | addToLib(obj); |
|---|
| 180 | | } |
|---|
| 181 | | } |
|---|
| 182 | | |
|---|
| 183 | | makeLib(true); |
|---|
| | 183 | auto obj = compile (file, gcc); |
|---|
| | 184 | addToLib(obj); |
|---|
| | 185 | } |
|---|
| | 186 | |
|---|
| | 187 | foreach (file; scan(".S")) { |
|---|
| | 188 | auto obj = compile (file, gcc); |
|---|
| | 189 | addToLib(obj); |
|---|
| | 190 | } |
|---|
| | 191 | } |
|---|
| | 192 | |
|---|
| | 193 | makeLib(args.march == " -m32"); |
|---|
| 184 | 194 | return count; |
|---|
| 185 | 195 | } |
|---|
| … | … | |
| 187 | 197 | int ldc () |
|---|
| 188 | 198 | { |
|---|
| 189 | | auto ldc = "ldc -c -I"~args.root~"/tango/core -I"~args.root~"/tango/core/rt/compiler/ldc -I"~args.root~" -I"~args.root~"/tango/core/vendor "~args.flags~" -of"; |
|---|
| | 199 | char[] gcc, march; |
|---|
| | 200 | |
|---|
| | 201 | if (args.march.length) |
|---|
| | 202 | { |
|---|
| | 203 | march = " -m" ~ args.march; |
|---|
| | 204 | gcc = args.march == "64" ? gcc64 : gcc32; |
|---|
| | 205 | } |
|---|
| | 206 | |
|---|
| | 207 | auto ldc = "ldc -c -I"~args.root~"/tango/core " ~ march ~ " -I"~args.root~"/tango/core/rt/compiler/ldc -I"~args.root~" -I"~args.root~"/tango/core/vendor "~args.flags~" -of"; |
|---|
| 190 | 208 | foreach (file; scan(".d")) { |
|---|
| 191 | 209 | auto obj = compile (file, ldc); |
|---|
| … | … | |
| 205 | 223 | } |
|---|
| 206 | 224 | |
|---|
| 207 | | makeLib; |
|---|
| | 225 | makeLib(args.march == "32"); |
|---|
| 208 | 226 | return count; |
|---|
| 209 | 227 | } |
|---|
| … | … | |
| 211 | 229 | int gdc () |
|---|
| 212 | 230 | { |
|---|
| 213 | | auto gdc = "gdc -c -I"~args.root~"/tango/core -I"~args.root~" "~args.flags~" -o"; |
|---|
| | 231 | char[] gcc, march; |
|---|
| | 232 | |
|---|
| | 233 | if (args.march.length) |
|---|
| | 234 | { |
|---|
| | 235 | march = " -m" ~ args.march; |
|---|
| | 236 | gcc = args.march == "64" ? gcc64 : gcc32; |
|---|
| | 237 | } |
|---|
| | 238 | |
|---|
| | 239 | auto gdc = "gdc -c -I"~args.root~"/tango/core -I"~args.root ~ |
|---|
| | 240 | march ~ " "~args.flags~" -o"; |
|---|
| 214 | 241 | foreach (file; scan(".d")) { |
|---|
| 215 | 242 | auto obj = compile (file, gdc); |
|---|
| … | … | |
| 228 | 255 | } |
|---|
| 229 | 256 | } |
|---|
| 230 | | |
|---|
| 231 | | makeLib; |
|---|
| | 257 | makeLib(args.march == "32"); |
|---|
| 232 | 258 | return count; |
|---|
| 233 | 259 | } |
|---|
| … | … | |
| 781 | 807 | { |
|---|
| 782 | 808 | foreach (str; cmd) |
|---|
| 783 | | stdout (str)(' '); |
|---|
| 784 | | stdout.newline; |
|---|
| | 809 | Stdout (str)(' '); |
|---|
| | 810 | Stdout.newline; |
|---|
| 785 | 811 | } |
|---|
| 786 | 812 | |
|---|
| … | … | |
| 795 | 821 | |
|---|
| 796 | 822 | proc.execute(); |
|---|
| 797 | | stdout.stream.copy (proc.stderr); |
|---|
| 798 | | stdout.stream.copy (proc.stdout); |
|---|
| | 823 | Stdout.stream.copy (proc.stderr); |
|---|
| | 824 | Stdout.stream.copy (proc.stdout); |
|---|
| 799 | 825 | auto result = proc.wait; |
|---|
| 800 | 826 | if (result.status != 0 || result.reason != Process.Result.Exit) |
|---|
| … | … | |
| 824 | 850 | flags, |
|---|
| 825 | 851 | target, |
|---|
| 826 | | compiler; |
|---|
| | 852 | compiler, |
|---|
| | 853 | march; |
|---|
| | 854 | |
|---|
| 827 | 855 | |
|---|
| 828 | 856 | char[] usage = "Bob is a build tool for the sole purpose to compile the Tango library.\n" |
|---|
| … | … | |
| 834 | 862 | "\t[-u]\t\t\tinclude user modules\n" |
|---|
| 835 | 863 | "\t[-d]\t\t\tbuild Tango as a dynamic/shared library\n" |
|---|
| | 864 | "\t[-m=64|32]\tCompile for 32/64 bit\n" |
|---|
| 836 | 865 | "\t[-r=dmd|gdc|ldc]\tinclude a runtime target\n" |
|---|
| 837 | 866 | "\t[-c=dmd|gdc|ldc]\tspecify a compiler to use\n" |
|---|
| … | … | |
| 858 | 887 | auto h = args("help").aliased('h').aliased('?').halt; |
|---|
| 859 | 888 | auto d = args('d'); |
|---|
| | 889 | auto m = args('m').params(1).restrict("64", "32"); |
|---|
| 860 | 890 | |
|---|
| 861 | 891 | version (Windows) |
|---|
| … | … | |
| 902 | 932 | gc = g.assigned[0]; |
|---|
| 903 | 933 | lib = l.assigned[0]; |
|---|
| | 934 | march = m.assigned.length > 0 ? m.assigned[0] : ""; |
|---|
| 904 | 935 | |
|---|
| 905 | 936 | if(compiler == "gdc" && flags == "-release") |
|---|
| r5609 |
r5652 |
|
| 120 | 120 | /// compares the types of this TypeInfo stored at p1 and p2 |
|---|
| 121 | 121 | int compare(void *p1, void *p2); |
|---|
| | 122 | /// Return alignment of type |
|---|
| | 123 | size_t talign() { return tsize(); } |
|---|
| 122 | 124 | /// returns the size of a type with the current TypeInfo |
|---|
| 123 | 125 | size_t tsize(); |
|---|
| … | … | |
| 132 | 134 | /// offsets of the various elements |
|---|
| 133 | 135 | OffsetTypeInfo[] offTi(); |
|---|
| | 136 | |
|---|
| | 137 | /** Return internal info on arguments fitting into 8byte. |
|---|
| | 138 | * See X86-64 ABI 3.2.3 |
|---|
| | 139 | */ |
|---|
| | 140 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2); |
|---|
| 134 | 141 | } |
|---|
| 135 | 142 | |
|---|
| r5607 |
r5652 |
|
| 349 | 349 | __builtin_unwind_init(); |
|---|
| 350 | 350 | } |
|---|
| | 351 | else version ( D_InlineAsm_X86_64 ) |
|---|
| | 352 | { |
|---|
| | 353 | asm |
|---|
| | 354 | { |
|---|
| | 355 | // Not sure what goes here, pushad is invalid in 64 bit code |
|---|
| | 356 | push RAX ; |
|---|
| | 357 | push RBX ; |
|---|
| | 358 | push RCX ; |
|---|
| | 359 | push RDX ; |
|---|
| | 360 | push RSI ; |
|---|
| | 361 | push RDI ; |
|---|
| | 362 | push RBP ; |
|---|
| | 363 | push R8 ; |
|---|
| | 364 | push R9 ; |
|---|
| | 365 | push R10 ; |
|---|
| | 366 | push R11 ; |
|---|
| | 367 | push R12 ; |
|---|
| | 368 | push R13 ; |
|---|
| | 369 | push R14 ; |
|---|
| | 370 | push R15 ; |
|---|
| | 371 | push EAX ; // 16 byte align the stack |
|---|
| | 372 | } |
|---|
| | 373 | } |
|---|
| 351 | 374 | else |
|---|
| 352 | 375 | { |
|---|
| … | … | |
| 411 | 434 | { |
|---|
| 412 | 435 | // registers will be popped automatically |
|---|
| | 436 | } |
|---|
| | 437 | else version ( D_InlineAsm_X86_64 ) |
|---|
| | 438 | { |
|---|
| | 439 | asm |
|---|
| | 440 | { |
|---|
| | 441 | // Not sure what goes here, popad is invalid in 64 bit code |
|---|
| | 442 | pop EAX ; // 16 byte align the stack |
|---|
| | 443 | pop R15 ; |
|---|
| | 444 | pop R14 ; |
|---|
| | 445 | pop R13 ; |
|---|
| | 446 | pop R12 ; |
|---|
| | 447 | pop R11 ; |
|---|
| | 448 | pop R10 ; |
|---|
| | 449 | pop R9 ; |
|---|
| | 450 | pop R8 ; |
|---|
| | 451 | pop RBP ; |
|---|
| | 452 | pop RDI ; |
|---|
| | 453 | pop RSI ; |
|---|
| | 454 | pop RDX ; |
|---|
| | 455 | pop RCX ; |
|---|
| | 456 | pop RBX ; |
|---|
| | 457 | pop RAX ; |
|---|
| | 458 | } |
|---|
| 413 | 459 | } |
|---|
| 414 | 460 | else |
|---|
| … | … | |
| 2671 | 2717 | else version( AsmX86_64_Posix ) |
|---|
| 2672 | 2718 | { |
|---|
| 2673 | | asm |
|---|
| | 2719 | version( DigitalMars ) const dmdgdc = true; |
|---|
| | 2720 | else version (GNU) const dmdgdc = true; |
|---|
| | 2721 | else const dmdgdc = false; |
|---|
| | 2722 | |
|---|
| | 2723 | static if (dmdgdc == true) asm |
|---|
| | 2724 | { |
|---|
| | 2725 | naked; |
|---|
| | 2726 | |
|---|
| | 2727 | // save current stack state |
|---|
| | 2728 | push RBP; |
|---|
| | 2729 | mov RBP, RSP; |
|---|
| | 2730 | push RBX; |
|---|
| | 2731 | push R12; |
|---|
| | 2732 | push R13; |
|---|
| | 2733 | push R14; |
|---|
| | 2734 | push R15; |
|---|
| | 2735 | sub RSP, 4; |
|---|
| | 2736 | stmxcsr [RSP]; |
|---|
| | 2737 | sub RSP, 4; |
|---|
| | 2738 | //version(SynchroFloatExcept){ |
|---|
| | 2739 | fstcw [RSP]; |
|---|
| | 2740 | fwait; |
|---|
| | 2741 | //} else { |
|---|
| | 2742 | // fnstcw [RSP]; |
|---|
| | 2743 | // fnclex; |
|---|
| | 2744 | //} |
|---|
| | 2745 | |
|---|
| | 2746 | // store oldp again with more accurate address |
|---|
| | 2747 | mov [RDI], RSP; |
|---|
| | 2748 | // load newp to begin context switch |
|---|
| | 2749 | mov RSP, RSI; |
|---|
| | 2750 | |
|---|
| | 2751 | // load saved state from new stack |
|---|
| | 2752 | fldcw [RSP]; |
|---|
| | 2753 | add RSP, 4; |
|---|
| | 2754 | ldmxcsr [RSP]; |
|---|
| | 2755 | add RSP, 4; |
|---|
| | 2756 | pop R15; |
|---|
| | 2757 | pop R14; |
|---|
| | 2758 | pop R13; |
|---|
| | 2759 | pop R12; |
|---|
| | 2760 | |
|---|
| | 2761 | pop RBX; |
|---|
| | 2762 | pop RBP; |
|---|
| | 2763 | |
|---|
| | 2764 | // 'return' to complete switch |
|---|
| | 2765 | ret; |
|---|
| | 2766 | |
|---|
| | 2767 | } |
|---|
| | 2768 | else asm |
|---|
| 2674 | 2769 | { |
|---|
| 2675 | 2770 | naked; |
|---|
| r5248 |
r5652 |
|
| 11 | 11 | module tango.core.Vararg; |
|---|
| 12 | 12 | |
|---|
| | 13 | /** |
|---|
| | 14 | |
|---|
| | 15 | Gdc |
|---|
| | 16 | |
|---|
| | 17 | |
|---|
| | 18 | **/ |
|---|
| | 19 | |
|---|
| 13 | 20 | |
|---|
| 14 | 21 | version( GNU ) |
|---|
| 15 | 22 | { |
|---|
| | 23 | // GDC doesn't need va_start/va_end |
|---|
| | 24 | // If the va_arg template version is used, |
|---|
| | 25 | |
|---|
| 16 | 26 | public import std.stdarg; |
|---|
| | 27 | |
|---|
| | 28 | version( X86_64 ) |
|---|
| | 29 | { |
|---|
| | 30 | alias va_list __va_argsave_t; |
|---|
| | 31 | //__va_argsave_t __va_argsave; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| | 34 | // va_start and va_end is not needed for gdc, stubs only exist for eased |
|---|
| | 35 | // cross-compiler programming |
|---|
| | 36 | void va_start(T)( va_list ap, T parmn) { } |
|---|
| | 37 | void va_end(va_list ap) { } |
|---|
| 17 | 38 | } |
|---|
| 18 | 39 | else version( LDC ) |
|---|
| … | … | |
| 22 | 43 | else |
|---|
| 23 | 44 | { |
|---|
| 24 | | /** |
|---|
| 25 | | * The base vararg list type. |
|---|
| 26 | | */ |
|---|
| 27 | | alias void* va_list; |
|---|
| | 45 | version (DigitalMars) version (X86_64) version = DigitalMarsX64; |
|---|
| | 46 | version (X86) |
|---|
| | 47 | { |
|---|
| | 48 | alias void* va_list; |
|---|
| 28 | 49 | |
|---|
| 29 | | |
|---|
| 30 | | /** |
|---|
| 31 | | * This function initializes the supplied argument pointer for subsequent |
|---|
| 32 | | * use by va_arg and va_end. |
|---|
| 33 | | * |
|---|
| 34 | | * Params: |
|---|
| 35 | | * ap = The argument pointer to initialize. |
|---|
| 36 | | * paramn = The identifier of the rightmost parameter in the function |
|---|
| 37 | | * parameter list. |
|---|
| 38 | | */ |
|---|
| 39 | | void va_start(T) ( out va_list ap, ref T parmn ) |
|---|
| | 50 | template va_arg(T) |
|---|
| | 51 | { |
|---|
| | 52 | T va_arg(ref va_list _argptr) |
|---|
| | 53 | { |
|---|
| | 54 | T arg = *cast(T*)_argptr; |
|---|
| | 55 | _argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1)); |
|---|
| | 56 | return arg; |
|---|
| | 57 | } |
|---|
| | 58 | } |
|---|
| | 59 | } |
|---|
| | 60 | else |
|---|
| 40 | 61 | { |
|---|
| 41 | | ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); |
|---|
| 42 | | } |
|---|
| 43 | | |
|---|
| 44 | | /** |
|---|
| 45 | | * This function returns the next argument in the sequence referenced by |
|---|
| 46 | | * the supplied argument pointer. The argument pointer will be adjusted |
|---|
| 47 | | * to point to the next arggument in the sequence. |
|---|
| 48 | | * |
|---|
| 49 | | * Params: |
|---|
| 50 | | * ap = The argument pointer. |
|---|
| 51 | | * |
|---|
| 52 | | * Returns: |
|---|
| 53 | | * The next argument in the sequence. The result is undefined if ap |
|---|
| 54 | | * does not point to a valid argument. |
|---|
| 55 | | */ |
|---|
| 56 | | T va_arg(T) ( ref va_list ap ) |
|---|
| 57 | | { |
|---|
| 58 | | T arg = *cast(T*) ap; |
|---|
| 59 | | ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); |
|---|
| 60 | | return arg; |
|---|
| 61 | | } |
|---|
| 62 | | |
|---|
| 63 | | /** |
|---|
| 64 | | * This function cleans up any resources allocated by va_start. It is |
|---|
| 65 | | * currently a no-op and exists mostly for syntax compatibility with |
|---|
| 66 | | * the variadric argument functions for C. |
|---|
| 67 | | * |
|---|
| 68 | | * Params: |
|---|
| 69 | | * ap = The argument pointer. |
|---|
| 70 | | */ |
|---|
| 71 | | void va_end( va_list ap ) |
|---|
| 72 | | { |
|---|
| 73 | | |
|---|
| 74 | | } |
|---|
| 75 | | |
|---|
| 76 | | |
|---|
| 77 | | /** |
|---|
| 78 | | * This function copied the argument pointer src to dst. |
|---|
| 79 | | * |
|---|
| 80 | | * Params: |
|---|
| 81 | | * src = The source pointer. |
|---|
| 82 | | * dst = The destination pointer. |
|---|
| 83 | | */ |
|---|
| 84 | | void va_copy( out va_list dst, va_list src ) |
|---|
| 85 | | { |
|---|
| 86 | | dst = src; |
|---|
| | 62 | public import tango.stdc.stdarg; |
|---|
| 87 | 63 | } |
|---|
| 88 | 64 | } |
|---|
| r5231 |
r5652 |
|
| 9 | 9 | |
|---|
| 10 | 10 | private import tango.core.Memory : GC; |
|---|
| 11 | | private import tango.core.Vararg : va_list; |
|---|
| | 11 | private import tango.core.Vararg; |
|---|
| 12 | 12 | private import tango.core.Traits; |
|---|
| 13 | 13 | private import tango.core.Tuple; |
|---|
| … | … | |
| 38 | 38 | } |
|---|
| 39 | 39 | } |
|---|
| | 40 | version( X86_64 ) |
|---|
| | 41 | { |
|---|
| | 42 | version( Windows ) |
|---|
| | 43 | { |
|---|
| | 44 | version=EnableVararg; |
|---|
| | 45 | } |
|---|
| | 46 | else version( Posix ) |
|---|
| | 47 | { |
|---|
| | 48 | version=EnableVararg; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | version = DigitalMarsX64; |
|---|
| | 52 | |
|---|
| | 53 | import tango.math.Math : max; |
|---|
| | 54 | |
|---|
| | 55 | } |
|---|
| 40 | 56 | } |
|---|
| 41 | 57 | else version( LDC ) |
|---|
| … | … | |
| 54 | 70 | version=EnableVararg; // thanks mwarning |
|---|
| 55 | 71 | } |
|---|
| | 72 | |
|---|
| | 73 | import tango.math.Math : max; |
|---|
| 56 | 74 | } |
|---|
| 57 | 75 | } |
|---|
| … | … | |
| 338 | 356 | * Returns: |
|---|
| 339 | 357 | * The new Variant. |
|---|
| 340 | | * |
|---|
| | 358 | * |
|---|
| 341 | 359 | * Example: |
|---|
| 342 | 360 | * ----- |
|---|
| … | … | |
| 367 | 385 | * Returns: |
|---|
| 368 | 386 | * The new Variant. |
|---|
| 369 | | * |
|---|
| | 387 | * |
|---|
| 370 | 388 | * Example: |
|---|
| 371 | 389 | * ----- |
|---|
| … | … | |
| 390 | 408 | * Returns: |
|---|
| 391 | 409 | * The new value of the assigned-to variant. |
|---|
| 392 | | * |
|---|
| | 410 | * |
|---|
| 393 | 411 | * Example: |
|---|
| 394 | 412 | * ----- |
|---|
| … | … | |
| 447 | 465 | * Returns: |
|---|
| 448 | 466 | * true if the Variant contains a value of type T, false otherwise. |
|---|
| 449 | | * |
|---|
| | 467 | * |
|---|
| 450 | 468 | * Example: |
|---|
| 451 | 469 | * ----- |
|---|
| … | … | |
| 469 | 487 | * contains a value that can be implicitly cast to type T; false |
|---|
| 470 | 488 | * otherwise. |
|---|
| 471 | | * |
|---|
| | 489 | * |
|---|
| 472 | 490 | * Example: |
|---|
| 473 | 491 | * ----- |
|---|
| … | … | |
| 740 | 758 | return value.heap.ptr; |
|---|
| 741 | 759 | } |
|---|
| 742 | | |
|---|
| | 760 | |
|---|
| 743 | 761 | version( EnableVararg ) |
|---|
| 744 | 762 | { |
|---|
| … | … | |
| 751 | 769 | |
|---|
| 752 | 770 | foreach( i, ref v ; vs ) |
|---|
| 753 | | args = Variant.fromPtr(types[i], args, v); |
|---|
| 754 | | |
|---|
| | 771 | { |
|---|
| | 772 | version(DigitalMars) version(X86_64) |
|---|
| | 773 | { |
|---|
| | 774 | scope void[] buffer; |
|---|
| | 775 | uint len = 0; |
|---|
| | 776 | |
|---|
| | 777 | foreach(argType; types) |
|---|
| | 778 | len = max(len,(argType.tsize + size_t.sizeof - 1) & ~ (size_t.sizeof - 1)); |
|---|
| | 779 | |
|---|
| | 780 | buffer.length = len; |
|---|
| | 781 | |
|---|
| | 782 | va_arg(args, types[i], buffer.ptr); |
|---|
| | 783 | |
|---|
| | 784 | Variant.fromPtr(types[i], buffer.ptr, v); |
|---|
| | 785 | } |
|---|
| | 786 | else |
|---|
| | 787 | args = Variant.fromPtr(types[i], args, v); |
|---|
| | 788 | } |
|---|
| | 789 | |
|---|
| 755 | 790 | return vs; |
|---|
| 756 | 791 | } |
|---|
| 757 | | |
|---|
| | 792 | |
|---|
| 758 | 793 | /// ditto |
|---|
| 759 | 794 | static Variant[] fromVararg(...) |
|---|
| 760 | 795 | { |
|---|
| 761 | | return Variant.fromVararg(_arguments, _argptr); |
|---|
| 762 | | } |
|---|
| 763 | | |
|---|
| | 796 | version(DigitalMarsX64) |
|---|
| | 797 | { |
|---|
| | 798 | va_list ap; |
|---|
| | 799 | va_start(ap, __va_argsave); |
|---|
| | 800 | |
|---|
| | 801 | scope (exit) va_end(ap); |
|---|
| | 802 | |
|---|
| | 803 | return Variant.fromVararg(_arguments, ap); |
|---|
| | 804 | } |
|---|
| | 805 | else |
|---|
| | 806 | return Variant.fromVararg(_arguments, _argptr); |
|---|
| | 807 | } |
|---|
| | 808 | |
|---|
| 764 | 809 | /** |
|---|
| 765 | 810 | * Converts an array of Variants into a vararg function argument list. |
|---|
| … | … | |
| 768 | 813 | * this memory when you are done with it if you feel so inclined. |
|---|
| 769 | 814 | */ |
|---|
| 770 | | static void toVararg(Variant[] vars, out TypeInfo[] types, out va_list args) |
|---|
| | 815 | deprecated static void toVararg(Variant[] vars, out TypeInfo[] types, out va_list args) |
|---|
| 771 | 816 | { |
|---|
| 772 | 817 | // First up, compute the total amount of space we'll need. While |
|---|
| … | … | |
| 781 | 826 | noptr = noptr && (ti.flags & 2); |
|---|
| 782 | 827 | } |
|---|
| 783 | | |
|---|
| | 828 | |
|---|
| 784 | 829 | // Create the storage, and tell the GC whether it needs to be scanned |
|---|
| 785 | 830 | // or not. |
|---|
| … | … | |
| 811 | 856 | return (_type = v); |
|---|
| 812 | 857 | } |
|---|
| 813 | | |
|---|
| | 858 | |
|---|
| 814 | 859 | /* |
|---|
| 815 | 860 | * Creates a Variant using a given TypeInfo and a void*. Returns the |
|---|
| … | … | |
| 862 | 907 | { |
|---|
| 863 | 908 | // Copy into storage |
|---|
| 864 | | r.value.data[0 .. type.tsize] = |
|---|
| | 909 | r.value.data[0 .. type.tsize] = |
|---|
| 865 | 910 | (cast(ubyte*)ptr)[0 .. type.tsize]; |
|---|
| 866 | 911 | } |
|---|
| … | … | |
| 1240 | 1285 | Variant[] scoop(...) |
|---|
| 1241 | 1286 | { |
|---|
| | 1287 | version(DigitalMarsX64) |
|---|
| | 1288 | { |
|---|
| | 1289 | va_list ap; |
|---|
| | 1290 | va_start(ap, __va_argsave); |
|---|
| | 1291 | |
|---|
| | 1292 | scope (exit) va_end(ap); |
|---|
| | 1293 | |
|---|
| | 1294 | return Variant.fromVararg(_arguments, ap); |
|---|
| | 1295 | } |
|---|
| | 1296 | |
|---|
| 1242 | 1297 | return Variant.fromVararg(_arguments, _argptr); |
|---|
| 1243 | 1298 | } |
|---|
| … | … | |
| 1256 | 1311 | C va_b = new D; |
|---|
| 1257 | 1312 | D va_c = new D; |
|---|
| 1258 | | |
|---|
| | 1313 | |
|---|
| 1259 | 1314 | auto vs = scoop(va_0, va_1, va_2, va_3, |
|---|
| 1260 | 1315 | va_4, va_5, va_6, va_7, |
|---|
| … | … | |
| 1278 | 1333 | assert( vs[0xa].get!(typeof(va_a)).msg == "B" ); |
|---|
| 1279 | 1334 | assert( vs[0xc].get!(typeof(va_c)).msg == "D" ); |
|---|
| 1280 | | |
|---|
| | 1335 | |
|---|
| 1281 | 1336 | assert( vs[0xb].get!(typeof(va_b)).name == "phil" ); |
|---|
| 1282 | 1337 | assert( vs[0xc].get!(typeof(va_c)).name == "phil" ); |
|---|
| 1283 | 1338 | |
|---|
| | 1339 | version (none) version(X86) // TODO toVararg won't work in x86_64 as it is now |
|---|
| 1284 | 1340 | { |
|---|
| 1285 | 1341 | TypeInfo[] types; |
|---|
| r5609 |
r5652 |
|
| 49 | 49 | debug(PRINTF) import tango.stdc.stdio: printf; |
|---|
| 50 | 50 | extern (C) Object _d_newclass(ClassInfo ci); |
|---|
| 51 | | |
|---|
| | 51 | |
|---|
| 52 | 52 | version (darwin) |
|---|
| 53 | 53 | import rt.compiler.dmd.darwin.Image; |
|---|
| … | … | |
| 74 | 74 | alias int equals_t; |
|---|
| 75 | 75 | |
|---|
| 76 | | version (PhobosCompatibility) |
|---|
| 77 | | { |
|---|
| | 76 | version (PhobosCompatibility) |
|---|
| | 77 | { |
|---|
| 78 | 78 | alias char[] string; |
|---|
| 79 | 79 | alias wchar[] wstring; |
|---|
| … | … | |
| 87 | 87 | { |
|---|
| 88 | 88 | /** |
|---|
| 89 | | * Override this to capture an explicit delete or an implicit |
|---|
| | 89 | * Override this to capture an explicit delete or an implicit |
|---|
| 90 | 90 | * delete via a scoped-instance. Unlike a dtor(), GC references |
|---|
| 91 | 91 | * are still intact when this method is invoked |
|---|
| … | … | |
| 332 | 332 | foreach (m; ModuleInfo) |
|---|
| 333 | 333 | { |
|---|
| | 334 | if (!m) |
|---|
| | 335 | continue; |
|---|
| | 336 | |
|---|
| 334 | 337 | //writefln("module %s, %d", m.name, m.localClasses.length); |
|---|
| 335 | 338 | foreach (c; m.localClasses) |
|---|
| … | … | |
| 417 | 420 | /// Compares two instances for <, ==, or >. |
|---|
| 418 | 421 | int compare(in void* p1, in void* p2) { return 0; } // throw new Exception("non comparable",__FILE__,__LINE__); |
|---|
| 419 | | |
|---|
| | 422 | /// Return alignment of type |
|---|
| | 423 | size_t talign() { return tsize(); } |
|---|
| 420 | 424 | /// Returns size of the type. |
|---|
| 421 | 425 | size_t tsize() { return 0; } |
|---|
| … | … | |
| 474 | 478 | /// Get type information on the contents of the type; null if not available |
|---|
| 475 | 479 | OffsetTypeInfo[] offTi() { return null; } |
|---|
| | 480 | |
|---|
| | 481 | |
|---|
| | 482 | /** Return internal info on arguments fitting into 8byte. |
|---|
| | 483 | * See X86-64 ABI 3.2.3 |
|---|
| | 484 | */ |
|---|
| | 485 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 486 | { |
|---|
| | 487 | arg1 = this; |
|---|
| | 488 | return 0; |
|---|
| | 489 | } |
|---|
| 476 | 490 | } |
|---|
| 477 | 491 | |
|---|
| … | … | |
| 499 | 513 | override PointerMap pointermap() { return base.pointermap(); } |
|---|
| 500 | 514 | override void[] init() { return m_init.length ? m_init : base.init(); } |
|---|
| | 515 | |
|---|
| | 516 | size_t talign() { return base.talign(); } |
|---|
| | 517 | |
|---|
| | 518 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 519 | { |
|---|
| | 520 | return base.argTypes(arg1, arg2); |
|---|
| | 521 | } |
|---|
| 501 | 522 | |
|---|
| 502 | 523 | TypeInfo base; |
|---|
| … | … | |
| 636 | 657 | |
|---|
| 637 | 658 | override uint flags() { return 1; } |
|---|
| | 659 | |
|---|
| | 660 | size_t talign() |
|---|
| | 661 | { |
|---|
| | 662 | return (void[]).alignof; |
|---|
| | 663 | } |
|---|
| | 664 | |
|---|
| | 665 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 666 | { //arg1 = typeid(size_t); |
|---|
| | 667 | //arg2 = typeid(void*); |
|---|
| | 668 | return 0; |
|---|
| | 669 | } |
|---|
| 638 | 670 | |
|---|
| 639 | 671 | override PointerMap pointermap() |
|---|
| … | … | |
| 751 | 783 | TypeInfo value; |
|---|
| 752 | 784 | size_t len; |
|---|
| | 785 | |
|---|
| | 786 | size_t talign() |
|---|
| | 787 | { |
|---|
| | 788 | return value.talign(); |
|---|
| | 789 | } |
|---|
| | 790 | |
|---|
| | 791 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 792 | { |
|---|
| | 793 | arg1 = typeid(void*); |
|---|
| | 794 | return 0; |
|---|
| | 795 | } |
|---|
| | 796 | |
|---|
| 753 | 797 | } |
|---|
| 754 | 798 | |
|---|
| … | … | |
| 819 | 863 | TypeInfo value; |
|---|
| 820 | 864 | TypeInfo key; |
|---|
| | 865 | |
|---|
| | 866 | size_t talign() |
|---|
| | 867 | { |
|---|
| | 868 | return (char[int]).alignof; |
|---|
| | 869 | } |
|---|
| | 870 | |
|---|
| | 871 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 872 | { |
|---|
| | 873 | arg1 = typeid(void*); |
|---|
| | 874 | return 0; |
|---|
| | 875 | } |
|---|
| 821 | 876 | } |
|---|
| 822 | 877 | |
|---|
| … | … | |
| 903 | 958 | |
|---|
| 904 | 959 | TypeInfo next; |
|---|
| | 960 | |
|---|
| | 961 | size_t talign() |
|---|
| | 962 | { |
|---|
| | 963 | alias int delegate() dg; |
|---|
| | 964 | return dg.alignof; |
|---|
| | 965 | } |
|---|
| | 966 | |
|---|
| | 967 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 968 | { //arg1 = typeid(void*); |
|---|
| | 969 | //arg2 = typeid(void*); |
|---|
| | 970 | return 0; |
|---|
| | 971 | } |
|---|
| | 972 | |
|---|
| 905 | 973 | } |
|---|
| 906 | 974 | |
|---|
| … | … | |
| 1115 | 1183 | override uint flags() { return m_flags; } |
|---|
| 1116 | 1184 | |
|---|
| | 1185 | size_t talign() { return m_align; } |
|---|
| | 1186 | |
|---|
| | 1187 | |
|---|
| 1117 | 1188 | char[] name; |
|---|
| 1118 | 1189 | void[] m_init; // initializer; init.ptr == null if 0 initialize |
|---|
| … | … | |
| 1125 | 1196 | |
|---|
| 1126 | 1197 | uint m_flags; |
|---|
| | 1198 | uint m_align; |
|---|
| 1127 | 1199 | |
|---|
| 1128 | 1200 | version (D_HavePointerMap) { |
|---|
| … | … | |
| 1130 | 1202 | |
|---|
| 1131 | 1203 | override PointerMap pointermap() { return m_pointermap; } |
|---|
| | 1204 | } |
|---|
| | 1205 | |
|---|
| | 1206 | version (X86_64) |
|---|
| | 1207 | { |
|---|
| | 1208 | int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 1209 | { |
|---|
| | 1210 | arg1 = m_arg1; |
|---|
| | 1211 | arg2 = m_arg2; |
|---|
| | 1212 | return 0; |
|---|
| | 1213 | } |
|---|
| | 1214 | TypeInfo m_arg1; |
|---|
| | 1215 | TypeInfo m_arg2; |
|---|
| 1132 | 1216 | } |
|---|
| 1133 | 1217 | } |
|---|
| … | … | |
| 1195 | 1279 | |
|---|
| 1196 | 1280 | override PointerMap pointermap() |
|---|
| | 1281 | { |
|---|
| | 1282 | assert(0); |
|---|
| | 1283 | } |
|---|
| | 1284 | |
|---|
| | 1285 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| 1197 | 1286 | { |
|---|
| 1198 | 1287 | assert(0); |
|---|
| … | … | |
| 1253 | 1342 | } |
|---|
| 1254 | 1343 | } |
|---|
| 1255 | | |
|---|
| | 1344 | |
|---|
| 1256 | 1345 | void clear(){ |
|---|
| 1257 | 1346 | line=0; |
|---|
| … | … | |
| 1441 | 1530 | version( freebsd ) |
|---|
| 1442 | 1531 | { |
|---|
| 1443 | | // This linked list is created by a compiler generated function inserted |
|---|
| 1444 | | // into the .ctor list by the compiler. |
|---|
| | 1532 | // This linked list is created by a compiler generated function inserted |
|---|
| | 1533 | // into the .ctor list by the compiler. |
|---|
| 1445 | 1534 | struct ModuleReference |
|---|
| 1446 | | { |
|---|
| 1447 | | ModuleReference* next; |
|---|
| 1448 | | ModuleInfo mod; |
|---|
| | 1535 | { |
|---|
| | 1536 | ModuleReference* next; |
|---|
| | 1537 | ModuleInfo mod; |
|---|
| 1449 | 1538 | } |
|---|
| 1450 | | extern (C) ModuleReference *_Dmodule_ref; // start of linked list |
|---|
| | 1539 | extern (C) ModuleReference *_Dmodule_ref; // start of linked list |
|---|
| 1451 | 1540 | } |
|---|
| 1452 | 1541 | |
|---|
| … | … | |
| 1477 | 1566 | len++; |
|---|
| 1478 | 1567 | } |
|---|
| | 1568 | |
|---|
| | 1569 | debug(PRINTF) foreach (m; _moduleinfo_array) |
|---|
| | 1570 | { |
|---|
| | 1571 | //printf("\t%p\n", m); |
|---|
| | 1572 | printf("\t%.*s\n", m.name.length,m.name.ptr); |
|---|
| | 1573 | } |
|---|
| | 1574 | |
|---|
| 1479 | 1575 | } |
|---|
| 1480 | 1576 | |
|---|
| … | … | |
| 1502 | 1598 | * are of zero size and are in the two bracketing segments, |
|---|
| 1503 | 1599 | * respectively. |
|---|
| 1504 | | * |
|---|
| | 1600 | * |
|---|
| 1505 | 1601 | * The __minfo_beg and __minfo_end sections are not put into |
|---|
| 1506 | 1602 | * dynamic libraries therefore we cannot use them or the |
|---|
| … | … | |
| 1509 | 1605 | * collect all the ModuleInfo references. |
|---|
| 1510 | 1606 | */ |
|---|
| 1511 | | _moduleinfo_array = getSectionData!(ModuleInfo, "__DATA", "__minfodata"); |
|---|
| | 1607 | _moduleinfo_array = getSectionData!(ModuleInfo, "__DATA", "__minfodata"); |
|---|
| 1512 | 1608 | debug(PRINTF) printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length); |
|---|
| 1513 | 1609 | |
|---|
| … | … | |
| 1518 | 1614 | } |
|---|
| 1519 | 1615 | } |
|---|
| 1520 | | |
|---|
| | 1616 | |
|---|
| 1521 | 1617 | version (Win32) |
|---|
| 1522 | 1618 | { |
|---|
| … | … | |
| 1543 | 1639 | } |
|---|
| 1544 | 1640 | |
|---|
| 1545 | | void _moduleCtor2(ModuleInfo from,ModuleInfo[] mi, int skip) |
|---|
| | 1641 | void _moduleCtor2(ModuleInfo from, ModuleInfo[] mi, int skip) |
|---|
| 1546 | 1642 | { |
|---|
| 1547 | 1643 | debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length); |
|---|
| … | … | |
| 1553 | 1649 | if (!m) |
|---|
| 1554 | 1650 | continue; |
|---|
| 1555 | | debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); |
|---|
| | 1651 | debug(PRINTF) printf("\tmodule[%d].name = '%s'\n", i, m.name); |
|---|
| 1556 | 1652 | if (m.flags & MIctordone) |
|---|
| 1557 | 1653 | continue; |
|---|
| … | … | |
| 1563 | 1659 | { if (skip || m.flags & MIstandalone) |
|---|
| 1564 | 1660 | continue; |
|---|
| 1565 | | throw new Exception( "Cyclic dependency in module " ~ (from is null ? "*null*" : from.name) ~ " for import " ~ m.name); |
|---|
| | 1661 | throw new Exception( "Cyclic dependency in module " ~ (from is null ? "*null*" : from.name) ~ " for import " ~ m.name); |
|---|
| 1566 | 1662 | } |
|---|
| 1567 | 1663 | |
|---|
| r5589 |
r5652 |
|
| 36 | 36 | { |
|---|
| 37 | 37 | version (darwin) {} |
|---|
| 38 | | |
|---|
| | 38 | |
|---|
| 39 | 39 | else |
|---|
| 40 | 40 | { |
|---|
| … | … | |
| 65 | 65 | uint espoffset; // offset of ESP from EBP |
|---|
| 66 | 66 | uint retoffset; // offset from start of function to return code |
|---|
| 67 | | uint nhandlers; // dimension of handler_info[] |
|---|
| | 67 | size_t nhandlers; // dimension of handler_info[] |
|---|
| 68 | 68 | DHandlerInfo handler_info[1]; |
|---|
| 69 | 69 | } |
|---|
| … | … | |
| 72 | 72 | { |
|---|
| 73 | 73 | ClassInfo type; // catch type |
|---|
| 74 | | uint bpoffset; // EBP offset of catch var |
|---|
| | 74 | size_t bpoffset; // EBP offset of catch var |
|---|
| 75 | 75 | void *code; // catch handler code |
|---|
| 76 | 76 | } |
|---|
| … | … | |
| 79 | 79 | struct DCatchInfo |
|---|
| 80 | 80 | { |
|---|
| 81 | | uint ncatches; // number of catch blocks |
|---|
| | 81 | size_t ncatches; // number of catch blocks |
|---|
| 82 | 82 | DCatchBlock catch_block[1]; // data for each catch block |
|---|
| 83 | 83 | } |
|---|
| … | … | |
| 112 | 112 | static FuncTable[] functionTables; |
|---|
| 113 | 113 | static bool hasFunctionTables; |
|---|
| 114 | | |
|---|
| | 114 | |
|---|
| 115 | 115 | if (!hasFunctionTables) |
|---|
| 116 | 116 | { |
|---|
| … | … | |
| 118 | 118 | hasFunctionTables = true; |
|---|
| 119 | 119 | } |
|---|
| 120 | | |
|---|
| | 120 | |
|---|
| 121 | 121 | foreach (ft ; functionTables) |
|---|
| 122 | 122 | { |
|---|
| … | … | |
| 124 | 124 | return ft.handlertable; |
|---|
| 125 | 125 | } |
|---|
| 126 | | |
|---|
| | 126 | |
|---|
| 127 | 127 | return null; |
|---|
| 128 | 128 | } |
|---|
| 129 | | |
|---|
| 130 | 129 | else |
|---|
| 131 | 130 | { |
|---|
| … | … | |
| 165 | 164 | */ |
|---|
| 166 | 165 | |
|---|
| 167 | | uint __eh_find_caller(uint regbp, uint *pretaddr) |
|---|
| 168 | | { |
|---|
| 169 | | uint bp = *cast(uint *)regbp; |
|---|
| | 166 | size_t __eh_find_caller(size_t regbp, size_t *pretaddr) |
|---|
| | 167 | { |
|---|
| | 168 | size_t bp = *cast(size_t *)regbp; |
|---|
| 170 | 169 | |
|---|
| 171 | 170 | if (bp) // if not end of call chain |
|---|
| … | … | |
| 177 | 176 | terminate(); |
|---|
| 178 | 177 | |
|---|
| 179 | | *pretaddr = *cast(uint *)(regbp + int.sizeof); |
|---|
| | 178 | *pretaddr = *cast(size_t *)(regbp + size_t.sizeof); |
|---|
| 180 | 179 | } |
|---|
| 181 | 180 | return bp; |
|---|
| … | … | |
| 196 | 195 | */ |
|---|
| 197 | 196 | |
|---|
| 198 | | extern(C) void _d_throwc(Object *h){ |
|---|
| 199 | | uint regebp; |
|---|
| | 197 | extern(C) void _d_throwc(Object *h) |
|---|
| | 198 | { |
|---|
| | 199 | size_t regebp; |
|---|
| 200 | 200 | |
|---|
| 201 | 201 | debug(deh) |
|---|
| … | … | |
| 205 | 205 | } |
|---|
| 206 | 206 | |
|---|
| 207 | | asm |
|---|
| 208 | | { |
|---|
| 209 | | mov regebp,EBP ; |
|---|
| 210 | | } |
|---|
| | 207 | version (D_InlineAsm_X86) |
|---|
| | 208 | asm |
|---|
| | 209 | { |
|---|
| | 210 | mov regebp,EBP ; |
|---|
| | 211 | } |
|---|
| | 212 | else version (D_InlineAsm_X86_64) |
|---|
| | 213 | asm |
|---|
| | 214 | { |
|---|
| | 215 | mov regebp,RBP ; |
|---|
| | 216 | } |
|---|
| | 217 | else |
|---|
| | 218 | static assert(0); |
|---|
| 211 | 219 | |
|---|
| 212 | 220 | //static uint abc; |
|---|
| … | … | |
| 219 | 227 | FuncTable *pfunc; |
|---|
| 220 | 228 | DHandlerInfo *phi; |
|---|
| 221 | | uint retaddr; |
|---|
| 222 | | uint funcoffset; |
|---|
| | 229 | size_t retaddr; |
|---|
| | 230 | size_t funcoffset; |
|---|
| 223 | 231 | uint spoff; |
|---|
| 224 | 232 | uint retoffset; |
|---|
| 225 | 233 | int index; |
|---|
| 226 | | int dim; |
|---|
| | 234 | size_t dim; |
|---|
| 227 | 235 | int ndx; |
|---|
| 228 | 236 | int prev_ndx; |
|---|
| … | … | |
| 245 | 253 | continue; |
|---|
| 246 | 254 | } |
|---|
| 247 | | funcoffset = cast(uint)handler_table.fptr; |
|---|
| | 255 | funcoffset = cast(size_t)handler_table.fptr; |
|---|
| 248 | 256 | spoff = handler_table.espoffset; |
|---|
| 249 | 257 | retoffset = handler_table.retoffset; |
|---|
| … | … | |
| 262 | 270 | { |
|---|
| 263 | 271 | printf("handler_info[]:\n"); |
|---|
| 264 | | for (int i = 0; i < dim; i++) |
|---|
| | 272 | for (size_t i = 0; i < dim; i++) |
|---|
| 265 | 273 | { |
|---|
| 266 | 274 | phi = handler_table.handler_info.ptr + i; |
|---|
| … | … | |
| 271 | 279 | |
|---|
| 272 | 280 | index = -1; |
|---|
| 273 | | for (int i = 0; i < dim; i++) |
|---|
| | 281 | for (size_t i = 0; i < dim; i++) |
|---|
| 274 | 282 | { |
|---|
| 275 | 283 | phi = handler_table.handler_info.ptr + i; |
|---|
| 276 | 284 | |
|---|
| 277 | 285 | debug(deh) printf("i = %d, phi.offset = %04x\n", i, funcoffset + phi.offset); |
|---|
| 278 | | if (cast(uint)retaddr > funcoffset + phi.offset && |
|---|
| 279 | | cast(uint)retaddr <= funcoffset + phi.endoffset) |
|---|
| | 286 | if (retaddr > funcoffset + phi.offset && |
|---|
| | 287 | retaddr <= funcoffset + phi.endoffset) |
|---|
| 280 | 288 | index = i; |
|---|
| 281 | 289 | } |
|---|
| … | … | |
| 288 | 296 | phi = handler_table.handler_info.ptr + ndx; |
|---|
| 289 | 297 | prev_ndx = phi.prev_index; |
|---|
| | 298 | |
|---|
| 290 | 299 | if (phi.cioffset) |
|---|
| 291 | 300 | { |
|---|
| 292 | 301 | // this is a catch handler (no finally) |
|---|
| 293 | 302 | DCatchInfo *pci; |
|---|
| 294 | | int ncatches; |
|---|
| 295 | | int i; |
|---|
| | 303 | size_t ncatches; |
|---|
| | 304 | size_t i; |
|---|
| 296 | 305 | |
|---|
| 297 | 306 | pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset); |
|---|
| 298 | 307 | ncatches = pci.ncatches; |
|---|
| | 308 | |
|---|
| 299 | 309 | for (i = 0; i < ncatches; i++) |
|---|
| 300 | 310 | { |
|---|
| … | … | |
| 312 | 322 | // Jump to catch block. Does not return. |
|---|
| 313 | 323 | { |
|---|
| 314 | | uint catch_esp; |
|---|
| | 324 | size_t catch_esp; |
|---|
| 315 | 325 | fp_t catch_addr; |
|---|
| 316 | 326 | |
|---|
| 317 | 327 | catch_addr = cast(fp_t)(pcb.code); |
|---|
| 318 | 328 | catch_esp = regebp - handler_table.espoffset - fp_t.sizeof; |
|---|
| 319 | | asm |
|---|
| 320 | | { |
|---|
| 321 | | mov EAX,catch_esp ; |
|---|
| 322 | | mov ECX,catch_addr ; |
|---|
| 323 | | mov [EAX],ECX ; |
|---|
| 324 | | mov EBP,regebp ; |
|---|
| 325 | | mov ESP,EAX ; // reset stack |
|---|
| 326 | | ret ; // jump to catch block |
|---|
| 327 | | } |
|---|
| | 329 | |
|---|
| | 330 | version (D_InlineAsm_X86) |
|---|
| | 331 | asm |
|---|
| | 332 | { |
|---|
| | 333 | mov EAX,catch_esp ; |
|---|
| | 334 | mov ECX,catch_addr ; |
|---|
| | 335 | mov [EAX],ECX ; |
|---|
| | 336 | mov EBP,regebp ; |
|---|
| | 337 | mov ESP,EAX ; // reset stack |
|---|
| | 338 | ret ; // jump to catch block |
|---|
| | 339 | } |
|---|
| | 340 | else version (D_InlineAsm_X86_64) |
|---|
| | 341 | asm |
|---|
| | 342 | { |
|---|
| | 343 | mov RAX,catch_esp ; |
|---|
| | 344 | mov RCX,catch_esp ; |
|---|
| | 345 | mov RCX,catch_addr ; |
|---|
| | 346 | mov [RAX],RCX ; |
|---|
| | 347 | mov RBP,regebp ; |
|---|
| | 348 | mov RSP,RAX ; // reset stack |
|---|
| | 349 | ret ; // jump to catch block |
|---|
| | 350 | } |
|---|
| | 351 | else |
|---|
| | 352 | static assert(0); |
|---|
| | 353 | |
|---|
| 328 | 354 | } |
|---|
| 329 | 355 | } |
|---|
| … | … | |
| 339 | 365 | version (OSX) |
|---|
| 340 | 366 | { |
|---|
| 341 | | asm { |
|---|
| 342 | | sub ESP,4 ; |
|---|
| 343 | | push EBX ; |
|---|
| 344 | | mov EBX,blockaddr ; |
|---|
| 345 | | push EBP ; |
|---|
| 346 | | mov EBP,regebp ; |
|---|
| 347 | | call EBX ; |
|---|
| 348 | | pop EBP ; |
|---|
| 349 | | pop EBX ; |
|---|
| 350 | | add ESP,4 ; |
|---|
| 351 | | } |
|---|
| 352 | | } else { |
|---|
| 353 | | asm { |
|---|
| 354 | | push EBX ; |
|---|
| 355 | | mov EBX,blockaddr ; |
|---|
| 356 | | push EBP ; |
|---|
| 357 | | mov EBP,regebp ; |
|---|
| 358 | | call EBX ; |
|---|
| 359 | | pop EBP ; |
|---|
| 360 | | pop EBX ; |
|---|
| 361 | | } |
|---|
| | 367 | version (D_InlineAsm_X86) |
|---|
| | 368 | asm |
|---|
| | 369 | { |
|---|
| | 370 | sub ESP,4 ; |
|---|
| | 371 | push EBX ; |
|---|
| | 372 | mov EBX,blockaddr ; |
|---|
| | 373 | push EBP ; |
|---|
| | 374 | mov EBP,regebp ; |
|---|
| | 375 | call EBX ; |
|---|
| | 376 | pop EBP ; |
|---|
| | 377 | pop EBX ; |
|---|
| | 378 | add ESP,4 ; |
|---|
| | 379 | } |
|---|
| | 380 | else version (D_InlineAsm_X86_64) |
|---|
| | 381 | asm |
|---|
| | 382 | { |
|---|
| | 383 | sub RSP,8 ; |
|---|
| | 384 | push RBX ; |
|---|
| | 385 | mov RBX,blockaddr ; |
|---|
| | 386 | push RBP ; |
|---|
| | 387 | mov RBP,regebp ; |
|---|
| | 388 | call RBX ; |
|---|
| | 389 | pop RBP ; |
|---|
| | 390 | pop RBX ; |
|---|
| | 391 | add RSP,8 ; |
|---|
| | 392 | } |
|---|
| | 393 | else |
|---|
| | 394 | static assert(0); |
|---|
| | 395 | } |
|---|
| | 396 | else |
|---|
| | 397 | { |
|---|
| | 398 | version (D_InlineAsm_X86) |
|---|
| | 399 | asm |
|---|
| | 400 | { |
|---|
| | 401 | push EBX ; |
|---|
| | 402 | mov EBX,blockaddr ; |
|---|
| | 403 | push EBP ; |
|---|
| | 404 | mov EBP,regebp ; |
|---|
| | 405 | call EBX ; |
|---|
| | 406 | pop EBP ; |
|---|
| | 407 | pop EBX ; |
|---|
| | 408 | } |
|---|
| | 409 | else version (D_InlineAsm_X86_64) |
|---|
| | 410 | asm |
|---|
| | 411 | { |
|---|
| | 412 | sub RSP,8 ; |
|---|
| | 413 | push RBX ; |
|---|
| | 414 | mov RBX,blockaddr ; |
|---|
| | 415 | push RBP ; |
|---|
| | 416 | mov RBP,regebp ; |
|---|
| | 417 | call RBX ; |
|---|
| | 418 | pop RBP ; |
|---|
| | 419 | pop RBX ; |
|---|
| | 420 | add RSP,8 ; |
|---|
| | 421 | } |
|---|
| | 422 | else |
|---|
| | 423 | static assert(0); |
|---|
| 362 | 424 | } |
|---|
| 363 | 425 | } |
|---|
| r5192 |
r5652 |
|
| 20 | 20 | */ |
|---|
| 21 | 21 | |
|---|
| | 22 | |
|---|
| 22 | 23 | void __ULDIV__() |
|---|
| 23 | 24 | { |
|---|
| | 25 | version (D_InlineAsm_X86) |
|---|
| 24 | 26 | asm |
|---|
| 25 | 27 | { |
|---|
| … | … | |
| 179 | 181 | ret ; |
|---|
| 180 | 182 | } |
|---|
| | 183 | else version (D_InlineAsm_X86_64) |
|---|
| | 184 | assert(0); |
|---|
| | 185 | else |
|---|
| | 186 | static assert(0); |
|---|
| 181 | 187 | } |
|---|
| 182 | 188 | |
|---|
| … | … | |
| 194 | 200 | void __LDIV__() |
|---|
| 195 | 201 | { |
|---|
| | 202 | version (D_InlineAsm_X86) |
|---|
| 196 | 203 | asm |
|---|
| 197 | 204 | { |
|---|
| … | … | |
| 242 | 249 | L12: jmp __ULDIV__ ; |
|---|
| 243 | 250 | } |
|---|
| 244 | | } |
|---|
| 245 | | |
|---|
| | 251 | else version (D_InlineAsm_X86_64) |
|---|
| | 252 | assert(0); |
|---|
| | 253 | else |
|---|
| | 254 | static assert(0); |
|---|
| | 255 | } |
|---|
| 246 | 256 | |
|---|
| 247 | 257 | /*************************************** |
|---|
| … | … | |
| 253 | 263 | void __LCMP__() |
|---|
| 254 | 264 | { |
|---|
| | 265 | version (D_InlineAsm_X86) |
|---|
| 255 | 266 | asm |
|---|
| 256 | 267 | { |
|---|
| … | … | |
| 271 | 282 | C1: ret ; |
|---|
| 272 | 283 | } |
|---|
| 273 | | } |
|---|
| 274 | | |
|---|
| 275 | | |
|---|
| 276 | | |
|---|
| | 284 | else version (D_InlineAsm_X86_64) |
|---|
| | 285 | assert(0); |
|---|
| | 286 | else |
|---|
| | 287 | static assert(0); |
|---|
| | 288 | } |
|---|
| 277 | 289 | |
|---|
| 278 | 290 | // Convert ulong to real |
|---|
| … | … | |
| 282 | 294 | real __U64_LDBL() |
|---|
| 283 | 295 | { |
|---|
| 284 | | version (OSX) { |
|---|
| 285 | | asm |
|---|
| 286 | | { naked ; |
|---|
| 287 | | push EDX ; |
|---|
| 288 | | push EAX ; |
|---|
| 289 | | and dword ptr 4[ESP], 0x7FFFFFFF ; |
|---|
| 290 | | fild qword ptr [ESP] ; |
|---|
| 291 | | test EDX,EDX ; |
|---|
| 292 | | jns L1 ; |
|---|
| 293 | | push 0x0000403e ; |
|---|
| 294 | | push 0x80000000 ; |
|---|
| 295 | | push 0 ; |
|---|
| 296 | | fld real ptr [ESP] ; // adjust |
|---|
| 297 | | add ESP,12 ; |
|---|
| 298 | | faddp ST(1), ST ; |
|---|
| 299 | | L1: ; |
|---|
| 300 | | add ESP, 8 ; |
|---|
| 301 | | ret ; |
|---|
| 302 | | } |
|---|
| 303 | | } else { |
|---|
| 304 | | asm |
|---|
| 305 | | { naked ; |
|---|
| 306 | | push EDX ; |
|---|
| 307 | | push EAX ; |
|---|
| 308 | | and dword ptr 4[ESP], 0x7FFFFFFF ; |
|---|
| 309 | | fild qword ptr [ESP] ; |
|---|
| 310 | | test EDX,EDX ; |
|---|
| 311 | | jns L1 ; |
|---|
| 312 | | fld real ptr adjust ; |
|---|
| 313 | | faddp ST(1), ST ; |
|---|
| 314 | | L1: ; |
|---|
| 315 | | add ESP, 8 ; |
|---|
| 316 | | ret ; |
|---|
| 317 | | } |
|---|
| | 296 | version (OSX) |
|---|
| | 297 | { |
|---|
| | 298 | version (D_InlineAsm_X86) |
|---|
| | 299 | asm |
|---|
| | 300 | { naked ; |
|---|
| | 301 | push EDX ; |
|---|
| | 302 | push EAX ; |
|---|
| | 303 | and dword ptr 4[ESP], 0x7FFFFFFF ; |
|---|
| | 304 | fild qword ptr [ESP] ; |
|---|
| | 305 | test EDX,EDX ; |
|---|
| | 306 | jns L1 ; |
|---|
| | 307 | push 0x0000403e ; |
|---|
| | 308 | push 0x80000000 ; |
|---|
| | 309 | push 0 ; |
|---|
| | 310 | fld real ptr [ESP] ; // adjust |
|---|
| | 311 | add ESP,12 ; |
|---|
| | 312 | faddp ST(1), ST ; |
|---|
| | 313 | L1: ; |
|---|
| | 314 | add ESP, 8 ; |
|---|
| | 315 | ret ; |
|---|
| | 316 | } |
|---|
| | 317 | else version (D_InlineAsm_X86_64) |
|---|
| | 318 | static assert(0); |
|---|
| | 319 | else |
|---|
| | 320 | static assert(0); |
|---|
| | 321 | } |
|---|
| | 322 | else |
|---|
| | 323 | { |
|---|
| | 324 | version (D_InlineAsm_X86) |
|---|
| | 325 | asm |
|---|
| | 326 | { naked ; |
|---|
| | 327 | push EDX ; |
|---|
| | 328 | push EAX ; |
|---|
| | 329 | and dword ptr 4[ESP], 0x7FFFFFFF ; |
|---|
| | 330 | fild qword ptr [ESP] ; |
|---|
| | 331 | test EDX,EDX ; |
|---|
| | 332 | jns L1 ; |
|---|
| | 333 | fld real ptr adjust ; |
|---|
| | 334 | faddp ST(1), ST ; |
|---|
| | 335 | L1: ; |
|---|
| | 336 | add ESP, 8 ; |
|---|
| | 337 | ret ; |
|---|
| | 338 | } |
|---|
| | 339 | else version (D_InlineAsm_X86_64) |
|---|
| | 340 | asm |
|---|
| | 341 | { naked ; |
|---|
| | 342 | push RAX ; |
|---|
| | 343 | and dword ptr 4[RSP], 0x7FFFFFFF ; |
|---|
| | 344 | fild qword ptr [RSP] ; |
|---|
| | 345 | test RAX,RAX ; |
|---|
| | 346 | jns L1 ; |
|---|
| | 347 | fld real ptr adjust ; |
|---|
| | 348 | faddp ST(1), ST ; |
|---|
| | 349 | L1: ; |
|---|
| | 350 | add RSP, 8 ; |
|---|
| | 351 | ret ; |
|---|
| | 352 | } |
|---|
| | 353 | else |
|---|
| | 354 | static assert(0); |
|---|
| 318 | 355 | } |
|---|
| 319 | 356 | } |
|---|
| … | … | |
| 322 | 359 | ulong __ULLNGDBL() |
|---|
| 323 | 360 | { |
|---|
| | 361 | version (D_InlineAsm_X86) |
|---|
| 324 | 362 | asm |
|---|
| 325 | 363 | { naked ; |
|---|
| … | … | |
| 331 | 369 | ret ; |
|---|
| 332 | 370 | } |
|---|
| 333 | | } |
|---|
| | 371 | else version (D_InlineAsm_X86_64) |
|---|
| | 372 | asm |
|---|
| | 373 | { naked ; |
|---|
| | 374 | call __U64_LDBL ; |
|---|
| | 375 | sub RSP,8 ; |
|---|
| | 376 | fstp double ptr [RSP] ; |
|---|
| | 377 | pop RAX ; |
|---|
| | 378 | ret ; |
|---|
| | 379 | } |
|---|
| | 380 | else |
|---|
| | 381 | static assert(0); |
|---|
| | 382 | } |
|---|
| | 383 | |
|---|
| 334 | 384 | |
|---|
| 335 | 385 | // Convert double to ulong |
|---|
| … | … | |
| 340 | 390 | { |
|---|
| 341 | 391 | // BUG: should handle NAN's and overflows |
|---|
| 342 | | version (OSX) { |
|---|
| 343 | | asm { |
|---|
| 344 | | naked ; |
|---|
| 345 | | push 0xFBF ; // roundTo0 |
|---|
| 346 | | push 0x0000403e ; |
|---|
| 347 | | push 0x80000000 ; |
|---|
| 348 | | push 0 ; // adjust |
|---|
| 349 | | push EDX ; |
|---|
| 350 | | push EAX ; |
|---|
| 351 | | fld double ptr [ESP] ; |
|---|
| 352 | | sub ESP,8 ; |
|---|
| 353 | | fld real ptr 16[ESP] ; // adjust |
|---|
| 354 | | fcomp ; |
|---|
| 355 | | fstsw AX ; |
|---|
| 356 | | fstcw 8[ESP] ; |
|---|
| 357 | | fldcw 28[ESP] ; // roundTo0 |
|---|
| 358 | | sahf ; |
|---|
| 359 | | jae L1 ; |
|---|
| 360 | | fld real ptr 16[ESP] ; // adjust |
|---|
| 361 | | fsubp ST(1), ST ; |
|---|
| 362 | | fistp qword ptr [ESP] ; |
|---|
| 363 | | pop EAX ; |
|---|
| 364 | | pop EDX ; |
|---|
| 365 | | fldcw [ESP] ; |
|---|
| 366 | | add ESP,24 ; |
|---|
| 367 | | add EDX,0x8000_0000 ; |
|---|
| 368 | | ret ; |
|---|
| 369 | | L1: ; |
|---|
| 370 | | fistp qword ptr [ESP] ; |
|---|
| 371 | | pop EAX ; |
|---|
| 372 | | pop EDX ; |
|---|
| 373 | | fldcw [ESP] ; |
|---|
| 374 | | add ESP,24 ; |
|---|
| 375 | | ret ; |
|---|
| 376 | | } |
|---|
| 377 | | } else { |
|---|
| 378 | | asm |
|---|
| 379 | | { naked ; |
|---|
| 380 | | push EDX ; |
|---|
| 381 | | push EAX ; |
|---|
| 382 | | fld double ptr [ESP] ; |
|---|
| 383 | | sub ESP,8 ; |
|---|
| 384 | | fld real ptr adjust ; |
|---|
| 385 | | fcomp ; |
|---|
| 386 | | fstsw AX ; |
|---|
| 387 | | fstcw 8[ESP] ; |
|---|
| 388 | | fldcw roundTo0 ; |
|---|
| 389 | | sahf ; |
|---|
| 390 | | jae L1 ; |
|---|
| 391 | | fld real ptr adjust ; |
|---|
| 392 | | fsubp ST(1), ST ; |
|---|
| 393 | | fistp qword ptr [ESP] ; |
|---|
| 394 | | pop EAX ; |
|---|
| 395 | | pop EDX ; |
|---|
| 396 | | fldcw [ESP] ; |
|---|
| 397 | | add ESP,8 ; |
|---|
| 398 | | add EDX,0x8000_0000 ; |
|---|
| 399 | | ret ; |
|---|
| 400 | | L1: ; |
|---|
| 401 | | fistp qword ptr [ESP] ; |
|---|
| 402 | | pop EAX ; |
|---|
| 403 | | pop EDX ; |
|---|
| 404 | | fldcw [ESP] ; |
|---|
| 405 | | add ESP,8 ; |
|---|
| 406 | | ret ; |
|---|
| 407 | | } |
|---|
| | 392 | version (OSX) |
|---|
| | 393 | { |
|---|
| | 394 | version (D_InlineAsm_X86) |
|---|
| | 395 | asm |
|---|
| | 396 | { naked ; |
|---|
| | 397 | push 0xFBF ; // roundTo0 |
|---|
| | 398 | push 0x0000403e ; |
|---|
| | 399 | push 0x80000000 ; |
|---|
| | 400 | push 0 ; // adjust |
|---|
| | 401 | push EDX ; |
|---|
| | 402 | push EAX ; |
|---|
| | 403 | fld double ptr [ESP] ; |
|---|
| | 404 | sub ESP,8 ; |
|---|
| | 405 | fld real ptr 16[ESP] ; // adjust |
|---|
| | 406 | fcomp ; |
|---|
| | 407 | fstsw AX ; |
|---|
| | 408 | fstcw 8[ESP] ; |
|---|
| | 409 | fldcw 28[ESP] ; // roundTo0 |
|---|
| | 410 | sahf ; |
|---|
| | 411 | jae L1 ; |
|---|
| | 412 | fld real ptr 16[ESP] ; // adjust |
|---|
| | 413 | fsubp ST(1), ST ; |
|---|
| | 414 | fistp qword ptr [ESP] ; |
|---|
| | 415 | pop EAX ; |
|---|
| | 416 | pop EDX ; |
|---|
| | 417 | fldcw [ESP] ; |
|---|
| | 418 | add ESP,24 ; |
|---|
| | 419 | add EDX,0x8000_0000 ; |
|---|
| | 420 | ret ; |
|---|
| | 421 | L1: ; |
|---|
| | 422 | fistp qword ptr [ESP] ; |
|---|
| | 423 | pop EAX ; |
|---|
| | 424 | pop EDX ; |
|---|
| | 425 | fldcw [ESP] ; |
|---|
| | 426 | add ESP,24 ; |
|---|
| | 427 | ret ; |
|---|
| | 428 | } |
|---|
| | 429 | else version (D_InlineAsm_X86_64) |
|---|
| | 430 | static assert(0); |
|---|
| | 431 | else |
|---|
| | 432 | static assert(0); |
|---|
| | 433 | } |
|---|
| | 434 | else |
|---|
| | 435 | { |
|---|
| | 436 | version (D_InlineAsm_X86) |
|---|
| | 437 | asm |
|---|
| | 438 | { naked ; |
|---|
| | 439 | push EDX ; |
|---|
| | 440 | push EAX ; |
|---|
| | 441 | fld double ptr [ESP] ; |
|---|
| | 442 | sub ESP,8 ; |
|---|
| | 443 | fld real ptr adjust ; |
|---|
| | 444 | fcomp ; |
|---|
| | 445 | fstsw AX ; |
|---|
| | 446 | fstcw 8[ESP] ; |
|---|
| | 447 | fldcw roundTo0 ; |
|---|
| | 448 | sahf ; |
|---|
| | 449 | jae L1 ; |
|---|
| | 450 | fld real ptr adjust ; |
|---|
| | 451 | fsubp ST(1), ST ; |
|---|
| | 452 | fistp qword ptr [ESP] ; |
|---|
| | 453 | pop EAX ; |
|---|
| | 454 | pop EDX ; |
|---|
| | 455 | fldcw [ESP] ; |
|---|
| | 456 | add ESP,8 ; |
|---|
| | 457 | add EDX,0x8000_0000 ; |
|---|
| | 458 | ret ; |
|---|
| | 459 | L1: ; |
|---|
| | 460 | fistp qword ptr [ESP] ; |
|---|
| | 461 | pop EAX ; |
|---|
| | 462 | pop EDX ; |
|---|
| | 463 | fldcw [ESP] ; |
|---|
| | 464 | add ESP,8 ; |
|---|
| | 465 | ret ; |
|---|
| | 466 | } |
|---|
| | 467 | else version (D_InlineAsm_X86_64) |
|---|
| | 468 | asm |
|---|
| | 469 | { naked ; |
|---|
| | 470 | push RAX ; |
|---|
| | 471 | fld double ptr [RSP] ; |
|---|
| | 472 | sub RSP,8 ; |
|---|
| | 473 | fld real ptr adjust ; |
|---|
| | 474 | fcomp ; |
|---|
| | 475 | fstsw AX ; |
|---|
| | 476 | fstcw 8[RSP] ; |
|---|
| | 477 | fldcw roundTo0 ; |
|---|
| | 478 | sahf ; |
|---|
| | 479 | jae L1 ; |
|---|
| | 480 | fld real ptr adjust ; |
|---|
| | 481 | fsubp ST(1), ST ; |
|---|
| | 482 | fistp qword ptr [RSP] ; |
|---|
| | 483 | pop RAX ; |
|---|
| | 484 | fldcw [RSP] ; |
|---|
| | 485 | add RSP,8 ; |
|---|
| | 486 | mov EDX,0x8000_0000 ; |
|---|
| | 487 | shl RDX,32 ; |
|---|
| | 488 | add RAX,RDX ; |
|---|
| | 489 | ret ; |
|---|
| | 490 | L1: ; |
|---|
| | 491 | fistp qword ptr [RSP] ; |
|---|
| | 492 | pop RAX ; |
|---|
| | 493 | fldcw [RSP] ; |
|---|
| | 494 | add RSP,8 ; |
|---|
| | 495 | ret ; |
|---|
| | 496 | } |
|---|
| | 497 | else |
|---|
| | 498 | static assert(0); |
|---|
| 408 | 499 | } |
|---|
| 409 | 500 | } |
|---|
| … | … | |
| 414 | 505 | { |
|---|
| 415 | 506 | // BUG: should handle NAN's and overflows |
|---|
| 416 | | version (OSX) { |
|---|
| 417 | | asm { |
|---|
| 418 | | naked ; |
|---|
| 419 | | push 0xFBF ; // roundTo0 |
|---|
| 420 | | sub ESP,12 ; |
|---|
| 421 | | fstcw 8[ESP] ; |
|---|
| 422 | | fldcw 12[ESP] ; // roundTo0 |
|---|
| 423 | | fistp qword ptr [ESP] ; |
|---|
| 424 | | fldcw 8[ESP] ; |
|---|
| 425 | | pop EAX ; |
|---|
| 426 | | add ESP,12 ; |
|---|
| 427 | | ret ; |
|---|
| 428 | | } |
|---|
| 429 | | } else { |
|---|
| 430 | | asm { |
|---|
| 431 | | naked ; |
|---|
| 432 | | sub ESP,16 ; |
|---|
| 433 | | fstcw 8[ESP] ; |
|---|
| 434 | | fldcw roundTo0 ; |
|---|
| 435 | | fistp qword ptr [ESP] ; |
|---|
| 436 | | fldcw 8[ESP] ; |
|---|
| 437 | | pop EAX ; |
|---|
| 438 | | add ESP,12 ; |
|---|
| 439 | | ret ; |
|---|
| 440 | | } |
|---|
| 441 | | } |
|---|
| 442 | | } |
|---|
| 443 | | |
|---|
| | 507 | version (OSX) |
|---|
| | 508 | { |
|---|
| | 509 | version (D_InlineAsm_X86) |
|---|
| | 510 | asm |
|---|
| | 511 | { naked ; |
|---|
| | 512 | push 0xFBF ; // roundTo0 |
|---|
| | 513 | sub ESP,12 ; |
|---|
| | 514 | fstcw 8[ESP] ; |
|---|
| | 515 | fldcw 12[ESP] ; // roundTo0 |
|---|
| | 516 | fistp qword ptr [ESP] ; |
|---|
| | 517 | fldcw 8[ESP] ; |
|---|
| | 518 | pop EAX ; |
|---|
| | 519 | add ESP,12 ; |
|---|
| | 520 | ret ; |
|---|
| | 521 | } |
|---|
| | 522 | else version (D_InlineAsm_X86_64) |
|---|
| | 523 | assert(0); |
|---|
| | 524 | else |
|---|
| | 525 | static assert(0); |
|---|
| | 526 | } |
|---|
| | 527 | else |
|---|
| | 528 | { |
|---|
| | 529 | version (D_InlineAsm_X86) |
|---|
| | 530 | asm |
|---|
| | 531 | { naked ; |
|---|
| | 532 | sub ESP,16 ; |
|---|
| | 533 | fstcw 8[ESP] ; |
|---|
| | 534 | fldcw roundTo0 ; |
|---|
| | 535 | fistp qword ptr [ESP] ; |
|---|
| | 536 | fldcw 8[ESP] ; |
|---|
| | 537 | pop EAX ; |
|---|
| | 538 | add ESP,12 ; |
|---|
| | 539 | ret ; |
|---|
| | 540 | } |
|---|
| | 541 | else version (D_InlineAsm_X86_64) |
|---|
| | 542 | asm |
|---|
| | 543 | { naked ; |
|---|
| | 544 | sub RSP,16 ; |
|---|
| | 545 | fstcw 8[RSP] ; |
|---|
| | 546 | fldcw roundTo0 ; |
|---|
| | 547 | fistp qword ptr [RSP] ; |
|---|
| | 548 | fldcw 8[RSP] ; |
|---|
| | 549 | pop RAX ; |
|---|
| | 550 | add RSP,8 ; |
|---|
| | 551 | ret ; |
|---|
| | 552 | } |
|---|
| | 553 | else |
|---|
| | 554 | static assert(0); |
|---|
| | 555 | } |
|---|
| | 556 | } |
|---|
| 444 | 557 | |
|---|
| 445 | 558 | // Convert real in ST0 to ulong |
|---|
| … | … | |
| 449 | 562 | version (OSX) |
|---|
| 450 | 563 | { |
|---|
| 451 | | asm |
|---|
| 452 | | { naked ; |
|---|
| 453 | | push 0xFBF ; // roundTo0 |
|---|
| 454 | | push 0x0000403e ; |
|---|
| 455 | | push 0x80000000 ; |
|---|
| 456 | | push 0 ; // adjust |
|---|
| 457 | | sub ESP,16 ; |
|---|
| 458 | | fld real ptr 16[ESP] ; // adjust |
|---|
| 459 | | fcomp ; |
|---|
| 460 | | fstsw AX ; |
|---|
| 461 | | fstcw 8[ESP] ; |
|---|
| 462 | | fldcw 28[ESP] ; // roundTo0 |
|---|
| 463 | | sahf ; |
|---|
| 464 | | jae L1 ; |
|---|
| 465 | | fld real ptr 16[ESP] ; // adjust |
|---|
| 466 | | fsubp ST(1), ST ; |
|---|
| 467 | | fistp qword ptr [ESP] ; |
|---|
| 468 | | pop EAX ; |
|---|
| 469 | | pop EDX ; |
|---|
| 470 | | fldcw [ESP] ; |
|---|
| 471 | | add ESP,24 ; |
|---|
| 472 | | add EDX,0x8000_0000 ; |
|---|
| 473 | | ret ; |
|---|
| 474 | | L1: ; |
|---|
| 475 | | fistp qword ptr [ESP] ; |
|---|
| 476 | | pop EAX ; |
|---|
| 477 | | pop EDX ; |
|---|
| 478 | | fldcw [ESP] ; |
|---|
| 479 | | add ESP,24 ; |
|---|
| 480 | | ret ; |
|---|
| 481 | | } |
|---|
| | 564 | version (D_InlineAsm_X86) |
|---|
| | 565 | asm |
|---|
| | 566 | { naked ; |
|---|
| | 567 | push 0xFBF ; // roundTo0 |
|---|
| | 568 | push 0x0000403e ; |
|---|
| | 569 | push 0x80000000 ; |
|---|
| | 570 | push 0 ; // adjust |
|---|
| | 571 | sub ESP,16 ; |
|---|
| | 572 | fld real ptr 16[ESP] ; // adjust |
|---|
| | 573 | fcomp ; |
|---|
| | 574 | fstsw AX ; |
|---|
| | 575 | fstcw 8[ESP] ; |
|---|
| | 576 | fldcw 28[ESP] ; // roundTo0 |
|---|
| | 577 | sahf ; |
|---|
| | 578 | jae L1 ; |
|---|
| | 579 | fld real ptr 16[ESP] ; // adjust |
|---|
| | 580 | fsubp ST(1), ST ; |
|---|
| | 581 | fistp qword ptr [ESP] ; |
|---|
| | 582 | pop EAX ; |
|---|
| | 583 | pop EDX ; |
|---|
| | 584 | fldcw [ESP] ; |
|---|
| | 585 | add ESP,24 ; |
|---|
| | 586 | add EDX,0x8000_0000 ; |
|---|
| | 587 | ret ; |
|---|
| | 588 | L1: ; |
|---|
| | 589 | fistp qword ptr [ESP] ; |
|---|
| | 590 | pop EAX ; |
|---|
| | 591 | pop EDX ; |
|---|
| | 592 | fldcw [ESP] ; |
|---|
| | 593 | add ESP,24 ; |
|---|
| | 594 | ret ; |
|---|
| | 595 | } |
|---|
| | 596 | else version (D_InlineAsm_X86_64) |
|---|
| | 597 | static assert(0); |
|---|
| | 598 | else |
|---|
| | 599 | static assert(0); |
|---|
| 482 | 600 | } |
|---|
| 483 | 601 | else |
|---|
| 484 | 602 | { |
|---|
| 485 | | asm |
|---|
| 486 | | { naked ; |
|---|
| 487 | | sub ESP,16 ; |
|---|
| 488 | | fld real ptr adjust ; |
|---|
| 489 | | fcomp ; |
|---|
| 490 | | fstsw AX ; |
|---|
| 491 | | fstcw 8[ESP] ; |
|---|
| 492 | | fldcw roundTo0 ; |
|---|
| 493 | | sahf ; |
|---|
| 494 | | jae L1 ; |
|---|
| 495 | | fld real ptr adjust ; |
|---|
| 496 | | fsubp ST(1), ST ; |
|---|
| 497 | | fistp qword ptr [ESP] ; |
|---|
| 498 | | pop EAX ; |
|---|
| 499 | | pop EDX ; |
|---|
| 500 | | fldcw [ESP] ; |
|---|
| 501 | | add ESP,8 ; |
|---|
| 502 | | add EDX,0x8000_0000 ; |
|---|
| 503 | | ret ; |
|---|
| 504 | | L1: ; |
|---|
| 505 | | fistp qword ptr [ESP] ; |
|---|
| 506 | | pop EAX ; |
|---|
| 507 | | pop EDX ; |
|---|
| 508 | | fldcw [ESP] ; |
|---|
| 509 | | add ESP,8 ; |
|---|
| 510 | | ret ; |
|---|
| 511 | | } |
|---|
| 512 | | } |
|---|
| 513 | | } |
|---|
| 514 | | |
|---|
| | 603 | version (D_InlineAsm_X86) |
|---|
| | 604 | asm |
|---|
| | 605 | { naked ; |
|---|
| | 606 | sub ESP,16 ; |
|---|
| | 607 | fld real ptr adjust ; |
|---|
| | 608 | fcomp ; |
|---|
| | 609 | fstsw AX ; |
|---|
| | 610 | fstcw 8[ESP] ; |
|---|
| | 611 | fldcw roundTo0 ; |
|---|
| | 612 | sahf ; |
|---|
| | 613 | jae L1 ; |
|---|
| | 614 | fld real ptr adjust ; |
|---|
| | 615 | fsubp ST(1), ST ; |
|---|
| | 616 | fistp qword ptr [ESP] ; |
|---|
| | 617 | pop EAX ; |
|---|
| | 618 | pop EDX ; |
|---|
| | 619 | fldcw [ESP] ; |
|---|
| | 620 | add ESP,8 ; |
|---|
| | 621 | add EDX,0x8000_0000 ; |
|---|
| | 622 | ret ; |
|---|
| | 623 | L1: ; |
|---|
| | 624 | fistp qword ptr [ESP] ; |
|---|
| | 625 | pop EAX ; |
|---|
| | 626 | pop EDX ; |
|---|
| | 627 | fldcw [ESP] ; |
|---|
| | 628 | add ESP,8 ; |
|---|
| | 629 | ret ; |
|---|
| | 630 | } |
|---|
| | 631 | else version (D_InlineAsm_X86_64) |
|---|
| | 632 | asm |
|---|
| | 633 | { naked ; |
|---|
| | 634 | sub RSP,16 ; |
|---|
| | 635 | fld real ptr adjust ; |
|---|
| | 636 | fcomp ; |
|---|
| | 637 | fstsw AX ; |
|---|
| | 638 | fstcw 8[RSP] ; |
|---|
| | 639 | fldcw roundTo0 ; |
|---|
| | 640 | sahf ; |
|---|
| | 641 | jae L1 ; |
|---|
| | 642 | fld real ptr adjust ; |
|---|
| | 643 | fsubp ST(1), ST ; |
|---|
| | 644 | fistp qword ptr [RSP] ; |
|---|
| | 645 | pop RAX ; |
|---|
| | 646 | fldcw [RSP] ; |
|---|
| | 647 | add RSP,8 ; |
|---|
| | 648 | mov RCX,0x8000_0000 ; |
|---|
| | 649 | shl RCX,32 ; |
|---|
| | 650 | add RAX,RCX ; |
|---|
| | 651 | ret ; |
|---|
| | 652 | L1: ; |
|---|
| | 653 | fistp qword ptr [RSP] ; |
|---|
| | 654 | pop RAX ; |
|---|
| | 655 | fldcw [RSP] ; |
|---|
| | 656 | add RSP,8 ; |
|---|
| | 657 | ret ; |
|---|
| | 658 | } |
|---|
| | 659 | else |
|---|
| | 660 | static assert(0); |
|---|
| | 661 | } |
|---|
| | 662 | } |
|---|
| r5609 |
r5652 |
|
| 70 | 70 | * gcc will not, so we instead use a 'long'. |
|---|
| 71 | 71 | */ |
|---|
| 72 | | alias long ArrayRet_t; |
|---|
| | 72 | alias void[] ArrayRet_t; |
|---|
| 73 | 73 | |
|---|
| 74 | 74 | struct Array |
|---|
| … | … | |
| 111 | 111 | size_t aligntsize(size_t tsize) |
|---|
| 112 | 112 | { |
|---|
| 113 | | // Is pointer alignment on the x64 4 bytes or 8? |
|---|
| 114 | | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 113 | version (X86_64) |
|---|
| | 114 | // Size of key needed to align value on 16 bytes |
|---|
| | 115 | return (tsize + 15) & ~(15); |
|---|
| | 116 | else |
|---|
| | 117 | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| 115 | 118 | } |
|---|
| 116 | 119 | |
|---|
| … | … | |
| 239 | 242 | |
|---|
| 240 | 243 | void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) |
|---|
| | 244 | { |
|---|
| | 245 | return _aaGetX(aa, keyti, valuesize, cast(void *)(&valuesize + 1)); |
|---|
| | 246 | } |
|---|
| | 247 | |
|---|
| | 248 | void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) |
|---|
| 241 | 249 | in |
|---|
| 242 | 250 | { |
|---|
| … | … | |
| 252 | 260 | body |
|---|
| 253 | 261 | { |
|---|
| 254 | | auto pkey = cast(void *)(&valuesize + 1); |
|---|
| 255 | 262 | size_t i; |
|---|
| 256 | 263 | aaA *e; |
|---|
| … | … | |
| 259 | 266 | if (!aa.a) |
|---|
| 260 | 267 | aa.a = new BB(); |
|---|
| | 268 | |
|---|
| 261 | 269 | aa.a.keyti = keyti; |
|---|
| 262 | 270 | |
|---|
| … | … | |
| 270 | 278 | |
|---|
| 271 | 279 | auto key_hash = keyti.getHash(pkey); |
|---|
| | 280 | |
|---|
| 272 | 281 | //printf("hash = %d\n", key_hash); |
|---|
| | 282 | |
|---|
| 273 | 283 | i = key_hash % aa.a.b.length; |
|---|
| 274 | 284 | auto pe = &aa.a.b[i]; |
|---|
| | 285 | |
|---|
| 275 | 286 | while ((e = *pe) !is null) |
|---|
| 276 | 287 | { |
|---|
| … | … | |
| 313 | 324 | void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) |
|---|
| 314 | 325 | { |
|---|
| | 326 | return _aaGetRvalueX(aa, keyti, valuesize, cast(void *)(&valuesize + 1)); |
|---|
| | 327 | } |
|---|
| | 328 | |
|---|
| | 329 | void* _aaGetRvalueX(AA aa, TypeInfo keyti, size_t valuesize, void* pkey) |
|---|
| | 330 | { |
|---|
| 315 | 331 | //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); |
|---|
| 316 | 332 | if (!aa.a) |
|---|
| 317 | 333 | return null; |
|---|
| 318 | 334 | |
|---|
| 319 | | auto pkey = cast(void *)(&valuesize + 1); |
|---|
| 320 | 335 | auto keysize = aligntsize(keyti.tsize()); |
|---|
| 321 | 336 | auto len = aa.a.b.length; |
|---|
| … | … | |
| 352 | 367 | |
|---|
| 353 | 368 | void* _aaIn(AA aa, TypeInfo keyti, ...) |
|---|
| | 369 | { |
|---|
| | 370 | return _aaInX(aa, keyti, cast(void *)(&keyti + 1)); |
|---|
| | 371 | } |
|---|
| | 372 | |
|---|
| | 373 | void* _aaInX(AA aa, TypeInfo keyti, void* pkey) |
|---|
| 354 | 374 | in |
|---|
| 355 | 375 | { |
|---|
| … | … | |
| 363 | 383 | if (aa.a) |
|---|
| 364 | 384 | { |
|---|
| 365 | | auto pkey = cast(void *)(&keyti + 1); |
|---|
| 366 | | |
|---|
| 367 | 385 | //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); |
|---|
| 368 | 386 | auto len = aa.a.b.length; |
|---|
| … | … | |
| 400 | 418 | void _aaDel(AA aa, TypeInfo keyti, ...) |
|---|
| 401 | 419 | { |
|---|
| 402 | | auto pkey = cast(void *)(&keyti + 1); |
|---|
| | 420 | return _aaDelX(aa, keyti, cast(void *)(&keyti + 1)); |
|---|
| | 421 | } |
|---|
| | 422 | |
|---|
| | 423 | void _aaDelX(AA aa, TypeInfo keyti, void* pkey) |
|---|
| | 424 | { |
|---|
| 403 | 425 | aaA *e; |
|---|
| 404 | 426 | |
|---|
| … | … | |
| 674 | 696 | auto len = _aaLen(aa); |
|---|
| 675 | 697 | if (!len) |
|---|
| 676 | | return 0; |
|---|
| | 698 | return null; |
|---|
| 677 | 699 | res = (cast(byte*) gc_malloc(len * keysize, |
|---|
| 678 | 700 | !(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize]; |
|---|
| … | … | |
| 802 | 824 | } |
|---|
| 803 | 825 | |
|---|
| | 826 | extern (C) BB* _d_assocarrayliteralTX(TypeInfo_AssociativeArray ti, void[] keys, void[] values) |
|---|
| | 827 | { |
|---|
| | 828 | auto valueti = ti.next; |
|---|
| | 829 | auto valuesize = valueti.tsize(); // value size |
|---|
| | 830 | auto keyti = ti.key; |
|---|
| | 831 | auto keysize = keyti.tsize(); // key size |
|---|
| | 832 | auto length = keys.length; |
|---|
| | 833 | BB* result; |
|---|
| | 834 | |
|---|
| | 835 | //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length); |
|---|
| | 836 | //printf("tivalue = %.*s\n", ti.next.classinfo.name); |
|---|
| | 837 | assert(length == values.length); |
|---|
| | 838 | if (length == 0 || valuesize == 0 || keysize == 0) |
|---|
| | 839 | { |
|---|
| | 840 | ; |
|---|
| | 841 | } |
|---|
| | 842 | else |
|---|
| | 843 | { |
|---|
| | 844 | result = new BB(); |
|---|
| | 845 | |
|---|
| | 846 | size_t i; |
|---|
| | 847 | for (i = 0; i < prime_list.length - 1; i++) |
|---|
| | 848 | { |
|---|
| | 849 | if (length <= prime_list[i]) |
|---|
| | 850 | break; |
|---|
| | 851 | } |
|---|
| | 852 | auto len = prime_list[i]; |
|---|
| | 853 | result.b = new aaA*[len]; |
|---|
| | 854 | |
|---|
| | 855 | size_t keytsize = aligntsize(keysize); |
|---|
| | 856 | |
|---|
| | 857 | for (size_t j = 0; j < length; j++) |
|---|
| | 858 | { auto pkey = keys.ptr + j * keysize; |
|---|
| | 859 | auto pvalue = values.ptr + j * valuesize; |
|---|
| | 860 | aaA* e; |
|---|
| | 861 | |
|---|
| | 862 | auto key_hash = keyti.getHash(pkey); |
|---|
| | 863 | //printf("hash = %d\n", key_hash); |
|---|
| | 864 | i = key_hash % len; |
|---|
| | 865 | auto pe = &result.b[i]; |
|---|
| | 866 | while (1) |
|---|
| | 867 | { |
|---|
| | 868 | e = *pe; |
|---|
| | 869 | if (!e) |
|---|
| | 870 | { |
|---|
| | 871 | // Not found, create new elem |
|---|
| | 872 | //printf("create new one\n"); |
|---|
| | 873 | e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize]; |
|---|
| | 874 | memcpy(e + 1, pkey, keysize); |
|---|
| | 875 | e.hash = key_hash; |
|---|
| | 876 | *pe = e; |
|---|
| | 877 | result.nodes++; |
|---|
| | 878 | break; |
|---|
| | 879 | } |
|---|
| | 880 | if (key_hash == e.hash) |
|---|
| | 881 | { |
|---|
| | 882 | auto c = keyti.compare(pkey, e + 1); |
|---|
| | 883 | if (c == 0) |
|---|
| | 884 | break; |
|---|
| | 885 | pe = (c < 0) ? &e.left : &e.right; |
|---|
| | 886 | } |
|---|
| | 887 | else |
|---|
| | 888 | pe = (key_hash < e.hash) ? &e.left : &e.right; |
|---|
| | 889 | } |
|---|
| | 890 | memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize); |
|---|
| | 891 | } |
|---|
| | 892 | } |
|---|
| | 893 | return result; |
|---|
| | 894 | } |
|---|
| 804 | 895 | |
|---|
| 805 | 896 | /*********************************** |
|---|
| … | … | |
| 808 | 899 | */ |
|---|
| 809 | 900 | |
|---|
| 810 | | extern (C) |
|---|
| 811 | | BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...) |
|---|
| | 901 | extern (C) BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...) |
|---|
| 812 | 902 | { |
|---|
| 813 | 903 | auto valuesize = ti.next.tsize(); // value size |
|---|
| … | … | |
| 825 | 915 | { |
|---|
| 826 | 916 | va_list q; |
|---|
| 827 | | va_start!(size_t)(q, length); |
|---|
| | 917 | version(X86_64) va_start(q, __va_argsave); else va_start!(size_t)(q, length); |
|---|
| 828 | 918 | |
|---|
| 829 | 919 | result = new BB(); |
|---|
| r5609 |
r5652 |
|
| 69 | 69 | */ |
|---|
| 70 | 70 | |
|---|
| 71 | | extern (C) long _adReverseChar(char[] a) |
|---|
| | 71 | extern (C) char[] _adReverseChar(char[] a) |
|---|
| 72 | 72 | { |
|---|
| 73 | 73 | bool hadErrors=false; |
|---|
| … | … | |
| 101 | 101 | |
|---|
| 102 | 102 | uint stridehi = 1; |
|---|
| 103 | | while ((chi & 0xC0) == 0x80 && hi >= lo) |
|---|
| | 103 | while ((chi & 0xC0) == 0x80) |
|---|
| 104 | 104 | { |
|---|
| 105 | 105 | chi = *--hi; |
|---|
| 106 | 106 | stridehi++; |
|---|
| 107 | 107 | } |
|---|
| 108 | | if (lo >= hi){ |
|---|
| | 108 | if (lo == hi) |
|---|
| | 109 | { |
|---|
| 109 | 110 | if (lo>hi){ |
|---|
| 110 | 111 | hadErrors=true; |
|---|
| … | … | |
| 132 | 133 | memcpy(tmp.ptr, hi, stridehi); |
|---|
| 133 | 134 | memcpy(tmplo.ptr, lo, stridelo); |
|---|
| 134 | | memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); |
|---|
| | 135 | memmove(lo + stridehi, lo + stridelo , cast(size_t)((hi - lo) - stridelo)); |
|---|
| 135 | 136 | memcpy(lo, tmp.ptr, stridehi); |
|---|
| 136 | 137 | memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); |
|---|
| 137 | 138 | |
|---|
| 138 | 139 | lo += stridehi; |
|---|
| 139 | | hi = hi - 1 + (stridehi - stridelo); |
|---|
| | 140 | hi = hi - 1 + cast(int)(stridehi - stridelo); |
|---|
| 140 | 141 | } |
|---|
| 141 | 142 | } |
|---|
| 142 | 143 | if (hadErrors) |
|---|
| 143 | 144 | throw new Exception("invalid UTF-8 sequence",__FILE__,__LINE__); |
|---|
| 144 | | return *cast(long*)(&a); |
|---|
| | 145 | return a; |
|---|
| 145 | 146 | } |
|---|
| 146 | 147 | |
|---|
| 147 | 148 | unittest |
|---|
| 148 | 149 | { |
|---|
| 149 | | auto a = "abcd"c[]; |
|---|
| | 150 | char[] a = "abcd"; |
|---|
| 150 | 151 | |
|---|
| 151 | 152 | auto r = a.dup.reverse; |
|---|
| r5015 |
r5652 |
|
| 28 | 28 | */ |
|---|
| 29 | 29 | |
|---|
| | 30 | |
|---|
| 30 | 31 | extern (C) void* __alloca(int nbytes) |
|---|
| 31 | 32 | { |
|---|
| | 33 | version (D_InlineAsm_X86) |
|---|
| | 34 | { |
|---|
| 32 | 35 | asm |
|---|
| 33 | 36 | { |
|---|
| … | … | |
| 38 | 41 | push EDI ; |
|---|
| 39 | 42 | push ESI ; |
|---|
| | 43 | } |
|---|
| | 44 | |
|---|
| | 45 | version (OSX) |
|---|
| | 46 | { |
|---|
| | 47 | asm |
|---|
| | 48 | { |
|---|
| | 49 | add EAX,15 ; |
|---|
| | 50 | and EAX,0xFFFFFFF0 ; // round up to 16 byte boundary |
|---|
| | 51 | } |
|---|
| | 52 | } |
|---|
| | 53 | else |
|---|
| | 54 | { |
|---|
| | 55 | asm |
|---|
| | 56 | { |
|---|
| 40 | 57 | add EAX,3 ; |
|---|
| 41 | 58 | and EAX,0xFFFFFFFC ; // round up to dword |
|---|
| | 59 | } |
|---|
| | 60 | } |
|---|
| | 61 | |
|---|
| | 62 | asm |
|---|
| | 63 | { |
|---|
| 42 | 64 | jnz Abegin ; |
|---|
| 43 | 65 | mov EAX,4 ; // allow zero bytes allocation, 0 rounded to dword is 4.. |
|---|
| … | … | |
| 108 | 130 | ret ; |
|---|
| 109 | 131 | } |
|---|
| | 132 | } |
|---|
| | 133 | else version (D_InlineAsm_X86_64) |
|---|
| | 134 | { |
|---|
| | 135 | asm |
|---|
| | 136 | { |
|---|
| | 137 | naked ; |
|---|
| | 138 | mov RDX,RCX ; |
|---|
| | 139 | mov RAX,RDI ; // get nbytes |
|---|
| | 140 | add RAX,15 ; |
|---|
| | 141 | and AL,0xF0 ; // round up to 16 byte boundary |
|---|
| | 142 | test RAX,RAX ; |
|---|
| | 143 | jnz Abegin ; |
|---|
| | 144 | mov RAX,16 ; // allow zero bytes allocation |
|---|
| | 145 | Abegin: |
|---|
| | 146 | mov RSI,RAX ; // RSI = nbytes |
|---|
| | 147 | neg RAX ; |
|---|
| | 148 | add RAX,RSP ; // RAX is now what the new RSP will be. |
|---|
| | 149 | jae Aoverflow ; |
|---|
| | 150 | } |
|---|
| | 151 | version (Win64) |
|---|
| | 152 | { |
|---|
| | 153 | asm |
|---|
| | 154 | { |
|---|
| | 155 | // We need to be careful about the guard page |
|---|
| | 156 | // Thus, for every 4k page, touch it to cause the OS to load it in. |
|---|
| | 157 | mov RCX,RAX ; // RCX is new location for stack |
|---|
| | 158 | mov RBX,RSI ; // RBX is size to "grow" stack |
|---|
| | 159 | L1: |
|---|
| | 160 | test [RCX+RBX],RBX ; // bring in page |
|---|
| | 161 | sub RBX,0x1000 ; // next 4K page down |
|---|
| | 162 | jae L1 ; // if more pages |
|---|
| | 163 | test [RCX],RBX ; // bring in last page |
|---|
| | 164 | } |
|---|
| | 165 | } |
|---|
| | 166 | version (Unix) |
|---|
| | 167 | { |
|---|
| | 168 | asm |
|---|
| | 169 | { |
|---|
| | 170 | cmp RAX,_pastdata ; |
|---|
| | 171 | jbe Aoverflow ; // Unlikely - ~2 Gbytes under UNIX |
|---|
| | 172 | } |
|---|
| | 173 | } |
|---|
| | 174 | asm |
|---|
| | 175 | { |
|---|
| | 176 | // Copy down to [RSP] the temps on the stack. |
|---|
| | 177 | // The number of temps is (RBP - RSP - locals). |
|---|
| | 178 | mov RCX,RBP ; |
|---|
| | 179 | sub RCX,RSP ; |
|---|
| | 180 | sub RCX,[RDX] ; // RCX = number of temps (bytes) to move. |
|---|
| | 181 | add [RDX],RSI ; // adjust locals by nbytes for next call to alloca() |
|---|
| | 182 | mov RSP,RAX ; // Set up new stack pointer. |
|---|
| | 183 | add RAX,RCX ; // Return value = RSP + temps. |
|---|
| | 184 | mov RDI,RSP ; // Destination of copy of temps. |
|---|
| | 185 | add RSI,RSP ; // Source of copy. |
|---|
| | 186 | shr RCX,3 ; // RCX to count of qwords in temps |
|---|
| | 187 | rep ; |
|---|
| | 188 | movsq ; |
|---|
| | 189 | jmp done ; |
|---|
| | 190 | |
|---|
| | 191 | Aoverflow: |
|---|
| | 192 | // Overflowed the stack. Return null |
|---|
| | 193 | xor RAX,RAX ; |
|---|
| | 194 | |
|---|
| | 195 | done: |
|---|
| | 196 | ret ; |
|---|
| | 197 | } |
|---|
| | 198 | } |
|---|
| | 199 | else |
|---|
| | 200 | static assert(0); |
|---|
| 110 | 201 | } |
|---|
| r5248 |
r5652 |
|
| 83 | 83 | Object _d_dynamic_cast(Object o, ClassInfo c) |
|---|
| 84 | 84 | { ClassInfo oc; |
|---|
| 85 | | size_t offset = 0; |
|---|
| | 85 | uint offset = 0; |
|---|
| 86 | 86 | |
|---|
| 87 | 87 | //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); |
|---|
| … | … | |
| 102 | 102 | } |
|---|
| 103 | 103 | |
|---|
| 104 | | int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset) |
|---|
| | 104 | int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref uint offset) |
|---|
| 105 | 105 | { int i; |
|---|
| 106 | 106 | |
|---|
| r5284 |
r5652 |
|
| 35 | 35 | { |
|---|
| 36 | 36 | size_t len; |
|---|
| 37 | | uint* ptr; |
|---|
| | 37 | size_t* ptr; |
|---|
| 38 | 38 | |
|---|
| 39 | 39 | bool opIndex( size_t i ) |
|---|
| r5603 |
r5652 |
|
| 17 | 17 | import tango.stdc.stdlib : malloc, free, exit, EXIT_FAILURE; |
|---|
| 18 | 18 | import tango.stdc.string : strlen; |
|---|
| 19 | | import tango.stdc.stdio : printf; |
|---|
| 20 | 19 | } |
|---|
| 21 | 20 | |
|---|
| … | … | |
| 91 | 90 | { |
|---|
| 92 | 91 | static bool hasBeenCalled; |
|---|
| 93 | | |
|---|
| | 92 | |
|---|
| 94 | 93 | if (hasBeenCalled) |
|---|
| 95 | 94 | return; |
|---|
| 96 | | |
|---|
| | 95 | |
|---|
| 97 | 96 | hasBeenCalled = true; |
|---|
| 98 | | |
|---|
| | 97 | |
|---|
| 99 | 98 | version (Posix) |
|---|
| 100 | 99 | { |
|---|
| … | … | |
| 109 | 108 | { |
|---|
| 110 | 109 | static bool result; |
|---|
| 111 | | |
|---|
| | 110 | |
|---|
| 112 | 111 | if (result) |
|---|
| 113 | 112 | return result; |
|---|
| 114 | | |
|---|
| | 113 | |
|---|
| 115 | 114 | _d_criticalInit(); |
|---|
| 116 | 115 | |
|---|
| … | … | |
| 146 | 145 | { |
|---|
| 147 | 146 | static bool hasBeenCalled; |
|---|
| 148 | | |
|---|
| | 147 | |
|---|
| 149 | 148 | if (hasBeenCalled) |
|---|
| 150 | 149 | return; |
|---|
| 151 | | |
|---|
| | 150 | |
|---|
| 152 | 151 | hasBeenCalled = true; |
|---|
| 153 | | |
|---|
| | 152 | |
|---|
| 154 | 153 | version (Posix) |
|---|
| 155 | 154 | { |
|---|
| … | … | |
| 162 | 161 | { |
|---|
| 163 | 162 | static bool result; |
|---|
| 164 | | |
|---|
| | 163 | |
|---|
| 165 | 164 | if (result) |
|---|
| 166 | 165 | return result; |
|---|
| 167 | | |
|---|
| | 166 | |
|---|
| 168 | 167 | try |
|---|
| 169 | 168 | { |
|---|
| 170 | 169 | _d_isHalting = true; |
|---|
| 171 | | thread_joinAll(); |
|---|
| | 170 | thread_joinAll(); |
|---|
| 172 | 171 | _moduleDtor(); |
|---|
| 173 | 172 | gc_term(); |
|---|
| … | … | |
| 215 | 214 | version(NoCMain) |
|---|
| 216 | 215 | { |
|---|
| 217 | | |
|---|
| | 216 | |
|---|
| 218 | 217 | } |
|---|
| 219 | 218 | else |
|---|
| … | … | |
| 254 | 253 | __libc_stack_end = cast(void*)&argv; |
|---|
| 255 | 254 | } |
|---|
| 256 | | |
|---|
| | 255 | |
|---|
| 257 | 256 | version (Posix) |
|---|
| 258 | 257 | _d_criticalInit(); |
|---|
| … | … | |
| 315 | 314 | catch (Object o) |
|---|
| 316 | 315 | { |
|---|
| 317 | | //fprintf(stderr, "%.*s\n", o.toString()); |
|---|
| 318 | 316 | console (o.toString)("\n"); |
|---|
| 319 | 317 | result = EXIT_FAILURE; |
|---|
| … | … | |
| 344 | 342 | rt_init(); |
|---|
| 345 | 343 | if (runModuleUnitTests()) |
|---|
| | 344 | { |
|---|
| 346 | 345 | tryExec(&runMain); |
|---|
| | 346 | } |
|---|
| | 347 | |
|---|
| 347 | 348 | rt_term(); |
|---|
| 348 | 349 | } |
|---|
| … | … | |
| 352 | 353 | version (Posix) |
|---|
| 353 | 354 | _d_criticalTerm(); |
|---|
| 354 | | |
|---|
| | 355 | |
|---|
| 355 | 356 | return result; |
|---|
| 356 | 357 | } |
|---|
| r5609 |
r5652 |
|
| 34 | 34 | import tango.stdc.stdarg; |
|---|
| 35 | 35 | debug(PRINTF) import tango.stdc.stdio : printf; |
|---|
| | 36 | |
|---|
| | 37 | alias void[] array_t; |
|---|
| 36 | 38 | } |
|---|
| 37 | 39 | |
|---|
| … | … | |
| 193 | 195 | * (For when the array is initialized to 0) |
|---|
| 194 | 196 | */ |
|---|
| 195 | | extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length) |
|---|
| | 197 | extern(C) array_t _d_newarrayT(TypeInfo ti, size_t length) |
|---|
| 196 | 198 | { |
|---|
| 197 | 199 | void* p; |
|---|
| 198 | | ulong result; |
|---|
| | 200 | array_t result; |
|---|
| 199 | 201 | auto size = ti.next.tsize(); // array element size |
|---|
| 200 | 202 | |
|---|
| 201 | 203 | debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size); |
|---|
| 202 | 204 | if (length == 0 || size == 0) |
|---|
| 203 | | result = 0; |
|---|
| | 205 | result = array_t.init; |
|---|
| 204 | 206 | else |
|---|
| 205 | 207 | { |
|---|
| … | … | |
| 214 | 216 | } |
|---|
| 215 | 217 | } |
|---|
| | 218 | else version (D_InlineAsm_X86_64) |
|---|
| | 219 | asm |
|---|
| | 220 | { |
|---|
| | 221 | mov RAX,size ; |
|---|
| | 222 | mul RAX,length ; |
|---|
| | 223 | mov size,RAX ; |
|---|
| | 224 | jc Loverflow ; |
|---|
| | 225 | } |
|---|
| 216 | 226 | else |
|---|
| 217 | 227 | size *= length; |
|---|
| | 228 | |
|---|
| 218 | 229 | PointerMap pm; |
|---|
| 219 | | version (D_HavePointerMap) { |
|---|
| 220 | | pm = ti.next.pointermap(); |
|---|
| 221 | | } |
|---|
| | 230 | version (D_HavePointerMap) pm = ti.next.pointermap(); |
|---|
| | 231 | |
|---|
| 222 | 232 | p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| 223 | 233 | debug(PRINTF) printf(" p = %p\n", p); |
|---|
| 224 | 234 | memset(p, 0, size); |
|---|
| 225 | | result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); |
|---|
| | 235 | result = cast(array_t)p[0..length]; |
|---|
| 226 | 236 | } |
|---|
| 227 | 237 | return result; |
|---|
| … | … | |
| 234 | 244 | * For when the array has a non-zero initializer. |
|---|
| 235 | 245 | */ |
|---|
| 236 | | extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length) |
|---|
| 237 | | { |
|---|
| 238 | | ulong result; |
|---|
| | 246 | extern(C) array_t _d_newarrayiT(TypeInfo ti, size_t length) |
|---|
| | 247 | { |
|---|
| | 248 | array_t result; |
|---|
| 239 | 249 | auto size = ti.next.tsize(); // array element size |
|---|
| 240 | 250 | |
|---|
| … | … | |
| 242 | 252 | |
|---|
| 243 | 253 | if (length == 0 || size == 0) |
|---|
| 244 | | result = 0; |
|---|
| | 254 | result = array_t.init; |
|---|
| 245 | 255 | else |
|---|
| 246 | 256 | { |
|---|
| … | … | |
| 258 | 268 | } |
|---|
| 259 | 269 | } |
|---|
| | 270 | else version (D_InlineAsm_X86_64) |
|---|
| | 271 | asm |
|---|
| | 272 | { |
|---|
| | 273 | mov RAX,size ; |
|---|
| | 274 | mul RAX,length ; |
|---|
| | 275 | mov size,RAX ; |
|---|
| | 276 | jc Loverflow ; |
|---|
| | 277 | } |
|---|
| 260 | 278 | else |
|---|
| 261 | 279 | size *= length; |
|---|
| | 280 | |
|---|
| 262 | 281 | PointerMap pm; |
|---|
| 263 | 282 | version (D_HavePointerMap) { |
|---|
| … | … | |
| 285 | 304 | } |
|---|
| 286 | 305 | va_end(q); |
|---|
| 287 | | result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); |
|---|
| | 306 | result = cast(array_t)p[0..length]; |
|---|
| 288 | 307 | } |
|---|
| 289 | 308 | return result; |
|---|
| … | … | |
| 296 | 315 | * |
|---|
| 297 | 316 | */ |
|---|
| 298 | | extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...) |
|---|
| 299 | | { |
|---|
| 300 | | ulong result; |
|---|
| | 317 | extern(C) array_t _d_newarraymT(TypeInfo ti, int ndims, ...) |
|---|
| | 318 | { |
|---|
| | 319 | array_t result; |
|---|
| 301 | 320 | |
|---|
| 302 | 321 | debug(PRINTF) printf("_d_newarraymT(ndims = %d)\n", ndims); |
|---|
| 303 | 322 | if (ndims == 0) |
|---|
| 304 | | result = 0; |
|---|
| | 323 | result = array_t.init; |
|---|
| 305 | 324 | else |
|---|
| 306 | | { va_list q; |
|---|
| 307 | | va_start!(int)(q, ndims); |
|---|
| 308 | | |
|---|
| 309 | | void[] foo(TypeInfo ti, size_t* pdim, int ndims) |
|---|
| 310 | | { |
|---|
| 311 | | size_t dim = *pdim; |
|---|
| | 325 | { |
|---|
| | 326 | va_list q; |
|---|
| | 327 | |
|---|
| | 328 | version(X86) |
|---|
| | 329 | va_start(q, ndims); |
|---|
| | 330 | else version(X86_64) |
|---|
| | 331 | va_start(q, __va_argsave); |
|---|
| | 332 | else |
|---|
| | 333 | static assert(false, "platform not supported"); |
|---|
| | 334 | |
|---|
| | 335 | void[] foo(TypeInfo ti, va_list ap, int ndims) |
|---|
| | 336 | { |
|---|
| | 337 | size_t dim; |
|---|
| | 338 | va_arg(ap, dim); |
|---|
| 312 | 339 | void[] p; |
|---|
| 313 | 340 | |
|---|
| … | … | |
| 321 | 348 | { |
|---|
| 322 | 349 | p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim]; |
|---|
| 323 | | for (int i = 0; i < dim; i++) |
|---|
| | 350 | |
|---|
| | 351 | version (X86) |
|---|
| 324 | 352 | { |
|---|
| 325 | | (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); |
|---|
| | 353 | va_list ap2; |
|---|
| | 354 | va_copy(ap2, ap); |
|---|
| 326 | 355 | } |
|---|
| | 356 | |
|---|
| | 357 | for (size_t i = 0; i < dim; i++) |
|---|
| | 358 | { |
|---|
| | 359 | version (X86_64) |
|---|
| | 360 | { |
|---|
| | 361 | __va_list argsave = *cast(__va_list*)ap; |
|---|
| | 362 | va_list ap2 = &argsave; |
|---|
| | 363 | } |
|---|
| | 364 | (cast(void[]*)p.ptr)[i] = foo(ti.next, ap2, ndims - 1); |
|---|
| | 365 | } |
|---|
| 327 | 366 | } |
|---|
| 328 | 367 | return p; |
|---|
| 329 | 368 | } |
|---|
| 330 | 369 | |
|---|
| 331 | | size_t* pdim = cast(size_t *)q; |
|---|
| 332 | | result = cast(ulong)foo(ti, pdim, ndims); |
|---|
| | 370 | result = cast(typeof(result))foo(ti, q, ndims); |
|---|
| 333 | 371 | debug(PRINTF) printf("result = %llx\n", result); |
|---|
| 334 | 372 | |
|---|
| … | … | |
| 349 | 387 | * |
|---|
| 350 | 388 | */ |
|---|
| 351 | | extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...) |
|---|
| 352 | | { |
|---|
| 353 | | ulong result; |
|---|
| | 389 | extern(C) array_t _d_newarraymiT(TypeInfo ti, size_t ndims, ...) |
|---|
| | 390 | { |
|---|
| | 391 | array_t result; |
|---|
| 354 | 392 | |
|---|
| 355 | 393 | debug(PRINTF) printf("_d_newarraymiT(ndims = %d)\n", ndims); |
|---|
| 356 | 394 | if (ndims == 0) |
|---|
| 357 | | result = 0; |
|---|
| | 395 | result = array_t.init; |
|---|
| 358 | 396 | else |
|---|
| 359 | 397 | { |
|---|
| 360 | 398 | va_list q; |
|---|
| 361 | | va_start!(int)(q, ndims); |
|---|
| 362 | | |
|---|
| 363 | | void[] foo(TypeInfo ti, size_t* pdim, int ndims) |
|---|
| 364 | | { |
|---|
| 365 | | size_t dim = *pdim; |
|---|
| | 399 | |
|---|
| | 400 | version(X86) |
|---|
| | 401 | va_start(q, ndims); |
|---|
| | 402 | else version(X86_64) |
|---|
| | 403 | va_start(q, __va_argsave); |
|---|
| | 404 | else |
|---|
| | 405 | static assert(false, "platform not supported"); |
|---|
| | 406 | |
|---|
| | 407 | void[] foo(TypeInfo ti, va_list ap, size_t ndims) |
|---|
| | 408 | { |
|---|
| | 409 | size_t dim; |
|---|
| | 410 | va_arg(ap, dim); |
|---|
| 366 | 411 | void[] p; |
|---|
| 367 | 412 | |
|---|
| … | … | |
| 374 | 419 | { |
|---|
| 375 | 420 | p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim]; |
|---|
| 376 | | for (int i = 0; i < dim; i++) |
|---|
| | 421 | |
|---|
| | 422 | version (X86) |
|---|
| 377 | 423 | { |
|---|
| 378 | | (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); |
|---|
| | 424 | va_list ap2; |
|---|
| | 425 | va_copy(ap2, ap); |
|---|
| 379 | 426 | } |
|---|
| 380 | | } |
|---|
| | 427 | |
|---|
| | 428 | for (size_t i = 0; i < dim; i++) |
|---|
| | 429 | { |
|---|
| | 430 | version (X86_64) |
|---|
| | 431 | { |
|---|
| | 432 | __va_list argsave = *cast(__va_list*)ap; |
|---|
| | 433 | va_list ap2 = &argsave; |
|---|
| | 434 | } |
|---|
| | 435 | (cast(void[]*)p.ptr)[i] = foo(ti.next, ap2, ndims - 1); |
|---|
| | 436 | } |
|---|
| | 437 | } |
|---|
| | 438 | |
|---|
| 381 | 439 | return p; |
|---|
| 382 | 440 | } |
|---|
| 383 | 441 | |
|---|
| 384 | | size_t* pdim = cast(size_t *)q; |
|---|
| 385 | | result = cast(ulong)foo(ti, pdim, ndims); |
|---|
| | 442 | result = cast(typeof(result))foo(ti, q, ndims); |
|---|
| 386 | 443 | debug(PRINTF) printf("result = %llx\n", result); |
|---|
| 387 | 444 | |
|---|
| … | … | |
| 458 | 515 | Interface *pi = **cast(Interface ***)p; |
|---|
| 459 | 516 | Object o = cast(Object)(p - pi.offset); |
|---|
| | 517 | debug(PRINTF) printf("finalizing..."); |
|---|
| 460 | 518 | rt_finalize(cast(void*)o); |
|---|
| 461 | 519 | } |
|---|
| … | … | |
| 468 | 526 | extern (C) void _d_callfinalizer(void* p) |
|---|
| 469 | 527 | { |
|---|
| | 528 | debug(PRINTF) printf("dcall finalizing..."); |
|---|
| 470 | 529 | rt_finalize( p ); |
|---|
| 471 | 530 | } |
|---|
| … | … | |
| 491 | 550 | { |
|---|
| 492 | 551 | if (det) |
|---|
| | 552 | { |
|---|
| | 553 | debug(PRINTF) printf("\t det=true, calling dispose\n"); |
|---|
| 493 | 554 | (cast(Object)p).dispose(); |
|---|
| | 555 | } |
|---|
| | 556 | debug(PRINTF) printf("\tcasting to class info\n"); |
|---|
| 494 | 557 | |
|---|
| 495 | 558 | ClassInfo** pc = cast(ClassInfo**)p; |
|---|
| 496 | 559 | |
|---|
| | 560 | debug(PRINTF) printf("\tdereferencing pc: %lu\n", *pc); |
|---|
| | 561 | |
|---|
| 497 | 562 | if (*pc) |
|---|
| 498 | 563 | { |
|---|
| … | … | |
| 501 | 566 | try |
|---|
| 502 | 567 | { |
|---|
| | 568 | debug(PRINTF) printf("\tdoing tests.. collecthandler is %lu\n", cast(void*)collectHandler); |
|---|
| 503 | 569 | if (det || collectHandler is null || collectHandler(cast(Object)p)) |
|---|
| 504 | 570 | { |
|---|
| … | … | |
| 510 | 576 | dg.ptr = p; |
|---|
| 511 | 577 | dg.funcptr = cast(void function()) c.destructor; |
|---|
| | 578 | debug(PRINTF) printf("\tcalling dtor of %s\n", c.name.ptr); |
|---|
| 512 | 579 | dg(); // call destructor |
|---|
| | 580 | debug(PRINTF) printf("\tdtor done.\n"); |
|---|
| 513 | 581 | } |
|---|
| 514 | 582 | c = c.base; |
|---|
| … | … | |
| 520 | 588 | catch (Exception e) |
|---|
| 521 | 589 | { |
|---|
| | 590 | debug(PRINTF) printf("\tException while finalizing\n"); |
|---|
| 522 | 591 | onFinalizeError(**pc, e); |
|---|
| 523 | 592 | } |
|---|
| … | … | |
| 528 | 597 | } |
|---|
| 529 | 598 | } |
|---|
| | 599 | debug(PRINTF) printf("\tLeaving.\n"); |
|---|
| 530 | 600 | } |
|---|
| 531 | 601 | |
|---|
| … | … | |
| 754 | 824 | } |
|---|
| 755 | 825 | |
|---|
| | 826 | /************************************** |
|---|
| | 827 | * Extend an array by n elements. |
|---|
| | 828 | * Caller must initialize that element. |
|---|
| | 829 | */ |
|---|
| | 830 | extern (C) byte[] _d_arrayappendcTX(TypeInfo ti, inout byte[] x, size_t n) |
|---|
| | 831 | { |
|---|
| | 832 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| | 833 | auto info = gc_query(x.ptr); |
|---|
| | 834 | auto length = x.length; |
|---|
| | 835 | auto newlength = length + n; |
|---|
| | 836 | auto newsize = newlength * sizeelem; |
|---|
| | 837 | |
|---|
| | 838 | assert(info.size == 0 || length * sizeelem <= info.size); |
|---|
| | 839 | |
|---|
| | 840 | //printf("_d_arrayappendcTX(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, cap); |
|---|
| | 841 | |
|---|
| | 842 | if (newsize >= info.size) |
|---|
| | 843 | { byte* newdata; |
|---|
| | 844 | |
|---|
| | 845 | if (info.size >= PAGESIZE) |
|---|
| | 846 | { // Try to extend in-place |
|---|
| | 847 | auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); |
|---|
| | 848 | if (u) |
|---|
| | 849 | { |
|---|
| | 850 | goto L1; |
|---|
| | 851 | } |
|---|
| | 852 | } |
|---|
| | 853 | |
|---|
| | 854 | PointerMap pm; |
|---|
| | 855 | version (D_HavePointerMap) { |
|---|
| | 856 | pm = ti.next.pointermap(); |
|---|
| | 857 | } |
|---|
| | 858 | |
|---|
| | 859 | uint attr = !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0; |
|---|
| | 860 | newdata = cast(byte *) gc_malloc(newCapacity(newlength, sizeelem) + 1, attr, pm); |
|---|
| | 861 | |
|---|
| | 862 | memcpy(newdata, x.ptr, length * sizeelem); |
|---|
| | 863 | |
|---|
| | 864 | (cast(void **)(&x))[1] = newdata; |
|---|
| | 865 | } |
|---|
| | 866 | |
|---|
| | 867 | L1: |
|---|
| | 868 | *cast(size_t *)&x = newlength; |
|---|
| | 869 | assert((cast(size_t)x.ptr & 15) == 0); |
|---|
| | 870 | assert(gc_query(x.ptr).size > x.length * sizeelem); |
|---|
| | 871 | return x; |
|---|
| | 872 | } |
|---|
| | 873 | |
|---|
| 756 | 874 | |
|---|
| 757 | 875 | /** |
|---|
| … | … | |
| 831 | 949 | const size_t a=100; // allocate at most a% of the requested size as extra space (rounding will change this) |
|---|
| 832 | 950 | const size_t minBits=1; // minimum bit size |
|---|
| 833 | | |
|---|
| | 951 | |
|---|
| 834 | 952 | |
|---|
| 835 | 953 | static size_t log2plusB(size_t c) |
|---|
| … | … | |
| 903 | 1021 | } |
|---|
| 904 | 1022 | |
|---|
| | 1023 | import tango.io.Stdout; |
|---|
| 905 | 1024 | |
|---|
| 906 | 1025 | /** |
|---|
| … | … | |
| 1114 | 1233 | auto size = ti.next.tsize(); // array element size |
|---|
| 1115 | 1234 | |
|---|
| 1116 | | p = cast(byte[]*)(&n + 1); |
|---|
| 1117 | | |
|---|
| 1118 | | for (i = 0; i < n; i++) |
|---|
| 1119 | | { |
|---|
| 1120 | | b = *p++; |
|---|
| 1121 | | length += b.length; |
|---|
| 1122 | | } |
|---|
| | 1235 | version (X86) |
|---|
| | 1236 | { |
|---|
| | 1237 | p = cast(byte[]*)(&n + 1); |
|---|
| | 1238 | for (i = 0; i < n; i++) |
|---|
| | 1239 | { |
|---|
| | 1240 | b = *p++; |
|---|
| | 1241 | length += b.length; |
|---|
| | 1242 | } |
|---|
| | 1243 | } |
|---|
| | 1244 | else version (X86_64) |
|---|
| | 1245 | { |
|---|
| | 1246 | __va_list argsave = __va_argsave.va; |
|---|
| | 1247 | va_list ap; |
|---|
| | 1248 | va_start(ap, __va_argsave); |
|---|
| | 1249 | for (i = 0; i < n; i++) |
|---|
| | 1250 | { |
|---|
| | 1251 | b.length = 0; |
|---|
| | 1252 | va_arg(ap, b); |
|---|
| | 1253 | length += b.length; |
|---|
| | 1254 | } |
|---|
| | 1255 | va_end(ap); |
|---|
| | 1256 | } |
|---|
| | 1257 | |
|---|
| 1123 | 1258 | if (!length) |
|---|
| 1124 | 1259 | return null; |
|---|
| … | … | |
| 1129 | 1264 | } |
|---|
| 1130 | 1265 | a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| 1131 | | p = cast(byte[]*)(&n + 1); |
|---|
| 1132 | | |
|---|
| 1133 | | uint j = 0; |
|---|
| 1134 | | for (i = 0; i < n; i++) |
|---|
| 1135 | | { |
|---|
| 1136 | | b = *p++; |
|---|
| 1137 | | if (b.length) |
|---|
| 1138 | | { |
|---|
| 1139 | | memcpy(a + j, b.ptr, b.length * size); |
|---|
| 1140 | | j += b.length * size; |
|---|
| 1141 | | } |
|---|
| | 1266 | |
|---|
| | 1267 | version (X86) |
|---|
| | 1268 | { |
|---|
| | 1269 | p = cast(byte[]*)(&n + 1); |
|---|
| | 1270 | size_t j = 0; |
|---|
| | 1271 | for (i = 0; i < n; i++) |
|---|
| | 1272 | { |
|---|
| | 1273 | b = *p++; |
|---|
| | 1274 | if (b.length) |
|---|
| | 1275 | { |
|---|
| | 1276 | memcpy(a + j, b.ptr, b.length * size); |
|---|
| | 1277 | j += b.length * size; |
|---|
| | 1278 | } |
|---|
| | 1279 | } |
|---|
| | 1280 | } |
|---|
| | 1281 | else version (X86_64) |
|---|
| | 1282 | { |
|---|
| | 1283 | va_list ap2 = &argsave; |
|---|
| | 1284 | size_t j = 0; |
|---|
| | 1285 | for (i = 0; i < n; i++) |
|---|
| | 1286 | { |
|---|
| | 1287 | b.length = 0; |
|---|
| | 1288 | va_arg(ap2, b); |
|---|
| | 1289 | if (b.length) |
|---|
| | 1290 | { |
|---|
| | 1291 | memcpy(a + j, b.ptr, b.length * size); |
|---|
| | 1292 | j += b.length * size; |
|---|
| | 1293 | } |
|---|
| | 1294 | } |
|---|
| | 1295 | va_end(ap2); |
|---|
| 1142 | 1296 | } |
|---|
| 1143 | 1297 | |
|---|
| … | … | |
| 1148 | 1302 | } |
|---|
| 1149 | 1303 | |
|---|
| 1150 | | |
|---|
| 1151 | | /** |
|---|
| 1152 | | * |
|---|
| 1153 | | */ |
|---|
| 1154 | | extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) |
|---|
| | 1304 | extern (C) void* _d_arrayliteralTX(TypeInfo ti, size_t length) |
|---|
| | 1305 | { |
|---|
| | 1306 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| | 1307 | void* result; |
|---|
| | 1308 | |
|---|
| | 1309 | //printf("_d_arrayliteralTX(sizeelem = %d, length = %d)\n", sizeelem, length); |
|---|
| | 1310 | if (length == 0 || sizeelem == 0) |
|---|
| | 1311 | result = null; |
|---|
| | 1312 | else |
|---|
| | 1313 | { |
|---|
| | 1314 | PointerMap pm; |
|---|
| | 1315 | version (D_HavePointerMap) { |
|---|
| | 1316 | pm = ti.next.pointermap(); |
|---|
| | 1317 | } |
|---|
| | 1318 | result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| | 1319 | } |
|---|
| | 1320 | return result; |
|---|
| | 1321 | } |
|---|
| | 1322 | |
|---|
| | 1323 | /** |
|---|
| | 1324 | * |
|---|
| | 1325 | */ |
|---|
| | 1326 | version (X86) extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) |
|---|
| 1155 | 1327 | { |
|---|
| 1156 | 1328 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| … | … | |
| 1168 | 1340 | result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| 1169 | 1341 | |
|---|
| 1170 | | va_list q; |
|---|
| 1171 | | va_start!(size_t)(q, length); |
|---|
| 1172 | | |
|---|
| 1173 | | size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); |
|---|
| 1174 | | |
|---|
| 1175 | | if (stacksize == sizeelem) |
|---|
| 1176 | | { |
|---|
| 1177 | | memcpy(result, q, length * sizeelem); |
|---|
| 1178 | | } |
|---|
| 1179 | | else |
|---|
| 1180 | | { |
|---|
| | 1342 | version(X86) |
|---|
| | 1343 | { |
|---|
| | 1344 | va_list q; |
|---|
| | 1345 | va_start!(size_t)(q, length); |
|---|
| | 1346 | |
|---|
| | 1347 | size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); |
|---|
| | 1348 | |
|---|
| | 1349 | if (stacksize == sizeelem) |
|---|
| | 1350 | { |
|---|
| | 1351 | memcpy(result, q, length * sizeelem); |
|---|
| | 1352 | } |
|---|
| | 1353 | else |
|---|
| | 1354 | { |
|---|
| | 1355 | for (size_t i = 0; i < length; i++) |
|---|
| | 1356 | { |
|---|
| | 1357 | memcpy(result + i * sizeelem, q, sizeelem); |
|---|
| | 1358 | q += stacksize; |
|---|
| | 1359 | } |
|---|
| | 1360 | } |
|---|
| | 1361 | |
|---|
| | 1362 | va_end(q); |
|---|
| | 1363 | } |
|---|
| | 1364 | else version(X86_64) |
|---|
| | 1365 | { |
|---|
| | 1366 | va_list q; |
|---|
| | 1367 | va_start(q, __va_argsave); |
|---|
| 1181 | 1368 | for (size_t i = 0; i < length; i++) |
|---|
| 1182 | 1369 | { |
|---|
| 1183 | | memcpy(result + i * sizeelem, q, sizeelem); |
|---|
| 1184 | | q += stacksize; |
|---|
| 1185 | | } |
|---|
| 1186 | | } |
|---|
| 1187 | | |
|---|
| 1188 | | va_end(q); |
|---|
| | 1370 | va_arg(q, ti.next, result + i * sizeelem); |
|---|
| | 1371 | } |
|---|
| | 1372 | va_end(q); |
|---|
| | 1373 | } |
|---|
| 1189 | 1374 | } |
|---|
| 1190 | 1375 | return result; |
|---|
| … | … | |
| 1205 | 1390 | * |
|---|
| 1206 | 1391 | */ |
|---|
| 1207 | | extern (C) long _adDupT(TypeInfo ti, Array2 a) |
|---|
| | 1392 | extern (C) array_t _adDupT(TypeInfo ti, Array2 a) |
|---|
| 1208 | 1393 | out (result) |
|---|
| 1209 | 1394 | { |
|---|
| … | … | |
| 1227 | 1412 | memcpy(r.ptr, a.ptr, size); |
|---|
| 1228 | 1413 | } |
|---|
| 1229 | | return *cast(long*)(&r); |
|---|
| | 1414 | return *cast(array_t*)(&r); |
|---|
| 1230 | 1415 | } |
|---|
| 1231 | 1416 | |
|---|
| r5149 |
r5652 |
|
| 110 | 110 | } |
|---|
| 111 | 111 | } |
|---|
| | 112 | else version( D_InlineAsm_X86_64 ) |
|---|
| | 113 | { |
|---|
| | 114 | asm |
|---|
| | 115 | { |
|---|
| | 116 | naked; |
|---|
| | 117 | mov RAX, RSP; |
|---|
| | 118 | ret; |
|---|
| | 119 | } |
|---|
| | 120 | } |
|---|
| 112 | 121 | else |
|---|
| 113 | 122 | { |
|---|
| … | … | |
| 156 | 165 | } |
|---|
| 157 | 166 | } |
|---|
| 158 | | |
|---|
| | 167 | |
|---|
| 159 | 168 | version (Solaris) |
|---|
| 160 | 169 | { |
|---|
| r5015 |
r5652 |
|
| 42 | 42 | } |
|---|
| 43 | 43 | |
|---|
| | 44 | |
|---|
| 44 | 45 | int *_memset32(int *p, int value, size_t count) |
|---|
| 45 | 46 | { |
|---|
| 46 | | version (X86) |
|---|
| | 47 | version (D_InlineAsm_X86) |
|---|
| 47 | 48 | { |
|---|
| 48 | 49 | asm |
|---|
| … | … | |
| 119 | 120 | return pstart; |
|---|
| 120 | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | float *_memsetFloat(float *p, float value, size_t count) |
|---|
| | 124 | { |
|---|
| | 125 | float *pstart = p; |
|---|
| | 126 | float *ptop; |
|---|
| | 127 | |
|---|
| | 128 | for (ptop = &p[count]; p < ptop; p++) |
|---|
| | 129 | *p = value; |
|---|
| | 130 | return pstart; |
|---|
| | 131 | } |
|---|
| | 132 | |
|---|
| | 133 | double *_memsetDouble(double *p, double value, size_t count) |
|---|
| | 134 | { |
|---|
| | 135 | double *pstart = p; |
|---|
| | 136 | double *ptop; |
|---|
| | 137 | |
|---|
| | 138 | for (ptop = &p[count]; p < ptop; p++) |
|---|
| | 139 | *p = value; |
|---|
| | 140 | return pstart; |
|---|
| | 141 | } |
|---|
| r5015 |
r5652 |
|
| 18 | 18 | import rt.compiler.util.string; |
|---|
| 19 | 19 | import tango.stdc.string : memset, memcpy, strlen; |
|---|
| 20 | | import tango.stdc.stdlib : malloc, free, exit, strtoul, strtoull, qsort, |
|---|
| | 20 | import tango.stdc.stdlib : malloc, free, exit, strtoul, strtoull, qsort, |
|---|
| 21 | 21 | EXIT_FAILURE; |
|---|
| 22 | 22 | import tango.stdc.ctype : isspace, isalpha, isgraph; |
|---|
| … | … | |
| 788 | 788 | * ascii string |
|---|
| 789 | 789 | */ |
|---|
| 790 | | |
|---|
| 791 | | version (OSX) { // 16 byte align stack |
|---|
| 792 | | asm { |
|---|
| 793 | | naked ; |
|---|
| 794 | | pushad ; |
|---|
| 795 | | mov ECX,8*4[ESP] ; |
|---|
| 796 | | xor EAX,EAX ; |
|---|
| 797 | | mov AL,[ECX] ; |
|---|
| 798 | | cmp AL,0xFF ; |
|---|
| 799 | | jne L1 ; |
|---|
| 800 | | cmp byte ptr 1[ECX],0 ; |
|---|
| 801 | | jne L1 ; |
|---|
| 802 | | mov AX,2[ECX] ; |
|---|
| 803 | | add 8*4[ESP],3 ; |
|---|
| 804 | | add ECX,3 ; |
|---|
| 805 | | L1: inc EAX ; |
|---|
| 806 | | inc ECX ; |
|---|
| 807 | | add 8*4[ESP],EAX ; |
|---|
| 808 | | dec EAX ; |
|---|
| 809 | | sub ESP,4 ; |
|---|
| 810 | | push ECX ; |
|---|
| 811 | | push EAX ; |
|---|
| 812 | | call trace_pro ; |
|---|
| 813 | | add ESP,12 ; |
|---|
| 814 | | popad ; |
|---|
| 815 | | ret ; |
|---|
| 816 | | } |
|---|
| 817 | | } else { |
|---|
| 818 | | asm { |
|---|
| 819 | | naked ; |
|---|
| 820 | | pushad ; |
|---|
| 821 | | mov ECX,8*4[ESP] ; |
|---|
| 822 | | xor EAX,EAX ; |
|---|
| 823 | | mov AL,[ECX] ; |
|---|
| 824 | | cmp AL,0xFF ; |
|---|
| 825 | | jne L1 ; |
|---|
| 826 | | cmp byte ptr 1[ECX],0 ; |
|---|
| 827 | | jne L1 ; |
|---|
| 828 | | mov AX,2[ECX] ; |
|---|
| 829 | | add 8*4[ESP],3 ; |
|---|
| 830 | | add ECX,3 ; |
|---|
| 831 | | L1: inc EAX ; |
|---|
| 832 | | inc ECX ; |
|---|
| 833 | | add 8*4[ESP],EAX ; |
|---|
| 834 | | dec EAX ; |
|---|
| 835 | | push ECX ; |
|---|
| 836 | | push EAX ; |
|---|
| 837 | | call trace_pro ; |
|---|
| 838 | | add ESP,8 ; |
|---|
| 839 | | popad ; |
|---|
| 840 | | ret ; |
|---|
| 841 | | } |
|---|
| 842 | | } |
|---|
| | 790 | version (OSX) |
|---|
| | 791 | { // 16 byte align stack |
|---|
| | 792 | version (D_InlineAsm_X86) |
|---|
| | 793 | asm |
|---|
| | 794 | { naked ; |
|---|
| | 795 | pushad ; |
|---|
| | 796 | mov ECX,8*4[ESP] ; |
|---|
| | 797 | xor EAX,EAX ; |
|---|
| | 798 | mov AL,[ECX] ; |
|---|
| | 799 | cmp AL,0xFF ; |
|---|
| | 800 | jne L1 ; |
|---|
| | 801 | cmp byte ptr 1[ECX],0 ; |
|---|
| | 802 | jne L1 ; |
|---|
| | 803 | mov AX,2[ECX] ; |
|---|
| | 804 | add 8*4[ESP],3 ; |
|---|
| | 805 | add ECX,3 ; |
|---|
| | 806 | L1: inc EAX ; |
|---|
| | 807 | inc ECX ; |
|---|
| | 808 | add 8*4[ESP],EAX ; |
|---|
| | 809 | dec EAX ; |
|---|
| | 810 | sub ESP,4 ; |
|---|
| | 811 | push ECX ; |
|---|
| | 812 | push EAX ; |
|---|
| | 813 | call trace_pro ; |
|---|
| | 814 | add ESP,12 ; |
|---|
| | 815 | popad ; |
|---|
| | 816 | ret ; |
|---|
| | 817 | } |
|---|
| | 818 | else version (D_InlineAsm_X86_64) |
|---|
| | 819 | static assert(0); |
|---|
| | 820 | else |
|---|
| | 821 | static assert(0); |
|---|
| | 822 | } |
|---|
| | 823 | else |
|---|
| | 824 | { |
|---|
| | 825 | version (D_InlineAsm_X86) |
|---|
| | 826 | asm |
|---|
| | 827 | { naked ; |
|---|
| | 828 | pushad ; |
|---|
| | 829 | mov ECX,8*4[ESP] ; |
|---|
| | 830 | xor EAX,EAX ; |
|---|
| | 831 | mov AL,[ECX] ; |
|---|
| | 832 | cmp AL,0xFF ; |
|---|
| | 833 | jne L1 ; |
|---|
| | 834 | cmp byte ptr 1[ECX],0 ; |
|---|
| | 835 | jne L1 ; |
|---|
| | 836 | mov AX,2[ECX] ; |
|---|
| | 837 | add 8*4[ESP],3 ; |
|---|
| | 838 | add ECX,3 ; |
|---|
| | 839 | L1: inc EAX ; |
|---|
| | 840 | inc ECX ; |
|---|
| | 841 | add 8*4[ESP],EAX ; |
|---|
| | 842 | dec EAX ; |
|---|
| | 843 | push ECX ; |
|---|
| | 844 | push EAX ; |
|---|
| | 845 | call trace_pro ; |
|---|
| | 846 | add ESP,8 ; |
|---|
| | 847 | popad ; |
|---|
| | 848 | ret ; |
|---|
| | 849 | } |
|---|
| | 850 | else version (D_InlineAsm_X86_64) |
|---|
| | 851 | asm |
|---|
| | 852 | { naked ; |
|---|
| | 853 | push RAX ; |
|---|
| | 854 | push RCX ; |
|---|
| | 855 | push RDX ; |
|---|
| | 856 | push RSI ; |
|---|
| | 857 | push RDI ; |
|---|
| | 858 | push R8 ; |
|---|
| | 859 | push R9 ; |
|---|
| | 860 | push R10 ; |
|---|
| | 861 | push R11 ; |
|---|
| | 862 | mov RCX,9*8[RSP] ; |
|---|
| | 863 | xor RAX,RAX ; |
|---|
| | 864 | mov AL,[RCX] ; |
|---|
| | 865 | cmp AL,0xFF ; |
|---|
| | 866 | jne L1 ; |
|---|
| | 867 | cmp byte ptr 1[RCX],0 ; |
|---|
| | 868 | jne L1 ; |
|---|
| | 869 | mov AX,2[RCX] ; |
|---|
| | 870 | add 9*8[RSP],3 ; |
|---|
| | 871 | add RCX,3 ; |
|---|
| | 872 | L1: inc RAX ; |
|---|
| | 873 | inc RCX ; |
|---|
| | 874 | add 9*8[RSP],RAX ; |
|---|
| | 875 | dec RAX ; |
|---|
| | 876 | push RCX ; |
|---|
| | 877 | push RAX ; |
|---|
| | 878 | call trace_pro ; |
|---|
| | 879 | add RSP,16 ; |
|---|
| | 880 | pop R11 ; |
|---|
| | 881 | pop R10 ; |
|---|
| | 882 | pop R8 ; |
|---|
| | 883 | pop R9 ; |
|---|
| | 884 | pop RDI ; |
|---|
| | 885 | pop RSI ; |
|---|
| | 886 | pop RDX ; |
|---|
| | 887 | pop RCX ; |
|---|
| | 888 | pop RAX ; |
|---|
| | 889 | ret ; |
|---|
| | 890 | } |
|---|
| | 891 | else |
|---|
| | 892 | static assert(0); |
|---|
| | 893 | } |
|---|
| 843 | 894 | } |
|---|
| 844 | 895 | |
|---|
| … | … | |
| 907 | 958 | } |
|---|
| 908 | 959 | } |
|---|
| | 960 | else version (D_InlineAsm_X86_64) |
|---|
| | 961 | { |
|---|
| | 962 | extern (D) |
|---|
| | 963 | { |
|---|
| | 964 | void QueryPerformanceCounter(timer_t* ctr) |
|---|
| | 965 | { |
|---|
| | 966 | asm |
|---|
| | 967 | { |
|---|
| | 968 | naked ; |
|---|
| | 969 | rdtsc ; |
|---|
| | 970 | mov [RDI],EAX ; |
|---|
| | 971 | mov 4[RDI],EDX ; |
|---|
| | 972 | ret ; |
|---|
| | 973 | } |
|---|
| | 974 | } |
|---|
| | 975 | |
|---|
| | 976 | void QueryPerformanceFrequency(timer_t* freq) |
|---|
| | 977 | { |
|---|
| | 978 | *freq = 3579545; |
|---|
| | 979 | } |
|---|
| | 980 | } |
|---|
| | 981 | } |
|---|
| 909 | 982 | else |
|---|
| 910 | 983 | { |
|---|
| r5594 |
r5652 |
|
| 7 | 7 | * integrated in with intrinsic functions, bringing to bear their full power on |
|---|
| 8 | 8 | * them. This can result in some surprising speedups. |
|---|
| 9 | | * |
|---|
| | 9 | * |
|---|
| 10 | 10 | * Note that this module is only present in Tango because the module name is |
|---|
| 11 | | * hardcoded into DMD, see http://d.puremagic.com/issues/show_bug.cgi?id=178 |
|---|
| | 11 | * hardcoded into DMD, see http://d.puremagic.com/issues/show_bug.cgi?id=178 |
|---|
| 12 | 12 | * To correctly use this functionality in Tango, import tango.core.BitManip. |
|---|
| 13 | 13 | * |
|---|
| … | … | |
| 26 | 26 | * The return value is undefined if v is zero. |
|---|
| 27 | 27 | */ |
|---|
| 28 | | int bsf( uint v ); |
|---|
| | 28 | int bsf( size_t v ); |
|---|
| 29 | 29 | |
|---|
| 30 | 30 | |
|---|
| … | … | |
| 134 | 134 | </pre> |
|---|
| 135 | 135 | */ |
|---|
| | 136 | |
|---|
| 136 | 137 | int bts( size_t* p, size_t bitnum ); |
|---|
| 137 | | |
|---|
| 138 | 138 | |
|---|
| 139 | 139 | /** |
|---|
| r4974 |
r5652 |
|
| 83 | 83 | } |
|---|
| 84 | 84 | |
|---|
| | 85 | override size_t talign() |
|---|
| | 86 | { |
|---|
| | 87 | return (Object[]).alignof; |
|---|
| | 88 | } |
|---|
| | 89 | |
|---|
| 85 | 90 | override size_t tsize() |
|---|
| 86 | 91 | { |
|---|
| … | … | |
| 97 | 102 | return typeid(Object); |
|---|
| 98 | 103 | } |
|---|
| | 104 | |
|---|
| | 105 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 106 | { |
|---|
| | 107 | return 0; |
|---|
| | 108 | } |
|---|
| 99 | 109 | } |
|---|
| r4974 |
r5652 |
|
| 76 | 76 | } |
|---|
| 77 | 77 | |
|---|
| | 78 | override size_t talign() |
|---|
| | 79 | { |
|---|
| | 80 | return (cdouble[]).alignof; |
|---|
| | 81 | } |
|---|
| | 82 | |
|---|
| 78 | 83 | override size_t tsize() |
|---|
| 79 | 84 | { |
|---|
| … | … | |
| 90 | 95 | return typeid(cdouble); |
|---|
| 91 | 96 | } |
|---|
| | 97 | |
|---|
| | 98 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 99 | { |
|---|
| | 100 | return 0; |
|---|
| | 101 | } |
|---|
| 92 | 102 | } |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (cfloat[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(cfloat); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (creal[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(creal); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (double[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(double); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| 94 | 104 | |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (float[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(float); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| 94 | 104 | |
|---|
| r5012 |
r5652 |
|
| 47 | 47 | return 1; |
|---|
| 48 | 48 | return 0; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | override size_t talign() |
|---|
| | 52 | { |
|---|
| | 53 | return (byte[]).alignof; |
|---|
| 49 | 54 | } |
|---|
| 50 | 55 | |
|---|
| … | … | |
| 118 | 123 | override hash_t getHash(in void* p){ |
|---|
| 119 | 124 | char[] s = *cast(char[]*)p; |
|---|
| | 125 | |
|---|
| 120 | 126 | version (OldHash) |
|---|
| 121 | 127 | { |
|---|
| … | … | |
| 134 | 140 | return typeid(char); |
|---|
| 135 | 141 | } |
|---|
| | 142 | |
|---|
| | 143 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 144 | { |
|---|
| | 145 | return 0; |
|---|
| | 146 | } |
|---|
| 136 | 147 | } |
|---|
| r5012 |
r5652 |
|
| 48 | 48 | } |
|---|
| 49 | 49 | |
|---|
| | 50 | override size_t talign() |
|---|
| | 51 | { |
|---|
| | 52 | return (int[]).alignof; |
|---|
| | 53 | } |
|---|
| | 54 | |
|---|
| 50 | 55 | override size_t tsize() |
|---|
| 51 | 56 | { |
|---|
| … | … | |
| 61 | 66 | { |
|---|
| 62 | 67 | return typeid(int); |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 71 | { |
|---|
| | 72 | return 0; |
|---|
| 63 | 73 | } |
|---|
| 64 | 74 | } |
|---|
| r5012 |
r5652 |
|
| 49 | 49 | } |
|---|
| 50 | 50 | |
|---|
| | 51 | override size_t talign() |
|---|
| | 52 | { |
|---|
| | 53 | return (long[]).alignof; |
|---|
| | 54 | } |
|---|
| | 55 | |
|---|
| 51 | 56 | override size_t tsize() |
|---|
| 52 | 57 | { |
|---|
| … | … | |
| 62 | 67 | { |
|---|
| 63 | 68 | return typeid(long); |
|---|
| | 69 | } |
|---|
| | 70 | |
|---|
| | 71 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 72 | { |
|---|
| | 73 | return 0; |
|---|
| 64 | 74 | } |
|---|
| 65 | 75 | } |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (real[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(real); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| 94 | 104 | |
|---|
| r5012 |
r5652 |
|
| 48 | 48 | } |
|---|
| 49 | 49 | |
|---|
| | 50 | override size_t talign() |
|---|
| | 51 | { |
|---|
| | 52 | return (short[]).alignof; |
|---|
| | 53 | } |
|---|
| | 54 | |
|---|
| 50 | 55 | override size_t tsize() |
|---|
| 51 | 56 | { |
|---|
| … | … | |
| 61 | 66 | { |
|---|
| 62 | 67 | return typeid(short); |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 71 | { |
|---|
| | 72 | arg1 = typeid(size_t); |
|---|
| | 73 | arg2 = typeid(void*); |
|---|
| | 74 | return 0; |
|---|
| 63 | 75 | } |
|---|
| 64 | 76 | } |
|---|
| r4974 |
r5652 |
|
| 63 | 63 | } |
|---|
| 64 | 64 | |
|---|
| | 65 | override size_t talign() |
|---|
| | 66 | { |
|---|
| | 67 | return Object.alignof; |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| 65 | 70 | override size_t tsize() |
|---|
| 66 | 71 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return byte.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return cdouble.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| … | … | |
| 64 | 69 | return (cast(cdouble *)&r)[0 .. 1]; |
|---|
| 65 | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 73 | { |
|---|
| | 74 | return 0; |
|---|
| | 75 | } |
|---|
| 66 | 76 | } |
|---|
| r4974 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return cfloat.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| … | … | |
| 64 | 69 | return (cast(cfloat *)&r)[0 .. 1]; |
|---|
| 65 | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 73 | { |
|---|
| | 74 | arg1 = typeid(double); |
|---|
| | 75 | return 0; |
|---|
| | 76 | } |
|---|
| 66 | 77 | } |
|---|
| r4974 |
r5652 |
|
| 21 | 21 | } |
|---|
| 22 | 22 | |
|---|
| | 23 | override size_t talign() |
|---|
| | 24 | { |
|---|
| | 25 | return char.alignof; |
|---|
| | 26 | } |
|---|
| | 27 | |
|---|
| 23 | 28 | override size_t tsize() |
|---|
| 24 | 29 | { |
|---|
| r4974 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return creal.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| … | … | |
| 64 | 69 | return (cast(creal *)&r)[0 .. 1]; |
|---|
| 65 | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 73 | { |
|---|
| | 74 | arg1 = typeid(real); |
|---|
| | 75 | arg2 = typeid(real); |
|---|
| | 76 | return 0; |
|---|
| | 77 | } |
|---|
| 66 | 78 | } |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return dchar.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 19 | 19 | } |
|---|
| 20 | 20 | |
|---|
| | 21 | override size_t talign() |
|---|
| | 22 | { |
|---|
| | 23 | return dg.alignof; |
|---|
| | 24 | } |
|---|
| | 25 | |
|---|
| 21 | 26 | override size_t tsize() |
|---|
| 22 | 27 | { |
|---|
| … | … | |
| 37 | 42 | return 1; |
|---|
| 38 | 43 | } |
|---|
| | 44 | |
|---|
| | 45 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 46 | { |
|---|
| | 47 | arg1 = typeid(void*); |
|---|
| | 48 | arg2 = typeid(void*); |
|---|
| | 49 | return 0; |
|---|
| | 50 | } |
|---|
| 39 | 51 | } |
|---|
| r4974 |
r5652 |
|
| 44 | 44 | } |
|---|
| 45 | 45 | |
|---|
| | 46 | override size_t talign() |
|---|
| | 47 | { |
|---|
| | 48 | return double.alignof; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| 46 | 51 | override size_t tsize() |
|---|
| 47 | 52 | { |
|---|
| r4974 |
r5652 |
|
| 43 | 43 | } |
|---|
| 44 | 44 | |
|---|
| | 45 | override size_t talign() |
|---|
| | 46 | { |
|---|
| | 47 | return float.alignof; |
|---|
| | 48 | } |
|---|
| | 49 | |
|---|
| 45 | 50 | override size_t tsize() |
|---|
| 46 | 51 | { |
|---|
| r4974 |
r5652 |
|
| 27 | 27 | } |
|---|
| 28 | 28 | |
|---|
| | 29 | override size_t talign() |
|---|
| | 30 | { |
|---|
| | 31 | return int.alignof; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| 29 | 34 | override size_t tsize() |
|---|
| 30 | 35 | { |
|---|
| r4974 |
r5652 |
|
| 32 | 32 | } |
|---|
| 33 | 33 | |
|---|
| | 34 | override size_t talign() |
|---|
| | 35 | { |
|---|
| | 36 | return long.alignof; |
|---|
| | 37 | } |
|---|
| | 38 | |
|---|
| 34 | 39 | override size_t tsize() |
|---|
| 35 | 40 | { |
|---|
| r4974 |
r5652 |
|
| 26 | 26 | } |
|---|
| 27 | 27 | |
|---|
| | 28 | override size_t talign() |
|---|
| | 29 | { |
|---|
| | 30 | return (void*).alignof; |
|---|
| | 31 | } |
|---|
| | 32 | |
|---|
| 28 | 33 | override size_t tsize() |
|---|
| 29 | 34 | { |
|---|
| r4974 |
r5652 |
|
| 44 | 44 | } |
|---|
| 45 | 45 | |
|---|
| | 46 | override size_t talign() |
|---|
| | 47 | { |
|---|
| | 48 | return real.alignof; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| 46 | 51 | override size_t tsize() |
|---|
| 47 | 52 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return short.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return ubyte.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 27 | 27 | } |
|---|
| 28 | 28 | |
|---|
| | 29 | override size_t talign() |
|---|
| | 30 | { |
|---|
| | 31 | return uint.alignof; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| 29 | 34 | override size_t tsize() |
|---|
| 30 | 35 | { |
|---|
| r4974 |
r5652 |
|
| 32 | 32 | } |
|---|
| 33 | 33 | |
|---|
| | 34 | override size_t talign() |
|---|
| | 35 | { |
|---|
| | 36 | return ulong.alignof; |
|---|
| | 37 | } |
|---|
| | 38 | |
|---|
| 34 | 39 | override size_t tsize() |
|---|
| 35 | 40 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return ushort.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return void.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 22 | 22 | } |
|---|
| 23 | 23 | |
|---|
| | 24 | override size_t talign() |
|---|
| | 25 | { |
|---|
| | 26 | return wchar.alignof; |
|---|
| | 27 | } |
|---|
| | 28 | |
|---|
| 24 | 29 | override size_t tsize() |
|---|
| 25 | 30 | { |
|---|
| r5609 |
r5652 |
|
| 47 | 47 | import rt.compiler.gdc.rt.aaA; |
|---|
| 48 | 48 | import tango.core.Exception : onOutOfMemoryError; |
|---|
| 49 | | debug(PRINTF) import tango.stdc.stdio : printf; |
|---|
| | 49 | import tango.stdc.stdio : printf; |
|---|
| 50 | 50 | extern (C) Object _d_newclass(ClassInfo ci); |
|---|
| 51 | 51 | } |
|---|
| 52 | 52 | |
|---|
| 53 | | // NOTE: For some reason, this declaration method doesn't work |
|---|
| 54 | | // in this particular file (and this file only). It must |
|---|
| 55 | | // be a DMD thing. |
|---|
| 56 | 53 | alias typeof(int.sizeof) size_t; |
|---|
| 57 | 54 | alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; |
|---|
| 58 | | /+ |
|---|
| 59 | | version( X86_64 ) |
|---|
| 60 | | { |
|---|
| 61 | | alias ulong size_t; |
|---|
| 62 | | alias long ptrdiff_t; |
|---|
| 63 | | } |
|---|
| 64 | | else |
|---|
| 65 | | { |
|---|
| 66 | | alias uint size_t; |
|---|
| 67 | | alias int ptrdiff_t; |
|---|
| 68 | | } |
|---|
| 69 | | +/ |
|---|
| | 55 | |
|---|
| 70 | 56 | alias size_t hash_t; |
|---|
| 71 | 57 | alias int equals_t; |
|---|
| 72 | 58 | |
|---|
| 73 | | version (PhobosCompatibility) |
|---|
| 74 | | { |
|---|
| | 59 | version (PhobosCompatibility) |
|---|
| | 60 | { |
|---|
| 75 | 61 | alias char[] string; |
|---|
| 76 | 62 | alias wchar[] wstring; |
|---|
| … | … | |
| 84 | 70 | { |
|---|
| 85 | 71 | /** |
|---|
| 86 | | * Override this to capture an explicit delete or an implicit |
|---|
| | 72 | * Override this to capture an explicit delete or an implicit |
|---|
| 87 | 73 | * delete via a scoped-instance. Unlike a dtor(), GC references |
|---|
| 88 | 74 | * are still intact when this method is invoked |
|---|
| … | … | |
| 328 | 314 | foreach (m; ModuleInfo) |
|---|
| 329 | 315 | { |
|---|
| | 316 | if (!m) |
|---|
| | 317 | continue; |
|---|
| | 318 | |
|---|
| 330 | 319 | //writefln("module %s, %d", m.name, m.localClasses.length); |
|---|
| 331 | 320 | foreach (c; m.localClasses) |
|---|
| … | … | |
| 413 | 402 | /// Compares two instances for <, ==, or >. |
|---|
| 414 | 403 | int compare(in void* p1, in void* p2) { return 0; } // throw new Exception("non comparable",__FILE__,__LINE__); |
|---|
| | 404 | |
|---|
| | 405 | /// Return alignment of type |
|---|
| | 406 | size_t talign() { return tsize(); } |
|---|
| 415 | 407 | |
|---|
| 416 | 408 | /// Returns size of the type. |
|---|
| … | … | |
| 470 | 462 | /// Get type information on the contents of the type; null if not available |
|---|
| 471 | 463 | OffsetTypeInfo[] offTi() { return null; } |
|---|
| | 464 | |
|---|
| | 465 | |
|---|
| | 466 | /** Return internal info on arguments fitting into 8byte. |
|---|
| | 467 | * See X86-64 ABI 3.2.3 |
|---|
| | 468 | */ |
|---|
| | 469 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 470 | { |
|---|
| | 471 | arg1 = this; |
|---|
| | 472 | return 0; |
|---|
| | 473 | } |
|---|
| 472 | 474 | } |
|---|
| 473 | 475 | |
|---|
| … | … | |
| 493 | 495 | override TypeInfo next() { return base; } |
|---|
| 494 | 496 | override uint flags() { return base.flags(); } |
|---|
| | 497 | override PointerMap pointermap() { return base.pointermap(); } |
|---|
| 495 | 498 | override void[] init() { return m_init.length ? m_init : base.init(); } |
|---|
| 496 | | override PointerMap pointermap() { return base.pointermap(); } |
|---|
| | 499 | |
|---|
| | 500 | size_t talign() { return base.talign(); } |
|---|
| | 501 | |
|---|
| | 502 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 503 | { |
|---|
| | 504 | return base.argTypes(arg1, arg2); |
|---|
| | 505 | } |
|---|
| 497 | 506 | |
|---|
| 498 | 507 | TypeInfo base; |
|---|
| … | … | |
| 632 | 641 | |
|---|
| 633 | 642 | override uint flags() { return 1; } |
|---|
| | 643 | |
|---|
| | 644 | size_t talign() |
|---|
| | 645 | { |
|---|
| | 646 | return (void[]).alignof; |
|---|
| | 647 | } |
|---|
| | 648 | |
|---|
| | 649 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 650 | { //arg1 = typeid(size_t); |
|---|
| | 651 | //arg2 = typeid(void*); |
|---|
| | 652 | return 0; |
|---|
| | 653 | } |
|---|
| 634 | 654 | |
|---|
| 635 | 655 | override PointerMap pointermap() |
|---|
| … | … | |
| 747 | 767 | TypeInfo value; |
|---|
| 748 | 768 | size_t len; |
|---|
| | 769 | |
|---|
| | 770 | size_t talign() |
|---|
| | 771 | { |
|---|
| | 772 | return value.talign(); |
|---|
| | 773 | } |
|---|
| | 774 | |
|---|
| | 775 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 776 | { |
|---|
| | 777 | arg1 = typeid(void*); |
|---|
| | 778 | return 0; |
|---|
| | 779 | } |
|---|
| | 780 | |
|---|
| 749 | 781 | } |
|---|
| 750 | 782 | |
|---|
| … | … | |
| 815 | 847 | TypeInfo value; |
|---|
| 816 | 848 | TypeInfo key; |
|---|
| | 849 | |
|---|
| | 850 | size_t talign() |
|---|
| | 851 | { |
|---|
| | 852 | return (char[int]).alignof; |
|---|
| | 853 | } |
|---|
| | 854 | |
|---|
| | 855 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 856 | { |
|---|
| | 857 | arg1 = typeid(void*); |
|---|
| | 858 | return 0; |
|---|
| | 859 | } |
|---|
| 817 | 860 | } |
|---|
| 818 | 861 | |
|---|
| … | … | |
| 899 | 942 | |
|---|
| 900 | 943 | TypeInfo next; |
|---|
| | 944 | |
|---|
| | 945 | size_t talign() |
|---|
| | 946 | { |
|---|
| | 947 | alias int delegate() dg; |
|---|
| | 948 | return dg.alignof; |
|---|
| | 949 | } |
|---|
| | 950 | |
|---|
| | 951 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 952 | { //arg1 = typeid(void*); |
|---|
| | 953 | //arg2 = typeid(void*); |
|---|
| | 954 | return 0; |
|---|
| | 955 | } |
|---|
| | 956 | |
|---|
| 901 | 957 | } |
|---|
| 902 | 958 | |
|---|
| … | … | |
| 1111 | 1167 | override uint flags() { return m_flags; } |
|---|
| 1112 | 1168 | |
|---|
| | 1169 | size_t talign() { return m_align; } |
|---|
| | 1170 | |
|---|
| | 1171 | |
|---|
| 1113 | 1172 | char[] name; |
|---|
| 1114 | 1173 | void[] m_init; // initializer; init.ptr == null if 0 initialize |
|---|
| … | … | |
| 1121 | 1180 | |
|---|
| 1122 | 1181 | uint m_flags; |
|---|
| | 1182 | uint m_align; |
|---|
| 1123 | 1183 | |
|---|
| 1124 | 1184 | version (D_HavePointerMap) { |
|---|
| … | … | |
| 1126 | 1186 | |
|---|
| 1127 | 1187 | override PointerMap pointermap() { return m_pointermap; } |
|---|
| | 1188 | } |
|---|
| | 1189 | |
|---|
| | 1190 | version (X86_64) |
|---|
| | 1191 | { |
|---|
| | 1192 | int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 1193 | { |
|---|
| | 1194 | arg1 = m_arg1; |
|---|
| | 1195 | arg2 = m_arg2; |
|---|
| | 1196 | return 0; |
|---|
| | 1197 | } |
|---|
| | 1198 | TypeInfo m_arg1; |
|---|
| | 1199 | TypeInfo m_arg2; |
|---|
| 1128 | 1200 | } |
|---|
| 1129 | 1201 | } |
|---|
| … | … | |
| 1191 | 1263 | |
|---|
| 1192 | 1264 | override PointerMap pointermap() |
|---|
| | 1265 | { |
|---|
| | 1266 | assert(0); |
|---|
| | 1267 | } |
|---|
| | 1268 | |
|---|
| | 1269 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| 1193 | 1270 | { |
|---|
| 1194 | 1271 | assert(0); |
|---|
| … | … | |
| 1246 | 1323 | sink(file); |
|---|
| 1247 | 1324 | sink(":"); |
|---|
| 1248 | | sink(ulongToUtf8(buf, line)); |
|---|
| | 1325 | sink(ulongToUtf8(buf, cast(size_t) line)); |
|---|
| 1249 | 1326 | } |
|---|
| 1250 | 1327 | } |
|---|
| 1251 | | |
|---|
| | 1328 | |
|---|
| 1252 | 1329 | void clear(){ |
|---|
| 1253 | 1330 | line=0; |
|---|
| … | … | |
| 1419 | 1496 | // Win32: this gets initialized by minit.asm |
|---|
| 1420 | 1497 | // linux: this gets initialized in _moduleCtor() |
|---|
| | 1498 | // GDC: mod you I won't do what you tell me. |
|---|
| 1421 | 1499 | extern (C) ModuleInfo[] _moduleinfo_array; |
|---|
| 1422 | 1500 | |
|---|
| 1423 | 1501 | |
|---|
| 1424 | | version (linux) |
|---|
| 1425 | | { |
|---|
| 1426 | | // This linked list is created by a compiler generated function inserted |
|---|
| 1427 | | // into the .ctor list by the compiler. |
|---|
| 1428 | | struct ModuleReference |
|---|
| 1429 | | { |
|---|
| 1430 | | ModuleReference* next; |
|---|
| 1431 | | ModuleInfo mod; |
|---|
| 1432 | | } |
|---|
| 1433 | | |
|---|
| 1434 | | extern (C) ModuleReference* _Dmodule_ref; // start of linked list |
|---|
| 1435 | | } |
|---|
| 1436 | | |
|---|
| 1437 | | version( freebsd ) |
|---|
| 1438 | | { |
|---|
| 1439 | | // This linked list is created by a compiler generated function inserted |
|---|
| 1440 | | // into the .ctor list by the compiler. |
|---|
| 1441 | | struct ModuleReference |
|---|
| 1442 | | { |
|---|
| 1443 | | ModuleReference* next; |
|---|
| 1444 | | ModuleInfo mod; |
|---|
| 1445 | | } |
|---|
| 1446 | | extern (C) ModuleReference *_Dmodule_ref; // start of linked list |
|---|
| 1447 | | } |
|---|
| | 1502 | // This linked list is created by a compiler generated function inserted |
|---|
| | 1503 | // into the .ctor list by the compiler. |
|---|
| | 1504 | struct ModuleReference |
|---|
| | 1505 | { |
|---|
| | 1506 | ModuleReference* next; |
|---|
| | 1507 | ModuleInfo mod; |
|---|
| | 1508 | } |
|---|
| | 1509 | |
|---|
| | 1510 | extern (C) ModuleReference* _Dmodule_ref; // start of linked list |
|---|
| 1448 | 1511 | |
|---|
| 1449 | 1512 | ModuleInfo[] _moduleinfo_dtors; |
|---|
| … | … | |
| 1460 | 1523 | { |
|---|
| 1461 | 1524 | debug(PRINTF) printf("_moduleCtor()\n"); |
|---|
| 1462 | | version (linux) |
|---|
| 1463 | | { |
|---|
| 1464 | | int len = 0; |
|---|
| 1465 | | ModuleReference *mr; |
|---|
| 1466 | | |
|---|
| 1467 | | for (mr = _Dmodule_ref; mr; mr = mr.next) |
|---|
| 1468 | | len++; |
|---|
| 1469 | | _moduleinfo_array = new ModuleInfo[len]; |
|---|
| 1470 | | len = 0; |
|---|
| 1471 | | for (mr = _Dmodule_ref; mr; mr = mr.next) |
|---|
| 1472 | | { _moduleinfo_array[len] = mr.mod; |
|---|
| 1473 | | len++; |
|---|
| 1474 | | } |
|---|
| 1475 | | } |
|---|
| 1476 | | |
|---|
| 1477 | | version( freebsd ) |
|---|
| 1478 | | { |
|---|
| 1479 | | int len = 0; |
|---|
| 1480 | | ModuleReference *mr; |
|---|
| 1481 | | |
|---|
| 1482 | | for (mr = _Dmodule_ref; mr; mr = mr.next) |
|---|
| 1483 | | len++; |
|---|
| 1484 | | _moduleinfo_array = new ModuleInfo[len]; |
|---|
| 1485 | | len = 0; |
|---|
| 1486 | | for (mr = _Dmodule_ref; mr; mr = mr.next) |
|---|
| 1487 | | { |
|---|
| 1488 | | _moduleinfo_array[len] = mr.mod; |
|---|
| 1489 | | len++; |
|---|
| 1490 | | } |
|---|
| 1491 | | } |
|---|
| 1492 | | |
|---|
| 1493 | | version( OSX ) |
|---|
| 1494 | | { |
|---|
| 1495 | | /* The ModuleInfo references are stored in the special segment |
|---|
| 1496 | | * __minfodata, which is bracketed by the segments __minfo_beg |
|---|
| 1497 | | * and __minfo_end. The variables _minfo_beg and _minfo_end |
|---|
| 1498 | | * are of zero size and are in the two bracketing segments, |
|---|
| 1499 | | * respectively. |
|---|
| 1500 | | * |
|---|
| 1501 | | * The __minfo_beg and __minfo_end sections are not put into |
|---|
| 1502 | | * dynamic libraries therefore we cannot use them or the |
|---|
| 1503 | | * _minfo_beg and _minfo_end variables. Instead we loop through |
|---|
| 1504 | | * all the loaded images (executables and dynamic libraries) and |
|---|
| 1505 | | * collect all the ModuleInfo references. |
|---|
| 1506 | | */ |
|---|
| 1507 | | _moduleinfo_array = getSectionData!(ModuleInfo, "__DATA", "__minfodata"); |
|---|
| 1508 | | debug(PRINTF) printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length); |
|---|
| 1509 | | |
|---|
| 1510 | | debug(PRINTF) foreach (m; _moduleinfo_array) |
|---|
| 1511 | | { |
|---|
| 1512 | | //printf("\t%p\n", m); |
|---|
| 1513 | | printf("\t%.*s\n", m.name.length,m.name.ptr); |
|---|
| 1514 | | } |
|---|
| 1515 | | } |
|---|
| 1516 | | |
|---|
| 1517 | | version (Win32) |
|---|
| 1518 | | { |
|---|
| 1519 | | // Ensure module destructors also get called on program termination |
|---|
| 1520 | | //_fatexit(&_STD_moduleDtor); |
|---|
| | 1525 | |
|---|
| | 1526 | int len = 0; |
|---|
| | 1527 | ModuleReference *mr; |
|---|
| | 1528 | |
|---|
| | 1529 | for (mr = _Dmodule_ref; mr; mr = mr.next) |
|---|
| | 1530 | len++; |
|---|
| | 1531 | _moduleinfo_array = new ModuleInfo[len]; |
|---|
| | 1532 | len = 0; |
|---|
| | 1533 | for (mr = _Dmodule_ref; mr; mr = mr.next) |
|---|
| | 1534 | { _moduleinfo_array[len] = mr.mod; |
|---|
| | 1535 | len++; |
|---|
| | 1536 | } |
|---|
| | 1537 | |
|---|
| | 1538 | debug(PRINTF) foreach (m; _moduleinfo_array) |
|---|
| | 1539 | { |
|---|
| | 1540 | //printf("\t%p\n", m); |
|---|
| | 1541 | printf("\t%.*s\n", m.name.length,m.name.ptr); |
|---|
| 1521 | 1542 | } |
|---|
| 1522 | 1543 | |
|---|
| … | … | |
| 1549 | 1570 | if (!m) |
|---|
| 1550 | 1571 | continue; |
|---|
| 1551 | | debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); |
|---|
| | 1572 | debug(PRINTF) printf("\tmodule[%d].name = '%s'\n", i, m.name); |
|---|
| 1552 | 1573 | if (m.flags & MIctordone) |
|---|
| 1553 | 1574 | continue; |
|---|
| … | … | |
| 1559 | 1580 | { if (skip || m.flags & MIstandalone) |
|---|
| 1560 | 1581 | continue; |
|---|
| 1561 | | throw new Exception( "Cyclic dependency in module " ~ (from is null ? "*null*" : from.name) ~ " for import " ~ m.name); |
|---|
| | 1582 | throw new Exception( "Cyclic dependency in module " ~ (from is null ? "*null*" : from.name) ~ " for import " ~ m.name); |
|---|
| 1562 | 1583 | } |
|---|
| 1563 | 1584 | |
|---|
| r5579 |
r5652 |
|
| 26 | 26 | */ |
|---|
| 27 | 27 | |
|---|
| | 28 | module rt.compiler.gdc.rt.aApply; |
|---|
| | 29 | |
|---|
| 28 | 30 | /* |
|---|
| 29 | 31 | * Modified by Sean Kelly <sean@f4.ca> for use with Tango. |
|---|
| … | … | |
| 34 | 36 | * and dchar, and 2 of each of those. |
|---|
| 35 | 37 | */ |
|---|
| 36 | | module rt.compiler.gdc.rt.aApply; |
|---|
| | 38 | |
|---|
| 37 | 39 | private import rt.compiler.util.utf; |
|---|
| 38 | 40 | |
|---|
| … | … | |
| 102 | 104 | else |
|---|
| 103 | 105 | { |
|---|
| 104 | | w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 106 | w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 105 | 107 | result = dg(cast(void *)&w); |
|---|
| 106 | 108 | if (result) |
|---|
| 107 | 109 | break; |
|---|
| 108 | | w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 110 | w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 109 | 111 | } |
|---|
| 110 | 112 | } |
|---|
| … | … | |
| 199 | 201 | else |
|---|
| 200 | 202 | { |
|---|
| 201 | | w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 203 | w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 202 | 204 | result = dg(cast(void *)&w); |
|---|
| 203 | 205 | if (result) |
|---|
| 204 | 206 | break; |
|---|
| 205 | | w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 207 | w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 206 | 208 | } |
|---|
| 207 | 209 | result = dg(cast(void *)&w); |
|---|
| … | … | |
| 290 | 292 | else |
|---|
| 291 | 293 | { |
|---|
| 292 | | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 294 | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 293 | 295 | result = dg(&i, cast(void *)&w); |
|---|
| 294 | 296 | if (result) |
|---|
| 295 | 297 | break; |
|---|
| 296 | | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 298 | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 297 | 299 | } |
|---|
| 298 | 300 | } |
|---|
| … | … | |
| 393 | 395 | else |
|---|
| 394 | 396 | { |
|---|
| 395 | | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 397 | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 396 | 398 | result = dg(&j, cast(void *)&w); |
|---|
| 397 | 399 | if (result) |
|---|
| 398 | 400 | break; |
|---|
| 399 | | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 401 | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 400 | 402 | } |
|---|
| 401 | 403 | result = dg(&j, cast(void *)&w); |
|---|
| r5579 |
r5652 |
|
| 27 | 27 | */ |
|---|
| 28 | 28 | |
|---|
| | 29 | module rt.compiler.gdc.rt.aApplyR; |
|---|
| | 30 | |
|---|
| 29 | 31 | /* |
|---|
| 30 | 32 | * Modified by Sean Kelly <sean@f4.ca> for use with Tango. |
|---|
| … | … | |
| 35 | 37 | * and dchar, and 2 of each of those. |
|---|
| 36 | 38 | */ |
|---|
| 37 | | module rt.compiler.gdc.rt.aApplyR; |
|---|
| | 39 | |
|---|
| 38 | 40 | private import rt.compiler.util.utf; |
|---|
| 39 | 41 | |
|---|
| … | … | |
| 80 | 82 | debug(apply) printf("_aApplyRcd1.unittest\n"); |
|---|
| 81 | 83 | |
|---|
| 82 | | { |
|---|
| 83 | | auto s = "hello"c; |
|---|
| 84 | | int i; |
|---|
| 85 | | |
|---|
| 86 | | foreach_reverse(dchar d; s) |
|---|
| 87 | | { |
|---|
| 88 | | switch (i) |
|---|
| 89 | | { |
|---|
| 90 | | case 0: assert(d == 'o'); break; |
|---|
| 91 | | case 1: assert(d == 'l'); break; |
|---|
| 92 | | case 2: assert(d == 'l'); break; |
|---|
| 93 | | case 3: assert(d == 'e'); break; |
|---|
| 94 | | case 4: assert(d == 'h'); break; |
|---|
| 95 | | default: assert(0); |
|---|
| 96 | | } |
|---|
| 97 | | i++; |
|---|
| 98 | | } |
|---|
| 99 | | assert(i == 5); |
|---|
| 100 | | } |
|---|
| 101 | | |
|---|
| 102 | | { |
|---|
| 103 | | auto s = "a\u1234\U00100456b"c; |
|---|
| 104 | | int i = 0; |
|---|
| 105 | | foreach_reverse(dchar d; s) |
|---|
| 106 | | { |
|---|
| 107 | | //printf("i = %d, d = %x\n", i, d); |
|---|
| 108 | | switch (i) |
|---|
| 109 | | { |
|---|
| 110 | | case 0: assert(d == 'b'); break; |
|---|
| 111 | | case 1: assert(d == '\U00100456'); break; |
|---|
| 112 | | case 2: assert(d == '\u1234'); break; |
|---|
| 113 | | case 3: assert(d == 'a'); break; |
|---|
| 114 | | default: assert(0); |
|---|
| 115 | | } |
|---|
| 116 | | i++; |
|---|
| 117 | | } |
|---|
| 118 | | assert(i == 4); |
|---|
| 119 | | } |
|---|
| | 84 | auto s = "hello"c[]; |
|---|
| | 85 | int i; |
|---|
| | 86 | |
|---|
| | 87 | foreach_reverse(dchar d; s) |
|---|
| | 88 | { |
|---|
| | 89 | switch (i) |
|---|
| | 90 | { |
|---|
| | 91 | case 0: assert(d == 'o'); break; |
|---|
| | 92 | case 1: assert(d == 'l'); break; |
|---|
| | 93 | case 2: assert(d == 'l'); break; |
|---|
| | 94 | case 3: assert(d == 'e'); break; |
|---|
| | 95 | case 4: assert(d == 'h'); break; |
|---|
| | 96 | default: assert(0); |
|---|
| | 97 | } |
|---|
| | 98 | i++; |
|---|
| | 99 | } |
|---|
| | 100 | assert(i == 5); |
|---|
| | 101 | |
|---|
| | 102 | s = "a\u1234\U00100456b"; |
|---|
| | 103 | i = 0; |
|---|
| | 104 | foreach_reverse(dchar d; s) |
|---|
| | 105 | { |
|---|
| | 106 | //printf("i = %d, d = %x\n", i, d); |
|---|
| | 107 | switch (i) |
|---|
| | 108 | { |
|---|
| | 109 | case 0: assert(d == 'b'); break; |
|---|
| | 110 | case 1: assert(d == '\U00100456'); break; |
|---|
| | 111 | case 2: assert(d == '\u1234'); break; |
|---|
| | 112 | case 3: assert(d == 'a'); break; |
|---|
| | 113 | default: assert(0); |
|---|
| | 114 | } |
|---|
| | 115 | i++; |
|---|
| | 116 | } |
|---|
| | 117 | assert(i == 4); |
|---|
| 120 | 118 | } |
|---|
| 121 | 119 | |
|---|
| … | … | |
| 166 | 164 | assert(i == 5); |
|---|
| 167 | 165 | |
|---|
| 168 | | s = "a\u1234\U00100456b"w[]; |
|---|
| | 166 | s = "a\u1234\U00100456b"; |
|---|
| 169 | 167 | i = 0; |
|---|
| 170 | 168 | foreach_reverse(dchar d; s) |
|---|
| … | … | |
| 216 | 214 | else |
|---|
| 217 | 215 | { |
|---|
| 218 | | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 216 | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 219 | 217 | result = dg(cast(void *)&w); |
|---|
| 220 | 218 | if (result) |
|---|
| 221 | 219 | break; |
|---|
| 222 | | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 220 | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 223 | 221 | } |
|---|
| 224 | 222 | } |
|---|
| … | … | |
| 252 | 250 | assert(i == 5); |
|---|
| 253 | 251 | |
|---|
| 254 | | s = "a\u1234\U00100456b"c[]; |
|---|
| | 252 | s = "a\u1234\U00100456b"; |
|---|
| 255 | 253 | i = 0; |
|---|
| 256 | 254 | foreach_reverse(wchar d; s) |
|---|
| … | … | |
| 333 | 331 | assert(i == 5); |
|---|
| 334 | 332 | |
|---|
| 335 | | s = "a\u1234\U00100456b"w[]; |
|---|
| | 333 | s = "a\u1234\U00100456b"; |
|---|
| 336 | 334 | i = 0; |
|---|
| 337 | 335 | foreach_reverse(char d; s) |
|---|
| … | … | |
| 412 | 410 | assert(i == 5); |
|---|
| 413 | 411 | |
|---|
| 414 | | s = "a\u1234\U00100456b"d[]; |
|---|
| | 412 | s = "a\u1234\U00100456b"; |
|---|
| 415 | 413 | i = 0; |
|---|
| 416 | 414 | foreach_reverse(char d; s) |
|---|
| … | … | |
| 449 | 447 | else |
|---|
| 450 | 448 | { |
|---|
| 451 | | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 449 | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 452 | 450 | result = dg(cast(void *)&w); |
|---|
| 453 | 451 | if (result) |
|---|
| 454 | 452 | break; |
|---|
| 455 | | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 453 | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 456 | 454 | } |
|---|
| 457 | 455 | result = dg(cast(void *)&w); |
|---|
| … | … | |
| 484 | 482 | assert(i == 5); |
|---|
| 485 | 483 | |
|---|
| 486 | | s = "a\u1234\U00100456b"d[]; |
|---|
| | 484 | s = "a\u1234\U00100456b"; |
|---|
| 487 | 485 | i = 0; |
|---|
| 488 | 486 | foreach_reverse(wchar d; s) |
|---|
| … | … | |
| 567 | 565 | assert(i == 5); |
|---|
| 568 | 566 | |
|---|
| 569 | | s = "a\u1234\U00100456b"c[]; |
|---|
| | 567 | s = "a\u1234\U00100456b"; |
|---|
| 570 | 568 | i = 0; |
|---|
| 571 | 569 | foreach_reverse(k, dchar d; s) |
|---|
| … | … | |
| 633 | 631 | assert(i == 5); |
|---|
| 634 | 632 | |
|---|
| 635 | | s = "a\u1234\U00100456b"w[]; |
|---|
| | 633 | s = "a\u1234\U00100456b"; |
|---|
| 636 | 634 | i = 0; |
|---|
| 637 | 635 | foreach_reverse(k, dchar d; s) |
|---|
| … | … | |
| 683 | 681 | else |
|---|
| 684 | 682 | { |
|---|
| 685 | | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 683 | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 686 | 684 | result = dg(&i, cast(void *)&w); |
|---|
| 687 | 685 | if (result) |
|---|
| 688 | 686 | break; |
|---|
| 689 | | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 687 | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 690 | 688 | } |
|---|
| 691 | 689 | } |
|---|
| … | … | |
| 721 | 719 | assert(i == 5); |
|---|
| 722 | 720 | |
|---|
| 723 | | s = "a\u1234\U00100456b"c[]; |
|---|
| | 721 | s = "a\u1234\U00100456b"; |
|---|
| 724 | 722 | i = 0; |
|---|
| 725 | 723 | foreach_reverse(k, wchar d; s) |
|---|
| … | … | |
| 804 | 802 | assert(i == 5); |
|---|
| 805 | 803 | |
|---|
| 806 | | s = "a\u1234\U00100456b"w[]; |
|---|
| | 804 | s = "a\u1234\U00100456b"; |
|---|
| 807 | 805 | i = 0; |
|---|
| 808 | 806 | foreach_reverse(k, char d; s) |
|---|
| … | … | |
| 884 | 882 | assert(i == 5); |
|---|
| 885 | 883 | |
|---|
| 886 | | s = "a\u1234\U00100456b"d[]; |
|---|
| | 884 | s = "a\u1234\U00100456b"; |
|---|
| 887 | 885 | i = 0; |
|---|
| 888 | 886 | foreach_reverse(k, char d; s) |
|---|
| … | … | |
| 921 | 919 | else |
|---|
| 922 | 920 | { |
|---|
| 923 | | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 921 | w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| 924 | 922 | result = dg(&i, cast(void *)&w); |
|---|
| 925 | 923 | if (result) |
|---|
| 926 | 924 | break; |
|---|
| 927 | | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 925 | w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| 928 | 926 | } |
|---|
| 929 | 927 | result = dg(&i, cast(void *)&w); |
|---|
| … | … | |
| 958 | 956 | assert(i == 5); |
|---|
| 959 | 957 | |
|---|
| 960 | | s = "a\u1234\U00100456b"d[]; |
|---|
| | 958 | s = "a\u1234\U00100456b"; |
|---|
| 961 | 959 | i = 0; |
|---|
| 962 | 960 | foreach_reverse(k, wchar d; s) |
|---|
| r5609 |
r5652 |
|
| 37 | 37 | * Modified by Sean Kelly <sean@f4.ca> for use with Tango. |
|---|
| 38 | 38 | */ |
|---|
| | 39 | |
|---|
| 39 | 40 | module rt.compiler.gdc.rt.aaA; |
|---|
| | 41 | |
|---|
| 40 | 42 | private |
|---|
| 41 | 43 | { |
|---|
| … | … | |
| 73 | 75 | * gcc will not, so we instead use a 'long'. |
|---|
| 74 | 76 | */ |
|---|
| 75 | | alias long ArrayRet_t; |
|---|
| | 77 | alias void[] ArrayRet_t; |
|---|
| 76 | 78 | |
|---|
| 77 | 79 | struct Array |
|---|
| … | … | |
| 114 | 116 | size_t aligntsize(size_t tsize) |
|---|
| 115 | 117 | { |
|---|
| 116 | | // Is pointer alignment on the x64 4 bytes or 8? |
|---|
| 117 | | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 118 | version (X86_64) |
|---|
| | 119 | // Size of key needed to align value on 16 bytes |
|---|
| | 120 | return (tsize + 15) & ~(15); |
|---|
| | 121 | else |
|---|
| | 122 | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| 118 | 123 | } |
|---|
| 119 | 124 | |
|---|
| … | … | |
| 261 | 266 | if (!aa.a) |
|---|
| 262 | 267 | aa.a = new BB(); |
|---|
| | 268 | |
|---|
| 263 | 269 | aa.a.keyti = keyti; |
|---|
| 264 | 270 | |
|---|
| … | … | |
| 272 | 278 | |
|---|
| 273 | 279 | auto key_hash = keyti.getHash(pkey); |
|---|
| | 280 | |
|---|
| 274 | 281 | //printf("hash = %d\n", key_hash); |
|---|
| | 282 | |
|---|
| 275 | 283 | i = key_hash % aa.a.b.length; |
|---|
| 276 | 284 | auto pe = &aa.a.b[i]; |
|---|
| | 285 | |
|---|
| 277 | 286 | while ((e = *pe) !is null) |
|---|
| 278 | 287 | { |
|---|
| … | … | |
| 364 | 373 | if (aa.a) |
|---|
| 365 | 374 | { |
|---|
| 366 | | |
|---|
| 367 | 375 | //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); |
|---|
| 368 | 376 | auto len = aa.a.b.length; |
|---|
| … | … | |
| 457 | 465 | */ |
|---|
| 458 | 466 | |
|---|
| 459 | | Array _aaValues(AA aa, size_t keysize, size_t valuesize) |
|---|
| | 467 | ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize) |
|---|
| 460 | 468 | in |
|---|
| 461 | 469 | { |
|---|
| … | … | |
| 499 | 507 | assert(resi == a.length); |
|---|
| 500 | 508 | } |
|---|
| 501 | | return a; |
|---|
| | 509 | return *cast(ArrayRet_t*)(&a); |
|---|
| 502 | 510 | } |
|---|
| 503 | 511 | |
|---|
| … | … | |
| 586 | 594 | _aaRehash_x(e); |
|---|
| 587 | 595 | } |
|---|
| | 596 | delete aa.b; |
|---|
| 588 | 597 | |
|---|
| 589 | 598 | newb.nodes = aa.nodes; |
|---|
| … | … | |
| 592 | 601 | |
|---|
| 593 | 602 | *paa.a = newb; |
|---|
| | 603 | _aaBalance(paa); |
|---|
| 594 | 604 | } |
|---|
| 595 | 605 | return *paa; |
|---|
| 596 | 606 | } |
|---|
| 597 | 607 | |
|---|
| | 608 | /******************************************** |
|---|
| | 609 | * Balance an array. |
|---|
| | 610 | */ |
|---|
| | 611 | |
|---|
| | 612 | void _aaBalance(AA* paa) |
|---|
| | 613 | { |
|---|
| | 614 | //printf("_aaBalance()\n"); |
|---|
| | 615 | if (paa.a) |
|---|
| | 616 | { |
|---|
| | 617 | aaA*[16] tmp; |
|---|
| | 618 | aaA*[] array = tmp; |
|---|
| | 619 | auto aa = paa.a; |
|---|
| | 620 | foreach (j, e; aa.b) |
|---|
| | 621 | { |
|---|
| | 622 | /* Temporarily store contents of bucket in array[] |
|---|
| | 623 | */ |
|---|
| | 624 | size_t k = 0; |
|---|
| | 625 | void addToArray(aaA* e) |
|---|
| | 626 | { |
|---|
| | 627 | while (e) |
|---|
| | 628 | { addToArray(e.left); |
|---|
| | 629 | if (k == array.length) |
|---|
| | 630 | array.length = array.length * 2; |
|---|
| | 631 | array[k++] = e; |
|---|
| | 632 | e = e.right; |
|---|
| | 633 | } |
|---|
| | 634 | } |
|---|
| | 635 | addToArray(e); |
|---|
| | 636 | /* The contents of the bucket are now sorted into array[]. |
|---|
| | 637 | * Rebuild the tree. |
|---|
| | 638 | */ |
|---|
| | 639 | void buildTree(aaA** p, size_t x1, size_t x2) |
|---|
| | 640 | { |
|---|
| | 641 | if (x1 >= x2) |
|---|
| | 642 | *p = null; |
|---|
| | 643 | else |
|---|
| | 644 | { auto mid = (x1 + x2) >> 1; |
|---|
| | 645 | *p = array[mid]; |
|---|
| | 646 | buildTree(&(*p).left, x1, mid); |
|---|
| | 647 | buildTree(&(*p).right, mid + 1, x2); |
|---|
| | 648 | } |
|---|
| | 649 | } |
|---|
| | 650 | auto p = &aa.b[j]; |
|---|
| | 651 | buildTree(p, 0, k); |
|---|
| | 652 | } |
|---|
| | 653 | } |
|---|
| | 654 | } |
|---|
| 598 | 655 | |
|---|
| 599 | 656 | /******************************************** |
|---|
| … | … | |
| 601 | 658 | */ |
|---|
| 602 | 659 | |
|---|
| 603 | | Array _aaKeys(AA aa, size_t keysize) |
|---|
| | 660 | ArrayRet_t _aaKeys(AA aa, size_t keysize) |
|---|
| 604 | 661 | { |
|---|
| 605 | 662 | byte[] res; |
|---|
| … | … | |
| 623 | 680 | } |
|---|
| 624 | 681 | |
|---|
| 625 | | Array a; |
|---|
| 626 | 682 | auto len = _aaLen(aa); |
|---|
| 627 | 683 | if (!len) |
|---|
| 628 | | return a; |
|---|
| | 684 | return null; |
|---|
| 629 | 685 | res = (cast(byte*) gc_malloc(len * keysize, |
|---|
| 630 | 686 | !(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize]; |
|---|
| … | … | |
| 637 | 693 | assert(resi == len); |
|---|
| 638 | 694 | |
|---|
| | 695 | Array a; |
|---|
| 639 | 696 | a.length = len; |
|---|
| 640 | 697 | a.ptr = res.ptr; |
|---|
| 641 | | return a; |
|---|
| | 698 | return *cast(ArrayRet_t*)(&a); |
|---|
| 642 | 699 | } |
|---|
| 643 | 700 | |
|---|
| … | … | |
| 758 | 815 | * length pairs of key/value pairs. |
|---|
| 759 | 816 | */ |
|---|
| 760 | | |
|---|
| 761 | | extern (C) |
|---|
| 762 | | BB* _d_assocarrayliteralTp(TypeInfo_AssociativeArray ti, size_t length, void *keys, void *values) |
|---|
| 763 | | { |
|---|
| 764 | | auto valuesize = ti.next.tsize(); // value size |
|---|
| | 817 | extern (C) BB* _d_assocarrayliteralTp(TypeInfo_AssociativeArray ti, void[] keys, void[] values) |
|---|
| | 818 | { |
|---|
| | 819 | auto valueti = ti.next; |
|---|
| | 820 | auto valuesize = valueti.tsize(); // value size |
|---|
| 765 | 821 | auto keyti = ti.key; |
|---|
| 766 | 822 | auto keysize = keyti.tsize(); // key size |
|---|
| | 823 | auto length = keys.length; |
|---|
| 767 | 824 | BB* result; |
|---|
| 768 | 825 | |
|---|
| 769 | 826 | //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length); |
|---|
| 770 | 827 | //printf("tivalue = %.*s\n", ti.next.classinfo.name); |
|---|
| | 828 | assert(length == values.length); |
|---|
| 771 | 829 | if (length == 0 || valuesize == 0 || keysize == 0) |
|---|
| 772 | 830 | { |
|---|
| … | … | |
| 775 | 833 | else |
|---|
| 776 | 834 | { |
|---|
| 777 | | //va_list q; |
|---|
| 778 | | //va_start!(size_t)(q, length); |
|---|
| 779 | | void * qkey = keys; |
|---|
| 780 | | void * qval = values; |
|---|
| 781 | | |
|---|
| 782 | 835 | result = new BB(); |
|---|
| 783 | | result.keyti = keyti; |
|---|
| | 836 | |
|---|
| 784 | 837 | size_t i; |
|---|
| 785 | | |
|---|
| 786 | 838 | for (i = 0; i < prime_list.length - 1; i++) |
|---|
| 787 | 839 | { |
|---|
| … | … | |
| 792 | 844 | result.b = new aaA*[len]; |
|---|
| 793 | 845 | |
|---|
| 794 | | size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1); |
|---|
| 795 | | size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1); |
|---|
| 796 | | |
|---|
| 797 | 846 | size_t keytsize = aligntsize(keysize); |
|---|
| 798 | 847 | |
|---|
| 799 | 848 | for (size_t j = 0; j < length; j++) |
|---|
| 800 | | { void* pkey = qkey; |
|---|
| 801 | | //q += keystacksize; |
|---|
| 802 | | qkey += keysize; |
|---|
| 803 | | void* pvalue = qval; |
|---|
| 804 | | //q += valuestacksize; |
|---|
| 805 | | qval += valuesize; |
|---|
| | 849 | { auto pkey = keys.ptr + j * keysize; |
|---|
| | 850 | auto pvalue = values.ptr + j * valuesize; |
|---|
| 806 | 851 | aaA* e; |
|---|
| 807 | 852 | |
|---|
| … | … | |
| 836 | 881 | memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize); |
|---|
| 837 | 882 | } |
|---|
| 838 | | |
|---|
| 839 | | //va_end(q); |
|---|
| 840 | 883 | } |
|---|
| 841 | 884 | return result; |
|---|
| 842 | 885 | } |
|---|
| 843 | 886 | |
|---|
| 844 | | |
|---|
| | 887 | /*********************************** |
|---|
| | 888 | * Compare AA contents for equality. |
|---|
| | 889 | * Returns: |
|---|
| | 890 | * 1 equal |
|---|
| | 891 | * 0 not equal |
|---|
| | 892 | */ |
|---|
| | 893 | int _aaEqual(TypeInfo_AssociativeArray ti, AA e1, AA e2) |
|---|
| | 894 | { |
|---|
| | 895 | //printf("_aaEqual()\n"); |
|---|
| | 896 | //printf("keyti = %.*s\n", ti.key.classinfo.name); |
|---|
| | 897 | //printf("valueti = %.*s\n", ti.next.classinfo.name); |
|---|
| | 898 | |
|---|
| | 899 | if (e1.a is e2.a) |
|---|
| | 900 | return 1; |
|---|
| | 901 | |
|---|
| | 902 | size_t len = _aaLen(e1); |
|---|
| | 903 | if (len != _aaLen(e2)) |
|---|
| | 904 | return 0; |
|---|
| | 905 | |
|---|
| | 906 | /* Algorithm: Visit each key/value pair in e1. If that key doesn't exist |
|---|
| | 907 | * in e2, or if the value in e1 doesn't match the one in e2, the arrays |
|---|
| | 908 | * are not equal, and exit early. |
|---|
| | 909 | * After all pairs are checked, the arrays must be equal. |
|---|
| | 910 | */ |
|---|
| | 911 | |
|---|
| | 912 | auto keyti = ti.key; |
|---|
| | 913 | auto valueti = ti.next; |
|---|
| | 914 | auto keysize = aligntsize(keyti.tsize()); |
|---|
| | 915 | auto len2 = e2.a.b.length; |
|---|
| | 916 | |
|---|
| | 917 | int _aaKeys_x(aaA* e) |
|---|
| | 918 | { |
|---|
| | 919 | do |
|---|
| | 920 | { |
|---|
| | 921 | auto pkey = cast(void*)(e + 1); |
|---|
| | 922 | auto pvalue = pkey + keysize; |
|---|
| | 923 | //printf("key = %d, value = %g\n", *cast(int*)pkey, *cast(double*)pvalue); |
|---|
| | 924 | |
|---|
| | 925 | // We have key/value for e1. See if they exist in e2 |
|---|
| | 926 | |
|---|
| | 927 | auto key_hash = keyti.getHash(pkey); |
|---|
| | 928 | //printf("hash = %d\n", key_hash); |
|---|
| | 929 | auto i = key_hash % len2; |
|---|
| | 930 | auto f = e2.a.b[i]; |
|---|
| | 931 | while (1) |
|---|
| | 932 | { |
|---|
| | 933 | //printf("f is %p\n", f); |
|---|
| | 934 | if (f is null) |
|---|
| | 935 | return 0; // key not found, so AA's are not equal |
|---|
| | 936 | if (key_hash == f.hash) |
|---|
| | 937 | { |
|---|
| | 938 | //printf("hash equals\n"); |
|---|
| | 939 | auto c = keyti.compare(pkey, f + 1); |
|---|
| | 940 | if (c == 0) |
|---|
| | 941 | { // Found key in e2. Compare values |
|---|
| | 942 | //printf("key equals\n"); |
|---|
| | 943 | auto pvalue2 = cast(void *)(f + 1) + keysize; |
|---|
| | 944 | if (valueti.equals(pvalue, pvalue2)) |
|---|
| | 945 | { |
|---|
| | 946 | //printf("value equals\n"); |
|---|
| | 947 | break; |
|---|
| | 948 | } |
|---|
| | 949 | else |
|---|
| | 950 | return 0; // values don't match, so AA's are not equal |
|---|
| | 951 | } |
|---|
| | 952 | f = (c < 0) ? f.left : f.right; |
|---|
| | 953 | } |
|---|
| | 954 | else |
|---|
| | 955 | f = (key_hash < f.hash) ? f.left : f.right; |
|---|
| | 956 | } |
|---|
| | 957 | |
|---|
| | 958 | // Look at next entry in e1 |
|---|
| | 959 | if (e.left) |
|---|
| | 960 | { if (!e.right) |
|---|
| | 961 | { e = e.left; |
|---|
| | 962 | continue; |
|---|
| | 963 | } |
|---|
| | 964 | if (_aaKeys_x(e.left) == 0) |
|---|
| | 965 | return 0; |
|---|
| | 966 | } |
|---|
| | 967 | e = e.right; |
|---|
| | 968 | } while (e !is null); |
|---|
| | 969 | return 1; // this subtree matches |
|---|
| | 970 | } |
|---|
| | 971 | |
|---|
| | 972 | foreach (e; e1.a.b) |
|---|
| | 973 | { |
|---|
| | 974 | if (e) |
|---|
| | 975 | { if (_aaKeys_x(e) == 0) |
|---|
| | 976 | return 0; |
|---|
| | 977 | } |
|---|
| | 978 | } |
|---|
| | 979 | |
|---|
| | 980 | return 1; // equal |
|---|
| | 981 | } |
|---|
| | 982 | |
|---|
| r5609 |
r5652 |
|
| 75 | 75 | */ |
|---|
| 76 | 76 | |
|---|
| 77 | | extern (C) Array _adReverseChar(char[] a) |
|---|
| | 77 | extern (C) char[] _adReverseChar(char[] a) |
|---|
| 78 | 78 | { |
|---|
| 79 | 79 | bool hadErrors=false; |
|---|
| … | … | |
| 103 | 103 | if (stridelo>6) { // invalid UTF-8 0xFF |
|---|
| 104 | 104 | stridelo=1; |
|---|
| 105 | | hadErrors=true; |
|---|
| | 105 | hadErrors=true; |
|---|
| 106 | 106 | } |
|---|
| 107 | 107 | |
|---|
| … | … | |
| 112 | 112 | stridehi++; |
|---|
| 113 | 113 | } |
|---|
| 114 | | if (lo >= hi){ |
|---|
| | 114 | if (lo >= hi) |
|---|
| | 115 | { |
|---|
| 115 | 116 | if (lo>hi){ |
|---|
| 116 | 117 | hadErrors=true; |
|---|
| … | … | |
| 138 | 139 | memcpy(tmp.ptr, hi, stridehi); |
|---|
| 139 | 140 | memcpy(tmplo.ptr, lo, stridelo); |
|---|
| 140 | | memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); |
|---|
| | 141 | memmove(lo + stridehi, lo + stridelo , cast(size_t)((hi - lo) - stridelo)); |
|---|
| 141 | 142 | memcpy(lo, tmp.ptr, stridehi); |
|---|
| 142 | | memcpy(hi + cast(int) stridehi - cast(int) stridelo, tmplo.ptr, stridelo); |
|---|
| | 143 | memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); |
|---|
| 143 | 144 | |
|---|
| 144 | 145 | lo += stridehi; |
|---|
| … | … | |
| 148 | 149 | if (hadErrors) |
|---|
| 149 | 150 | throw new Exception("invalid UTF-8 sequence",__FILE__,__LINE__); |
|---|
| 150 | | return *cast(Array*)(&a); |
|---|
| | 151 | return a; |
|---|
| 151 | 152 | } |
|---|
| 152 | 153 | |
|---|
| 153 | 154 | unittest |
|---|
| 154 | 155 | { |
|---|
| 155 | | auto a = "abcd"c[]; |
|---|
| | 156 | char[] a = "abcd"; |
|---|
| 156 | 157 | |
|---|
| 157 | 158 | auto r = a.dup.reverse; |
|---|
| … | … | |
| 183 | 184 | */ |
|---|
| 184 | 185 | |
|---|
| 185 | | extern (C) Array _adReverseWchar(wchar[] a) |
|---|
| | 186 | extern (C) wchar[] _adReverseWchar(wchar[] a) |
|---|
| 186 | 187 | { |
|---|
| 187 | 188 | bool hadErrors=false; |
|---|
| … | … | |
| 237 | 238 | */ |
|---|
| 238 | 239 | memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); |
|---|
| 239 | | memcpy(hi + cast(int) stridehi - cast(int) stridelo, lo, stridelo * wchar.sizeof); |
|---|
| | 240 | memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); |
|---|
| 240 | 241 | memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); |
|---|
| 241 | 242 | memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); |
|---|
| 242 | 243 | |
|---|
| 243 | 244 | lo += stridehi; |
|---|
| 244 | | hi = hi - 1 + (cast(int) stridehi - cast(int) stridelo); |
|---|
| | 245 | hi = hi - 1 + (stridehi - stridelo); |
|---|
| 245 | 246 | } |
|---|
| 246 | 247 | } |
|---|
| 247 | 248 | if (hadErrors) |
|---|
| 248 | 249 | throw new Exception("invalid UTF-16 sequence",__FILE__,__LINE__); |
|---|
| 249 | | return *cast(Array*)(&a); |
|---|
| | 250 | return a; |
|---|
| 250 | 251 | } |
|---|
| 251 | 252 | |
|---|
| 252 | 253 | unittest |
|---|
| 253 | 254 | { |
|---|
| 254 | | alias wchar[] wstring; |
|---|
| 255 | | wstring a = "abcd"; |
|---|
| 256 | | wstring r; |
|---|
| | 255 | wchar[] a = "abcd"; |
|---|
| | 256 | wchar[] r; |
|---|
| 257 | 257 | |
|---|
| 258 | 258 | r = a.dup.reverse; |
|---|
| … | … | |
| 549 | 549 | /*************************************** |
|---|
| 550 | 550 | * Support for array equality test. |
|---|
| | 551 | * Returns: |
|---|
| | 552 | * 1 equal |
|---|
| | 553 | * 0 not equal |
|---|
| 551 | 554 | */ |
|---|
| 552 | 555 | |
|---|
| 553 | 556 | extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) |
|---|
| 554 | 557 | { |
|---|
| 555 | | /+ |
|---|
| 556 | | + TODO: Re-enable once the correct TypeInfo is passed: |
|---|
| 557 | | + http://d.puremagic.com/issues/show_bug.cgi?id=2161 |
|---|
| 558 | | + |
|---|
| 559 | | debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); |
|---|
| 560 | | |
|---|
| 561 | | if (a1.length != a2.length) |
|---|
| 562 | | return 0; // not equal |
|---|
| 563 | | if (a1.ptr == a2.ptr) |
|---|
| 564 | | return 1; // equal |
|---|
| 565 | | |
|---|
| 566 | | // We should really have a ti.isPOD() check for this |
|---|
| 567 | | if (ti.tsize() != 1) |
|---|
| 568 | | return ti.equals(&a1, &a2); |
|---|
| 569 | | return memcmp(a1.ptr, a2.ptr, a1.length) == 0; |
|---|
| 570 | | +/ |
|---|
| 571 | 558 | debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); |
|---|
| 572 | 559 | if (a1.length != a2.length) |
|---|
| … | … | |
| 588 | 575 | } |
|---|
| 589 | 576 | |
|---|
| | 577 | extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti) |
|---|
| | 578 | { |
|---|
| | 579 | debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); |
|---|
| | 580 | if (a1.length != a2.length) |
|---|
| | 581 | return 0; // not equal |
|---|
| | 582 | if (!ti.equals(&a1, &a2)) |
|---|
| | 583 | return 0; |
|---|
| | 584 | return 1; |
|---|
| | 585 | } |
|---|
| | 586 | |
|---|
| 590 | 587 | unittest |
|---|
| 591 | 588 | { |
|---|
| … | … | |
| 607 | 604 | extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) |
|---|
| 608 | 605 | { |
|---|
| 609 | | /+ |
|---|
| 610 | | + TODO: Re-enable once the correct TypeInfo is passed: |
|---|
| 611 | | + http://d.puremagic.com/issues/show_bug.cgi?id=2161 |
|---|
| 612 | | + |
|---|
| 613 | | debug(adi) printf("adCmp()\n"); |
|---|
| 614 | | |
|---|
| 615 | | if (a1.ptr == a2.ptr && |
|---|
| 616 | | a1.length == a2.length) |
|---|
| 617 | | return 0; |
|---|
| 618 | | |
|---|
| 619 | | auto len = a1.length; |
|---|
| 620 | | if (a2.length < len) |
|---|
| 621 | | len = a2.length; |
|---|
| 622 | | |
|---|
| 623 | | // We should really have a ti.isPOD() check for this |
|---|
| 624 | | if (ti.tsize() != 1) |
|---|
| 625 | | return ti.compare(&a1, &a2); |
|---|
| 626 | | auto c = memcmp(a1.ptr, a2.ptr, len); |
|---|
| 627 | | if (c) |
|---|
| 628 | | return c; |
|---|
| 629 | | if (a1.length == a2.length) |
|---|
| 630 | | return 0; |
|---|
| 631 | | return a1.length > a2.length ? 1 : -1; |
|---|
| 632 | | +/ |
|---|
| 633 | 606 | debug(adi) printf("adCmp()\n"); |
|---|
| 634 | 607 | auto len = a1.length; |
|---|
| … | … | |
| 657 | 630 | return 0; |
|---|
| 658 | 631 | return (a1.length > a2.length) ? 1 : -1; |
|---|
| | 632 | } |
|---|
| | 633 | |
|---|
| | 634 | extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti) |
|---|
| | 635 | { |
|---|
| | 636 | debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); |
|---|
| | 637 | return ti.compare(&a1, &a2); |
|---|
| 659 | 638 | } |
|---|
| 660 | 639 | |
|---|
| r5579 |
r5652 |
|
| 55 | 55 | { |
|---|
| 56 | 56 | throw new Exception("overlapping array copy"); |
|---|
| 57 | | } |
|---|
| | 57 | } |
|---|
| 58 | 58 | return to; |
|---|
| 59 | 59 | } |
|---|
| r5609 |
r5652 |
|
| 30 | 30 | private |
|---|
| 31 | 31 | { |
|---|
| 32 | | import tango.stdc.stdlib; |
|---|
| 33 | | import tango.stdc.string; |
|---|
| | 32 | import tango.stdc.stdlib : free, malloc; |
|---|
| | 33 | import tango.stdc.string : memcpy, memset, memcmp; |
|---|
| 34 | 34 | import tango.stdc.stdarg; |
|---|
| 35 | 35 | debug(PRINTF) import tango.stdc.stdio; |
|---|
| | 36 | |
|---|
| | 37 | alias void[] array_t; |
|---|
| 36 | 38 | } |
|---|
| 37 | 39 | |
|---|
| … | … | |
| 95 | 97 | * to zero. |
|---|
| 96 | 98 | */ |
|---|
| 97 | | p = tango.stdc.stdlib.malloc(ci.init.length); |
|---|
| | 99 | p = malloc(ci.init.length); |
|---|
| 98 | 100 | if (!p) |
|---|
| 99 | 101 | onOutOfMemoryError(); |
|---|
| … | … | |
| 186 | 188 | } |
|---|
| 187 | 189 | |
|---|
| 188 | | |
|---|
| 189 | 190 | /** |
|---|
| 190 | 191 | * Allocate a new array of length elements. |
|---|
| … | … | |
| 192 | 193 | * (For when the array is initialized to 0) |
|---|
| 193 | 194 | */ |
|---|
| 194 | | extern (C) Array _d_newarrayT(TypeInfo ti, size_t length) |
|---|
| 195 | | { |
|---|
| 196 | | Array result; |
|---|
| | 195 | extern(C) array_t _d_newarrayT(TypeInfo ti, size_t length) |
|---|
| | 196 | { |
|---|
| | 197 | void* p; |
|---|
| | 198 | array_t result; |
|---|
| 197 | 199 | auto size = ti.next.tsize(); // array element size |
|---|
| 198 | 200 | |
|---|
| 199 | 201 | debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size); |
|---|
| 200 | 202 | if (length == 0 || size == 0) |
|---|
| 201 | | {} |
|---|
| | 203 | result = array_t.init; |
|---|
| 202 | 204 | else |
|---|
| 203 | | { |
|---|
| 204 | | result.length = length; |
|---|
| 205 | | /*version (D_InlineAsm_X86) |
|---|
| | 205 | { |
|---|
| | 206 | version (GNU) |
|---|
| | 207 | { |
|---|
| | 208 | // required to output the label; |
|---|
| | 209 | static char x = 0; |
|---|
| | 210 | if (x) |
|---|
| | 211 | goto Loverflow; |
|---|
| | 212 | } |
|---|
| | 213 | |
|---|
| | 214 | version (D_InlineAsm_X86) |
|---|
| 206 | 215 | { |
|---|
| 207 | 216 | asm |
|---|
| … | … | |
| 213 | 222 | } |
|---|
| 214 | 223 | } |
|---|
| 215 | | else*/ |
|---|
| | 224 | else version (D_InlineAsm_X86_64) |
|---|
| | 225 | asm |
|---|
| | 226 | { |
|---|
| | 227 | mov RAX,size ; |
|---|
| | 228 | mul RAX,length ; |
|---|
| | 229 | mov size,RAX ; |
|---|
| | 230 | jc Loverflow ; |
|---|
| | 231 | } |
|---|
| | 232 | else |
|---|
| 216 | 233 | size *= length; |
|---|
| | 234 | |
|---|
| 217 | 235 | PointerMap pm; |
|---|
| 218 | | version (D_HavePointerMap) { |
|---|
| 219 | | pm = ti.next.pointermap(); |
|---|
| 220 | | } |
|---|
| 221 | | result.data = cast(byte*) gc_malloc(size + 1, |
|---|
| 222 | | !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, |
|---|
| 223 | | pm); |
|---|
| 224 | | memset(result.data, 0, size); |
|---|
| | 236 | version (D_HavePointerMap) pm = ti.next.pointermap(); |
|---|
| | 237 | |
|---|
| | 238 | p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| | 239 | debug(PRINTF) printf(" p = %p\n", p); |
|---|
| | 240 | memset(p, 0, size); |
|---|
| | 241 | result = cast(array_t)p[0..length]; |
|---|
| 225 | 242 | } |
|---|
| 226 | 243 | return result; |
|---|
| … | … | |
| 234 | 251 | * For when the array has a non-zero initializer. |
|---|
| 235 | 252 | */ |
|---|
| 236 | | extern (C) Array _d_newarrayiT(TypeInfo ti, size_t length) |
|---|
| 237 | | { |
|---|
| 238 | | Array result; |
|---|
| 239 | | auto size = ti.next.tsize(); // array element size |
|---|
| | 253 | extern(C) array_t _d_newarrayiT(TypeInfo ti, size_t length) |
|---|
| | 254 | { |
|---|
| | 255 | array_t result; |
|---|
| | 256 | auto size = ti.next.tsize(); // array element size |
|---|
| 240 | 257 | |
|---|
| 241 | 258 | debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d)\n", length, size); |
|---|
| 242 | 259 | |
|---|
| 243 | 260 | if (length == 0 || size == 0) |
|---|
| 244 | | {} |
|---|
| | 261 | result = array_t.init; |
|---|
| 245 | 262 | else |
|---|
| 246 | 263 | { |
|---|
| 247 | 264 | auto initializer = ti.next.init(); |
|---|
| 248 | 265 | auto isize = initializer.length; |
|---|
| 249 | | auto q = initializer.ptr; |
|---|
| 250 | | /*version (D_InlineAsm_X86) |
|---|
| | 266 | auto q = initializer.ptr; |
|---|
| | 267 | |
|---|
| | 268 | version (GNU) |
|---|
| | 269 | { |
|---|
| | 270 | // required to output the label; |
|---|
| | 271 | static char x = 0; |
|---|
| | 272 | if (x) |
|---|
| | 273 | goto Loverflow; |
|---|
| | 274 | } |
|---|
| | 275 | |
|---|
| | 276 | version (D_InlineAsm_X86) |
|---|
| 251 | 277 | { |
|---|
| 252 | 278 | asm |
|---|
| … | … | |
| 258 | 284 | } |
|---|
| 259 | 285 | } |
|---|
| 260 | | else*/ |
|---|
| | 286 | else version (D_InlineAsm_X86_64) |
|---|
| | 287 | asm |
|---|
| | 288 | { |
|---|
| | 289 | mov RAX,size ; |
|---|
| | 290 | mul RAX,length ; |
|---|
| | 291 | mov size,RAX ; |
|---|
| | 292 | jc Loverflow ; |
|---|
| | 293 | } |
|---|
| | 294 | else |
|---|
| 261 | 295 | size *= length; |
|---|
| | 296 | |
|---|
| 262 | 297 | PointerMap pm; |
|---|
| 263 | 298 | version (D_HavePointerMap) { |
|---|
| 264 | 299 | pm = ti.next.pointermap(); |
|---|
| 265 | 300 | } |
|---|
| 266 | | auto p = gc_malloc(size + 1, |
|---|
| 267 | | !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, |
|---|
| 268 | | pm); |
|---|
| | 301 | auto p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| 269 | 302 | debug(PRINTF) printf(" p = %p\n", p); |
|---|
| 270 | 303 | if (isize == 1) |
|---|
| … | … | |
| 286 | 319 | } |
|---|
| 287 | 320 | } |
|---|
| 288 | | result.length = length; |
|---|
| 289 | | result.data = cast(byte*) p; |
|---|
| | 321 | result = cast(array_t)p[0..length]; |
|---|
| 290 | 322 | } |
|---|
| 291 | 323 | return result; |
|---|
| … | … | |
| 323 | 355 | { |
|---|
| 324 | 356 | p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim]; |
|---|
| 325 | | for (int i = 0; i < dim; i++) |
|---|
| | 357 | for (size_t i = 0; i < dim; i++) |
|---|
| 326 | 358 | { |
|---|
| 327 | 359 | (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); |
|---|
| … | … | |
| 602 | 634 | pm = ti.next.pointermap(); |
|---|
| 603 | 635 | } |
|---|
| 604 | | newdata = cast(byte *)gc_malloc(newsize + 1, info.attr, pm); |
|---|
| | 636 | newdata = cast(byte *)gc_malloc(newsize + 1, |
|---|
| | 637 | !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| | 638 | |
|---|
| 605 | 639 | newdata[0 .. size] = p.data[0 .. size]; |
|---|
| 606 | 640 | } |
|---|
| … | … | |
| 719 | 753 | pm = ti.next.pointermap(); |
|---|
| 720 | 754 | } |
|---|
| 721 | | newdata = cast(byte *)gc_malloc(newsize + 1, info.attr, pm); |
|---|
| | 755 | |
|---|
| | 756 | newdata = cast(byte *)gc_malloc(newsize + 1, |
|---|
| | 757 | !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| | 758 | |
|---|
| | 759 | |
|---|
| 722 | 760 | newdata[0 .. size] = p.data[0 .. size]; |
|---|
| 723 | 761 | L1: ; |
|---|
| … | … | |
| 767 | 805 | } |
|---|
| 768 | 806 | |
|---|
| | 807 | /************************************** |
|---|
| | 808 | * Extend an array by n elements. |
|---|
| | 809 | * Caller must initialize that element. |
|---|
| | 810 | */ |
|---|
| | 811 | extern (C) byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, size_t n) |
|---|
| | 812 | { |
|---|
| | 813 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| | 814 | auto info = gc_query(x.ptr); |
|---|
| | 815 | auto length = x.length; |
|---|
| | 816 | auto newlength = length + n; |
|---|
| | 817 | auto newsize = newlength * sizeelem; |
|---|
| | 818 | |
|---|
| | 819 | assert(info.size == 0 || length * sizeelem <= info.size); |
|---|
| | 820 | |
|---|
| | 821 | //printf("_d_arrayappendcTp(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, cap); |
|---|
| | 822 | |
|---|
| | 823 | if (newsize >= info.size) |
|---|
| | 824 | { byte* newdata; |
|---|
| | 825 | |
|---|
| | 826 | if (info.size >= PAGESIZE) |
|---|
| | 827 | { // Try to extend in-place |
|---|
| | 828 | auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); |
|---|
| | 829 | if (u) |
|---|
| | 830 | { |
|---|
| | 831 | goto L1; |
|---|
| | 832 | } |
|---|
| | 833 | } |
|---|
| | 834 | |
|---|
| | 835 | PointerMap pm; |
|---|
| | 836 | version (D_HavePointerMap) { |
|---|
| | 837 | pm = ti.next.pointermap(); |
|---|
| | 838 | } |
|---|
| | 839 | |
|---|
| | 840 | uint attr = !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0; |
|---|
| | 841 | newdata = cast(byte *) gc_malloc(newCapacity(newlength, sizeelem) + 1, attr, pm); |
|---|
| | 842 | |
|---|
| | 843 | memcpy(newdata, x.ptr, length * sizeelem); |
|---|
| | 844 | |
|---|
| | 845 | (cast(void **)(&x))[1] = newdata; |
|---|
| | 846 | } |
|---|
| | 847 | |
|---|
| | 848 | L1: |
|---|
| | 849 | *cast(size_t *)&x = newlength; |
|---|
| | 850 | assert((cast(size_t)x.ptr & 15) == 0); |
|---|
| | 851 | assert(gc_query(x.ptr).size > x.length * sizeelem); |
|---|
| | 852 | return x; |
|---|
| | 853 | } |
|---|
| 769 | 854 | |
|---|
| 770 | 855 | /** |
|---|
| … | … | |
| 791 | 876 | } |
|---|
| 792 | 877 | } |
|---|
| 793 | | uint attr = info.attr; |
|---|
| 794 | | // If this is the first allocation, set the NO_SCAN attribute appropriately |
|---|
| 795 | | if (info.base is null && ti.next.flags() == 0) |
|---|
| 796 | | attr = BlkAttr.NO_SCAN; |
|---|
| 797 | 878 | PointerMap pm; |
|---|
| 798 | 879 | version (D_HavePointerMap) { |
|---|
| 799 | 880 | pm = ti.next.pointermap(); |
|---|
| 800 | 881 | } |
|---|
| 801 | | newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, |
|---|
| 802 | | attr, pm); |
|---|
| | 882 | |
|---|
| | 883 | uint attr = !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0; |
|---|
| | 884 | newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, attr, pm); |
|---|
| | 885 | |
|---|
| 803 | 886 | memcpy(newdata, px.data, length * sizeelem); |
|---|
| 804 | 887 | px.data = newdata; |
|---|
| … | … | |
| 847 | 930 | const size_t a=100; // allocate at most a% of the requested size as extra space (rounding will change this) |
|---|
| 848 | 931 | const size_t minBits=1; // minimum bit size |
|---|
| 849 | | |
|---|
| | 932 | |
|---|
| 850 | 933 | |
|---|
| 851 | 934 | static size_t log2plusB(size_t c) |
|---|
| … | … | |
| 870 | 953 | } |
|---|
| 871 | 954 | |
|---|
| 872 | | |
|---|
| 873 | | /** |
|---|
| 874 | | * |
|---|
| 875 | | */ |
|---|
| 876 | | extern (C) byte[] _d_arrayappendcTp(TypeInfo ti, ref byte[] x, void *argp) |
|---|
| 877 | | { |
|---|
| 878 | | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| | 955 | /** |
|---|
| | 956 | * Append dchar to char[] |
|---|
| | 957 | */ |
|---|
| | 958 | extern (C) char[] _d_arrayappendcd(ref char[] x, dchar c) |
|---|
| | 959 | { |
|---|
| | 960 | const sizeelem = c.sizeof; // array element size |
|---|
| 879 | 961 | auto info = gc_query(x.ptr); |
|---|
| 880 | 962 | auto length = x.length; |
|---|
| 881 | | auto newlength = length + 1; |
|---|
| | 963 | |
|---|
| | 964 | // c could encode into from 1 to 4 characters |
|---|
| | 965 | int nchars; |
|---|
| | 966 | if (c <= 0x7F) |
|---|
| | 967 | nchars = 1; |
|---|
| | 968 | else if (c <= 0x7FF) |
|---|
| | 969 | nchars = 2; |
|---|
| | 970 | else if (c <= 0xFFFF) |
|---|
| | 971 | nchars = 3; |
|---|
| | 972 | else if (c <= 0x10FFFF) |
|---|
| | 973 | nchars = 4; |
|---|
| | 974 | else |
|---|
| | 975 | assert(0); // invalid utf character - should we throw an exception instead? |
|---|
| | 976 | |
|---|
| | 977 | auto newlength = length + nchars; |
|---|
| 882 | 978 | auto newsize = newlength * sizeelem; |
|---|
| 883 | 979 | |
|---|
| 884 | 980 | assert(info.size == 0 || length * sizeelem <= info.size); |
|---|
| 885 | 981 | |
|---|
| 886 | | debug(PRINTF) printf("_d_arrayappendcTp(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); |
|---|
| | 982 | debug(PRINTF) printf("_d_arrayappendcd(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); |
|---|
| 887 | 983 | |
|---|
| 888 | 984 | if (info.size <= newsize || info.base != x.ptr) |
|---|
| … | … | |
| 897 | 993 | } |
|---|
| 898 | 994 | } |
|---|
| 899 | | debug(PRINTF) printf("_d_arrayappendcTp(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); |
|---|
| | 995 | debug(PRINTF) printf("_d_arrayappendcd(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); |
|---|
| 900 | 996 | auto newcap = newCapacity(newlength, sizeelem); |
|---|
| 901 | 997 | assert(newcap >= newlength * sizeelem); |
|---|
| 902 | | uint attr = info.attr; |
|---|
| 903 | | // If this is the first allocation, set the NO_SCAN attribute appropriately |
|---|
| 904 | | if (info.base is null && ti.next.flags() == 0) |
|---|
| 905 | | attr = BlkAttr.NO_SCAN; |
|---|
| 906 | | PointerMap pm; |
|---|
| 907 | | version (D_HavePointerMap) { |
|---|
| 908 | | pm = ti.next.pointermap(); |
|---|
| 909 | | } |
|---|
| 910 | | newdata = cast(byte *)gc_malloc(newcap + 1, attr, pm); |
|---|
| | 998 | newdata = cast(byte *)gc_malloc(newcap + 1, BlkAttr.NO_SCAN); |
|---|
| 911 | 999 | memcpy(newdata, x.ptr, length * sizeelem); |
|---|
| 912 | 1000 | (cast(void**)(&x))[1] = newdata; |
|---|
| … | … | |
| 914 | 1002 | L1: |
|---|
| 915 | 1003 | *cast(size_t *)&x = newlength; |
|---|
| 916 | | x.ptr[length * sizeelem .. newsize] = (cast(byte*)argp)[0 .. sizeelem]; |
|---|
| | 1004 | char* ptr = &x.ptr[length]; |
|---|
| | 1005 | |
|---|
| | 1006 | if (c <= 0x7F) |
|---|
| | 1007 | { |
|---|
| | 1008 | ptr[0] = cast(char) c; |
|---|
| | 1009 | } |
|---|
| | 1010 | else if (c <= 0x7FF) |
|---|
| | 1011 | { |
|---|
| | 1012 | ptr[0] = cast(char)(0xC0 | (c >> 6)); |
|---|
| | 1013 | ptr[1] = cast(char)(0x80 | (c & 0x3F)); |
|---|
| | 1014 | } |
|---|
| | 1015 | else if (c <= 0xFFFF) |
|---|
| | 1016 | { |
|---|
| | 1017 | ptr[0] = cast(char)(0xE0 | (c >> 12)); |
|---|
| | 1018 | ptr[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); |
|---|
| | 1019 | ptr[2] = cast(char)(0x80 | (c & 0x3F)); |
|---|
| | 1020 | } |
|---|
| | 1021 | else if (c <= 0x10FFFF) |
|---|
| | 1022 | { |
|---|
| | 1023 | ptr[0] = cast(char)(0xF0 | (c >> 18)); |
|---|
| | 1024 | ptr[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); |
|---|
| | 1025 | ptr[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); |
|---|
| | 1026 | ptr[3] = cast(char)(0x80 | (c & 0x3F)); |
|---|
| | 1027 | } |
|---|
| | 1028 | else |
|---|
| | 1029 | assert(0); |
|---|
| | 1030 | |
|---|
| 917 | 1031 | assert((cast(size_t)x.ptr & 15) == 0); |
|---|
| 918 | 1032 | assert(gc_sizeOf(x.ptr) > x.length * sizeelem); |
|---|
| 919 | 1033 | return x; |
|---|
| 920 | 1034 | } |
|---|
| | 1035 | |
|---|
| | 1036 | |
|---|
| | 1037 | /** |
|---|
| | 1038 | * Append dchar to wchar[] |
|---|
| | 1039 | */ |
|---|
| | 1040 | extern (C) wchar[] _d_arrayappendwd(ref wchar[] x, dchar c) |
|---|
| | 1041 | { |
|---|
| | 1042 | const sizeelem = c.sizeof; // array element size |
|---|
| | 1043 | auto info = gc_query(x.ptr); |
|---|
| | 1044 | auto length = x.length; |
|---|
| | 1045 | |
|---|
| | 1046 | // c could encode into from 1 to 2 w characters |
|---|
| | 1047 | int nchars; |
|---|
| | 1048 | if (c <= 0xFFFF) |
|---|
| | 1049 | nchars = 1; |
|---|
| | 1050 | else |
|---|
| | 1051 | nchars = 2; |
|---|
| | 1052 | |
|---|
| | 1053 | auto newlength = length + nchars; |
|---|
| | 1054 | auto newsize = newlength * sizeelem; |
|---|
| | 1055 | |
|---|
| | 1056 | assert(info.size == 0 || length * sizeelem <= info.size); |
|---|
| | 1057 | |
|---|
| | 1058 | debug(PRINTF) printf("_d_arrayappendwd(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); |
|---|
| | 1059 | |
|---|
| | 1060 | if (info.size <= newsize || info.base != x.ptr) |
|---|
| | 1061 | { byte* newdata; |
|---|
| | 1062 | |
|---|
| | 1063 | if (info.size >= PAGESIZE && info.base == x.ptr) |
|---|
| | 1064 | { // Try to extend in-place |
|---|
| | 1065 | auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); |
|---|
| | 1066 | if (u) |
|---|
| | 1067 | { |
|---|
| | 1068 | goto L1; |
|---|
| | 1069 | } |
|---|
| | 1070 | } |
|---|
| | 1071 | debug(PRINTF) printf("_d_arrayappendwd(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); |
|---|
| | 1072 | auto newcap = newCapacity(newlength, sizeelem); |
|---|
| | 1073 | assert(newcap >= newlength * sizeelem); |
|---|
| | 1074 | newdata = cast(byte *)gc_malloc(newcap + 1, BlkAttr.NO_SCAN); |
|---|
| | 1075 | memcpy(newdata, x.ptr, length * sizeelem); |
|---|
| | 1076 | (cast(void**)(&x))[1] = newdata; |
|---|
| | 1077 | } |
|---|
| | 1078 | L1: |
|---|
| | 1079 | *cast(size_t *)&x = newlength; |
|---|
| | 1080 | wchar* ptr = &x.ptr[length]; |
|---|
| | 1081 | |
|---|
| | 1082 | if (c <= 0xFFFF) |
|---|
| | 1083 | { |
|---|
| | 1084 | ptr[0] = cast(wchar) c; |
|---|
| | 1085 | } |
|---|
| | 1086 | else |
|---|
| | 1087 | { |
|---|
| | 1088 | ptr[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 1089 | ptr[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 1090 | } |
|---|
| | 1091 | |
|---|
| | 1092 | assert((cast(size_t)x.ptr & 15) == 0); |
|---|
| | 1093 | assert(gc_sizeOf(x.ptr) > x.length * sizeelem); |
|---|
| | 1094 | return x; |
|---|
| | 1095 | } |
|---|
| | 1096 | |
|---|
| 921 | 1097 | |
|---|
| 922 | 1098 | |
|---|
| … | … | |
| 1024 | 1200 | |
|---|
| 1025 | 1201 | |
|---|
| 1026 | | /** |
|---|
| 1027 | | * |
|---|
| 1028 | | */ |
|---|
| 1029 | | version (GNU) { } else |
|---|
| 1030 | | extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) |
|---|
| | 1202 | extern (C) void* _d_arrayliteralTp(TypeInfo ti, size_t length) |
|---|
| 1031 | 1203 | { |
|---|
| 1032 | 1204 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| 1033 | 1205 | void* result; |
|---|
| 1034 | 1206 | |
|---|
| 1035 | | debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length); |
|---|
| | 1207 | //printf("_d_arrayliteralTX(sizeelem = %d, length = %d)\n", sizeelem, length); |
|---|
| 1036 | 1208 | if (length == 0 || sizeelem == 0) |
|---|
| 1037 | 1209 | result = null; |
|---|
| … | … | |
| 1042 | 1214 | pm = ti.next.pointermap(); |
|---|
| 1043 | 1215 | } |
|---|
| 1044 | | result = gc_malloc(length * sizeelem, |
|---|
| 1045 | | !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, |
|---|
| 1046 | | pm); |
|---|
| 1047 | | |
|---|
| 1048 | | va_list q; |
|---|
| 1049 | | va_start!(size_t)(q, length); |
|---|
| 1050 | | |
|---|
| 1051 | | size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); |
|---|
| 1052 | | |
|---|
| 1053 | | if (stacksize == sizeelem) |
|---|
| 1054 | | { |
|---|
| 1055 | | memcpy(result, q, length * sizeelem); |
|---|
| 1056 | | } |
|---|
| 1057 | | else |
|---|
| 1058 | | { |
|---|
| 1059 | | for (size_t i = 0; i < length; i++) |
|---|
| 1060 | | { |
|---|
| 1061 | | memcpy(result + i * sizeelem, q, sizeelem); |
|---|
| 1062 | | q += stacksize; |
|---|
| 1063 | | } |
|---|
| 1064 | | } |
|---|
| 1065 | | |
|---|
| 1066 | | va_end(q); |
|---|
| | 1216 | result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); |
|---|
| 1067 | 1217 | } |
|---|
| 1068 | 1218 | return result; |
|---|
| 1069 | 1219 | } |
|---|
| 1070 | | |
|---|
| 1071 | 1220 | |
|---|
| 1072 | 1221 | /** |
|---|
| r5579 |
r5652 |
|
| 102 | 102 | body |
|---|
| 103 | 103 | { |
|---|
| 104 | | //printf("body _d_switch_string(%.*s)\n", ca); |
|---|
| | 104 | //printf("body _d_switch_string(%.*s)\n", ca); |
|---|
| 105 | 105 | int low; |
|---|
| 106 | 106 | int high; |
|---|
| … | … | |
| 180 | 180 | |
|---|
| 181 | 181 | int _d_switch_ustring(wchar[][] table, wchar[] ca) |
|---|
| 182 | | in |
|---|
| 183 | | { |
|---|
| 184 | | //printf("in _d_switch_ustring()\n"); |
|---|
| 185 | | assert(table.length >= 0); |
|---|
| 186 | | assert(ca.length >= 0); |
|---|
| 187 | | |
|---|
| 188 | | // Make sure table[] is sorted correctly |
|---|
| 189 | | int j; |
|---|
| 190 | | |
|---|
| 191 | | for (j = 1; j < table.length; j++) |
|---|
| 192 | | { |
|---|
| 193 | | int len1 = table[j - 1].length; |
|---|
| 194 | | int len2 = table[j].length; |
|---|
| 195 | | |
|---|
| 196 | | assert(len1 <= len2); |
|---|
| 197 | | if (len1 == len2) |
|---|
| 198 | | { |
|---|
| 199 | | int c; |
|---|
| 200 | | |
|---|
| 201 | | c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof); |
|---|
| 202 | | assert(c < 0); // c==0 means a duplicate |
|---|
| 203 | | } |
|---|
| 204 | | } |
|---|
| 205 | | } |
|---|
| 206 | | out (result) |
|---|
| 207 | | { |
|---|
| 208 | | int i; |
|---|
| 209 | | int c; |
|---|
| 210 | | |
|---|
| 211 | | //printf("out _d_switch_string()\n"); |
|---|
| 212 | | if (result == -1) |
|---|
| 213 | | { |
|---|
| 214 | | // Not found |
|---|
| 215 | | for (i = 0; i < table.length; i++) |
|---|
| 216 | | { |
|---|
| 217 | | if (table[i].length == ca.length) |
|---|
| 218 | | { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); |
|---|
| 219 | | assert(c != 0); |
|---|
| 220 | | } |
|---|
| 221 | | } |
|---|
| | 182 | in |
|---|
| | 183 | { |
|---|
| | 184 | //printf("in _d_switch_ustring()\n"); |
|---|
| | 185 | assert(table.length >= 0); |
|---|
| | 186 | assert(ca.length >= 0); |
|---|
| | 187 | |
|---|
| | 188 | // Make sure table[] is sorted correctly |
|---|
| | 189 | int j; |
|---|
| | 190 | |
|---|
| | 191 | for (j = 1; j < table.length; j++) |
|---|
| | 192 | { |
|---|
| | 193 | int len1 = table[j - 1].length; |
|---|
| | 194 | int len2 = table[j].length; |
|---|
| | 195 | |
|---|
| | 196 | assert(len1 <= len2); |
|---|
| | 197 | if (len1 == len2) |
|---|
| | 198 | { |
|---|
| | 199 | int c; |
|---|
| | 200 | |
|---|
| | 201 | c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof); |
|---|
| | 202 | assert(c < 0); // c==0 means a duplicate |
|---|
| | 203 | } |
|---|
| | 204 | } |
|---|
| | 205 | } |
|---|
| | 206 | out (result) |
|---|
| | 207 | { |
|---|
| | 208 | int i; |
|---|
| | 209 | int c; |
|---|
| | 210 | |
|---|
| | 211 | //printf("out _d_switch_string()\n"); |
|---|
| | 212 | if (result == -1) |
|---|
| | 213 | { |
|---|
| | 214 | // Not found |
|---|
| | 215 | for (i = 0; i < table.length; i++) |
|---|
| | 216 | { |
|---|
| | 217 | if (table[i].length == ca.length) |
|---|
| | 218 | { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); |
|---|
| | 219 | assert(c != 0); |
|---|
| | 220 | } |
|---|
| | 221 | } |
|---|
| | 222 | } |
|---|
| | 223 | else |
|---|
| | 224 | { |
|---|
| | 225 | assert(0 <= result && result < table.length); |
|---|
| | 226 | for (i = 0; 1; i++) |
|---|
| | 227 | { |
|---|
| | 228 | assert(i < table.length); |
|---|
| | 229 | if (table[i].length == ca.length) |
|---|
| | 230 | { |
|---|
| | 231 | c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); |
|---|
| | 232 | if (c == 0) |
|---|
| | 233 | { |
|---|
| | 234 | assert(i == result); |
|---|
| | 235 | break; |
|---|
| | 236 | } |
|---|
| | 237 | } |
|---|
| | 238 | } |
|---|
| | 239 | } |
|---|
| | 240 | } |
|---|
| | 241 | body |
|---|
| | 242 | { |
|---|
| | 243 | //printf("body _d_switch_ustring()\n"); |
|---|
| | 244 | int low; |
|---|
| | 245 | int high; |
|---|
| | 246 | int mid; |
|---|
| | 247 | int c; |
|---|
| | 248 | wchar[] pca; |
|---|
| | 249 | |
|---|
| | 250 | low = 0; |
|---|
| | 251 | high = table.length; |
|---|
| | 252 | |
|---|
| | 253 | /* |
|---|
| | 254 | // Print table |
|---|
| | 255 | wprintf("ca[] = '%.*s'\n", ca); |
|---|
| | 256 | for (mid = 0; mid < high; mid++) |
|---|
| | 257 | { |
|---|
| | 258 | pca = table[mid]; |
|---|
| | 259 | wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); |
|---|
| | 260 | } |
|---|
| | 261 | */ |
|---|
| | 262 | |
|---|
| | 263 | // Do binary search |
|---|
| | 264 | while (low < high) |
|---|
| | 265 | { |
|---|
| | 266 | mid = (low + high) >> 1; |
|---|
| | 267 | pca = table[mid]; |
|---|
| | 268 | c = ca.length - pca.length; |
|---|
| | 269 | if (c == 0) |
|---|
| | 270 | { |
|---|
| | 271 | c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof); |
|---|
| | 272 | if (c == 0) |
|---|
| | 273 | { //printf("found %d\n", mid); |
|---|
| | 274 | return mid; |
|---|
| | 275 | } |
|---|
| | 276 | } |
|---|
| | 277 | if (c < 0) |
|---|
| | 278 | { |
|---|
| | 279 | high = mid; |
|---|
| 222 | 280 | } |
|---|
| 223 | 281 | else |
|---|
| 224 | 282 | { |
|---|
| 225 | | assert(0 <= result && result < table.length); |
|---|
| 226 | | for (i = 0; 1; i++) |
|---|
| 227 | | { |
|---|
| 228 | | assert(i < table.length); |
|---|
| 229 | | if (table[i].length == ca.length) |
|---|
| 230 | | { |
|---|
| 231 | | c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); |
|---|
| 232 | | if (c == 0) |
|---|
| 233 | | { |
|---|
| 234 | | assert(i == result); |
|---|
| 235 | | break; |
|---|
| 236 | | } |
|---|
| 237 | | } |
|---|
| 238 | | } |
|---|
| 239 | | } |
|---|
| 240 | | } |
|---|
| 241 | | body |
|---|
| 242 | | { |
|---|
| 243 | | //printf("body _d_switch_ustring()\n"); |
|---|
| 244 | | int low; |
|---|
| 245 | | int high; |
|---|
| 246 | | int mid; |
|---|
| 247 | | int c; |
|---|
| 248 | | wchar[] pca; |
|---|
| 249 | | |
|---|
| 250 | | low = 0; |
|---|
| 251 | | high = table.length; |
|---|
| 252 | | |
|---|
| 253 | | /* |
|---|
| 254 | | // Print table |
|---|
| 255 | | wprintf("ca[] = '%.*s'\n", ca); |
|---|
| 256 | | for (mid = 0; mid < high; mid++) |
|---|
| 257 | | { |
|---|
| 258 | | pca = table[mid]; |
|---|
| 259 | | wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); |
|---|
| 260 | | } |
|---|
| 261 | | */ |
|---|
| 262 | | |
|---|
| 263 | | // Do binary search |
|---|
| 264 | | while (low < high) |
|---|
| 265 | | { |
|---|
| 266 | | mid = (low + high) >> 1; |
|---|
| 267 | | pca = table[mid]; |
|---|
| 268 | | c = ca.length - pca.length; |
|---|
| 269 | | if (c == 0) |
|---|
| 270 | | { |
|---|
| 271 | | c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof); |
|---|
| 272 | | if (c == 0) |
|---|
| 273 | | { //printf("found %d\n", mid); |
|---|
| 274 | | return mid; |
|---|
| 275 | | } |
|---|
| 276 | | } |
|---|
| 277 | | if (c < 0) |
|---|
| 278 | | { |
|---|
| 279 | | high = mid; |
|---|
| 280 | | } |
|---|
| 281 | | else |
|---|
| 282 | | { |
|---|
| 283 | | low = mid + 1; |
|---|
| 284 | | } |
|---|
| 285 | | } |
|---|
| 286 | | //printf("not found\n"); |
|---|
| 287 | | return -1; // not found |
|---|
| 288 | | } |
|---|
| | 283 | low = mid + 1; |
|---|
| | 284 | } |
|---|
| | 285 | } |
|---|
| | 286 | //printf("not found\n"); |
|---|
| | 287 | return -1; // not found |
|---|
| | 288 | } |
|---|
| 289 | 289 | |
|---|
| 290 | 290 | |
|---|
| … | … | |
| 293 | 293 | switch (cast(wchar []) "c") |
|---|
| 294 | 294 | { |
|---|
| 295 | | case "coo": |
|---|
| 296 | | default: |
|---|
| 297 | | break; |
|---|
| | 295 | case "coo": |
|---|
| | 296 | default: |
|---|
| | 297 | break; |
|---|
| 298 | 298 | } |
|---|
| 299 | 299 | } |
|---|
| r5594 |
r5652 |
|
| 1 | | |
|---|
| 2 | | // Written in the D programming language |
|---|
| 3 | | // written by Walter Bright |
|---|
| 4 | | // www.digitalmars.com |
|---|
| 5 | | // Placed into the public domain |
|---|
| 6 | | |
|---|
| 7 | | /* NOTE: This file has been patched from the original DMD distribution to |
|---|
| 8 | | work with the GDC compiler. |
|---|
| 9 | | |
|---|
| 10 | | Modified by David Friedman, May 2006 |
|---|
| 11 | | */ |
|---|
| 12 | | |
|---|
| 13 | | /** These functions are built-in intrinsics to the compiler. |
|---|
| | 1 | /** |
|---|
| | 2 | * These functions are built-in intrinsics to the compiler. |
|---|
| 14 | 3 | * |
|---|
| 15 | | Intrinsic functions are functions built in to the compiler, |
|---|
| 16 | | usually to take advantage of specific CPU features that |
|---|
| 17 | | are inefficient to handle via external functions. |
|---|
| 18 | | The compiler's optimizer and code generator are fully |
|---|
| 19 | | integrated in with intrinsic functions, bringing to bear |
|---|
| 20 | | their full power on them. |
|---|
| 21 | | This can result in some surprising speedups. |
|---|
| | 4 | * Intrinsic functions are functions built in to the compiler, usually to take |
|---|
| | 5 | * advantage of specific CPU features that are inefficient to handle via |
|---|
| | 6 | * external functions. The compiler's optimizer and code generator are fully |
|---|
| | 7 | * integrated in with intrinsic functions, bringing to bear their full power on |
|---|
| | 8 | * them. This can result in some surprising speedups. |
|---|
| | 9 | * |
|---|
| | 10 | * Note that this module is only present in Tango because the module name is |
|---|
| | 11 | * hardcoded into DMD, see http://d.puremagic.com/issues/show_bug.cgi?id=178 |
|---|
| | 12 | * To correctly use this functionality in Tango, import tango.core.BitManip. |
|---|
| 22 | 13 | * |
|---|
| 23 | 14 | * Copyright: Public Domain |
|---|
| 24 | 15 | * License: Public Domain |
|---|
| 25 | 16 | * Authors: Walter Bright |
|---|
| 26 | | * Macros: |
|---|
| 27 | | * WIKI=Phobos/StdIntrinsic |
|---|
| 28 | 17 | */ |
|---|
| | 18 | module std.intrinsic; |
|---|
| 29 | 19 | |
|---|
| 30 | | module std.intrinsic; |
|---|
| 31 | 20 | |
|---|
| 32 | 21 | /** |
|---|
| … | … | |
| 34 | 23 | * for the first set bit. |
|---|
| 35 | 24 | * Returns: |
|---|
| 36 | | * The bit number of the first bit set. |
|---|
| 37 | | * The return value is undefined if v is zero. |
|---|
| | 25 | * The bit number of the first bit set. |
|---|
| | 26 | * The return value is undefined if v is zero. |
|---|
| 38 | 27 | */ |
|---|
| 39 | | version (GNU) |
|---|
| 40 | | int bsf(uint v) |
|---|
| 41 | | { |
|---|
| 42 | | uint m = 1; |
|---|
| 43 | | uint i; |
|---|
| 44 | | for (i = 0; i < 32; i++,m<<=1) { |
|---|
| 45 | | if (v&m) |
|---|
| 46 | | return i; |
|---|
| 47 | | } |
|---|
| 48 | | return i; // supposed to be undefined |
|---|
| 49 | | } |
|---|
| 50 | | else |
|---|
| 51 | | int bsf(uint v); |
|---|
| | 28 | int bsf( size_t v ); |
|---|
| | 29 | |
|---|
| 52 | 30 | |
|---|
| 53 | 31 | /** |
|---|
| … | … | |
| 56 | 34 | * for the first set bit. |
|---|
| 57 | 35 | * Returns: |
|---|
| 58 | | * The bit number of the first bit set. |
|---|
| 59 | | * The return value is undefined if v is zero. |
|---|
| | 36 | * The bit number of the first bit set. |
|---|
| | 37 | * The return value is undefined if v is zero. |
|---|
| 60 | 38 | * Example: |
|---|
| 61 | 39 | * --- |
|---|
| 62 | | * import std.stdio; |
|---|
| 63 | 40 | * import std.intrinsic; |
|---|
| 64 | 41 | * |
|---|
| … | … | |
| 70 | 47 | * v = 0x21; |
|---|
| 71 | 48 | * x = bsf(v); |
|---|
| 72 | | * writefln("bsf(x%x) = %d", v, x); |
|---|
| | 49 | * printf("bsf(x%x) = %d\n", v, x); |
|---|
| 73 | 50 | * x = bsr(v); |
|---|
| 74 | | * writefln("bsr(x%x) = %d", v, x); |
|---|
| | 51 | * printf("bsr(x%x) = %d\n", v, x); |
|---|
| 75 | 52 | * return 0; |
|---|
| 76 | 53 | * } |
|---|
| … | … | |
| 80 | 57 | * bsr(x21) = 5 |
|---|
| 81 | 58 | */ |
|---|
| 82 | | version (GNU) |
|---|
| 83 | | int bsr(size_t v) |
|---|
| 84 | | { |
|---|
| 85 | | size_t m = 0x80000000; |
|---|
| 86 | | size_t i; |
|---|
| 87 | | for (i = 32; i ; i--,m>>>=1) { |
|---|
| 88 | | if (v&m) |
|---|
| 89 | | return i-1; |
|---|
| 90 | | } |
|---|
| 91 | | return i; // supposed to be undefined |
|---|
| 92 | | } |
|---|
| 93 | | else |
|---|
| 94 | | int bsr(size_t v); |
|---|
| | 59 | int bsr( size_t v ); |
|---|
| | 60 | |
|---|
| 95 | 61 | |
|---|
| 96 | 62 | /** |
|---|
| 97 | 63 | * Tests the bit. |
|---|
| 98 | 64 | */ |
|---|
| 99 | | version (GNU) |
|---|
| 100 | | int bt(in size_t* p, size_t bitnum) |
|---|
| 101 | | { |
|---|
| 102 | | return (p[bitnum / (size_t.sizeof*8)] & (1<<(bitnum & ((size_t.sizeof*8)-1)))) ? -1 : 0 ; |
|---|
| 103 | | } |
|---|
| 104 | | else |
|---|
| 105 | | int bt(in size_t* p, size_t bitnum); |
|---|
| | 65 | int bt( size_t* p, size_t bitnum ); |
|---|
| | 66 | |
|---|
| 106 | 67 | |
|---|
| 107 | 68 | /** |
|---|
| 108 | 69 | * Tests and complements the bit. |
|---|
| 109 | 70 | */ |
|---|
| 110 | | version (GNU) |
|---|
| 111 | | int btc(size_t* p, size_t bitnum) |
|---|
| 112 | | { |
|---|
| 113 | | size_t* q = p + (bitnum / (size_t.sizeof*8)); |
|---|
| 114 | | size_t mask = 1 << (bitnum & ((size_t.sizeof*8) - 1)); |
|---|
| 115 | | int result = *q & mask; |
|---|
| 116 | | *q ^= mask; |
|---|
| 117 | | return result ? -1 : 0; |
|---|
| 118 | | } |
|---|
| 119 | | else |
|---|
| 120 | | int btc(size_t* p, size_t bitnum); |
|---|
| | 71 | int btc( size_t* p, size_t bitnum ); |
|---|
| | 72 | |
|---|
| 121 | 73 | |
|---|
| 122 | 74 | /** |
|---|
| 123 | 75 | * Tests and resets (sets to 0) the bit. |
|---|
| 124 | 76 | */ |
|---|
| 125 | | version (GNU) |
|---|
| 126 | | int btr(size_t* p, size_t bitnum) |
|---|
| 127 | | { |
|---|
| 128 | | size_t* q = p + (bitnum / (size_t.sizeof*8)); |
|---|
| 129 | | size_t mask = 1 << (bitnum & ((size_t.sizeof*8) - 1)); |
|---|
| 130 | | int result = *q & mask; |
|---|
| 131 | | *q &= ~mask; |
|---|
| 132 | | return result ? -1 : 0; |
|---|
| 133 | | } |
|---|
| 134 | | else |
|---|
| 135 | | int btr(size_t* p, size_t bitnum); |
|---|
| | 77 | int btr( size_t* p, size_t bitnum ); |
|---|
| | 78 | |
|---|
| 136 | 79 | |
|---|
| 137 | 80 | /** |
|---|
| … | … | |
| 145 | 88 | --- |
|---|
| 146 | 89 | * Returns: |
|---|
| 147 | | * A non-zero value if the bit was set, and a zero |
|---|
| 148 | | * if it was clear. |
|---|
| | 90 | * A non-zero value if the bit was set, and a zero |
|---|
| | 91 | * if it was clear. |
|---|
| 149 | 92 | * |
|---|
| 150 | 93 | * Example: |
|---|
| 151 | 94 | * --- |
|---|
| 152 | | import std.stdio; |
|---|
| 153 | 95 | import std.intrinsic; |
|---|
| 154 | 96 | |
|---|
| 155 | 97 | int main() |
|---|
| 156 | 98 | { |
|---|
| 157 | | size_t[2] array; |
|---|
| | 99 | size_t array[2]; |
|---|
| 158 | 100 | |
|---|
| 159 | 101 | array[0] = 2; |
|---|
| 160 | 102 | array[1] = 0x100; |
|---|
| 161 | 103 | |
|---|
| 162 | | writefln("btc(array, 35) = %d", <b>btc</b>(array, 35)); |
|---|
| 163 | | writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); |
|---|
| | 104 | printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35)); |
|---|
| | 105 | printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); |
|---|
| 164 | 106 | |
|---|
| 165 | | writefln("btc(array, 35) = %d", <b>btc</b>(array, 35)); |
|---|
| 166 | | writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); |
|---|
| | 107 | printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35)); |
|---|
| | 108 | printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); |
|---|
| 167 | 109 | |
|---|
| 168 | | writefln("bts(array, 35) = %d", <b>bts</b>(array, 35)); |
|---|
| 169 | | writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); |
|---|
| | 110 | printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35)); |
|---|
| | 111 | printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); |
|---|
| 170 | 112 | |
|---|
| 171 | | writefln("btr(array, 35) = %d", <b>btr</b>(array, 35)); |
|---|
| 172 | | writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); |
|---|
| | 113 | printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35)); |
|---|
| | 114 | printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); |
|---|
| 173 | 115 | |
|---|
| 174 | | writefln("bt(array, 1) = %d", <b>bt</b>(array, 1)); |
|---|
| 175 | | writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); |
|---|
| | 116 | printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1)); |
|---|
| | 117 | printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); |
|---|
| 176 | 118 | |
|---|
| 177 | 119 | return 0; |
|---|
| … | … | |
| 192 | 134 | </pre> |
|---|
| 193 | 135 | */ |
|---|
| 194 | | version (GNU) |
|---|
| 195 | | int bts(size_t* p, size_t bitnum) |
|---|
| 196 | | { |
|---|
| 197 | | size_t* q = p + (bitnum / (size_t.sizeof*8)); |
|---|
| 198 | | size_t mask = 1 << (bitnum & ((size_t.sizeof*8) - 1)); |
|---|
| 199 | | int result = *q & mask; |
|---|
| 200 | | *q |= mask; |
|---|
| 201 | | return result ? -1 : 0; |
|---|
| 202 | | } |
|---|
| 203 | | else |
|---|
| 204 | | int bts(size_t* p, size_t bitnum); |
|---|
| 205 | 136 | |
|---|
| | 137 | int bts( size_t* p, size_t bitnum ); |
|---|
| 206 | 138 | |
|---|
| 207 | 139 | /** |
|---|
| 208 | 140 | * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes |
|---|
| 209 | | byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 |
|---|
| 210 | | becomes byte 0. |
|---|
| | 141 | * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 |
|---|
| | 142 | * becomes byte 0. |
|---|
| 211 | 143 | */ |
|---|
| 212 | | version (GNU) |
|---|
| 213 | | uint bswap(uint v) |
|---|
| 214 | | { |
|---|
| 215 | | return ((v&0xFF)<<24)|((v&0xFF00)<<8)|((v&0xFF0000)>>>8)|((v&0xFF000000)>>>24); |
|---|
| 216 | | } |
|---|
| 217 | | else |
|---|
| 218 | | uint bswap(uint v); |
|---|
| | 144 | uint bswap( uint v ); |
|---|
| 219 | 145 | |
|---|
| 220 | 146 | |
|---|
| … | … | |
| 222 | 148 | * Reads I/O port at port_address. |
|---|
| 223 | 149 | */ |
|---|
| 224 | | version (GNU) |
|---|
| 225 | | ubyte inp(uint p) { return 0; } |
|---|
| 226 | | else |
|---|
| 227 | | ubyte inp(uint port_address); |
|---|
| | 150 | ubyte inp( uint port_address ); |
|---|
| | 151 | |
|---|
| 228 | 152 | |
|---|
| 229 | 153 | /** |
|---|
| 230 | 154 | * ditto |
|---|
| 231 | 155 | */ |
|---|
| 232 | | version (GNU) |
|---|
| 233 | | ushort inpw(uint p) { return 0; } |
|---|
| 234 | | else |
|---|
| 235 | | ushort inpw(uint port_address); |
|---|
| | 156 | ushort inpw( uint port_address ); |
|---|
| | 157 | |
|---|
| 236 | 158 | |
|---|
| 237 | 159 | /** |
|---|
| 238 | 160 | * ditto |
|---|
| 239 | 161 | */ |
|---|
| 240 | | version (GNU) |
|---|
| 241 | | uint inpl(uint p) { return 0; } |
|---|
| 242 | | else |
|---|
| 243 | | uint inpl(uint port_address); |
|---|
| | 162 | uint inpl( uint port_address ); |
|---|
| 244 | 163 | |
|---|
| 245 | 164 | |
|---|
| … | … | |
| 247 | 166 | * Writes and returns value to I/O port at port_address. |
|---|
| 248 | 167 | */ |
|---|
| 249 | | version (GNU) |
|---|
| 250 | | ubyte outp(uint p, ubyte v) { return v; } |
|---|
| 251 | | else |
|---|
| 252 | | ubyte outp(uint port_address, ubyte value); |
|---|
| | 168 | ubyte outp( uint port_address, ubyte value ); |
|---|
| | 169 | |
|---|
| 253 | 170 | |
|---|
| 254 | 171 | /** |
|---|
| 255 | 172 | * ditto |
|---|
| 256 | 173 | */ |
|---|
| 257 | | version (GNU) |
|---|
| 258 | | ushort outpw(uint p, ushort v) { return v; } |
|---|
| 259 | | else |
|---|
| 260 | | ushort outpw(uint port_address, ushort value); |
|---|
| | 174 | ushort outpw( uint port_address, ushort value ); |
|---|
| | 175 | |
|---|
| 261 | 176 | |
|---|
| 262 | 177 | /** |
|---|
| 263 | 178 | * ditto |
|---|
| 264 | 179 | */ |
|---|
| 265 | | version (GNU) |
|---|
| 266 | | uint outpl(uint p, uint v) { return v; } |
|---|
| 267 | | else |
|---|
| 268 | | uint outpl(uint port_address, uint value); |
|---|
| 269 | | |
|---|
| 270 | | |
|---|
| | 180 | uint outpl( uint port_address, uint value ); |
|---|
| r5577 |
r5652 |
|
| 83 | 83 | } |
|---|
| 84 | 84 | |
|---|
| | 85 | override size_t talign() |
|---|
| | 86 | { |
|---|
| | 87 | return (Object[]).alignof; |
|---|
| | 88 | } |
|---|
| | 89 | |
|---|
| 85 | 90 | override size_t tsize() |
|---|
| 86 | 91 | { |
|---|
| … | … | |
| 97 | 102 | return typeid(Object); |
|---|
| 98 | 103 | } |
|---|
| | 104 | |
|---|
| | 105 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 106 | { |
|---|
| | 107 | return 0; |
|---|
| | 108 | } |
|---|
| 99 | 109 | } |
|---|
| r5577 |
r5652 |
|
| 76 | 76 | } |
|---|
| 77 | 77 | |
|---|
| | 78 | override size_t talign() |
|---|
| | 79 | { |
|---|
| | 80 | return (cdouble[]).alignof; |
|---|
| | 81 | } |
|---|
| | 82 | |
|---|
| 78 | 83 | override size_t tsize() |
|---|
| 79 | 84 | { |
|---|
| … | … | |
| 90 | 95 | return typeid(cdouble); |
|---|
| 91 | 96 | } |
|---|
| | 97 | |
|---|
| | 98 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 99 | { |
|---|
| | 100 | return 0; |
|---|
| | 101 | } |
|---|
| 92 | 102 | } |
|---|
| r5577 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (cfloat[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(cfloat); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| r5577 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (creal[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(creal); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| r5577 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (double[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(double); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| 94 | 104 | |
|---|
| r5577 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (float[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(float); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| 94 | 104 | |
|---|
| r5577 |
r5652 |
|
| 47 | 47 | return 1; |
|---|
| 48 | 48 | return 0; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | override size_t talign() |
|---|
| | 52 | { |
|---|
| | 53 | return (byte[]).alignof; |
|---|
| 49 | 54 | } |
|---|
| 50 | 55 | |
|---|
| … | … | |
| 134 | 139 | return typeid(char); |
|---|
| 135 | 140 | } |
|---|
| | 141 | |
|---|
| | 142 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 143 | { |
|---|
| | 144 | return 0; |
|---|
| | 145 | } |
|---|
| 136 | 146 | } |
|---|
| r5577 |
r5652 |
|
| 48 | 48 | } |
|---|
| 49 | 49 | |
|---|
| | 50 | override size_t talign() |
|---|
| | 51 | { |
|---|
| | 52 | return (int[]).alignof; |
|---|
| | 53 | } |
|---|
| | 54 | |
|---|
| 50 | 55 | override size_t tsize() |
|---|
| 51 | 56 | { |
|---|
| … | … | |
| 61 | 66 | { |
|---|
| 62 | 67 | return typeid(int); |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 71 | { |
|---|
| | 72 | return 0; |
|---|
| 63 | 73 | } |
|---|
| 64 | 74 | } |
|---|
| r5577 |
r5652 |
|
| 49 | 49 | } |
|---|
| 50 | 50 | |
|---|
| | 51 | override size_t talign() |
|---|
| | 52 | { |
|---|
| | 53 | return (long[]).alignof; |
|---|
| | 54 | } |
|---|
| | 55 | |
|---|
| 51 | 56 | override size_t tsize() |
|---|
| 52 | 57 | { |
|---|
| … | … | |
| 62 | 67 | { |
|---|
| 63 | 68 | return typeid(long); |
|---|
| | 69 | } |
|---|
| | 70 | |
|---|
| | 71 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 72 | { |
|---|
| | 73 | return 0; |
|---|
| 64 | 74 | } |
|---|
| 65 | 75 | } |
|---|
| r5577 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (real[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| … | … | |
| 91 | 96 | return typeid(real); |
|---|
| 92 | 97 | } |
|---|
| | 98 | |
|---|
| | 99 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 100 | { |
|---|
| | 101 | return 0; |
|---|
| | 102 | } |
|---|
| 93 | 103 | } |
|---|
| 94 | 104 | |
|---|
| r5577 |
r5652 |
|
| 46 | 46 | return 1; |
|---|
| 47 | 47 | return 0; |
|---|
| | 48 | } |
|---|
| | 49 | |
|---|
| | 50 | override size_t talign() |
|---|
| | 51 | { |
|---|
| | 52 | return (short[]).alignof; |
|---|
| 48 | 53 | } |
|---|
| 49 | 54 | |
|---|
| … | … | |
| 109 | 114 | return typeid(wchar); |
|---|
| 110 | 115 | } |
|---|
| | 116 | |
|---|
| | 117 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 118 | { |
|---|
| | 119 | arg1 = typeid(size_t); |
|---|
| | 120 | arg2 = typeid(void*); |
|---|
| | 121 | return 0; |
|---|
| | 122 | } |
|---|
| 111 | 123 | } |
|---|
| r5577 |
r5652 |
|
| 63 | 63 | } |
|---|
| 64 | 64 | |
|---|
| | 65 | override size_t talign() |
|---|
| | 66 | { |
|---|
| | 67 | return Object.alignof; |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| 65 | 70 | override size_t tsize() |
|---|
| 66 | 71 | { |
|---|
| r5577 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return byte.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r5577 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return cdouble.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| … | … | |
| 64 | 69 | return (cast(cdouble *)&r)[0 .. 1]; |
|---|
| 65 | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 73 | { |
|---|
| | 74 | return 0; |
|---|
| | 75 | } |
|---|
| 66 | 76 | } |
|---|
| r5577 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return cfloat.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| … | … | |
| 64 | 69 | return (cast(cfloat *)&r)[0 .. 1]; |
|---|
| 65 | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 73 | { |
|---|
| | 74 | return 0; |
|---|
| | 75 | } |
|---|
| 66 | 76 | } |
|---|
| r5577 |
r5652 |
|
| 21 | 21 | } |
|---|
| 22 | 22 | |
|---|
| | 23 | override size_t talign() |
|---|
| | 24 | { |
|---|
| | 25 | return char.alignof; |
|---|
| | 26 | } |
|---|
| | 27 | |
|---|
| 23 | 28 | override size_t tsize() |
|---|
| 24 | 29 | { |
|---|
| r5577 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return creal.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| … | … | |
| 64 | 69 | return (cast(creal *)&r)[0 .. 1]; |
|---|
| 65 | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 73 | { |
|---|
| | 74 | arg1 = typeid(real); |
|---|
| | 75 | arg2 = typeid(real); |
|---|
| | 76 | return 0; |
|---|
| | 77 | } |
|---|
| 66 | 78 | } |
|---|
| r5577 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return dchar.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r5577 |
r5652 |
|
| 19 | 19 | } |
|---|
| 20 | 20 | |
|---|
| | 21 | override size_t talign() |
|---|
| | 22 | { |
|---|
| | 23 | return dg.alignof; |
|---|
| | 24 | } |
|---|
| | 25 | |
|---|
| 21 | 26 | override size_t tsize() |
|---|
| 22 | 27 | { |
|---|
| … | … | |
| 37 | 42 | return 1; |
|---|
| 38 | 43 | } |
|---|
| | 44 | |
|---|
| | 45 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 46 | { |
|---|
| | 47 | arg1 = typeid(void*); |
|---|
| | 48 | arg2 = typeid(void*); |
|---|
| | 49 | return 0; |
|---|
| | 50 | } |
|---|
| 39 | 51 | } |
|---|
| r5577 |
r5652 |
|
| 44 | 44 | } |
|---|
| 45 | 45 | |
|---|
| | 46 | override size_t talign() |
|---|
| | 47 | { |
|---|
| | 48 | return double.alignof; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| 46 | 51 | override size_t tsize() |
|---|
| 47 | 52 | { |
|---|
| r5577 |
r5652 |
|
| 43 | 43 | } |
|---|
| 44 | 44 | |
|---|
| | 45 | override size_t talign() |
|---|
| | 46 | { |
|---|
| | 47 | return float.alignof; |
|---|
| | 48 | } |
|---|
| | 49 | |
|---|
| 45 | 50 | override size_t tsize() |
|---|
| 46 | 51 | { |
|---|
| r5577 |
r5652 |
|
| 27 | 27 | } |
|---|
| 28 | 28 | |
|---|
| | 29 | override size_t talign() |
|---|
| | 30 | { |
|---|
| | 31 | return int.alignof; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| 29 | 34 | override size_t tsize() |
|---|
| 30 | 35 | { |
|---|
| r5577 |
r5652 |
|
| 32 | 32 | } |
|---|
| 33 | 33 | |
|---|
| | 34 | override size_t talign() |
|---|
| | 35 | { |
|---|
| | 36 | return long.alignof; |
|---|
| | 37 | } |
|---|
| | 38 | |
|---|
| 34 | 39 | override size_t tsize() |
|---|
| 35 | 40 | { |
|---|
| r5577 |
r5652 |
|
| 26 | 26 | } |
|---|
| 27 | 27 | |
|---|
| | 28 | override size_t talign() |
|---|
| | 29 | { |
|---|
| | 30 | return (void*).alignof; |
|---|
| | 31 | } |
|---|
| | 32 | |
|---|
| 28 | 33 | override size_t tsize() |
|---|
| 29 | 34 | { |
|---|
| r5577 |
r5652 |
|
| 44 | 44 | } |
|---|
| 45 | 45 | |
|---|
| | 46 | override size_t talign() |
|---|
| | 47 | { |
|---|
| | 48 | return real.alignof; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| 46 | 51 | override size_t tsize() |
|---|
| 47 | 52 | { |
|---|
| r5577 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return short.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r5577 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return ubyte.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r5577 |
r5652 |
|
| 27 | 27 | } |
|---|
| 28 | 28 | |
|---|
| | 29 | override size_t talign() |
|---|
| | 30 | { |
|---|
| | 31 | return uint.alignof; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| 29 | 34 | override size_t tsize() |
|---|
| 30 | 35 | { |
|---|
| r5577 |
r5652 |
|
| 32 | 32 | } |
|---|
| 33 | 33 | |
|---|
| | 34 | override size_t talign() |
|---|
| | 35 | { |
|---|
| | 36 | return ulong.alignof; |
|---|
| | 37 | } |
|---|
| | 38 | |
|---|
| 34 | 39 | override size_t tsize() |
|---|
| 35 | 40 | { |
|---|
| r5577 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return ushort.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r5577 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return void.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r5577 |
r5652 |
|
| 22 | 22 | } |
|---|
| 23 | 23 | |
|---|
| | 24 | override size_t talign() |
|---|
| | 25 | { |
|---|
| | 26 | return wchar.alignof; |
|---|
| | 27 | } |
|---|
| | 28 | |
|---|
| 24 | 29 | override size_t tsize() |
|---|
| 25 | 30 | { |
|---|
| r5609 |
r5652 |
|
| 323 | 323 | foreach (m; ModuleInfo) |
|---|
| 324 | 324 | { |
|---|
| | 325 | if (!m) |
|---|
| | 326 | continue; |
|---|
| | 327 | |
|---|
| 325 | 328 | //writefln("module %s, %d", m.name, m.localClasses.length); |
|---|
| 326 | 329 | foreach (c; m.localClasses) |
|---|
| … | … | |
| 412 | 415 | /// Compares two instances for <, ==, or >. |
|---|
| 413 | 416 | int compare(in void* p1, in void* p2) { return 0; } //throw new Exception("non comparable",__FILE__,__LINE__); |
|---|
| | 417 | |
|---|
| | 418 | /// Return alignment of type |
|---|
| | 419 | size_t talign() { return tsize(); } |
|---|
| 414 | 420 | |
|---|
| 415 | 421 | /// Returns size of the type. |
|---|
| … | … | |
| 469 | 475 | /// Get type information on the contents of the type; null if not available |
|---|
| 470 | 476 | OffsetTypeInfo[] offTi() { return null; } |
|---|
| | 477 | |
|---|
| | 478 | |
|---|
| | 479 | /** Return internal info on arguments fitting into 8byte. |
|---|
| | 480 | * See X86-64 ABI 3.2.3 |
|---|
| | 481 | */ |
|---|
| | 482 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 483 | { |
|---|
| | 484 | arg1 = this; |
|---|
| | 485 | return 0; |
|---|
| | 486 | } |
|---|
| 471 | 487 | } |
|---|
| 472 | 488 | |
|---|
| … | … | |
| 494 | 510 | override PointerMap pointermap() { return base.pointermap(); } |
|---|
| 495 | 511 | override void[] init() { return m_init.length ? m_init : base.init(); } |
|---|
| | 512 | |
|---|
| | 513 | size_t talign() { return base.talign(); } |
|---|
| | 514 | |
|---|
| | 515 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 516 | { |
|---|
| | 517 | return base.argTypes(arg1, arg2); |
|---|
| | 518 | } |
|---|
| 496 | 519 | |
|---|
| 497 | 520 | TypeInfo base; |
|---|
| … | … | |
| 632 | 655 | |
|---|
| 633 | 656 | override uint flags() { return 1; } |
|---|
| | 657 | |
|---|
| | 658 | size_t talign() |
|---|
| | 659 | { |
|---|
| | 660 | return (void[]).alignof; |
|---|
| | 661 | } |
|---|
| | 662 | |
|---|
| | 663 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 664 | { //arg1 = typeid(size_t); |
|---|
| | 665 | //arg2 = typeid(void*); |
|---|
| | 666 | return 0; |
|---|
| | 667 | } |
|---|
| 634 | 668 | |
|---|
| 635 | 669 | override PointerMap pointermap() |
|---|
| … | … | |
| 747 | 781 | TypeInfo value; |
|---|
| 748 | 782 | size_t len; |
|---|
| | 783 | |
|---|
| | 784 | size_t talign() |
|---|
| | 785 | { |
|---|
| | 786 | return value.talign(); |
|---|
| | 787 | } |
|---|
| | 788 | |
|---|
| | 789 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 790 | { |
|---|
| | 791 | arg1 = typeid(void*); |
|---|
| | 792 | return 0; |
|---|
| | 793 | } |
|---|
| | 794 | |
|---|
| 749 | 795 | } |
|---|
| 750 | 796 | |
|---|
| … | … | |
| 816 | 862 | TypeInfo value; |
|---|
| 817 | 863 | TypeInfo key; |
|---|
| | 864 | |
|---|
| | 865 | size_t talign() |
|---|
| | 866 | { |
|---|
| | 867 | return (char[int]).alignof; |
|---|
| | 868 | } |
|---|
| | 869 | |
|---|
| | 870 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 871 | { |
|---|
| | 872 | arg1 = typeid(void*); |
|---|
| | 873 | return 0; |
|---|
| | 874 | } |
|---|
| 818 | 875 | } |
|---|
| 819 | 876 | |
|---|
| … | … | |
| 900 | 957 | |
|---|
| 901 | 958 | TypeInfo next; |
|---|
| | 959 | |
|---|
| | 960 | size_t talign() |
|---|
| | 961 | { |
|---|
| | 962 | alias int delegate() dg; |
|---|
| | 963 | return dg.alignof; |
|---|
| | 964 | } |
|---|
| | 965 | |
|---|
| | 966 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 967 | { //arg1 = typeid(void*); |
|---|
| | 968 | //arg2 = typeid(void*); |
|---|
| | 969 | return 0; |
|---|
| | 970 | } |
|---|
| | 971 | |
|---|
| 902 | 972 | } |
|---|
| 903 | 973 | |
|---|
| … | … | |
| 1112 | 1182 | override uint flags() { return m_flags; } |
|---|
| 1113 | 1183 | |
|---|
| | 1184 | size_t talign() { return m_align; } |
|---|
| | 1185 | |
|---|
| | 1186 | |
|---|
| 1114 | 1187 | char[] name; |
|---|
| 1115 | 1188 | void[] m_init; // initializer; init.ptr == null if 0 initialize |
|---|
| … | … | |
| 1122 | 1195 | |
|---|
| 1123 | 1196 | uint m_flags; |
|---|
| | 1197 | uint m_align; |
|---|
| 1124 | 1198 | |
|---|
| 1125 | 1199 | version (D_HavePointerMap) { |
|---|
| … | … | |
| 1127 | 1201 | |
|---|
| 1128 | 1202 | override PointerMap pointermap() { return m_pointermap; } |
|---|
| | 1203 | } |
|---|
| | 1204 | |
|---|
| | 1205 | version (X86_64) |
|---|
| | 1206 | { |
|---|
| | 1207 | int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 1208 | { |
|---|
| | 1209 | arg1 = m_arg1; |
|---|
| | 1210 | arg2 = m_arg2; |
|---|
| | 1211 | return 0; |
|---|
| | 1212 | } |
|---|
| | 1213 | TypeInfo m_arg1; |
|---|
| | 1214 | TypeInfo m_arg2; |
|---|
| 1129 | 1215 | } |
|---|
| 1130 | 1216 | } |
|---|
| … | … | |
| 1195 | 1281 | assert(0); |
|---|
| 1196 | 1282 | } |
|---|
| | 1283 | |
|---|
| | 1284 | version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) |
|---|
| | 1285 | { |
|---|
| | 1286 | assert(0); |
|---|
| | 1287 | } |
|---|
| 1197 | 1288 | } |
|---|
| 1198 | 1289 | |
|---|
| … | … | |
| 1470 | 1561 | } |
|---|
| 1471 | 1562 | } |
|---|
| 1472 | | debug(PRINTF) printf("_moduleIndependentCtors() DONE\n"); |
|---|
| 1473 | 1563 | } |
|---|
| 1474 | 1564 | |
|---|
| r4974 |
r5652 |
|
| 83 | 83 | } |
|---|
| 84 | 84 | |
|---|
| | 85 | override size_t talign() |
|---|
| | 86 | { |
|---|
| | 87 | return (Object[]).alignof; |
|---|
| | 88 | } |
|---|
| | 89 | |
|---|
| 85 | 90 | override size_t tsize() |
|---|
| 86 | 91 | { |
|---|
| r4974 |
r5652 |
|
| 76 | 76 | } |
|---|
| 77 | 77 | |
|---|
| | 78 | override size_t talign() |
|---|
| | 79 | { |
|---|
| | 80 | return (cdouble[]).alignof; |
|---|
| | 81 | } |
|---|
| | 82 | |
|---|
| 78 | 83 | override size_t tsize() |
|---|
| 79 | 84 | { |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (cfloat[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (creal[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (double[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (float[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| r5012 |
r5652 |
|
| 47 | 47 | return 1; |
|---|
| 48 | 48 | return 0; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | override size_t talign() |
|---|
| | 52 | { |
|---|
| | 53 | return (byte[]).alignof; |
|---|
| 49 | 54 | } |
|---|
| 50 | 55 | |
|---|
| r5012 |
r5652 |
|
| 46 | 46 | return 1; |
|---|
| 47 | 47 | return 0; |
|---|
| | 48 | } |
|---|
| | 49 | |
|---|
| | 50 | override size_t talign() |
|---|
| | 51 | { |
|---|
| | 52 | return (int[]).alignof; |
|---|
| 48 | 53 | } |
|---|
| 49 | 54 | |
|---|
| r5012 |
r5652 |
|
| 47 | 47 | return 1; |
|---|
| 48 | 48 | return 0; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | override size_t talign() |
|---|
| | 52 | { |
|---|
| | 53 | return (long[]).alignof; |
|---|
| 49 | 54 | } |
|---|
| 50 | 55 | |
|---|
| r4974 |
r5652 |
|
| 77 | 77 | } |
|---|
| 78 | 78 | |
|---|
| | 79 | override size_t talign() |
|---|
| | 80 | { |
|---|
| | 81 | return (real[]).alignof; |
|---|
| | 82 | } |
|---|
| | 83 | |
|---|
| 79 | 84 | override size_t tsize() |
|---|
| 80 | 85 | { |
|---|
| r5012 |
r5652 |
|
| 46 | 46 | return 1; |
|---|
| 47 | 47 | return 0; |
|---|
| | 48 | } |
|---|
| | 49 | |
|---|
| | 50 | override size_t talign() |
|---|
| | 51 | { |
|---|
| | 52 | return (short[]).alignof; |
|---|
| 48 | 53 | } |
|---|
| 49 | 54 | |
|---|
| r4974 |
r5652 |
|
| 63 | 63 | } |
|---|
| 64 | 64 | |
|---|
| | 65 | override size_t talign() |
|---|
| | 66 | { |
|---|
| | 67 | return Object.alignof; |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| 65 | 70 | override size_t tsize() |
|---|
| 66 | 71 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return byte.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return cdouble.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| r4974 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return cfloat.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| r4974 |
r5652 |
|
| 21 | 21 | } |
|---|
| 22 | 22 | |
|---|
| | 23 | override size_t talign() |
|---|
| | 24 | { |
|---|
| | 25 | return char.alignof; |
|---|
| | 26 | } |
|---|
| | 27 | |
|---|
| 23 | 28 | override size_t tsize() |
|---|
| 24 | 29 | { |
|---|
| r4974 |
r5652 |
|
| 45 | 45 | } |
|---|
| 46 | 46 | |
|---|
| | 47 | override size_t talign() |
|---|
| | 48 | { |
|---|
| | 49 | return creal.alignof; |
|---|
| | 50 | } |
|---|
| | 51 | |
|---|
| 47 | 52 | override size_t tsize() |
|---|
| 48 | 53 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return dchar.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 17 | 17 | { |
|---|
| 18 | 18 | return *cast(dg *)p1 == *cast(dg *)p2; |
|---|
| | 19 | } |
|---|
| | 20 | |
|---|
| | 21 | override size_t talign() |
|---|
| | 22 | { |
|---|
| | 23 | return dg.alignof; |
|---|
| 19 | 24 | } |
|---|
| 20 | 25 | |
|---|
| r4974 |
r5652 |
|
| 44 | 44 | } |
|---|
| 45 | 45 | |
|---|
| | 46 | override size_t talign() |
|---|
| | 47 | { |
|---|
| | 48 | return double.alignof; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| 46 | 51 | override size_t tsize() |
|---|
| 47 | 52 | { |
|---|
| r4974 |
r5652 |
|
| 43 | 43 | } |
|---|
| 44 | 44 | |
|---|
| | 45 | override size_t talign() |
|---|
| | 46 | { |
|---|
| | 47 | return float.alignof; |
|---|
| | 48 | } |
|---|
| | 49 | |
|---|
| 45 | 50 | override size_t tsize() |
|---|
| 46 | 51 | { |
|---|
| r4974 |
r5652 |
|
| 27 | 27 | } |
|---|
| 28 | 28 | |
|---|
| | 29 | override size_t talign() |
|---|
| | 30 | { |
|---|
| | 31 | return int.alignof; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| 29 | 34 | override size_t tsize() |
|---|
| 30 | 35 | { |
|---|
| r4974 |
r5652 |
|
| 32 | 32 | } |
|---|
| 33 | 33 | |
|---|
| | 34 | override size_t talign() |
|---|
| | 35 | { |
|---|
| | 36 | return long.alignof; |
|---|
| | 37 | } |
|---|
| | 38 | |
|---|
| 34 | 39 | override size_t tsize() |
|---|
| 35 | 40 | { |
|---|
| r4974 |
r5652 |
|
| 26 | 26 | } |
|---|
| 27 | 27 | |
|---|
| | 28 | override size_t talign() |
|---|
| | 29 | { |
|---|
| | 30 | return (void*).alignof; |
|---|
| | 31 | } |
|---|
| | 32 | |
|---|
| 28 | 33 | override size_t tsize() |
|---|
| 29 | 34 | { |
|---|
| r4974 |
r5652 |
|
| 44 | 44 | } |
|---|
| 45 | 45 | |
|---|
| | 46 | override size_t talign() |
|---|
| | 47 | { |
|---|
| | 48 | return real.alignof; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| 46 | 51 | override size_t tsize() |
|---|
| 47 | 52 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return short.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return ubyte.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 27 | 27 | } |
|---|
| 28 | 28 | |
|---|
| | 29 | override size_t talign() |
|---|
| | 30 | { |
|---|
| | 31 | return uint.alignof; |
|---|
| | 32 | } |
|---|
| | 33 | |
|---|
| 29 | 34 | override size_t tsize() |
|---|
| 30 | 35 | { |
|---|
| r4974 |
r5652 |
|
| 32 | 32 | } |
|---|
| 33 | 33 | |
|---|
| | 34 | override size_t talign() |
|---|
| | 35 | { |
|---|
| | 36 | return ulong.alignof; |
|---|
| | 37 | } |
|---|
| | 38 | |
|---|
| 34 | 39 | override size_t tsize() |
|---|
| 35 | 40 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return ushort.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 23 | 23 | } |
|---|
| 24 | 24 | |
|---|
| | 25 | override size_t talign() |
|---|
| | 26 | { |
|---|
| | 27 | return void.alignof; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 25 | 30 | override size_t tsize() |
|---|
| 26 | 31 | { |
|---|
| r4974 |
r5652 |
|
| 22 | 22 | } |
|---|
| 23 | 23 | |
|---|
| | 24 | override size_t talign() |
|---|
| | 25 | { |
|---|
| | 26 | return wchar.alignof; |
|---|
| | 27 | } |
|---|
| | 28 | |
|---|
| 24 | 29 | override size_t tsize() |
|---|
| 25 | 30 | { |
|---|
| r5248 |
r5652 |
|
| 69 | 69 | } |
|---|
| 70 | 70 | |
|---|
| | 71 | debug import tango.stdc.stdio : printf; |
|---|
| | 72 | |
|---|
| 71 | 73 | unittest |
|---|
| 72 | 74 | { |
|---|
| … | … | |
| 885 | 887 | assert(w == "hello"); |
|---|
| 886 | 888 | |
|---|
| | 889 | debug(utf) printf("utf.toUTF.unittest\n"); |
|---|
| 887 | 890 | |
|---|
| 888 | 891 | c = "hel\u1234o"; |
|---|
| … | … | |
| 902 | 905 | assert(w == "hel\u1234o"); |
|---|
| 903 | 906 | |
|---|
| | 907 | debug(utf) printf("utf.toUTF.unittest\n"); |
|---|
| 904 | 908 | |
|---|
| 905 | 909 | c = "he\U0010AAAAllo"; |
|---|
| r5396 |
r5652 |
|
| 116 | 116 | else static if (is(typeof(mmap))) // else version (GC_Use_Alloc_MMap) |
|---|
| 117 | 117 | { |
|---|
| | 118 | debug(PRINTF) import tango.stdc.stdio: printf; |
|---|
| | 119 | |
|---|
| | 120 | |
|---|
| 118 | 121 | void *os_mem_map(size_t nbytes) |
|---|
| 119 | 122 | { void *p; |
|---|
| 120 | 123 | |
|---|
| | 124 | debug(PRINTF) printf("mmap alloc of %p bytes\n", nbytes); |
|---|
| 121 | 125 | p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); |
|---|
| 122 | 126 | return (p == MAP_FAILED) ? null : p; |
|---|
| r5529 |
r5652 |
|
| 51 | 51 | struct GCBits |
|---|
| 52 | 52 | { |
|---|
| 53 | | const int BITS_PER_WORD = 32; |
|---|
| 54 | | const int BITS_SHIFT = 5; |
|---|
| 55 | | const int BITS_MASK = 31; |
|---|
| 56 | | |
|---|
| 57 | | uint* data = null; |
|---|
| | 53 | alias size_t wordtype; |
|---|
| | 54 | |
|---|
| | 55 | const BITS_PER_WORD = (wordtype.sizeof * 8); |
|---|
| | 56 | const BITS_SHIFT = (wordtype.sizeof == 8 ? 6 : 5); |
|---|
| | 57 | const BITS_MASK = (BITS_PER_WORD - 1); |
|---|
| | 58 | const BITS_1 = cast(wordtype)1; |
|---|
| | 59 | |
|---|
| | 60 | wordtype* data = null; |
|---|
| 58 | 61 | size_t nwords = 0; // allocated words in data[] excluding sentinals |
|---|
| 59 | 62 | size_t nbits = 0; // number of bits in data[] excluding sentinals |
|---|
| … | … | |
| 80 | 83 | this.nbits = nbits; |
|---|
| 81 | 84 | nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT; |
|---|
| 82 | | data = cast(uint*)calloc(nwords + 2, uint.sizeof); |
|---|
| | 85 | data = cast(wordtype*)calloc(nwords + 2, wordtype.sizeof); |
|---|
| 83 | 86 | if (!data) |
|---|
| 84 | 87 | onOutOfMemoryError(); |
|---|
| 85 | 88 | } |
|---|
| 86 | 89 | |
|---|
| 87 | | uint test(size_t i) |
|---|
| | 90 | wordtype test(size_t i) |
|---|
| 88 | 91 | in |
|---|
| 89 | 92 | { |
|---|
| … | … | |
| 93 | 96 | { |
|---|
| 94 | 97 | //return (cast(bit *)(data + 1))[i]; |
|---|
| 95 | | return data[1 + (i >> BITS_SHIFT)] & (1 << (i & BITS_MASK)); |
|---|
| | 98 | return data[1 + (i >> BITS_SHIFT)] & (BITS_1 << (i & BITS_MASK)); |
|---|
| 96 | 99 | } |
|---|
| 97 | 100 | |
|---|
| … | … | |
| 104 | 107 | { |
|---|
| 105 | 108 | //(cast(bit *)(data + 1))[i] = 1; |
|---|
| 106 | | data[1 + (i >> BITS_SHIFT)] |= (1 << (i & BITS_MASK)); |
|---|
| | 109 | data[1 + (i >> BITS_SHIFT)] |= (BITS_1 << (i & BITS_MASK)); |
|---|
| 107 | 110 | } |
|---|
| 108 | 111 | |
|---|
| … | … | |
| 115 | 118 | { |
|---|
| 116 | 119 | //(cast(bit *)(data + 1))[i] = 0; |
|---|
| 117 | | data[1 + (i >> BITS_SHIFT)] &= ~(1 << (i & BITS_MASK)); |
|---|
| 118 | | } |
|---|
| 119 | | |
|---|
| 120 | | uint testClear(size_t i) |
|---|
| | 120 | data[1 + (i >> BITS_SHIFT)] &= ~(BITS_1 << (i & BITS_MASK)); |
|---|
| | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | wordtype testClear(size_t i) |
|---|
| 121 | 124 | { |
|---|
| 122 | 125 | version (bitops) |
|---|
| … | … | |
| 137 | 140 | } |
|---|
| 138 | 141 | else |
|---|
| 139 | | { uint result; |
|---|
| | 142 | { wordtype result; |
|---|
| 140 | 143 | |
|---|
| 141 | 144 | //result = (cast(bit *)(data + 1))[i]; |
|---|
| 142 | 145 | //(cast(bit *)(data + 1))[i] = 0; |
|---|
| 143 | 146 | |
|---|
| 144 | | uint* p = &data[1 + (i >> BITS_SHIFT)]; |
|---|
| 145 | | uint mask = (1 << (i & BITS_MASK)); |
|---|
| | 147 | wordtype* p = &data[1 + (i >> BITS_SHIFT)]; |
|---|
| | 148 | wordtype mask = (BITS_1 << (i & BITS_MASK)); |
|---|
| 146 | 149 | result = *p & mask; |
|---|
| 147 | 150 | *p &= ~mask; |
|---|
| … | … | |
| 150 | 153 | } |
|---|
| 151 | 154 | |
|---|
| 152 | | uint testSet(size_t i) |
|---|
| | 155 | wordtype testSet(size_t i) |
|---|
| 153 | 156 | { |
|---|
| 154 | 157 | version (bitops) |
|---|
| … | … | |
| 169 | 172 | } |
|---|
| 170 | 173 | else |
|---|
| 171 | | { uint result; |
|---|
| 172 | | |
|---|
| | 174 | { |
|---|
| 173 | 175 | //result = (cast(bit *)(data + 1))[i]; |
|---|
| 174 | 176 | //(cast(bit *)(data + 1))[i] = 0; |
|---|
| 175 | 177 | |
|---|
| 176 | | uint* p = &data[1 + (i >> BITS_SHIFT)]; |
|---|
| 177 | | uint mask = (1 << (i & BITS_MASK)); |
|---|
| 178 | | result = *p & mask; |
|---|
| | 178 | auto p = &data[1 + (i >> BITS_SHIFT)]; |
|---|
| | 179 | auto mask = (BITS_1 << (i & BITS_MASK)); |
|---|
| | 180 | auto result = *p & mask; |
|---|
| 179 | 181 | *p |= mask; |
|---|
| 180 | 182 | return result; |
|---|
| … | … | |
| 189 | 191 | *d1=0u; |
|---|
| 190 | 192 | } else { |
|---|
| 191 | | memset(data + 1, 0, nwords * uint.sizeof); |
|---|
| | 193 | memset(data + 1, 0, nwords * wordtype.sizeof); |
|---|
| 192 | 194 | } |
|---|
| 193 | 195 | } |
|---|
| … | … | |
| 201 | 203 | { |
|---|
| 202 | 204 | version(MEMCPY_NON_SIG_SAFE) { |
|---|
| 203 | | uint * d1=data+1,d2=f.data+1,dEnd=d1+nwords; |
|---|
| | 205 | wordtype * d1=data+1,d2=f.data+1,dEnd=d1+nwords; |
|---|
| 204 | 206 | for (;d1!=dEnd;++d1,++d2) |
|---|
| 205 | 207 | *d1=*d2; |
|---|
| 206 | 208 | } else { |
|---|
| 207 | | memcpy(data + 1, f.data + 1, nwords * uint.sizeof); |
|---|
| 208 | | } |
|---|
| 209 | | } |
|---|
| 210 | | |
|---|
| 211 | | uint* base() |
|---|
| | 209 | memcpy(data + 1, f.data + 1, nwords * wordtype.sizeof); |
|---|
| | 210 | } |
|---|
| | 211 | } |
|---|
| | 212 | |
|---|
| | 213 | wordtype* base() |
|---|
| 212 | 214 | in |
|---|
| 213 | 215 | { |
|---|
| r5560 |
r5652 |
|
| 65 | 65 | } |
|---|
| 66 | 66 | |
|---|
| 67 | | |
|---|
| 68 | 67 | struct BlkInfo |
|---|
| 69 | 68 | { |
|---|
| … | … | |
| 238 | 237 | Gcx *gcx; // implementation |
|---|
| 239 | 238 | static ClassInfo gcLock; // global lock |
|---|
| 240 | | |
|---|
| | 239 | |
|---|
| 241 | 240 | |
|---|
| 242 | 241 | final void initialize() |
|---|
| … | … | |
| 1340 | 1339 | |
|---|
| 1341 | 1340 | //call locked if necessary |
|---|
| 1342 | | private T locked(T)(in T delegate() code) |
|---|
| | 1341 | private T locked(T)(in T delegate() code) |
|---|
| 1343 | 1342 | { |
|---|
| 1344 | 1343 | if (thread_needLock) |
|---|
| … | … | |
| 1348 | 1347 | } |
|---|
| 1349 | 1348 | |
|---|
| 1350 | | private struct WeakPointer |
|---|
| | 1349 | private struct WeakPointer |
|---|
| 1351 | 1350 | { |
|---|
| 1352 | 1351 | Object reference; |
|---|
| 1353 | 1352 | |
|---|
| 1354 | | void ondestroy(Object r) |
|---|
| | 1353 | void ondestroy(Object r) |
|---|
| 1355 | 1354 | { |
|---|
| 1356 | 1355 | assert(r is reference); |
|---|
| … | … | |
| 1358 | 1357 | // |
|---|
| 1359 | 1358 | //also ensures that weakpointerDestroy can be called while another |
|---|
| 1360 | | //thread is freeing the reference with "delete" |
|---|
| | 1359 | //thread is freeing the reference with "delete" |
|---|
| 1361 | 1360 | locked!(void)({ reference = null; }); |
|---|
| 1362 | 1361 | } |
|---|
| … | … | |
| 1390 | 1389 | final void weakpointerDestroy( void* p ) |
|---|
| 1391 | 1390 | { |
|---|
| 1392 | | if (p) |
|---|
| | 1391 | if (p) |
|---|
| 1393 | 1392 | { |
|---|
| 1394 | 1393 | auto wp = cast(WeakPointer*)p; |
|---|
| … | … | |
| 1491 | 1490 | void thread_Invariant() { } |
|---|
| 1492 | 1491 | } |
|---|
| 1493 | | |
|---|
| | 1492 | |
|---|
| 1494 | 1493 | void *cached_size_key; |
|---|
| 1495 | 1494 | size_t cached_size_val; |
|---|
| 1496 | | |
|---|
| | 1495 | |
|---|
| 1497 | 1496 | void *cached_info_key; |
|---|
| 1498 | 1497 | BlkInfo cached_info_val; |
|---|
| … | … | |
| 1667 | 1666 | void addRange(void *pbot, void *ptop) |
|---|
| 1668 | 1667 | { |
|---|
| 1669 | | debug(PRINTF) printf("Thread %x ", pthread_self()); |
|---|
| | 1668 | debug(PRINTF) debug(THREADINVARIANT) printf("Thread %x ", pthread_self()); |
|---|
| 1670 | 1669 | debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges); |
|---|
| 1671 | 1670 | if (nranges == rangedim) |
|---|
| … | … | |
| 1695 | 1694 | void removeRange(void *pbot) |
|---|
| 1696 | 1695 | { |
|---|
| 1697 | | debug(PRINTF) printf("Thread %x ", pthread_self()); |
|---|
| | 1696 | debug(PRINTF) debug(THREADINVARIANT) printf("Thread %x ", pthread_self()); |
|---|
| 1698 | 1697 | debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges); |
|---|
| 1699 | 1698 | for (size_t i = nranges; i--;) |
|---|
| … | … | |
| 1799 | 1798 | if (USE_CACHE && p == cached_size_key) |
|---|
| 1800 | 1799 | return cached_size_val; |
|---|
| 1801 | | |
|---|
| | 1800 | |
|---|
| 1802 | 1801 | pool = findPool(p); |
|---|
| 1803 | 1802 | if (pool) |
|---|
| … | … | |
| 1836 | 1835 | Pool* pool; |
|---|
| 1837 | 1836 | BlkInfo info; |
|---|
| 1838 | | |
|---|
| | 1837 | |
|---|
| 1839 | 1838 | if (USE_CACHE && p == cached_info_key) |
|---|
| 1840 | 1839 | return cached_info_val; |
|---|
| … | … | |
| 1889 | 1888 | // getBits |
|---|
| 1890 | 1889 | //////////////////////////////////////////////////////////////////// |
|---|
| 1891 | | |
|---|
| | 1890 | |
|---|
| 1892 | 1891 | assert(p >= info.base && p< info.base + info.size); |
|---|
| 1893 | 1892 | info.attr = getBits(pool, cast(size_t) (info.base - pool.baseAddr) / 16); |
|---|
| … | … | |
| 2099 | 2098 | size_t i; |
|---|
| 2100 | 2099 | |
|---|
| 2101 | | //debug(PRINTF) printf("************Gcx::newPool(npages = %d)****************\n", npages); |
|---|
| | 2100 | |
|---|
| | 2101 | debug(PRINTF) printf("************Gcx::newPool(npages = %x)****************\n", npages); |
|---|
| 2102 | 2102 | |
|---|
| 2103 | 2103 | // Round up to COMMITSIZE pages |
|---|
| … | … | |
| 2327 | 2327 | movq rsi[RBP], RSI ; |
|---|
| 2328 | 2328 | movq rdi[RBP], RDI ; |
|---|
| 2329 | | movq r8 [RBP], R8 ; |
|---|
| 2330 | | movq r9 [RBP], R9 ; |
|---|
| | 2329 | movq r8 [RBP], R8 ; |
|---|
| | 2330 | movq r9 [RBP], R9 ; |
|---|
| 2331 | 2331 | movq r10[RBP], R10 ; |
|---|
| 2332 | 2332 | movq r11[RBP], R11 ; |
|---|
| … | … | |
| 2345 | 2345 | else |
|---|
| 2346 | 2346 | { |
|---|
| 2347 | | asm |
|---|
| 2348 | | { |
|---|
| 2349 | | pushad ; |
|---|
| 2350 | | mov sp[EBP],ESP ; |
|---|
| | 2347 | version (D_InlineAsm_X86) |
|---|
| | 2348 | { |
|---|
| | 2349 | asm |
|---|
| | 2350 | { |
|---|
| | 2351 | pushad ; |
|---|
| | 2352 | mov sp[EBP],ESP ; |
|---|
| | 2353 | } |
|---|
| | 2354 | } |
|---|
| | 2355 | else version (D_InlineAsm_X86_64) |
|---|
| | 2356 | { |
|---|
| | 2357 | asm |
|---|
| | 2358 | { |
|---|
| | 2359 | push RAX ; |
|---|
| | 2360 | push RBX ; |
|---|
| | 2361 | push RCX ; |
|---|
| | 2362 | push RDX ; |
|---|
| | 2363 | push RSI ; |
|---|
| | 2364 | push RDI ; |
|---|
| | 2365 | push RBP ; |
|---|
| | 2366 | push R8 ; |
|---|
| | 2367 | push R9 ; |
|---|
| | 2368 | push R10 ; |
|---|
| | 2369 | push R11 ; |
|---|
| | 2370 | push R12 ; |
|---|
| | 2371 | push R13 ; |
|---|
| | 2372 | push R14 ; |
|---|
| | 2373 | push R15 ; |
|---|
| | 2374 | push EAX ; // 16 byte align the stack |
|---|
| | 2375 | } |
|---|
| | 2376 | } |
|---|
| | 2377 | else |
|---|
| | 2378 | { |
|---|
| | 2379 | static assert( false, "Architecture not supported." ); |
|---|
| 2351 | 2380 | } |
|---|
| 2352 | 2381 | } |
|---|
| … | … | |
| 2360 | 2389 | // nothing to do |
|---|
| 2361 | 2390 | } |
|---|
| | 2391 | else version (D_InlineAsm_X86) |
|---|
| | 2392 | { |
|---|
| | 2393 | asm |
|---|
| | 2394 | { |
|---|
| | 2395 | popad; |
|---|
| | 2396 | } |
|---|
| | 2397 | } |
|---|
| | 2398 | else version (D_InlineAsm_X86_64) |
|---|
| | 2399 | { |
|---|
| | 2400 | asm |
|---|
| | 2401 | { |
|---|
| | 2402 | pop EAX ; // 16 byte align the stack |
|---|
| | 2403 | pop R15 ; |
|---|
| | 2404 | pop R14 ; |
|---|
| | 2405 | pop R13 ; |
|---|
| | 2406 | pop R12 ; |
|---|
| | 2407 | pop R11 ; |
|---|
| | 2408 | pop R10 ; |
|---|
| | 2409 | pop R9 ; |
|---|
| | 2410 | pop R8 ; |
|---|
| | 2411 | pop RBP ; |
|---|
| | 2412 | pop RDI ; |
|---|
| | 2413 | pop RSI ; |
|---|
| | 2414 | pop RDX ; |
|---|
| | 2415 | pop RCX ; |
|---|
| | 2416 | pop RBX ; |
|---|
| | 2417 | pop RAX ; |
|---|
| | 2418 | } |
|---|
| | 2419 | } |
|---|
| 2362 | 2420 | else |
|---|
| 2363 | 2421 | { |
|---|
| 2364 | | asm |
|---|
| 2365 | | { |
|---|
| 2366 | | popad ; |
|---|
| 2367 | | } |
|---|
| | 2422 | static assert( false, "Architecture not supported." ); |
|---|
| 2368 | 2423 | } |
|---|
| 2369 | 2424 | return result; |
|---|
| … | … | |
| 2472 | 2527 | *b = 0; |
|---|
| 2473 | 2528 | |
|---|
| 2474 | | auto o = pool.baseAddr + (b - bbase) * 32 * 16; |
|---|
| | 2529 | auto o = pool.baseAddr + (b - bbase) * (typeof(bitm).sizeof*8) * 16; |
|---|
| 2475 | 2530 | if (!(bitm & 0xFFFF)) |
|---|
| 2476 | 2531 | { |
|---|
| … | … | |
| 2520 | 2575 | { size_t pn; |
|---|
| 2521 | 2576 | size_t ncommitted; |
|---|
| 2522 | | uint* bbase; |
|---|
| 2523 | 2577 | |
|---|
| 2524 | 2578 | pool = pooltable[n]; |
|---|
| 2525 | | bbase = pool.mark.base(); |
|---|
| | 2579 | auto bbase = pool.mark.base(); |
|---|
| 2526 | 2580 | ncommitted = pool.ncommitted; |
|---|
| 2527 | 2581 | for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16)) |
|---|
| … | … | |
| 2572 | 2626 | |
|---|
| 2573 | 2627 | pool.freebits.set(biti); |
|---|
| | 2628 | |
|---|
| 2574 | 2629 | if (pool.finals.nbits && pool.finals.testClear(biti)) |
|---|
| 2575 | 2630 | rt_finalize(cast(List *)sentinel_add(p), false/*noStack > 0*/); |
|---|
| … | … | |
| 2910 | 2965 | poolsize = npages * PAGESIZE; |
|---|
| 2911 | 2966 | assert(poolsize >= POOLSIZE); |
|---|
| | 2967 | |
|---|
| | 2968 | debug(PRINTF) printf("alloc of pool: %p bytes\n", poolsize); |
|---|
| | 2969 | |
|---|
| 2912 | 2970 | baseAddr = cast(byte *)os_mem_map(poolsize); |
|---|
| 2913 | 2971 | |
|---|
| r5621 |
r5652 |
|
| 768 | 768 | else |
|---|
| 769 | 769 | { |
|---|
| 770 | | asm |
|---|
| 771 | | { |
|---|
| 772 | | pushad ; |
|---|
| 773 | | mov sp[EBP],ESP ; |
|---|
| 774 | | } |
|---|
| | 770 | version (D_InlineAsm_X86) |
|---|
| | 771 | { |
|---|
| | 772 | asm |
|---|
| | 773 | { |
|---|
| | 774 | pushad ; |
|---|
| | 775 | mov sp[EBP],ESP ; |
|---|
| | 776 | } |
|---|
| | 777 | } |
|---|
| | 778 | else version (D_InlineAsm_X86_64) |
|---|
| | 779 | { |
|---|
| | 780 | asm |
|---|
| | 781 | { |
|---|
| | 782 | push RAX ; |
|---|
| | 783 | push RBX ; |
|---|
| | 784 | push RCX ; |
|---|
| | 785 | push RDX ; |
|---|
| | 786 | push RSI ; |
|---|
| | 787 | push RDI ; |
|---|
| | 788 | push RBP ; |
|---|
| | 789 | push R8 ; |
|---|
| | 790 | push R9 ; |
|---|
| | 791 | push R10 ; |
|---|
| | 792 | push R11 ; |
|---|
| | 793 | push R12 ; |
|---|
| | 794 | push R13 ; |
|---|
| | 795 | push R14 ; |
|---|
| | 796 | push R15 ; |
|---|
| | 797 | push EAX ; // 16 byte align the stack |
|---|
| | 798 | } |
|---|
| | 799 | } |
|---|
| | 800 | else |
|---|
| | 801 | { |
|---|
| | 802 | static assert( false, "Architecture not supported." ); |
|---|
| | 803 | } |
|---|
| 775 | 804 | } |
|---|
| 776 | 805 | result = fullcollect(sp, early, force_block); |
|---|
| r5607 |
r5652 |
|
| 246 | 246 | } |
|---|
| 247 | 247 | } else version(D_InlineAsm_X86) { |
|---|
| 248 | | T atomicSwap( T )( inout T val, T newval ) |
|---|
| | 248 | T atomicSwap( T )( ref T val, T newval ) |
|---|
| 249 | 249 | in { |
|---|
| 250 | 250 | // NOTE: 32 bit x86 systems support 8 byte CAS, which only requires |
|---|
| … | … | |
| 290 | 290 | } |
|---|
| 291 | 291 | } else version (D_InlineAsm_X86_64){ |
|---|
| 292 | | T atomicSwap( T )( inout T val, T newval ) |
|---|
| | 292 | T atomicSwap( T )( ref T val, T newval ) |
|---|
| 293 | 293 | in { |
|---|
| 294 | 294 | assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); |
|---|
| … | … | |
| 333 | 333 | } |
|---|
| 334 | 334 | } else { |
|---|
| 335 | | T atomicSwap( T )( inout T val, T newval ) |
|---|
| | 335 | T atomicSwap( T )( ref T val, T newval ) |
|---|
| 336 | 336 | in { |
|---|
| 337 | 337 | assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); |
|---|
| r5607 |
r5652 |
|
| 184 | 184 | STB_LOCAL = 0, |
|---|
| 185 | 185 | } |
|---|
| 186 | | |
|---|
| | 186 | |
|---|
| 187 | 187 | } |
|---|
| 188 | 188 | |
|---|
| … | … | |
| 232 | 232 | return newV; |
|---|
| 233 | 233 | } |
|---|
| 234 | | |
|---|
| | 234 | |
|---|
| 235 | 235 | // stores the global sections |
|---|
| 236 | 236 | const MAX_SECTS=5; |
|---|
| … | … | |
| 238 | 238 | static size_t _nGSections,_nFileBuf; |
|---|
| 239 | 239 | static char[MAX_SECTS*256] _fileNameBuf; |
|---|
| 240 | | |
|---|
| | 240 | |
|---|
| 241 | 241 | /// loops on the global sections |
|---|
| 242 | 242 | static int opApply(int delegate(ref StaticSectionInfo) loop){ |
|---|
| … | … | |
| 383 | 383 | } |
|---|
| 384 | 384 | |
|---|
| 385 | | |
|---|
| | 385 | |
|---|
| 386 | 386 | /* find sections */ |
|---|
| 387 | 387 | char[] string_table; |
|---|
| … | … | |
| 590 | 590 | return; |
|---|
| 591 | 591 | } |
|---|
| 592 | | |
|---|
| | 592 | |
|---|
| 593 | 593 | } |
|---|
| 594 | 594 | } |
|---|
| … | … | |
| 671 | 671 | } |
|---|
| 672 | 672 | long sleb128() { |
|---|
| 673 | | return cast(size_t) do_read_leb(true); |
|---|
| | 673 | return cast(long) do_read_leb(true); |
|---|
| 674 | 674 | } |
|---|
| 675 | 675 | |
|---|
| … | … | |
| 697 | 697 | } |
|---|
| 698 | 698 | |
|---|
| 699 | | unittest { |
|---|
| | 699 | unittest |
|---|
| | 700 | { |
|---|
| 700 | 701 | //examples from dwarf spec section 7.6 |
|---|
| 701 | | ubyte[] bytes = [2,127,0x80,1,0x81,1,0x82,1,57+0x80,100,2,0x7e,127+0x80,0, |
|---|
| 702 | | 0x81,0x7f,0x80,1,0x80,0x7f,0x81,1,0x7f+0x80,0x7e]; |
|---|
| | 702 | ubyte[] bytes = [2, 127, 0x80,1, 0x81,1, 0x82,1, 57+0x80,100, |
|---|
| | 703 | 2, 0x7e, 127+0x80,0, 0x81,0x7f, 0x80,1, 0x80,0x7f, 0x81,1, 0x7f+0x80,0x7e]; |
|---|
| | 704 | |
|---|
| 703 | 705 | ulong[] u = [2, 127, 128, 129, 130, 12857]; |
|---|
| 704 | 706 | long[] s = [2, -2, 127, -127, 128, -128, 129, -129]; |
|---|
| | 707 | |
|---|
| 705 | 708 | auto rd = DwarfReader(bytes); |
|---|
| | 709 | |
|---|
| 706 | 710 | foreach (x; u) |
|---|
| 707 | 711 | assert(rd.uleb128() == x); |
|---|
| | 712 | |
|---|
| 708 | 713 | foreach (x; s) |
|---|
| 709 | 714 | assert(rd.sleb128() == x); |
|---|
| r5607 |
r5652 |
|
| 73 | 73 | /// *return* addresses, the most likely the calling instruction is the one before them |
|---|
| 74 | 74 | /// (stack top excluded.) |
|---|
| 75 | | extern(C) size_t rt_addrBacktrace(TraceContext* context, TraceContext *contextOut,size_t*traceBuf,size_t bufLength,int *flags){ |
|---|
| 76 | | if (addrBacktraceFnc !is null){ |
|---|
| | 75 | extern(C) size_t rt_addrBacktrace(TraceContext* context, TraceContext *contextOut,size_t*traceBuf,size_t bufLength,int *flags) |
|---|
| | 76 | { |
|---|
| | 77 | if (addrBacktraceFnc !is null) |
|---|
| 77 | 78 | return addrBacktraceFnc(context,contextOut,traceBuf,bufLength,flags); |
|---|
| 78 | | } else { |
|---|
| | 79 | else |
|---|
| 79 | 80 | return 0; |
|---|
| 80 | | } |
|---|
| 81 | 81 | } |
|---|
| 82 | 82 | |
|---|
| 83 | 83 | /// Tries to sybolize a frame information, this should try to build the best |
|---|
| 84 | | /// backtrace information, if possible finding the calling context, thus |
|---|
| | 84 | /// backtrace information, if possible finding the calling context, thus |
|---|
| 85 | 85 | /// if fInfo.exactAddress is false the address might be changed to the one preceding it |
|---|
| 86 | 86 | /// returns true if it managed to at least find the function name. |
|---|
| … | … | |
| 142 | 142 | |
|---|
| 143 | 143 | /// Basic class that represents a stacktrace. |
|---|
| 144 | | class BasicTraceInfo: Exception.TraceInfo{ |
|---|
| | 144 | class BasicTraceInfo: Exception.TraceInfo |
|---|
| | 145 | { |
|---|
| 145 | 146 | size_t[] traceAddresses; |
|---|
| 146 | 147 | size_t[128] traceBuf; |
|---|
| … | … | |
| 160 | 161 | } |
|---|
| 161 | 162 | /// Takes a stacktrace. |
|---|
| 162 | | void trace(TraceContext *contextIn=null,int skipFrames=0){ |
|---|
| | 163 | void trace(TraceContext *contextIn=null,int skipFrames=0) |
|---|
| | 164 | { |
|---|
| 163 | 165 | int flags; |
|---|
| 164 | 166 | size_t nFrames=rt_addrBacktrace(contextIn,&context,traceBuf.ptr,traceBuf.length,&flags); |
|---|
| … | … | |
| 179 | 181 | fInfo.exactAddress=(addrPrecision & 2) || (iframe==0 && (addrPrecision & 1)); |
|---|
| 180 | 182 | rt_symbolizeFrameInfo(fInfo,&context,buf); |
|---|
| 181 | | |
|---|
| | 183 | |
|---|
| 182 | 184 | auto r= fInfo.func in internalFuncs; |
|---|
| 183 | 185 | fInfo.internalFunction |= (r !is null); |
|---|
| … | … | |
| 212 | 214 | } |
|---|
| 213 | 215 | |
|---|
| | 216 | |
|---|
| | 217 | |
|---|
| 214 | 218 | /// Default (tango given) backtrace function. |
|---|
| 215 | | size_t defaultAddrBacktrace(TraceContext* context,TraceContext*contextOut, |
|---|
| 216 | | size_t*traceBuf,size_t length,int*flags){ |
|---|
| 217 | | version(LibCBacktrace){ |
|---|
| | 219 | size_t defaultAddrBacktrace(TraceContext* context, TraceContext*contextOut, |
|---|
| | 220 | size_t*traceBuf,size_t length,int*flags) |
|---|
| | 221 | { |
|---|
| | 222 | version(LibCBacktrace) |
|---|
| | 223 | { |
|---|
| 218 | 224 | //if (context!is null) return 0; // now it just gives a local trace, uncomment & skip? |
|---|
| 219 | 225 | *flags=AddrPrecision.TopExact; |
|---|
| 220 | 226 | return cast(size_t)backtrace(cast(void**)traceBuf,length); |
|---|
| 221 | | } else version (Windows){ |
|---|
| | 227 | } |
|---|
| | 228 | else version (Windows) |
|---|
| | 229 | { |
|---|
| 222 | 230 | return winAddrBacktrace(context,contextOut,traceBuf,length,flags); |
|---|
| 223 | | } else { |
|---|
| | 231 | } |
|---|
| | 232 | else |
|---|
| | 233 | { |
|---|
| 224 | 234 | return 0; |
|---|
| 225 | 235 | } |
|---|
| … | … | |
| 309 | 319 | |
|---|
| 310 | 320 | /// Function that generates a trace (handler compatible with old TraceInfo.) |
|---|
| 311 | | Exception.TraceInfo basicTracer( void* ptr = null ){ |
|---|
| | 321 | Exception.TraceInfo basicTracer( void* ptr = null ) |
|---|
| | 322 | { |
|---|
| 312 | 323 | BasicTraceInfo res; |
|---|
| 313 | | try{ |
|---|
| 314 | | version(CatchRecursiveTracing){ |
|---|
| | 324 | try |
|---|
| | 325 | { |
|---|
| | 326 | version(CatchRecursiveTracing) |
|---|
| | 327 | { |
|---|
| 315 | 328 | recursiveStackTraces.val=recursiveStackTraces.val+1; |
|---|
| 316 | 329 | scope(exit) recursiveStackTraces.val=recursiveStackTraces.val-1; |
|---|
| 317 | 330 | // printf("tracer %d\n",recursiveStackTraces.val); |
|---|
| 318 | | if (recursiveStackTraces.val>10) { |
|---|
| | 331 | if (recursiveStackTraces.val>10) |
|---|
| | 332 | { |
|---|
| 319 | 333 | Runtime.console.stderr("hit maximum recursive tracing (tracer asserting...?)\n"); |
|---|
| 320 | 334 | abort(); |
|---|
| … | … | |
| 324 | 338 | res=new BasicTraceInfo(); |
|---|
| 325 | 339 | res.trace(cast(TraceContext*)ptr); |
|---|
| 326 | | } catch (Exception e){ |
|---|
| | 340 | } |
|---|
| | 341 | catch (Exception e) |
|---|
| | 342 | { |
|---|
| 327 | 343 | Runtime.console.stderr("tracer got exception:\n"); |
|---|
| 328 | 344 | Runtime.console.stderr(e.msg); |
|---|
| 329 | 345 | e.writeOut((char[]s){ Runtime.console.stderr(s); }); |
|---|
| 330 | 346 | Runtime.console.stderr("\n"); |
|---|
| 331 | | } catch (Object o){ |
|---|
| | 347 | } |
|---|
| | 348 | catch (Object o) |
|---|
| | 349 | { |
|---|
| 332 | 350 | Runtime.console.stderr("tracer got object exception:\n"); |
|---|
| 333 | 351 | Runtime.console.stderr(o.toString()); |
|---|
| … | … | |
| 382 | 400 | |
|---|
| 383 | 401 | sigaction_t fault_action; |
|---|
| 384 | | |
|---|
| | 402 | |
|---|
| 385 | 403 | void setupSegfaultTracer(){ |
|---|
| 386 | 404 | //use an alternative stack; this is useful when infinite recursion |
|---|
| … | … | |
| 400 | 418 | } |
|---|
| 401 | 419 | } |
|---|
| 402 | | |
|---|
| | 420 | |
|---|
| 403 | 421 | version(noSegfaultTrace){ |
|---|
| 404 | 422 | } else { |
|---|
| r5594 |
r5652 |
|
| 26 | 26 | * The return value is undefined if v is zero. |
|---|
| 27 | 27 | */ |
|---|
| 28 | | int bsf( uint v ); |
|---|
| | 28 | int bsf( size_t v ); |
|---|
| 29 | 29 | |
|---|
| 30 | 30 | |
|---|
| r5615 |
r5652 |
|
| 639 | 639 | } |
|---|
| 640 | 640 | |
|---|
| 641 | | |
|---|
| 642 | 641 | /****************************************************************************** |
|---|
| 643 | 642 | |
|---|
| r5615 |
r5652 |
|
| 185 | 185 | /*********************************************************************** |
|---|
| 186 | 186 | |
|---|
| | 187 | Return an adjusted path such that non-empty instances always |
|---|
| | 188 | have a leading separator. |
|---|
| | 189 | |
|---|
| | 190 | Note: Allocates memory where path is not already terminated. |
|---|
| | 191 | |
|---|
| | 192 | ***********************************************************************/ |
|---|
| | 193 | |
|---|
| | 194 | static char[] paddedLeading (char[] path, char c = '/') |
|---|
| | 195 | { |
|---|
| | 196 | if (path.length && path[0] != c) |
|---|
| | 197 | path = c ~ path; |
|---|
| | 198 | return path; |
|---|
| | 199 | } |
|---|
| | 200 | |
|---|
| | 201 | /*********************************************************************** |
|---|
| | 202 | |
|---|
| 187 | 203 | Return an adjusted path such that non-empty instances do not |
|---|
| 188 | 204 | have a trailing separator. |
|---|
| … | … | |
| 211 | 227 | |
|---|
| 212 | 228 | if (paths.length) |
|---|
| 213 | | { |
|---|
| 214 | | foreach (path; paths[0 .. $-1]) |
|---|
| 215 | | result ~= padded (path); |
|---|
| 216 | | result ~= paths [$-1]; |
|---|
| | 229 | { |
|---|
| | 230 | result ~= paths[0]; |
|---|
| | 231 | |
|---|
| | 232 | foreach (path; paths[1 .. $-1]) |
|---|
| | 233 | result ~= paddedLeading (stripped(path)); |
|---|
| | 234 | |
|---|
| | 235 | result ~= paddedLeading(paths[$-1]); |
|---|
| | 236 | |
|---|
| 217 | 237 | return result; |
|---|
| 218 | | } |
|---|
| | 238 | } |
|---|
| 219 | 239 | return ""; |
|---|
| 220 | 240 | } |
|---|
| r5615 |
r5652 |
|
| 292 | 292 | override size_t read (void[] dst) |
|---|
| 293 | 293 | { |
|---|
| 294 | | int read = posix.read (handle, dst.ptr, dst.length); |
|---|
| | 294 | auto read = posix.read (handle, dst.ptr, dst.length); |
|---|
| | 295 | |
|---|
| 295 | 296 | if (read is -1) |
|---|
| 296 | 297 | error; |
|---|
| r5615 |
r5652 |
|
| 16 | 16 | |
|---|
| 17 | 17 | private import tango.text.convert.Layout; |
|---|
| | 18 | |
|---|
| | 19 | version(DigitalMars) |
|---|
| | 20 | { |
|---|
| | 21 | version(X86_64) version=DigitalMarsX64; |
|---|
| | 22 | |
|---|
| | 23 | private import tango.core.Vararg; |
|---|
| | 24 | } |
|---|
| | 25 | else version (GNU) |
|---|
| | 26 | { |
|---|
| | 27 | private import tango.core.Vararg; |
|---|
| | 28 | } |
|---|
| | 29 | |
|---|
| 18 | 30 | |
|---|
| 19 | 31 | /******************************************************************************* |
|---|
| … | … | |
| 137 | 149 | final FormatOutput format (T[] fmt, ...) |
|---|
| 138 | 150 | { |
|---|
| | 151 | version (DigitalMarsX64) |
|---|
| | 152 | { |
|---|
| | 153 | va_list ap; |
|---|
| | 154 | |
|---|
| | 155 | va_start(ap, __va_argsave); |
|---|
| | 156 | |
|---|
| | 157 | scope(exit) va_end(ap); |
|---|
| | 158 | |
|---|
| | 159 | convert (&emit, _arguments, ap, fmt); |
|---|
| | 160 | } |
|---|
| | 161 | else |
|---|
| 139 | 162 | convert (&emit, _arguments, _argptr, fmt); |
|---|
| 140 | | return this; |
|---|
| | 163 | |
|---|
| | 164 | return this; |
|---|
| 141 | 165 | } |
|---|
| 142 | 166 | |
|---|
| … | … | |
| 149 | 173 | final FormatOutput formatln (T[] fmt, ...) |
|---|
| 150 | 174 | { |
|---|
| | 175 | version (DigitalMarsX64) |
|---|
| | 176 | { |
|---|
| | 177 | va_list ap; |
|---|
| | 178 | |
|---|
| | 179 | va_start(ap, __va_argsave); |
|---|
| | 180 | |
|---|
| | 181 | scope(exit) va_end(ap); |
|---|
| | 182 | |
|---|
| | 183 | convert (&emit, _arguments, ap, fmt); |
|---|
| | 184 | } |
|---|
| | 185 | else |
|---|
| 151 | 186 | convert (&emit, _arguments, _argptr, fmt); |
|---|
| 152 | | return newline; |
|---|
| | 187 | |
|---|
| | 188 | return newline; |
|---|
| 153 | 189 | } |
|---|
| 154 | 190 | |
|---|
| … | … | |
| 160 | 196 | **********************************************************************/ |
|---|
| 161 | 197 | |
|---|
| 162 | | final FormatOutput print (...) |
|---|
| 163 | | { |
|---|
| 164 | | static T[] slice = "{}, {}, {}, {}, {}, {}, {}, {}, " |
|---|
| 165 | | "{}, {}, {}, {}, {}, {}, {}, {}, " |
|---|
| 166 | | "{}, {}, {}, {}, {}, {}, {}, {}, "; |
|---|
| | 198 | final FormatOutput print ( ... ) |
|---|
| | 199 | { |
|---|
| | 200 | static T[] slice = "{}, {}, {}, {}, {}, {}, {}, {}, " |
|---|
| | 201 | "{}, {}, {}, {}, {}, {}, {}, {}, " |
|---|
| | 202 | "{}, {}, {}, {}, {}, {}, {}, {}, "; |
|---|
| 167 | 203 | |
|---|
| 168 | 204 | assert (_arguments.length <= slice.length/4, "FormatOutput :: too many arguments"); |
|---|
| 169 | 205 | |
|---|
| 170 | | if (_arguments.length is 0) |
|---|
| | 206 | if (_arguments.length == 0) |
|---|
| 171 | 207 | sink.flush; |
|---|
| 172 | 208 | else |
|---|
| 173 | | convert (&emit, _arguments, _argptr, slice[0 .. _arguments.length * 4 - 2]); |
|---|
| 174 | | |
|---|
| | 209 | { |
|---|
| | 210 | |
|---|
| | 211 | version (DigitalMarsX64) |
|---|
| | 212 | { |
|---|
| | 213 | va_list ap; |
|---|
| | 214 | |
|---|
| | 215 | va_start(ap, __va_argsave); |
|---|
| | 216 | |
|---|
| | 217 | scope(exit) va_end(ap); |
|---|
| | 218 | |
|---|
| | 219 | convert (&emit, _arguments, ap, slice[0 .. _arguments.length * 4 - 2]); |
|---|
| | 220 | } |
|---|
| | 221 | else |
|---|
| | 222 | convert (&emit, _arguments, _argptr, slice[0 .. _arguments.length * 4 - 2]); |
|---|
| | 223 | } |
|---|
| 175 | 224 | return this; |
|---|
| 176 | 225 | } |
|---|
| r5615 |
r5652 |
|
| 17 | 17 | |
|---|
| 18 | 18 | private import tango.text.convert.Format; |
|---|
| | 19 | |
|---|
| | 20 | version(DigitalMars) |
|---|
| | 21 | { |
|---|
| | 22 | private import tango.core.Vararg; |
|---|
| | 23 | }else version (GNU) |
|---|
| | 24 | private import tango.core.Vararg; |
|---|
| 19 | 25 | |
|---|
| 20 | 26 | private alias void delegate(char[]) Snoop; |
|---|
| r5615 |
r5652 |
|
| 456 | 456 | } |
|---|
| 457 | 457 | |
|---|
| | 458 | |
|---|
| | 459 | // workaround for a bug in gdb. See ticket #190 |
|---|
| | 460 | version (GNU) |
|---|
| | 461 | { |
|---|
| | 462 | override VfsFolder close(bool commit = true) |
|---|
| | 463 | { |
|---|
| | 464 | assert( valid ); |
|---|
| | 465 | return closeImpl(commit); |
|---|
| | 466 | } |
|---|
| | 467 | |
|---|
| | 468 | override VfsFolder sync() |
|---|
| | 469 | { |
|---|
| | 470 | assert( valid ); |
|---|
| | 471 | return syncImpl(); |
|---|
| | 472 | } |
|---|
| | 473 | } |
|---|
| | 474 | else |
|---|
| | 475 | { |
|---|
| | 476 | override VfsFolder close(bool commit = true) |
|---|
| | 477 | in { assert( valid ); } |
|---|
| | 478 | body |
|---|
| | 479 | { |
|---|
| | 480 | return closeImpl(commit); |
|---|
| | 481 | } |
|---|
| | 482 | |
|---|
| | 483 | |
|---|
| | 484 | override VfsFolder sync() |
|---|
| | 485 | in { assert( valid ); } |
|---|
| | 486 | body |
|---|
| | 487 | { |
|---|
| | 488 | return syncImpl(); |
|---|
| | 489 | } |
|---|
| | 490 | } |
|---|
| | 491 | |
|---|
| 458 | 492 | /** |
|---|
| 459 | 493 | * Closes this folder object. If commit is true, then the folder is |
|---|
| 460 | 494 | * sync'ed before being closed. |
|---|
| 461 | 495 | */ |
|---|
| 462 | | override VfsFolder close(bool commit = true) |
|---|
| 463 | | in { assert( valid ); } |
|---|
| 464 | | body |
|---|
| | 496 | protected VfsFolder closeImpl(bool commit = true) |
|---|
| 465 | 497 | { |
|---|
| 466 | 498 | // MUTATE |
|---|
| … | … | |
| 477 | 509 | * applies to the entire archive, not just this folder and its contents. |
|---|
| 478 | 510 | */ |
|---|
| 479 | | override VfsFolder sync() |
|---|
| 480 | | in { assert( valid ); } |
|---|
| 481 | | body |
|---|
| | 511 | protected VfsFolder syncImpl() |
|---|
| 482 | 512 | { |
|---|
| 483 | 513 | // MUTATE |
|---|
| … | … | |
| 634 | 664 | * argument is true (the default), then changes to the archive will be |
|---|
| 635 | 665 | * flushed out to disk. If false, changes will simply be discarded. |
|---|
| | 666 | |
|---|
| 636 | 667 | */ |
|---|
| | 668 | |
|---|
| 637 | 669 | final override VfsFolder close(bool commit = true) |
|---|
| 638 | 670 | in { assert( valid ); } |
|---|
| r5650 |
r5652 |
|
| 27 | 27 | LINGER = consts.SO_LINGER , /* linger on close if data present */ |
|---|
| 28 | 28 | DONTLINGER = ~(consts.SO_LINGER), |
|---|
| 29 | | |
|---|
| | 29 | |
|---|
| 30 | 30 | OOBINLINE = consts.SO_OOBINLINE , /* leave received OOB data in line */ |
|---|
| 31 | 31 | ACCEPTCONN = consts.SO_ACCEPTCONN, /* socket has had listen() */ |
|---|
| … | … | |
| 33 | 33 | DONTROUTE = consts.SO_DONTROUTE , /* just use interface addresses */ |
|---|
| 34 | 34 | TYPE = consts.SO_TYPE , /* get socket type */ |
|---|
| 35 | | |
|---|
| | 35 | |
|---|
| 36 | 36 | /* |
|---|
| 37 | 37 | * Additional options, not kept in so_options. |
|---|
| … | … | |
| 46 | 46 | ADD_MEMBERSHIP = consts.IP_ADD_MEMBERSHIP , |
|---|
| 47 | 47 | DROP_MEMBERSHIP = consts.IP_DROP_MEMBERSHIP, |
|---|
| 48 | | |
|---|
| | 48 | |
|---|
| 49 | 49 | // OptionLevel.TCP settings |
|---|
| 50 | 50 | TCP_NODELAY = consts.TCP_NODELAY , |
|---|
| 51 | 51 | |
|---|
| 52 | | // Windows specifics |
|---|
| 53 | | WIN_UPDATE_ACCEPT_CONTEXT = 0x700B, |
|---|
| 54 | | WIN_CONNECT_TIME = 0x700C, |
|---|
| 55 | | WIN_UPDATE_CONNECT_CONTEXT = 0x7010, |
|---|
| | 52 | // Windows specifics |
|---|
| | 53 | WIN_UPDATE_ACCEPT_CONTEXT = 0x700B, |
|---|
| | 54 | WIN_CONNECT_TIME = 0x700C, |
|---|
| | 55 | WIN_UPDATE_CONNECT_CONTEXT = 0x7010, |
|---|
| 56 | 56 | } |
|---|
| 57 | | |
|---|
| | 57 | |
|---|
| 58 | 58 | /******************************************************************************* |
|---|
| 59 | 59 | |
|---|
| … | … | |
| 63 | 63 | { |
|---|
| 64 | 64 | SOCKET = consts.SOL_SOCKET , |
|---|
| 65 | | IP = consts.IPPROTO_IP , |
|---|
| 66 | | TCP = consts.IPPROTO_TCP , |
|---|
| 67 | | UDP = consts.IPPROTO_UDP , |
|---|
| | 65 | IP = consts.IPPROTO_IP , |
|---|
| | 66 | TCP = consts.IPPROTO_TCP , |
|---|
| | 67 | UDP = consts.IPPROTO_UDP , |
|---|
| 68 | 68 | } |
|---|
| 69 | | |
|---|
| | 69 | |
|---|
| 70 | 70 | /******************************************************************************* |
|---|
| 71 | 71 | |
|---|
| … | … | |
| 134 | 134 | } |
|---|
| 135 | 135 | |
|---|
| 136 | | enum AIFlags: int |
|---|
| | 136 | enum AIFlags: int |
|---|
| 137 | 137 | { |
|---|
| 138 | 138 | PASSIVE = consts.AI_PASSIVE, /// get address to use bind() |
|---|
| 139 | 139 | CANONNAME = consts.AI_CANONNAME, /// fill ai_canonname |
|---|
| 140 | 140 | NUMERICHOST = consts.AI_NUMERICHOST, /// prevent host name resolution |
|---|
| 141 | | NUMERICSERV = consts.AI_NUMERICSERV, /// prevent service name resolution valid |
|---|
| 142 | | /// flags for addrinfo (not a standard def, |
|---|
| | 141 | NUMERICSERV = consts.AI_NUMERICSERV, /// prevent service name resolution valid |
|---|
| | 142 | /// flags for addrinfo (not a standard def, |
|---|
| 143 | 143 | /// apps should not use it) |
|---|
| 144 | | ALL = consts.AI_ALL, /// IPv6 and IPv4-mapped (with AI_V4MAPPED) |
|---|
| | 144 | ALL = consts.AI_ALL, /// IPv6 and IPv4-mapped (with AI_V4MAPPED) |
|---|
| 145 | 145 | ADDRCONFIG = consts.AI_ADDRCONFIG, /// only if any address is assigned |
|---|
| 146 | | V4MAPPED = consts.AI_V4MAPPED, /// accept IPv4-mapped IPv6 address special |
|---|
| | 146 | V4MAPPED = consts.AI_V4MAPPED, /// accept IPv4-mapped IPv6 address special |
|---|
| 147 | 147 | /// recommended flags for getipnodebyname |
|---|
| 148 | 148 | MASK = consts.AI_MASK, |
|---|
| … | … | |
| 164 | 164 | |
|---|
| 165 | 165 | |
|---|
| 166 | | enum NIFlags: int |
|---|
| | 166 | enum NIFlags: int |
|---|
| 167 | 167 | { |
|---|
| 168 | 168 | MAXHOST = consts.NI_MAXHOST, |
|---|
| … | … | |
| 175 | 175 | } |
|---|
| 176 | 176 | |
|---|
| 177 | | |
|---|
| | 177 | |
|---|
| 178 | 178 | /******************************************************************************* |
|---|
| 179 | 179 | |
|---|
| … | … | |
| 194 | 194 | } |
|---|
| 195 | 195 | } |
|---|
| 196 | | else |
|---|
| | 196 | else |
|---|
| 197 | 197 | { |
|---|
| 198 | 198 | private import tango.core.BitManip; |
|---|
| … | … | |
| 225 | 225 | { |
|---|
| 226 | 226 | alias closesocket close; |
|---|
| 227 | | |
|---|
| | 227 | |
|---|
| 228 | 228 | socket_t socket(int af, int type, int protocol); |
|---|
| 229 | 229 | int ioctlsocket(socket_t s, int cmd, uint* argp); |
|---|
| … | … | |
| 249 | 249 | NetHost.hostent* gethostbyaddr(void* addr, int len, int type); |
|---|
| 250 | 250 | /** |
|---|
| 251 | | The gai_strerror function translates error codes of getaddrinfo, |
|---|
| 252 | | freeaddrinfo and getnameinfo to a human readable string, suitable |
|---|
| | 251 | The gai_strerror function translates error codes of getaddrinfo, |
|---|
| | 252 | freeaddrinfo and getnameinfo to a human readable string, suitable |
|---|
| 253 | 253 | for error reporting. (C) MAN |
|---|
| 254 | 254 | */ |
|---|
| … | … | |
| 256 | 256 | |
|---|
| 257 | 257 | /** |
|---|
| 258 | | Given node and service, which identify an Internet host and a service, |
|---|
| 259 | | getaddrinfo() returns one or more addrinfo structures, each of which |
|---|
| 260 | | contains an Internet address that can be specified in a call to bind |
|---|
| 261 | | or connect. The getaddrinfo() function combines the functionality |
|---|
| 262 | | provided by the getservbyname and getservbyport functions into a single |
|---|
| 263 | | interface, but unlike the latter functions, getaddrinfo() is reentrant |
|---|
| | 258 | Given node and service, which identify an Internet host and a service, |
|---|
| | 259 | getaddrinfo() returns one or more addrinfo structures, each of which |
|---|
| | 260 | contains an Internet address that can be specified in a call to bind |
|---|
| | 261 | or connect. The getaddrinfo() function combines the functionality |
|---|
| | 262 | provided by the getservbyname and getservbyport functions into a single |
|---|
| | 263 | interface, but unlike the latter functions, getaddrinfo() is reentrant |
|---|
| 264 | 264 | and allows programs to eliminate IPv4-versus-IPv6 dependencies.(C) MAN |
|---|
| 265 | 265 | */ |
|---|
| 266 | 266 | int function(char* node, char* service, Address.addrinfo* hints, Address.addrinfo** res) getaddrinfo; |
|---|
| 267 | | |
|---|
| | 267 | |
|---|
| 268 | 268 | /** |
|---|
| 269 | | The freeaddrinfo() function frees the memory that was allocated for the |
|---|
| | 269 | The freeaddrinfo() function frees the memory that was allocated for the |
|---|
| 270 | 270 | dynamically allocated linked list res. (C) MAN |
|---|
| 271 | | */ |
|---|
| 272 | | void function(Address.addrinfo *res) freeaddrinfo; |
|---|
| 273 | | |
|---|
| | 271 | */ |
|---|
| | 272 | void function(Address.addrinfo *res) freeaddrinfo; |
|---|
| | 273 | |
|---|
| 274 | 274 | /** |
|---|
| 275 | | The getnameinfo() function is the inverse of getaddrinfo: it converts |
|---|
| | 275 | The getnameinfo() function is the inverse of getaddrinfo: it converts |
|---|
| 276 | 276 | a socket address to a corresponding host and service, in a protocol- |
|---|
| 277 | | independent manner. It combines the functionality of gethostbyaddr and |
|---|
| 278 | | getservbyport, but unlike those functions, getaddrinfo is reentrant and |
|---|
| | 277 | independent manner. It combines the functionality of gethostbyaddr and |
|---|
| | 278 | getservbyport, but unlike those functions, getaddrinfo is reentrant and |
|---|
| 279 | 279 | allows programs to eliminate IPv4-versus-IPv6 dependencies. (C) MAN |
|---|
| 280 | 280 | */ |
|---|
| 281 | | int function(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags) getnameinfo; |
|---|
| 282 | | |
|---|
| | 281 | int function(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags) getnameinfo; |
|---|
| | 282 | |
|---|
| 283 | 283 | bool function (socket_t, uint, void*, DWORD, DWORD, DWORD, DWORD*, OVERLAPPED*) AcceptEx; |
|---|
| 284 | 284 | bool function (socket_t, HANDLE, DWORD, DWORD, OVERLAPPED*, void*, DWORD) TransmitFile; |
|---|
| 285 | 285 | bool function (socket_t, void*, int, void*, DWORD, DWORD*, OVERLAPPED*) ConnectEx; |
|---|
| 286 | | |
|---|
| | 286 | |
|---|
| 287 | 287 | //char* inet_ntop(int af, void *src, char *dst, int len); |
|---|
| 288 | 288 | } |
|---|
| 289 | 289 | |
|---|
| 290 | | private HMODULE lib; |
|---|
| | 290 | private HMODULE lib; |
|---|
| 291 | 291 | |
|---|
| 292 | 292 | static this() |
|---|
| … | … | |
| 294 | 294 | lib = LoadLibraryA ("Ws2_32.dll"); |
|---|
| 295 | 295 | getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo"); |
|---|
| 296 | | if (!getnameinfo) |
|---|
| 297 | | { |
|---|
| | 296 | if (!getnameinfo) |
|---|
| | 297 | { |
|---|
| 298 | 298 | FreeLibrary (lib); |
|---|
| 299 | 299 | lib = LoadLibraryA ("Wship6.dll"); |
|---|
| 300 | | } |
|---|
| 301 | | getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo"); |
|---|
| 302 | | getaddrinfo = cast(typeof(getaddrinfo)) GetProcAddress(lib, "getaddrinfo"); |
|---|
| 303 | | freeaddrinfo = cast(typeof(freeaddrinfo)) GetProcAddress(lib, "freeaddrinfo"); |
|---|
| 304 | | if (!getnameinfo) |
|---|
| 305 | | { |
|---|
| | 300 | } |
|---|
| | 301 | getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo"); |
|---|
| | 302 | getaddrinfo = cast(typeof(getaddrinfo)) GetProcAddress(lib, "getaddrinfo"); |
|---|
| | 303 | freeaddrinfo = cast(typeof(freeaddrinfo)) GetProcAddress(lib, "freeaddrinfo"); |
|---|
| | 304 | if (!getnameinfo) |
|---|
| | 305 | { |
|---|
| 306 | 306 | FreeLibrary (lib); |
|---|
| 307 | 307 | lib = null; |
|---|
| 308 | | } |
|---|
| | 308 | } |
|---|
| 309 | 309 | |
|---|
| 310 | 310 | WSADATA wd = void; |
|---|
| … | … | |
| 319 | 319 | auto s = cast(HANDLE) socket (AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP); |
|---|
| 320 | 320 | assert (s != cast(HANDLE) -1); |
|---|
| 321 | | |
|---|
| 322 | | WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, |
|---|
| 323 | | &connectG, connectG.sizeof, &ConnectEx, |
|---|
| | 321 | |
|---|
| | 322 | WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, |
|---|
| | 323 | &connectG, connectG.sizeof, &ConnectEx, |
|---|
| 324 | 324 | ConnectEx.sizeof, &result, null, null); |
|---|
| 325 | 325 | |
|---|
| 326 | | WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, |
|---|
| 327 | | &acceptG, acceptG.sizeof, &AcceptEx, |
|---|
| | 326 | WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, |
|---|
| | 327 | &acceptG, acceptG.sizeof, &AcceptEx, |
|---|
| 328 | 328 | AcceptEx.sizeof, &result, null, null); |
|---|
| 329 | 329 | |
|---|
| 330 | | WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, |
|---|
| 331 | | &transmitG, transmitG.sizeof, &TransmitFile, |
|---|
| | 330 | WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, |
|---|
| | 331 | &transmitG, transmitG.sizeof, &TransmitFile, |
|---|
| 332 | 332 | TransmitFile.sizeof, &result, null, null); |
|---|
| 333 | 333 | closesocket (cast(socket_t) s); |
|---|
| … | … | |
| 371 | 371 | NetHost.hostent* gethostbyname(char* name); |
|---|
| 372 | 372 | NetHost.hostent* gethostbyaddr(void* addr, int len, int type); |
|---|
| 373 | | |
|---|
| | 373 | |
|---|
| 374 | 374 | /** |
|---|
| 375 | | Given node and service, which identify an Internet host and a service, |
|---|
| 376 | | getaddrinfo() returns one or more addrinfo structures, each of which |
|---|
| 377 | | contains an Internet address that can be specified in a call to bind or |
|---|
| 378 | | connect. The getaddrinfo() function combines the functionality provided |
|---|
| | 375 | Given node and service, which identify an Internet host and a service, |
|---|
| | 376 | getaddrinfo() returns one or more addrinfo structures, each of which |
|---|
| | 377 | contains an Internet address that can be specified in a call to bind or |
|---|
| | 378 | connect. The getaddrinfo() function combines the functionality provided |
|---|
| 379 | 379 | by the getservbyname and getservbyport functions into a single interface, |
|---|
| 380 | | but unlike the latter functions, getaddrinfo() is reentrant and allows |
|---|
| | 380 | but unlike the latter functions, getaddrinfo() is reentrant and allows |
|---|
| 381 | 381 | programs to eliminate IPv4-versus-IPv6 dependencies. (C) MAN |
|---|
| 382 | 382 | */ |
|---|
| 383 | | int getaddrinfo(char* node, char* service, Address.addrinfo* hints, Address.addrinfo** res); |
|---|
| 384 | | |
|---|
| | 383 | int getaddrinfo(char* node, char* service, Address.addrinfo* hints, Address.addrinfo** res); |
|---|
| | 384 | |
|---|
| 385 | 385 | /** |
|---|
| 386 | | The freeaddrinfo() function frees the memory that was allocated for the |
|---|
| | 386 | The freeaddrinfo() function frees the memory that was allocated for the |
|---|
| 387 | 387 | dynamically allocated linked list res. (C) MAN |
|---|
| 388 | 388 | */ |
|---|
| 389 | | void freeaddrinfo(Address.addrinfo *res); |
|---|
| 390 | | |
|---|
| | 389 | void freeaddrinfo(Address.addrinfo *res); |
|---|
| | 390 | |
|---|
| 391 | 391 | /** |
|---|
| 392 | 392 | The getnameinfo() function is the inverse of getaddrinfo: it converts a socket |
|---|
| 393 | | address to a corresponding host and service, in a protocol-independent manner. |
|---|
| 394 | | It combines the functionality of gethostbyaddr and getservbyport, but unlike |
|---|
| 395 | | those functions, getaddrinfo is reentrant and allows programs to eliminate |
|---|
| | 393 | address to a corresponding host and service, in a protocol-independent manner. |
|---|
| | 394 | It combines the functionality of gethostbyaddr and getservbyport, but unlike |
|---|
| | 395 | those functions, getaddrinfo is reentrant and allows programs to eliminate |
|---|
| 396 | 396 | IPv4-versus-IPv6 dependencies. (C) MAN |
|---|
| 397 | 397 | */ |
|---|
| 398 | | int getnameinfo(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags); |
|---|
| 399 | | |
|---|
| | 398 | int getnameinfo(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags); |
|---|
| | 399 | |
|---|
| 400 | 400 | /** |
|---|
| 401 | | The gai_strerror function translates error codes of getaddrinfo, freeaddrinfo |
|---|
| | 401 | The gai_strerror function translates error codes of getaddrinfo, freeaddrinfo |
|---|
| 402 | 402 | and getnameinfo to a human readable string, suitable for error reporting. (C) MAN |
|---|
| 403 | 403 | */ |
|---|
| 404 | | char* gai_strerror(int errcode); |
|---|
| 405 | | |
|---|
| | 404 | char* gai_strerror(int errcode); |
|---|
| | 405 | |
|---|
| 406 | 406 | char* inet_ntop(int af, void *src, char *dst, int len); |
|---|
| 407 | 407 | } |
|---|
| … | … | |
| 422 | 422 | bool synchronous; |
|---|
| 423 | 423 | |
|---|
| 424 | | enum : socket_t |
|---|
| | 424 | enum : socket_t |
|---|
| 425 | 425 | { |
|---|
| 426 | 426 | INVALID_SOCKET = socket_t.init |
|---|
| 427 | 427 | } |
|---|
| 428 | | |
|---|
| 429 | | enum |
|---|
| | 428 | |
|---|
| | 429 | enum |
|---|
| 430 | 430 | { |
|---|
| 431 | 431 | Error = -1 |
|---|
| … | … | |
| 435 | 435 | alias noDelay setNoDelay; // backward compatibility |
|---|
| 436 | 436 | alias addressReuse setAddressReuse; // backward compatibility |
|---|
| 437 | | |
|---|
| | 437 | |
|---|
| 438 | 438 | |
|---|
| 439 | 439 | /*********************************************************************** |
|---|
| … | … | |
| 608 | 608 | void accept (ref Berkeley target) |
|---|
| 609 | 609 | { |
|---|
| 610 | | auto newsock = .accept (sock, null, null); |
|---|
| | 610 | auto newsock = .accept (sock, null, null); |
|---|
| 611 | 611 | if (socket_t.init is newsock) |
|---|
| 612 | 612 | exception ("Unable to accept socket connection: "); |
|---|
| … | … | |
| 795 | 795 | /*********************************************************************** |
|---|
| 796 | 796 | |
|---|
| 797 | | Send data on the connection. Returns the number of bytes |
|---|
| 798 | | actually sent, or ERROR on failure. If the socket is blocking |
|---|
| | 797 | Send data on the connection. Returns the number of bytes |
|---|
| | 798 | actually sent, or ERROR on failure. If the socket is blocking |
|---|
| 799 | 799 | and there is no buffer space left, send waits. |
|---|
| 800 | 800 | |
|---|
| … | … | |
| 804 | 804 | |
|---|
| 805 | 805 | int send (void[] buf, SocketFlags flags=SocketFlags.NONE) |
|---|
| 806 | | { |
|---|
| | 806 | { |
|---|
| 807 | 807 | if (buf.length is 0) |
|---|
| 808 | 808 | return 0; |
|---|
| … | … | |
| 810 | 810 | version (Posix) |
|---|
| 811 | 811 | { |
|---|
| 812 | | auto ret = .send (sock, buf.ptr, buf.length, |
|---|
| | 812 | auto ret = .send (sock, buf.ptr, buf.length, |
|---|
| 813 | 813 | SocketFlags.NOSIGNAL + cast(int) flags); |
|---|
| 814 | 814 | if (errno is EPIPE) |
|---|
| … | … | |
| 822 | 822 | /*********************************************************************** |
|---|
| 823 | 823 | |
|---|
| 824 | | Send data to a specific destination Address. If the |
|---|
| 825 | | destination address is not specified, a connection |
|---|
| 826 | | must have been made and that address is used. If the |
|---|
| 827 | | socket is blocking and there is no buffer space left, |
|---|
| | 824 | Send data to a specific destination Address. If the |
|---|
| | 825 | destination address is not specified, a connection |
|---|
| | 826 | must have been made and that address is used. If the |
|---|
| | 827 | socket is blocking and there is no buffer space left, |
|---|
| 828 | 828 | sendTo waits. |
|---|
| 829 | 829 | |
|---|
| … | … | |
| 859 | 859 | /*********************************************************************** |
|---|
| 860 | 860 | |
|---|
| 861 | | Send data to a specific destination Address. If the |
|---|
| 862 | | destination address is not specified, a connection |
|---|
| 863 | | must have been made and that address is used. If the |
|---|
| 864 | | socket is blocking and there is no buffer space left, |
|---|
| | 861 | Send data to a specific destination Address. If the |
|---|
| | 862 | destination address is not specified, a connection |
|---|
| | 863 | must have been made and that address is used. If the |
|---|
| | 864 | socket is blocking and there is no buffer space left, |
|---|
| 865 | 865 | sendTo waits. |
|---|
| 866 | 866 | |
|---|
| … | … | |
| 874 | 874 | version (Posix) |
|---|
| 875 | 875 | { |
|---|
| 876 | | auto ret = .sendto (sock, buf.ptr, buf.length, |
|---|
| | 876 | auto ret = .sendto (sock, buf.ptr, buf.length, |
|---|
| 877 | 877 | flags | SocketFlags.NOSIGNAL, to, len); |
|---|
| 878 | 878 | if (errno is EPIPE) |
|---|
| … | … | |
| 885 | 885 | |
|---|
| 886 | 886 | /*********************************************************************** |
|---|
| 887 | | Receive data on the connection. Returns the number of |
|---|
| 888 | | bytes actually received, 0 if the remote side has closed |
|---|
| 889 | | the connection, or ERROR on failure. If the socket is blocking, |
|---|
| | 887 | Receive data on the connection. Returns the number of |
|---|
| | 888 | bytes actually received, 0 if the remote side has closed |
|---|
| | 889 | the connection, or ERROR on failure. If the socket is blocking, |
|---|
| 890 | 890 | receive waits until there is data to be received. |
|---|
| 891 | | |
|---|
| 892 | | Returns number of bytes actually received, 0 on connection |
|---|
| | 891 | |
|---|
| | 892 | Returns number of bytes actually received, 0 on connection |
|---|
| 893 | 893 | closure, or -1 on error |
|---|
| 894 | 894 | |
|---|
| … | … | |
| 905 | 905 | /*********************************************************************** |
|---|
| 906 | 906 | |
|---|
| 907 | | Receive data and get the remote endpoint Address. Returns |
|---|
| 908 | | the number of bytes actually received, 0 if the remote side |
|---|
| 909 | | has closed the connection, or ERROR on failure. If the socket |
|---|
| 910 | | is blocking, receiveFrom waits until there is data to be |
|---|
| | 907 | Receive data and get the remote endpoint Address. Returns |
|---|
| | 908 | the number of bytes actually received, 0 if the remote side |
|---|
| | 909 | has closed the connection, or ERROR on failure. If the socket |
|---|
| | 910 | is blocking, receiveFrom waits until there is data to be |
|---|
| 911 | 911 | received. |
|---|
| 912 | 912 | |
|---|
| … | … | |
| 1003 | 1003 | synchronous = yes; |
|---|
| 1004 | 1004 | } |
|---|
| 1005 | | else |
|---|
| | 1005 | else |
|---|
| 1006 | 1006 | { |
|---|
| 1007 | 1007 | int x = fcntl(sock, F_GETFL, 0); |
|---|
| … | … | |
| 1013 | 1013 | exception("Unable to set socket blocking: "); |
|---|
| 1014 | 1014 | } |
|---|
| 1015 | | return; |
|---|
| | 1015 | return; |
|---|
| 1016 | 1016 | } |
|---|
| 1017 | 1017 | |
|---|
| … | … | |
| 1050 | 1050 | } |
|---|
| 1051 | 1051 | |
|---|
| 1052 | | struct addrinfo |
|---|
| 1053 | | { |
|---|
| 1054 | | int ai_flags; |
|---|
| 1055 | | int ai_family; |
|---|
| 1056 | | int ai_socktype; |
|---|
| 1057 | | int ai_protocol; |
|---|
| 1058 | | uint ai_addrlen; |
|---|
| | 1052 | struct addrinfo |
|---|
| | 1053 | { |
|---|
| | 1054 | int ai_flags; |
|---|
| | 1055 | int ai_family; |
|---|
| | 1056 | int ai_socktype; |
|---|
| | 1057 | int ai_protocol; |
|---|
| | 1058 | uint ai_addrlen; |
|---|
| 1059 | 1059 | version (freebsd) |
|---|
| 1060 | 1060 | { |
|---|
| 1061 | | char* ai_canonname; |
|---|
| 1062 | | sockaddr* ai_addr; |
|---|
| | 1061 | char* ai_canonname; |
|---|
| | 1062 | sockaddr* ai_addr; |
|---|
| 1063 | 1063 | } |
|---|
| 1064 | 1064 | else |
|---|
| 1065 | 1065 | { |
|---|
| 1066 | | sockaddr* ai_addr; |
|---|
| 1067 | | char* ai_canonname; |
|---|
| | 1066 | sockaddr* ai_addr; |
|---|
| | 1067 | char* ai_canonname; |
|---|
| 1068 | 1068 | } |
|---|
| 1069 | | addrinfo* ai_next; |
|---|
| 1070 | | } |
|---|
| | 1069 | addrinfo* ai_next; |
|---|
| | 1070 | } |
|---|
| 1071 | 1071 | |
|---|
| 1072 | 1072 | abstract sockaddr* name(); |
|---|
| … | … | |
| 1162 | 1162 | throw new SocketException (msg); |
|---|
| 1163 | 1163 | } |
|---|
| 1164 | | |
|---|
| | 1164 | |
|---|
| 1165 | 1165 | /*********************************************************************** |
|---|
| 1166 | 1166 | |
|---|
| … | … | |
| 1169 | 1169 | ***********************************************************************/ |
|---|
| 1170 | 1170 | |
|---|
| 1171 | | static Address create (sockaddr* sa) |
|---|
| 1172 | | { |
|---|
| 1173 | | switch (sa.sa_family) |
|---|
| 1174 | | { |
|---|
| 1175 | | case AddressFamily.INET: |
|---|
| 1176 | | return new IPv4Address(sa); |
|---|
| 1177 | | case AddressFamily.INET6: |
|---|
| 1178 | | return new IPv6Address(sa); |
|---|
| 1179 | | default: |
|---|
| 1180 | | return null; |
|---|
| 1181 | | } |
|---|
| 1182 | | } |
|---|
| 1183 | | |
|---|
| 1184 | | /*********************************************************************** |
|---|
| 1185 | | |
|---|
| 1186 | | ***********************************************************************/ |
|---|
| 1187 | | |
|---|
| 1188 | | static Address resolve (char[] host, char[] service = null, |
|---|
| 1189 | | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| 1190 | | AIFlags flags = cast(AIFlags)0) |
|---|
| 1191 | | { |
|---|
| 1192 | | return resolveAll (host, service, af, flags)[0]; |
|---|
| 1193 | | } |
|---|
| 1194 | | |
|---|
| 1195 | | /*********************************************************************** |
|---|
| 1196 | | |
|---|
| 1197 | | ***********************************************************************/ |
|---|
| 1198 | | |
|---|
| 1199 | | static Address resolve (char[] host, ushort port, |
|---|
| 1200 | | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| 1201 | | AIFlags flags = cast(AIFlags)0) |
|---|
| 1202 | | { |
|---|
| 1203 | | return resolveAll (host, port, af, flags)[0]; |
|---|
| 1204 | | } |
|---|
| 1205 | | |
|---|
| 1206 | | /*********************************************************************** |
|---|
| 1207 | | |
|---|
| 1208 | | ***********************************************************************/ |
|---|
| 1209 | | |
|---|
| 1210 | | static Address[] resolveAll (char[] host, char[] service = null, |
|---|
| 1211 | | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| 1212 | | AIFlags flags = cast(AIFlags)0) |
|---|
| 1213 | | { |
|---|
| 1214 | | Address[] retVal; |
|---|
| 1215 | | version (Win32) |
|---|
| 1216 | | { |
|---|
| 1217 | | if (!getaddrinfo) |
|---|
| 1218 | | { // *old* windows, let's fall back to NetHost |
|---|
| 1219 | | uint port = toInt(service); |
|---|
| 1220 | | if (flags & AIFlags.PASSIVE && host is null) |
|---|
| 1221 | | return [new IPv4Address(0, port)]; |
|---|
| 1222 | | |
|---|
| 1223 | | auto nh = new NetHost; |
|---|
| 1224 | | if (!nh.getHostByName(host)) |
|---|
| 1225 | | throw new AddressException("couldn't resolve " ~ host); |
|---|
| 1226 | | |
|---|
| 1227 | | retVal.length = nh.addrList.length; |
|---|
| | 1171 | static Address create (sockaddr* sa) |
|---|
| | 1172 | { |
|---|
| | 1173 | switch (sa.sa_family) |
|---|
| | 1174 | { |
|---|
| | 1175 | case AddressFamily.INET: |
|---|
| | 1176 | return new IPv4Address(sa); |
|---|
| | 1177 | case AddressFamily.INET6: |
|---|
| | 1178 | return new IPv6Address(sa); |
|---|
| | 1179 | default: |
|---|
| | 1180 | return null; |
|---|
| | 1181 | } |
|---|
| | 1182 | } |
|---|
| | 1183 | |
|---|
| | 1184 | /*********************************************************************** |
|---|
| | 1185 | |
|---|
| | 1186 | ***********************************************************************/ |
|---|
| | 1187 | |
|---|
| | 1188 | static Address resolve (char[] host, char[] service = null, |
|---|
| | 1189 | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| | 1190 | AIFlags flags = cast(AIFlags)0) |
|---|
| | 1191 | { |
|---|
| | 1192 | return resolveAll (host, service, af, flags)[0]; |
|---|
| | 1193 | } |
|---|
| | 1194 | |
|---|
| | 1195 | /*********************************************************************** |
|---|
| | 1196 | |
|---|
| | 1197 | ***********************************************************************/ |
|---|
| | 1198 | |
|---|
| | 1199 | static Address resolve (char[] host, ushort port, |
|---|
| | 1200 | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| | 1201 | AIFlags flags = cast(AIFlags)0) |
|---|
| | 1202 | { |
|---|
| | 1203 | return resolveAll (host, port, af, flags)[0]; |
|---|
| | 1204 | } |
|---|
| | 1205 | |
|---|
| | 1206 | /*********************************************************************** |
|---|
| | 1207 | |
|---|
| | 1208 | ***********************************************************************/ |
|---|
| | 1209 | |
|---|
| | 1210 | static Address[] resolveAll (char[] host, char[] service = null, |
|---|
| | 1211 | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| | 1212 | AIFlags flags = cast(AIFlags)0) |
|---|
| | 1213 | { |
|---|
| | 1214 | Address[] retVal; |
|---|
| | 1215 | version (Win32) |
|---|
| | 1216 | { |
|---|
| | 1217 | if (!getaddrinfo) |
|---|
| | 1218 | { // *old* windows, let's fall back to NetHost |
|---|
| | 1219 | uint port = toInt(service); |
|---|
| | 1220 | if (flags & AIFlags.PASSIVE && host is null) |
|---|
| | 1221 | return [new IPv4Address(0, port)]; |
|---|
| | 1222 | |
|---|
| | 1223 | auto nh = new NetHost; |
|---|
| | 1224 | if (!nh.getHostByName(host)) |
|---|
| | 1225 | throw new AddressException("couldn't resolve " ~ host); |
|---|
| | 1226 | |
|---|
| | 1227 | retVal.length = nh.addrList.length; |
|---|
| 1228 | 1228 | foreach (i, addr; nh.addrList) |
|---|
| 1229 | | retVal[i] = new IPv4Address(addr, port); |
|---|
| 1230 | | return retVal; |
|---|
| 1231 | | } |
|---|
| 1232 | | } |
|---|
| 1233 | | |
|---|
| 1234 | | addrinfo* info; |
|---|
| 1235 | | addrinfo hints; |
|---|
| 1236 | | hints.ai_flags = flags; |
|---|
| 1237 | | hints.ai_family = (flags & AIFlags.PASSIVE && af == AddressFamily.UNSPEC) ? AddressFamily.INET6 : af; |
|---|
| 1238 | | hints.ai_socktype = SocketType.STREAM; |
|---|
| 1239 | | int error = getaddrinfo(toStringz(host), service.length == 0 ? null : toStringz(service), &hints, &info); |
|---|
| 1240 | | if (error != 0) |
|---|
| 1241 | | throw new AddressException("couldn't resolve " ~ host); |
|---|
| 1242 | | |
|---|
| 1243 | | retVal.length = 16; |
|---|
| 1244 | | retVal.length = 0; |
|---|
| 1245 | | while (info) |
|---|
| 1246 | | { |
|---|
| 1247 | | if (auto addr = create(info.ai_addr)) |
|---|
| 1248 | | retVal ~= addr; |
|---|
| 1249 | | info = info.ai_next; |
|---|
| 1250 | | } |
|---|
| 1251 | | freeaddrinfo (info); |
|---|
| 1252 | | return retVal; |
|---|
| 1253 | | } |
|---|
| 1254 | | |
|---|
| 1255 | | /*********************************************************************** |
|---|
| 1256 | | |
|---|
| 1257 | | ***********************************************************************/ |
|---|
| 1258 | | |
|---|
| 1259 | | static Address[] resolveAll (char host[], ushort port, |
|---|
| 1260 | | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| 1261 | | AIFlags flags = cast(AIFlags)0) |
|---|
| 1262 | | { |
|---|
| 1263 | | char[16] buf; |
|---|
| 1264 | | return resolveAll (host, fromInt(buf, port), af, flags); |
|---|
| 1265 | | } |
|---|
| 1266 | | |
|---|
| 1267 | | /*********************************************************************** |
|---|
| 1268 | | |
|---|
| 1269 | | ***********************************************************************/ |
|---|
| 1270 | | |
|---|
| 1271 | | static Address passive (char[] service, |
|---|
| 1272 | | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| 1273 | | AIFlags flags = cast(AIFlags)0) |
|---|
| 1274 | | { |
|---|
| 1275 | | return resolve (null, service, af, flags | AIFlags.PASSIVE); |
|---|
| 1276 | | } |
|---|
| 1277 | | |
|---|
| 1278 | | /*********************************************************************** |
|---|
| 1279 | | |
|---|
| 1280 | | ***********************************************************************/ |
|---|
| 1281 | | |
|---|
| 1282 | | static Address passive (ushort port, AddressFamily af = AddressFamily.UNSPEC, |
|---|
| 1283 | | AIFlags flags = cast(AIFlags)0) |
|---|
| 1284 | | { |
|---|
| 1285 | | return resolve (null, port, af, flags | AIFlags.PASSIVE); |
|---|
| 1286 | | } |
|---|
| 1287 | | |
|---|
| 1288 | | /*********************************************************************** |
|---|
| 1289 | | |
|---|
| 1290 | | ***********************************************************************/ |
|---|
| 1291 | | |
|---|
| 1292 | | char[] toAddrString() |
|---|
| 1293 | | { |
|---|
| 1294 | | char[1025] host = void; |
|---|
| 1295 | | // Getting name info. Don't look up hostname, returns |
|---|
| | 1229 | retVal[i] = new IPv4Address(addr, port); |
|---|
| | 1230 | return retVal; |
|---|
| | 1231 | } |
|---|
| | 1232 | } |
|---|
| | 1233 | |
|---|
| | 1234 | addrinfo* info; |
|---|
| | 1235 | addrinfo hints; |
|---|
| | 1236 | hints.ai_flags = flags; |
|---|
| | 1237 | hints.ai_family = (flags & AIFlags.PASSIVE && af == AddressFamily.UNSPEC) ? AddressFamily.INET6 : af; |
|---|
| | 1238 | hints.ai_socktype = SocketType.STREAM; |
|---|
| | 1239 | int error = getaddrinfo(toStringz(host), service.length == 0 ? null : toStringz(service), &hints, &info); |
|---|
| | 1240 | if (error != 0) |
|---|
| | 1241 | throw new AddressException("couldn't resolve " ~ host); |
|---|
| | 1242 | |
|---|
| | 1243 | retVal.length = 16; |
|---|
| | 1244 | retVal.length = 0; |
|---|
| | 1245 | while (info) |
|---|
| | 1246 | { |
|---|
| | 1247 | if (auto addr = create(info.ai_addr)) |
|---|
| | 1248 | retVal ~= addr; |
|---|
| | 1249 | info = info.ai_next; |
|---|
| | 1250 | } |
|---|
| | 1251 | freeaddrinfo (info); |
|---|
| | 1252 | return retVal; |
|---|
| | 1253 | } |
|---|
| | 1254 | |
|---|
| | 1255 | /*********************************************************************** |
|---|
| | 1256 | |
|---|
| | 1257 | ***********************************************************************/ |
|---|
| | 1258 | |
|---|
| | 1259 | static Address[] resolveAll (char host[], ushort port, |
|---|
| | 1260 | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| | 1261 | AIFlags flags = cast(AIFlags)0) |
|---|
| | 1262 | { |
|---|
| | 1263 | char[16] buf; |
|---|
| | 1264 | return resolveAll (host, fromInt(buf, port), af, flags); |
|---|
| | 1265 | } |
|---|
| | 1266 | |
|---|
| | 1267 | /*********************************************************************** |
|---|
| | 1268 | |
|---|
| | 1269 | ***********************************************************************/ |
|---|
| | 1270 | |
|---|
| | 1271 | static Address passive (char[] service, |
|---|
| | 1272 | AddressFamily af = AddressFamily.UNSPEC, |
|---|
| | 1273 | AIFlags flags = cast(AIFlags)0) |
|---|
| | 1274 | { |
|---|
| | 1275 | return resolve (null, service, af, flags | AIFlags.PASSIVE); |
|---|
| | 1276 | } |
|---|
| | 1277 | |
|---|
| | 1278 | /*********************************************************************** |
|---|
| | 1279 | |
|---|
| | 1280 | ***********************************************************************/ |
|---|
| | 1281 | |
|---|
| | 1282 | static Address passive (ushort port, AddressFamily af = AddressFamily.UNSPEC, |
|---|
| | 1283 | AIFlags flags = cast(AIFlags)0) |
|---|
| | 1284 | { |
|---|
| | 1285 | return resolve (null, port, af, flags | AIFlags.PASSIVE); |
|---|
| | 1286 | } |
|---|
| | 1287 | |
|---|
| | 1288 | /*********************************************************************** |
|---|
| | 1289 | |
|---|
| | 1290 | ***********************************************************************/ |
|---|
| | 1291 | |
|---|
| | 1292 | char[] toAddrString() |
|---|
| | 1293 | { |
|---|
| | 1294 | char[1025] host = void; |
|---|
| | 1295 | // Getting name info. Don't look up hostname, returns |
|---|
| 1296 | 1296 | // numeric name. (NIFlags.NUMERICHOST) |
|---|
| 1297 | | getnameinfo (name, nameLen, host.ptr, host.length, null, 0, NIFlags.NUMERICHOST); |
|---|
| 1298 | | return fromStringz (host.ptr); |
|---|
| 1299 | | } |
|---|
| 1300 | | |
|---|
| 1301 | | /*********************************************************************** |
|---|
| 1302 | | |
|---|
| 1303 | | ***********************************************************************/ |
|---|
| 1304 | | |
|---|
| 1305 | | char[] toPortString() |
|---|
| 1306 | | { |
|---|
| 1307 | | char[32] service = void; |
|---|
| 1308 | | // Getting name info. Returns port number, not |
|---|
| | 1297 | getnameinfo (name, nameLen, host.ptr, host.length, null, 0, NIFlags.NUMERICHOST); |
|---|
| | 1298 | return fromStringz (host.ptr); |
|---|
| | 1299 | } |
|---|
| | 1300 | |
|---|
| | 1301 | /*********************************************************************** |
|---|
| | 1302 | |
|---|
| | 1303 | ***********************************************************************/ |
|---|
| | 1304 | |
|---|
| | 1305 | char[] toPortString() |
|---|
| | 1306 | { |
|---|
| | 1307 | char[32] service = void; |
|---|
| | 1308 | // Getting name info. Returns port number, not |
|---|
| 1309 | 1309 | // service name. (NIFlags.NUMERICSERV) |
|---|
| 1310 | | getnameinfo (name, nameLen, null, 0, service.ptr, service.length, NIFlags.NUMERICSERV); |
|---|
| 1311 | | foreach (i, c; service) |
|---|
| 1312 | | if (c == '\0') |
|---|
| 1313 | | return service[0..i].dup; |
|---|
| | 1310 | getnameinfo (name, nameLen, null, 0, service.ptr, service.length, NIFlags.NUMERICSERV); |
|---|
| | 1311 | foreach (i, c; service) |
|---|
| | 1312 | if (c == '\0') |
|---|
| | 1313 | return service[0..i].dup; |
|---|
| 1314 | 1314 | return null; |
|---|
| 1315 | | } |
|---|
| 1316 | | |
|---|
| 1317 | | /*********************************************************************** |
|---|
| 1318 | | |
|---|
| 1319 | | ***********************************************************************/ |
|---|
| 1320 | | |
|---|
| 1321 | | char[] toString() |
|---|
| 1322 | | { |
|---|
| 1323 | | return toAddrString ~ ":" ~ toPortString; |
|---|
| 1324 | | } |
|---|
| 1325 | | |
|---|
| 1326 | | /*********************************************************************** |
|---|
| 1327 | | |
|---|
| 1328 | | ***********************************************************************/ |
|---|
| 1329 | | |
|---|
| 1330 | | AddressFamily addressFamily() |
|---|
| 1331 | | { |
|---|
| 1332 | | return cast(AddressFamily)name.sa_family; |
|---|
| 1333 | | } |
|---|
| | 1315 | } |
|---|
| | 1316 | |
|---|
| | 1317 | /*********************************************************************** |
|---|
| | 1318 | |
|---|
| | 1319 | ***********************************************************************/ |
|---|
| | 1320 | |
|---|
| | 1321 | char[] toString() |
|---|
| | 1322 | { |
|---|
| | 1323 | return toAddrString ~ ":" ~ toPortString; |
|---|
| | 1324 | } |
|---|
| | 1325 | |
|---|
| | 1326 | /*********************************************************************** |
|---|
| | 1327 | |
|---|
| | 1328 | ***********************************************************************/ |
|---|
| | 1329 | |
|---|
| | 1330 | AddressFamily addressFamily() |
|---|
| | 1331 | { |
|---|
| | 1332 | return cast(AddressFamily)name.sa_family; |
|---|
| | 1333 | } |
|---|
| 1334 | 1334 | } |
|---|
| 1335 | 1335 | |
|---|
| … | … | |
| 1392 | 1392 | ***********************************************************************/ |
|---|
| 1393 | 1393 | |
|---|
| 1394 | | enum |
|---|
| 1395 | | { |
|---|
| 1396 | | ADDR_ANY = 0, |
|---|
| 1397 | | ADDR_NONE = cast(uint)-1, |
|---|
| | 1394 | enum |
|---|
| | 1395 | { |
|---|
| | 1396 | ADDR_ANY = 0, |
|---|
| | 1397 | ADDR_NONE = cast(uint)-1, |
|---|
| 1398 | 1398 | PORT_ANY = 0 |
|---|
| 1399 | 1399 | } |
|---|
| … | … | |
| 1409 | 1409 | ubyte sin_len; |
|---|
| 1410 | 1410 | ubyte sinfamily = AddressFamily.INET; |
|---|
| 1411 | | } |
|---|
| 1412 | | else |
|---|
| | 1411 | } |
|---|
| | 1412 | else |
|---|
| 1413 | 1413 | { |
|---|
| 1414 | 1414 | ushort sinfamily = AddressFamily.INET; |
|---|
| … | … | |
| 1479 | 1479 | ***********************************************************************/ |
|---|
| 1480 | 1480 | |
|---|
| 1481 | | this (sockaddr* addr) |
|---|
| 1482 | | { |
|---|
| 1483 | | sin = *(cast(sockaddr_in*)addr); |
|---|
| 1484 | | } |
|---|
| 1485 | | |
|---|
| 1486 | | /*********************************************************************** |
|---|
| 1487 | | |
|---|
| 1488 | | ***********************************************************************/ |
|---|
| 1489 | | |
|---|
| | 1481 | this (sockaddr* addr) |
|---|
| | 1482 | { |
|---|
| | 1483 | sin = *(cast(sockaddr_in*)addr); |
|---|
| | 1484 | } |
|---|
| | 1485 | |
|---|
| | 1486 | /*********************************************************************** |
|---|
| | 1487 | |
|---|
| | 1488 | ***********************************************************************/ |
|---|
| | 1489 | |
|---|
| 1490 | 1490 | sockaddr* name() |
|---|
| 1491 | 1491 | { |
|---|
| … | … | |
| 1590 | 1590 | } |
|---|
| 1591 | 1591 | |
|---|
| 1592 | | /******************************************************************************* |
|---|
| 1593 | | |
|---|
| | 1592 | /******************************************************************************* |
|---|
| | 1593 | |
|---|
| 1594 | 1594 | IPv6 is the next-generation Internet Protocol version |
|---|
| 1595 | 1595 | designated as the successor to IPv4, the first |
|---|
| 1596 | 1596 | implementation used in the Internet that is still in |
|---|
| 1597 | 1597 | dominant use currently. |
|---|
| 1598 | | |
|---|
| | 1598 | |
|---|
| 1599 | 1599 | More information: http://ipv6.com/ |
|---|
| 1600 | | |
|---|
| | 1600 | |
|---|
| 1601 | 1601 | IPv6 supports 128-bit address space as opposed to 32-bit |
|---|
| 1602 | 1602 | address space of IPv4. |
|---|
| 1603 | | |
|---|
| | 1603 | |
|---|
| 1604 | 1604 | IPv6 is written as 8 blocks of 4 octal digits (16 bit) |
|---|
| 1605 | 1605 | separated by a colon (":"). Zero block can be replaced by "::". |
|---|
| 1606 | | |
|---|
| 1607 | | For example: |
|---|
| | 1606 | |
|---|
| | 1607 | For example: |
|---|
| 1608 | 1608 | --- |
|---|
| 1609 | 1609 | 0000:0000:0000:0000:0000:0000:0000:0001 |
|---|
| … | … | |
| 1613 | 1613 | ::1 |
|---|
| 1614 | 1614 | is analogue IPv4 127.0.0.1 |
|---|
| 1615 | | |
|---|
| | 1615 | |
|---|
| 1616 | 1616 | 0000:0000:0000:0000:0000:0000:0000:0000 |
|---|
| 1617 | 1617 | is equal |
|---|
| 1618 | 1618 | :: |
|---|
| 1619 | 1619 | is analogue IPv4 0.0.0.0 |
|---|
| 1620 | | |
|---|
| 1621 | | 2001:cdba:0000:0000:0000:0000:3257:9652 |
|---|
| | 1620 | |
|---|
| | 1621 | 2001:cdba:0000:0000:0000:0000:3257:9652 |
|---|
| 1622 | 1622 | is equal |
|---|
| 1623 | 1623 | 2001:cdba::3257:9652 |
|---|
| 1624 | | |
|---|
| | 1624 | |
|---|
| 1625 | 1625 | IPv4 address can be submitted through IPv6 as ::ffff:xx.xx.xx.xx, |
|---|
| 1626 | 1626 | where xx.xx.xx.xx 32-bit IPv4 addresses. |
|---|
| 1627 | | |
|---|
| | 1627 | |
|---|
| 1628 | 1628 | ::ffff:51b0:ec6d |
|---|
| 1629 | 1629 | is equal |
|---|
| 1630 | 1630 | ::ffff:81.176.236.109 |
|---|
| 1631 | 1631 | is analogue IPv4 81.176.236.109 |
|---|
| 1632 | | |
|---|
| | 1632 | |
|---|
| 1633 | 1633 | The URL for the IPv6 address will be of the form: |
|---|
| 1634 | 1634 | http://[2001:cdba:0000:0000:0000:0000:3257:9652]/ |
|---|
| 1635 | | |
|---|
| | 1635 | |
|---|
| 1636 | 1636 | If needed to specify a port, it will be listed after the |
|---|
| 1637 | 1637 | closing square bracket followed by a colon. |
|---|
| 1638 | | |
|---|
| | 1638 | |
|---|
| 1639 | 1639 | http://[2001:cdba:0000:0000:0000:0000:3257:9652]:8080/ |
|---|
| 1640 | 1640 | address: "2001:cdba:0000:0000:0000:0000:3257:9652" |
|---|
| 1641 | 1641 | port: 8080 |
|---|
| 1642 | | |
|---|
| | 1642 | |
|---|
| 1643 | 1643 | IPv6Address can be used as well as IPv4Address. |
|---|
| 1644 | | |
|---|
| 1645 | | scope addr = new IPv6Address(8080); |
|---|
| | 1644 | |
|---|
| | 1645 | scope addr = new IPv6Address(8080); |
|---|
| 1646 | 1646 | address: "::" |
|---|
| 1647 | 1647 | port: 8080 |
|---|
| 1648 | | |
|---|
| 1649 | | scope addr_2 = new IPv6Address("::1", 8081); |
|---|
| | 1648 | |
|---|
| | 1649 | scope addr_2 = new IPv6Address("::1", 8081); |
|---|
| 1650 | 1650 | address: "::1" |
|---|
| 1651 | 1651 | port: 8081 |
|---|
| 1652 | | |
|---|
| 1653 | | scope addr_3 = new IPv6Address("::1"); |
|---|
| | 1652 | |
|---|
| | 1653 | scope addr_3 = new IPv6Address("::1"); |
|---|
| 1654 | 1654 | address: "::1" |
|---|
| 1655 | 1655 | port: PORT_ANY |
|---|
| 1656 | | |
|---|
| | 1656 | |
|---|
| 1657 | 1657 | Also in the IPv6Address constructor can specify the service name |
|---|
| 1658 | 1658 | or port as string |
|---|
| 1659 | | |
|---|
| 1660 | | scope addr_3 = new IPv6Address("::", "ssh"); |
|---|
| | 1659 | |
|---|
| | 1660 | scope addr_3 = new IPv6Address("::", "ssh"); |
|---|
| 1661 | 1661 | address: "::" |
|---|
| 1662 | 1662 | port: 22 (ssh service port) |
|---|
| 1663 | | |
|---|
| 1664 | | scope addr_4 = new IPv6Address("::", "8080"); |
|---|
| | 1663 | |
|---|
| | 1664 | scope addr_4 = new IPv6Address("::", "8080"); |
|---|
| 1665 | 1665 | address: "::" |
|---|
| 1666 | 1666 | port: 8080 |
|---|
| 1667 | | |
|---|
| 1668 | | *******************************************************************************/ |
|---|
| 1669 | | |
|---|
| 1670 | | class IPv6Address : Address |
|---|
| 1671 | | { |
|---|
| | 1667 | |
|---|
| | 1668 | *******************************************************************************/ |
|---|
| | 1669 | |
|---|
| | 1670 | class IPv6Address : Address |
|---|
| | 1671 | { |
|---|
| 1672 | 1672 | protected: |
|---|
| 1673 | | /*********************************************************************** |
|---|
| 1674 | | |
|---|
| 1675 | | ***********************************************************************/ |
|---|
| 1676 | | |
|---|
| 1677 | | struct sockaddr_in6 |
|---|
| 1678 | | { |
|---|
| 1679 | | ushort sin_family; |
|---|
| 1680 | | ushort sin_port; |
|---|
| 1681 | | |
|---|
| 1682 | | uint sin6_flowinfo; |
|---|
| 1683 | | ubyte[16] sin6_addr; |
|---|
| 1684 | | uint sin6_scope_id; |
|---|
| 1685 | | } |
|---|
| 1686 | | |
|---|
| 1687 | | sockaddr_in6 sin; |
|---|
| 1688 | | |
|---|
| 1689 | | /*********************************************************************** |
|---|
| 1690 | | |
|---|
| 1691 | | ***********************************************************************/ |
|---|
| 1692 | | |
|---|
| 1693 | | this () |
|---|
| 1694 | | { |
|---|
| 1695 | | } |
|---|
| 1696 | | |
|---|
| 1697 | | /*********************************************************************** |
|---|
| 1698 | | |
|---|
| 1699 | | ***********************************************************************/ |
|---|
| 1700 | | |
|---|
| 1701 | | this (sockaddr* sa) |
|---|
| 1702 | | { |
|---|
| 1703 | | sin = *cast(sockaddr_in6*)sa; |
|---|
| 1704 | | } |
|---|
| 1705 | | |
|---|
| 1706 | | /*********************************************************************** |
|---|
| 1707 | | |
|---|
| 1708 | | ***********************************************************************/ |
|---|
| 1709 | | |
|---|
| 1710 | | sockaddr* name() |
|---|
| 1711 | | { |
|---|
| 1712 | | return cast(sockaddr*)&sin; |
|---|
| 1713 | | } |
|---|
| 1714 | | |
|---|
| 1715 | | /*********************************************************************** |
|---|
| 1716 | | |
|---|
| 1717 | | ***********************************************************************/ |
|---|
| 1718 | | |
|---|
| 1719 | | int nameLen() |
|---|
| 1720 | | { |
|---|
| 1721 | | return sin.sizeof; |
|---|
| 1722 | | } |
|---|
| 1723 | | |
|---|
| 1724 | | public: |
|---|
| | 1673 | /*********************************************************************** |
|---|
| | 1674 | |
|---|
| | 1675 | ***********************************************************************/ |
|---|
| | 1676 | |
|---|
| | 1677 | struct sockaddr_in6 |
|---|
| | 1678 | { |
|---|
| | 1679 | ushort sin_family; |
|---|
| | 1680 | ushort sin_port; |
|---|
| | 1681 | |
|---|
| | 1682 | uint sin6_flowinfo; |
|---|
| | 1683 | ubyte[16] sin6_addr; |
|---|
| | 1684 | uint sin6_scope_id; |
|---|
| | 1685 | } |
|---|
| | 1686 | |
|---|
| | 1687 | sockaddr_in6 sin; |
|---|
| | 1688 | |
|---|
| | 1689 | /*********************************************************************** |
|---|
| | 1690 | |
|---|
| | 1691 | ***********************************************************************/ |
|---|
| | 1692 | |
|---|
| | 1693 | this () |
|---|
| | 1694 | { |
|---|
| | 1695 | } |
|---|
| | 1696 | |
|---|
| | 1697 | /*********************************************************************** |
|---|
| | 1698 | |
|---|
| | 1699 | ***********************************************************************/ |
|---|
| | 1700 | |
|---|
| | 1701 | this (sockaddr* sa) |
|---|
| | 1702 | { |
|---|
| | 1703 | sin = *cast(sockaddr_in6*)sa; |
|---|
| | 1704 | } |
|---|
| | 1705 | |
|---|
| | 1706 | /*********************************************************************** |
|---|
| | 1707 | |
|---|
| | 1708 | ***********************************************************************/ |
|---|
| | 1709 | |
|---|
| | 1710 | sockaddr* name() |
|---|
| | 1711 | { |
|---|
| | 1712 | return cast(sockaddr*)&sin; |
|---|
| | 1713 | } |
|---|
| | 1714 | |
|---|
| | 1715 | /*********************************************************************** |
|---|
| | 1716 | |
|---|
| | 1717 | ***********************************************************************/ |
|---|
| | 1718 | |
|---|
| | 1719 | int nameLen() |
|---|
| | 1720 | { |
|---|
| | 1721 | return sin.sizeof; |
|---|
| | 1722 | } |
|---|
| | 1723 | |
|---|
| | 1724 | public: |
|---|
| 1725 | 1725 | |
|---|
| 1726 | 1726 | /*********************************************************************** |
|---|
| … | … | |
| 1733 | 1733 | } |
|---|
| 1734 | 1734 | |
|---|
| 1735 | | |
|---|
| 1736 | | const ushort PORT_ANY = 0; |
|---|
| 1737 | | |
|---|
| 1738 | | /*********************************************************************** |
|---|
| 1739 | | |
|---|
| 1740 | | ***********************************************************************/ |
|---|
| 1741 | | |
|---|
| 1742 | | ushort port() |
|---|
| 1743 | | { |
|---|
| 1744 | | return ntohs(sin.sin_port); |
|---|
| 1745 | | } |
|---|
| 1746 | | |
|---|
| 1747 | | /*********************************************************************** |
|---|
| 1748 | | |
|---|
| | 1735 | |
|---|
| | 1736 | const ushort PORT_ANY = 0; |
|---|
| | 1737 | |
|---|
| | 1738 | /*********************************************************************** |
|---|
| | 1739 | |
|---|
| | 1740 | ***********************************************************************/ |
|---|
| | 1741 | |
|---|
| | 1742 | ushort port() |
|---|
| | 1743 | { |
|---|
| | 1744 | return ntohs(sin.sin_port); |
|---|
| | 1745 | } |
|---|
| | 1746 | |
|---|
| | 1747 | /*********************************************************************** |
|---|
| | 1748 | |
|---|
| 1749 | 1749 | Create IPv6Address with zero address |
|---|
| 1750 | 1750 | |
|---|
| 1751 | | ***********************************************************************/ |
|---|
| 1752 | | |
|---|
| 1753 | | this (int port) |
|---|
| 1754 | | { |
|---|
| | 1751 | ***********************************************************************/ |
|---|
| | 1752 | |
|---|
| | 1753 | this (int port) |
|---|
| | 1754 | { |
|---|
| 1755 | 1755 | this ("::", port); |
|---|
| 1756 | | } |
|---|
| 1757 | | |
|---|
| 1758 | | /*********************************************************************** |
|---|
| 1759 | | |
|---|
| 1760 | | -port- can be PORT_ANY |
|---|
| 1761 | | -addr- is an IP address or host name |
|---|
| 1762 | | |
|---|
| 1763 | | ***********************************************************************/ |
|---|
| 1764 | | |
|---|
| 1765 | | this (char[] addr, int port = PORT_ANY) |
|---|
| 1766 | | { |
|---|
| 1767 | | version (Win32) |
|---|
| 1768 | | { |
|---|
| 1769 | | if (!getaddrinfo) |
|---|
| 1770 | | exception ("This platform does not support IPv6."); |
|---|
| 1771 | | } |
|---|
| 1772 | | addrinfo* info; |
|---|
| 1773 | | addrinfo hints; |
|---|
| 1774 | | hints.ai_family = AddressFamily.INET6; |
|---|
| 1775 | | int error = getaddrinfo((addr ~ '\0').ptr, null, &hints, &info); |
|---|
| 1776 | | if (error != 0) |
|---|
| 1777 | | exception("failed to create IPv6Address: "); |
|---|
| 1778 | | |
|---|
| 1779 | | sin = *cast(sockaddr_in6*)(info.ai_addr); |
|---|
| 1780 | | sin.sin_port = htons(cast(ushort) port); |
|---|
| 1781 | | } |
|---|
| 1782 | | |
|---|
| 1783 | | /*********************************************************************** |
|---|
| 1784 | | |
|---|
| 1785 | | -service- can be a port number or service name |
|---|
| 1786 | | -addr- is an IP address or host name |
|---|
| 1787 | | |
|---|
| 1788 | | ***********************************************************************/ |
|---|
| 1789 | | |
|---|
| 1790 | | this (char[] addr, char[] service) |
|---|
| 1791 | | { |
|---|
| 1792 | | version (Win32) |
|---|
| 1793 | | { |
|---|
| 1794 | | if(! getaddrinfo) |
|---|
| 1795 | | exception ("This platform does not support IPv6."); |
|---|
| 1796 | | } |
|---|
| 1797 | | addrinfo* info; |
|---|
| 1798 | | addrinfo hints; |
|---|
| 1799 | | hints.ai_family = AddressFamily.INET6; |
|---|
| 1800 | | int error = getaddrinfo((addr ~ '\0').ptr, (service ~ '\0').ptr, &hints, &info); |
|---|
| 1801 | | if (error != 0) |
|---|
| 1802 | | exception ("failed to create IPv6Address: "); |
|---|
| 1803 | | sin = *cast(sockaddr_in6*)(info.ai_addr); |
|---|
| 1804 | | } |
|---|
| 1805 | | |
|---|
| 1806 | | /*********************************************************************** |
|---|
| 1807 | | |
|---|
| 1808 | | ***********************************************************************/ |
|---|
| 1809 | | |
|---|
| 1810 | | ubyte[] addr() |
|---|
| 1811 | | { |
|---|
| 1812 | | return sin.sin6_addr; |
|---|
| 1813 | | } |
|---|
| 1814 | | |
|---|
| 1815 | | /*********************************************************************** |
|---|
| 1816 | | |
|---|
| 1817 | | ***********************************************************************/ |
|---|
| 1818 | | |
|---|
| | 1756 | } |
|---|
| | 1757 | |
|---|
| | 1758 | /*********************************************************************** |
|---|
| | 1759 | |
|---|
| | 1760 | -port- can be PORT_ANY |
|---|
| | 1761 | -addr- is an IP address or host name |
|---|
| | 1762 | |
|---|
| | 1763 | ***********************************************************************/ |
|---|
| | 1764 | |
|---|
| | 1765 | this (char[] addr, int port = PORT_ANY) |
|---|
| | 1766 | { |
|---|
| | 1767 | version (Win32) |
|---|
| | 1768 | { |
|---|
| | 1769 | if (!getaddrinfo) |
|---|
| | 1770 | exception ("This platform does not support IPv6."); |
|---|
| | 1771 | } |
|---|
| | 1772 | addrinfo* info; |
|---|
| | 1773 | addrinfo hints; |
|---|
| | 1774 | hints.ai_family = AddressFamily.INET6; |
|---|
| | 1775 | int error = getaddrinfo((addr ~ '\0').ptr, null, &hints, &info); |
|---|
| | 1776 | if (error != 0) |
|---|
| | 1777 | exception("failed to create IPv6Address: "); |
|---|
| | 1778 | |
|---|
| | 1779 | sin = *cast(sockaddr_in6*)(info.ai_addr); |
|---|
| | 1780 | sin.sin_port = htons(cast(ushort) port); |
|---|
| | 1781 | } |
|---|
| | 1782 | |
|---|
| | 1783 | /*********************************************************************** |
|---|
| | 1784 | |
|---|
| | 1785 | -service- can be a port number or service name |
|---|
| | 1786 | -addr- is an IP address or host name |
|---|
| | 1787 | |
|---|
| | 1788 | ***********************************************************************/ |
|---|
| | 1789 | |
|---|
| | 1790 | this (char[] addr, char[] service) |
|---|
| | 1791 | { |
|---|
| | 1792 | version (Win32) |
|---|
| | 1793 | { |
|---|
| | 1794 | if(! getaddrinfo) |
|---|
| | 1795 | exception ("This platform does not support IPv6."); |
|---|
| | 1796 | } |
|---|
| | 1797 | addrinfo* info; |
|---|
| | 1798 | addrinfo hints; |
|---|
| | 1799 | hints.ai_family = AddressFamily.INET6; |
|---|
| | 1800 | int error = getaddrinfo((addr ~ '\0').ptr, (service ~ '\0').ptr, &hints, &info); |
|---|
| | 1801 | if (error != 0) |
|---|
| | 1802 | exception ("failed to create IPv6Address: "); |
|---|
| | 1803 | sin = *cast(sockaddr_in6*)(info.ai_addr); |
|---|
| | 1804 | } |
|---|
| | 1805 | |
|---|
| | 1806 | /*********************************************************************** |
|---|
| | 1807 | |
|---|
| | 1808 | ***********************************************************************/ |
|---|
| | 1809 | |
|---|
| | 1810 | ubyte[] addr() |
|---|
| | 1811 | { |
|---|
| | 1812 | return sin.sin6_addr; |
|---|
| | 1813 | } |
|---|
| | 1814 | |
|---|
| | 1815 | /*********************************************************************** |
|---|
| | 1816 | |
|---|
| | 1817 | ***********************************************************************/ |
|---|
| | 1818 | |
|---|
| 1819 | 1819 | version (Posix) |
|---|
| 1820 | 1820 | char[] toAddrString() |
|---|
| 1821 | 1821 | { |
|---|
| 1822 | | |
|---|
| | 1822 | |
|---|
| 1823 | 1823 | char[100] buff = 0; |
|---|
| 1824 | 1824 | return fromStringz(inet_ntop(AddressFamily.INET6, &sin.sin6_addr, buff.ptr, 100)).dup; |
|---|
| … | … | |
| 1834 | 1834 | return fromInt (_port, port()).dup; |
|---|
| 1835 | 1835 | } |
|---|
| 1836 | | |
|---|
| 1837 | | /*********************************************************************** |
|---|
| 1838 | | |
|---|
| 1839 | | ***********************************************************************/ |
|---|
| 1840 | | |
|---|
| 1841 | | char[] toString() |
|---|
| 1842 | | { |
|---|
| 1843 | | return "[" ~ toAddrString ~ "]:" ~ toPortString; |
|---|
| 1844 | | } |
|---|
| 1845 | | } |
|---|
| | 1836 | |
|---|
| | 1837 | /*********************************************************************** |
|---|
| | 1838 | |
|---|
| | 1839 | ***********************************************************************/ |
|---|
| | 1840 | |
|---|
| | 1841 | char[] toString() |
|---|
| | 1842 | { |
|---|
| | 1843 | return "[" ~ toAddrString ~ "]:" ~ toPortString; |
|---|
| | 1844 | } |
|---|
| | 1845 | } |
|---|
| 1846 | 1846 | |
|---|
| 1847 | 1847 | /******************************************************************************* |
|---|
| … | … | |
| 1884 | 1884 | short h_length; |
|---|
| 1885 | 1885 | } |
|---|
| 1886 | | else |
|---|
| | 1886 | else |
|---|
| 1887 | 1887 | { |
|---|
| 1888 | 1888 | int h_addrtype; |
|---|
| … | … | |
| 2024 | 2024 | assert(ih.addrList.length > 0); |
|---|
| 2025 | 2025 | IPv4Address ia = new IPv4Address(ih.addrList[0], IPv4Address.PORT_ANY); |
|---|
| | 2026 | printf("addrses: %x %x\n", ia.toAddrString.ptr, ih.name.ptr); |
|---|
| 2026 | 2027 | printf("IP address = %.*s\nname = %.*s\n", ia.toAddrString(), ih.name); |
|---|
| 2027 | 2028 | foreach(int i, char[] s; ih.aliases) |
|---|
| … | … | |
| 2054 | 2055 | struct timeval |
|---|
| 2055 | 2056 | { |
|---|
| 2056 | | c_long seconds, microseconds; |
|---|
| | 2057 | c_long seconds, microseconds; |
|---|
| 2057 | 2058 | } |
|---|
| 2058 | 2059 | |
|---|
| … | … | |
| 2138 | 2139 | } |
|---|
| 2139 | 2140 | |
|---|
| 2140 | | this (SocketSet o) |
|---|
| | 2141 | this (SocketSet o) |
|---|
| 2141 | 2142 | { |
|---|
| 2142 | 2143 | nbytes = o.nbytes; |
|---|
| 2143 | 2144 | auto size = nbytes; |
|---|
| 2144 | | version (Win32) |
|---|
| | 2145 | version (Win32) |
|---|
| 2145 | 2146 | size += uint.sizeof; |
|---|
| 2146 | 2147 | |
|---|
| 2147 | | version (Posix) |
|---|
| | 2148 | version (Posix) |
|---|
| 2148 | 2149 | { |
|---|
| 2149 | 2150 | nfdbits = o.nfdbits; |
|---|
| 2150 | 2151 | _maxfd = o._maxfd; |
|---|
| 2151 | 2152 | } |
|---|
| 2152 | | |
|---|
| | 2153 | |
|---|
| 2153 | 2154 | auto b = new byte[size]; |
|---|
| 2154 | 2155 | b[] = o.buf[0..size]; |
|---|
| … | … | |
| 2172 | 2173 | } |
|---|
| 2173 | 2174 | |
|---|
| 2174 | | SocketSet dup() |
|---|
| | 2175 | SocketSet dup() |
|---|
| 2175 | 2176 | { |
|---|
| 2176 | 2177 | return new SocketSet (this); |
|---|
| 2177 | 2178 | } |
|---|
| 2178 | | |
|---|
| | 2179 | |
|---|
| 2179 | 2180 | SocketSet reset() |
|---|
| 2180 | 2181 | { |
|---|
| … | … | |
| 2408 | 2409 | |
|---|
| 2409 | 2410 | static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, long microseconds) |
|---|
| 2410 | | { |
|---|
| | 2411 | { |
|---|
| 2411 | 2412 | timeval tv = { |
|---|
| 2412 | | cast(typeof(timeval.seconds)) (microseconds / 1000000), |
|---|
| | 2413 | cast(typeof(timeval.seconds)) (microseconds / 1000000), |
|---|
| 2413 | 2414 | cast(typeof(timeval.microseconds)) (microseconds % 1000000) |
|---|
| 2414 | 2415 | }; |
|---|
| r3686 |
r5652 |
|
| 156 | 156 | GatewayTimeout = 504, |
|---|
| 157 | 157 | VersionNotSupported = 505, |
|---|
| 158 | | }; |
|---|
| | 158 | } |
|---|
| 159 | 159 | |
|---|
| 160 | 160 | /******************************************************************************* |
|---|
| … | … | |
| 178 | 178 | struct HttpResponses |
|---|
| 179 | 179 | { |
|---|
| | 180 | const: |
|---|
| 180 | 181 | static HttpStatus Continue = {HttpResponseCode.Continue, "Continue"}; |
|---|
| 181 | 182 | static HttpStatus SwitchingProtocols = {HttpResponseCode.SwitchingProtocols, "SwitchingProtocols"}; |
|---|
| r4378 |
r5652 |
|
| 17 | 17 | |
|---|
| 18 | 18 | // |
|---|
| 19 | | // Required |
|---|
| | 19 | // Required |
|---|
| 20 | 20 | // |
|---|
| 21 | 21 | /* |
|---|
| … | … | |
| 223 | 223 | } |
|---|
| 224 | 224 | } |
|---|
| 225 | | |
|---|
| | 225 | |
|---|
| 226 | 226 | struct sockaddr_in6 |
|---|
| 227 | 227 | { |
|---|
| … | … | |
| 232 | 232 | uint32_t sin6_scope_id; |
|---|
| 233 | 233 | } |
|---|
| 234 | | |
|---|
| | 234 | |
|---|
| 235 | 235 | extern in6_addr in6addr_any; |
|---|
| 236 | 236 | extern in6_addr in6addr_loopback; |
|---|
| 237 | | |
|---|
| | 237 | |
|---|
| 238 | 238 | struct ipv6_mreq |
|---|
| 239 | 239 | { |
|---|
| … | … | |
| 241 | 241 | uint ipv6mr_interface; |
|---|
| 242 | 242 | } |
|---|
| 243 | | |
|---|
| | 243 | |
|---|
| 244 | 244 | enum : uint |
|---|
| 245 | 245 | { |
|---|
| 246 | 246 | IPPROTO_IPV6 = 41, |
|---|
| 247 | | |
|---|
| | 247 | |
|---|
| 248 | 248 | INET6_ADDRSTRLEN = 46, |
|---|
| 249 | | |
|---|
| | 249 | |
|---|
| 250 | 250 | IPV6_JOIN_GROUP = 20, |
|---|
| 251 | 251 | IPV6_LEAVE_GROUP = 21, |
|---|
| … | … | |
| 345 | 345 | } |
|---|
| 346 | 346 | } |
|---|
| 347 | | |
|---|
| | 347 | |
|---|
| 348 | 348 | struct sockaddr_in6 |
|---|
| 349 | 349 | { |
|---|
| … | … | |
| 355 | 355 | uint32_t __sin6_src_id; /* Impl. specific - UDP replies */ |
|---|
| 356 | 356 | } |
|---|
| 357 | | |
|---|
| | 357 | |
|---|
| 358 | 358 | extern in6_addr in6addr_any; |
|---|
| 359 | 359 | extern in6_addr in6addr_loopback; |
|---|
| 360 | | |
|---|
| | 360 | |
|---|
| 361 | 361 | struct ipv6_mreq |
|---|
| 362 | 362 | { |
|---|
| … | … | |
| 364 | 364 | uint ipv6mr_interface; |
|---|
| 365 | 365 | } |
|---|
| 366 | | |
|---|
| | 366 | |
|---|
| 367 | 367 | enum : uint |
|---|
| 368 | 368 | { |
|---|
| 369 | 369 | IPPROTO_IPV6 = 41, |
|---|
| 370 | | |
|---|
| | 370 | |
|---|
| 371 | 371 | INET6_ADDRSTRLEN = 46, |
|---|
| 372 | | |
|---|
| | 372 | |
|---|
| 373 | 373 | IPV6_JOIN_GROUP = 0x9, |
|---|
| 374 | 374 | IPV6_LEAVE_GROUP = 0xa, |
|---|
| … | … | |
| 395 | 395 | version(BigEndian) enum : uint { N = 0x00000001 } |
|---|
| 396 | 396 | else enum : uint { N = 0x01000000 } |
|---|
| 397 | | |
|---|
| | 397 | |
|---|
| 398 | 398 | return addr.s6_addr32[3] == N && |
|---|
| 399 | 399 | addr.s6_addr32[2] == 0 && |
|---|
| … | … | |
| 411 | 411 | { |
|---|
| 412 | 412 | version(BigEndian) |
|---|
| 413 | | return addr.s6_addr32[0] & 0xff000000 == 0xff000000; |
|---|
| 414 | | else |
|---|
| 415 | | return addr.s6_addr32[0] & 0x000000ff == 0x000000ff; |
|---|
| | 413 | return (addr.s6_addr32[0] & 0xff000000) == 0xff000000; |
|---|
| | 414 | else |
|---|
| | 415 | return (addr.s6_addr32[0] & 0x000000ff) == 0x000000ff; |
|---|
| 416 | 416 | } |
|---|
| 417 | 417 | |
|---|
| … | … | |
| 419 | 419 | { |
|---|
| 420 | 420 | version(BigEndian) |
|---|
| 421 | | return addr.s6_addr32[0] & 0xffc00000 == 0xfe800000; |
|---|
| 422 | | else |
|---|
| 423 | | return addr.s6_addr32[0] & 0x0000c0ff == 0x000080fe; |
|---|
| | 421 | return (addr.s6_addr32[0] & 0xffc00000) == 0xfe800000; |
|---|
| | 422 | else |
|---|
| | 423 | return (addr.s6_addr32[0] & 0x0000c0ff) == 0x000080fe; |
|---|
| 424 | 424 | } |
|---|
| 425 | 425 | |
|---|
| … | … | |
| 427 | 427 | { |
|---|
| 428 | 428 | version(BigEndian) |
|---|
| 429 | | return addr.s6_addr32[0] & 0xffc00000 == 0xfec00000; |
|---|
| 430 | | else |
|---|
| 431 | | return addr.s6_addr32[0] & 0x0000c0ff == 0x0000c0fe; |
|---|
| | 429 | return (addr.s6_addr32[0] & 0xffc00000) == 0xfec00000; |
|---|
| | 430 | else |
|---|
| | 431 | return (addr.s6_addr32[0] & 0x0000c0ff) == 0x0000c0fe; |
|---|
| 432 | 432 | } |
|---|
| 433 | 433 | |
|---|
| … | … | |
| 436 | 436 | version(BigEndian) enum : uint { N = 0x0000ffff } |
|---|
| 437 | 437 | else enum : uint { N = 0xffff0000 } |
|---|
| 438 | | |
|---|
| | 438 | |
|---|
| 439 | 439 | return addr.s6_addr32[2] == N && |
|---|
| 440 | 440 | addr.s6_addr32[1] == 0 && |
|---|
| … | … | |
| 446 | 446 | version(BigEndian) enum : uint { N = 0x00000001 } |
|---|
| 447 | 447 | else enum : uint { N = 0x01000000 } |
|---|
| 448 | | |
|---|
| | 448 | |
|---|
| 449 | 449 | return addr.s6_addr32[2] == 0 && |
|---|
| 450 | 450 | addr.s6_addr32[1] == 0 && |
|---|
| … | … | |
| 457 | 457 | { |
|---|
| 458 | 458 | version(BigEndian) |
|---|
| 459 | | return addr.s6_addr32[0] & 0xff0f0000 == 0xff010000; |
|---|
| 460 | | else |
|---|
| 461 | | return addr.s6_addr32[0] & 0x00000fff == 0x000001ff; |
|---|
| | 459 | return (addr.s6_addr32[0] & 0xff0f0000) == 0xff010000; |
|---|
| | 460 | else |
|---|
| | 461 | return (addr.s6_addr32[0] & 0x00000fff) == 0x000001ff; |
|---|
| 462 | 462 | } |
|---|
| 463 | 463 | |
|---|
| … | … | |
| 465 | 465 | { |
|---|
| 466 | 466 | version(BigEndian) |
|---|
| 467 | | return addr.s6_addr32[0] & 0xff0f0000 == 0xff020000; |
|---|
| 468 | | else |
|---|
| 469 | | return addr.s6_addr32[0] & 0x00000fff == 0x000002ff; |
|---|
| | 467 | return (addr.s6_addr32[0] & 0xff0f0000) == 0xff020000; |
|---|
| | 468 | else |
|---|
| | 469 | return (addr.s6_addr32[0] & 0x00000fff) == 0x000002ff; |
|---|
| 470 | 470 | } |
|---|
| 471 | 471 | |
|---|
| … | … | |
| 473 | 473 | { |
|---|
| 474 | 474 | version(BigEndian) |
|---|
| 475 | | return addr.s6_addr32[0] & 0xff0f0000 == 0xff050000; |
|---|
| 476 | | else |
|---|
| 477 | | return addr.s6_addr32[0] & 0x00000fff == 0x000005ff; |
|---|
| | 475 | return (addr.s6_addr32[0] & 0xff0f0000) == 0xff050000; |
|---|
| | 476 | else |
|---|
| | 477 | return (addr.s6_addr32[0] & 0x00000fff) == 0x000005ff; |
|---|
| 478 | 478 | } |
|---|
| 479 | 479 | |
|---|
| … | … | |
| 481 | 481 | { |
|---|
| 482 | 482 | version(BigEndian) |
|---|
| 483 | | return addr.s6_addr32[0] & 0xff0f0000 == 0xff080000; |
|---|
| 484 | | else |
|---|
| 485 | | return addr.s6_addr32[0] & 0x00000fff == 0x000008ff; |
|---|
| | 483 | return (addr.s6_addr32[0] & 0xff0f0000) == 0xff080000; |
|---|
| | 484 | else |
|---|
| | 485 | return (addr.s6_addr32[0] & 0x00000fff) == 0x000008ff; |
|---|
| 486 | 486 | } |
|---|
| 487 | 487 | |
|---|
| … | … | |
| 489 | 489 | { |
|---|
| 490 | 490 | version(BigEndian) |
|---|
| 491 | | return addr.s6_addr32[0] & 0xff0f0000 == 0xff0e0000; |
|---|
| 492 | | else |
|---|
| 493 | | return addr.s6_addr32[0] & 0x00000fff == 0x00000eff; |
|---|
| | 491 | return (addr.s6_addr32[0] & 0xff0f0000) == 0xff0e0000; |
|---|
| | 492 | else |
|---|
| | 493 | return (addr.s6_addr32[0] & 0x00000fff) == 0x00000eff; |
|---|
| 494 | 494 | } |
|---|
| 495 | 495 | } |
|---|
| r5248 |
r5652 |
|
| 10 | 10 | |
|---|
| 11 | 11 | |
|---|
| | 12 | debug(PRINTF) import tango.stdc.stdio: printf; |
|---|
| | 13 | |
|---|
| | 14 | |
|---|
| 12 | 15 | version( GNU ) |
|---|
| 13 | 16 | { |
|---|
| … | … | |
| 20 | 23 | else |
|---|
| 21 | 24 | { |
|---|
| | 25 | version (X86) |
|---|
| | 26 | { |
|---|
| | 27 | /********************* |
|---|
| | 28 | * The argument pointer type. |
|---|
| | 29 | */ |
|---|
| 22 | 30 | alias void* va_list; |
|---|
| 23 | 31 | |
|---|
| 24 | | template va_start( T ) |
|---|
| 25 | | { |
|---|
| 26 | | void va_start( out va_list ap, ref T parmn ) |
|---|
| | 32 | /********** |
|---|
| | 33 | * Initialize ap. |
|---|
| | 34 | * For 32 bit code, parmn should be the last named parameter. |
|---|
| | 35 | * For 64 bit code, parmn should be __va_argsave. |
|---|
| | 36 | */ |
|---|
| | 37 | void va_start(T)(out va_list ap, ref T parmn) |
|---|
| | 38 | { |
|---|
| | 39 | ap = cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); |
|---|
| | 40 | } |
|---|
| | 41 | |
|---|
| | 42 | /************ |
|---|
| | 43 | * Retrieve and return the next value that is type T. |
|---|
| | 44 | * Should use the other va_arg instead, as this won't work for 64 bit code. |
|---|
| | 45 | */ |
|---|
| | 46 | T va_arg(T)(ref va_list ap) |
|---|
| | 47 | { |
|---|
| | 48 | T arg = *cast(T*)ap; |
|---|
| | 49 | ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); |
|---|
| | 50 | return arg; |
|---|
| | 51 | } |
|---|
| | 52 | |
|---|
| | 53 | /************ |
|---|
| | 54 | * Retrieve and return the next value that is type T. |
|---|
| | 55 | * This is the preferred version. |
|---|
| | 56 | */ |
|---|
| | 57 | void va_arg(T)(ref va_list ap, ref T parmn) |
|---|
| | 58 | { |
|---|
| | 59 | parmn = *cast(T*)ap; |
|---|
| | 60 | ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); |
|---|
| | 61 | } |
|---|
| | 62 | |
|---|
| | 63 | /************* |
|---|
| | 64 | * Retrieve and store through parmn the next value that is of TypeInfo ti. |
|---|
| | 65 | * Used when the static type is not known. |
|---|
| | 66 | */ |
|---|
| | 67 | void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) |
|---|
| | 68 | { |
|---|
| | 69 | // Wait until everyone updates to get TypeInfo.talign() |
|---|
| | 70 | //auto talign = ti.talign(); |
|---|
| | 71 | //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1); |
|---|
| | 72 | auto p = ap; |
|---|
| | 73 | auto tsize = ti.tsize(); |
|---|
| | 74 | ap = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); |
|---|
| | 75 | parmn[0..tsize] = p[0..tsize]; |
|---|
| | 76 | } |
|---|
| | 77 | |
|---|
| | 78 | /*********************** |
|---|
| | 79 | * End use of ap. |
|---|
| | 80 | */ |
|---|
| | 81 | void va_end(va_list ap) |
|---|
| | 82 | { |
|---|
| | 83 | } |
|---|
| | 84 | |
|---|
| | 85 | void va_copy(out va_list dest, va_list src) |
|---|
| | 86 | { |
|---|
| | 87 | dest = src; |
|---|
| | 88 | } |
|---|
| | 89 | } |
|---|
| | 90 | else version (X86_64) |
|---|
| | 91 | { |
|---|
| | 92 | // Layout of this struct must match __gnuc_va_list for C ABI compatibility |
|---|
| | 93 | struct __va_list |
|---|
| | 94 | { |
|---|
| | 95 | uint offset_regs = 6 * 8; // no regs |
|---|
| | 96 | uint offset_fpregs = 6 * 8 + 8 * 16; // no fp regs |
|---|
| | 97 | void* stack_args; |
|---|
| | 98 | void* reg_args; |
|---|
| | 99 | } |
|---|
| | 100 | |
|---|
| | 101 | struct __va_argsave_t |
|---|
| | 102 | { |
|---|
| | 103 | size_t[6] regs; // RDI,RSI,RDX,RCX,R8,R9 |
|---|
| | 104 | real[8] fpregs; // XMM0..XMM7 |
|---|
| | 105 | __va_list va; |
|---|
| | 106 | } |
|---|
| | 107 | |
|---|
| | 108 | /* |
|---|
| | 109 | * Making it an array of 1 causes va_list to be passed as a pointer in |
|---|
| | 110 | * function argument lists |
|---|
| | 111 | */ |
|---|
| | 112 | alias void* va_list; |
|---|
| | 113 | |
|---|
| | 114 | void va_start(T)(out va_list ap, ref T parmn) |
|---|
| | 115 | { |
|---|
| | 116 | ap = &parmn.va; |
|---|
| | 117 | } |
|---|
| | 118 | |
|---|
| | 119 | T va_arg(T)(va_list ap) |
|---|
| | 120 | { T a; |
|---|
| | 121 | va_arg(ap, a); |
|---|
| | 122 | return a; |
|---|
| | 123 | } |
|---|
| | 124 | |
|---|
| | 125 | void va_arg(T)(va_list apx, ref T parmn) |
|---|
| | 126 | { |
|---|
| | 127 | debug(PRINTF) printf("va_arg(T) called\n"); |
|---|
| | 128 | __va_list* ap = cast(__va_list*)apx; |
|---|
| | 129 | static if (is(T U == __argTypes)) |
|---|
| 27 | 130 | { |
|---|
| 28 | | ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); |
|---|
| | 131 | static if (U.length == 0 || T.sizeof > 16 || U[0].sizeof > 8) |
|---|
| | 132 | { // Always passed in memory |
|---|
| | 133 | // The arg may have more strict alignment than the stack |
|---|
| | 134 | auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1); |
|---|
| | 135 | ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); |
|---|
| | 136 | parmn = *cast(T*)p; |
|---|
| | 137 | } |
|---|
| | 138 | else static if (U.length == 1) |
|---|
| | 139 | { // Arg is passed in one register |
|---|
| | 140 | alias U[0] T1; |
|---|
| | 141 | static if (is(T1 == double) || is(T1 == float)) |
|---|
| | 142 | { // Passed in XMM register |
|---|
| | 143 | if (ap.offset_fpregs < (6 * 8 + 16 * 8)) |
|---|
| | 144 | { |
|---|
| | 145 | parmn = *cast(T*)(ap.reg_args + ap.offset_fpregs); |
|---|
| | 146 | ap.offset_fpregs += 16; |
|---|
| | 147 | } |
|---|
| | 148 | else |
|---|
| | 149 | { |
|---|
| | 150 | parmn = *cast(T*)ap.stack_args; |
|---|
| | 151 | ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 152 | } |
|---|
| | 153 | } |
|---|
| | 154 | else |
|---|
| | 155 | { // Passed in regular register |
|---|
| | 156 | if (ap.offset_regs < 6 * 8 && T.sizeof <= 8) |
|---|
| | 157 | { |
|---|
| | 158 | parmn = *cast(T*)(ap.reg_args + ap.offset_regs); |
|---|
| | 159 | ap.offset_regs += 8; |
|---|
| | 160 | } |
|---|
| | 161 | else |
|---|
| | 162 | { |
|---|
| | 163 | auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1); |
|---|
| | 164 | ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); |
|---|
| | 165 | parmn = *cast(T*)p; |
|---|
| | 166 | } |
|---|
| | 167 | } |
|---|
| | 168 | } |
|---|
| | 169 | else static if (U.length == 2) |
|---|
| | 170 | { // Arg is passed in two registers |
|---|
| | 171 | alias U[0] T1; |
|---|
| | 172 | alias U[1] T2; |
|---|
| | 173 | |
|---|
| | 174 | static if (is(T1 == double) || is(T1 == float)) |
|---|
| | 175 | { |
|---|
| | 176 | if (ap.offset_fpregs < (6 * 8 + 16 * 8)) |
|---|
| | 177 | { |
|---|
| | 178 | *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_fpregs); |
|---|
| | 179 | ap.offset_fpregs += 16; |
|---|
| | 180 | } |
|---|
| | 181 | else |
|---|
| | 182 | { |
|---|
| | 183 | *cast(T1*)&parmn = *cast(T1*)ap.stack_args; |
|---|
| | 184 | ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 185 | } |
|---|
| | 186 | } |
|---|
| | 187 | else |
|---|
| | 188 | { |
|---|
| | 189 | if (ap.offset_regs < 6 * 8 && T1.sizeof <= 8) |
|---|
| | 190 | { |
|---|
| | 191 | *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_regs); |
|---|
| | 192 | ap.offset_regs += 8; |
|---|
| | 193 | } |
|---|
| | 194 | else |
|---|
| | 195 | { |
|---|
| | 196 | *cast(T1*)&parmn = *cast(T1*)ap.stack_args; |
|---|
| | 197 | ap.stack_args += 8; |
|---|
| | 198 | } |
|---|
| | 199 | } |
|---|
| | 200 | |
|---|
| | 201 | auto p = cast(void*)&parmn + 8; |
|---|
| | 202 | static if (is(T2 == double) || is(T2 == float)) |
|---|
| | 203 | { |
|---|
| | 204 | if (ap.offset_fpregs < (6 * 8 + 16 * 8)) |
|---|
| | 205 | { |
|---|
| | 206 | *cast(T2*)p = *cast(T2*)(ap.reg_args + ap.offset_fpregs); |
|---|
| | 207 | ap.offset_fpregs += 16; |
|---|
| | 208 | } |
|---|
| | 209 | else |
|---|
| | 210 | { |
|---|
| | 211 | *cast(T2*)p = *cast(T2*)ap.stack_args; |
|---|
| | 212 | ap.stack_args += (T2.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 213 | } |
|---|
| | 214 | } |
|---|
| | 215 | else |
|---|
| | 216 | { |
|---|
| | 217 | void* a = void; |
|---|
| | 218 | if (ap.offset_regs < 6 * 8 && T2.sizeof <= 8) |
|---|
| | 219 | { |
|---|
| | 220 | a = ap.reg_args + ap.offset_regs; |
|---|
| | 221 | ap.offset_regs += 8; |
|---|
| | 222 | } |
|---|
| | 223 | else |
|---|
| | 224 | { |
|---|
| | 225 | a = ap.stack_args; |
|---|
| | 226 | ap.stack_args += 8; |
|---|
| | 227 | } |
|---|
| | 228 | // Be careful not to go past the size of the actual argument |
|---|
| | 229 | const sz2 = T.sizeof - 8; |
|---|
| | 230 | p[0..sz2] = a[0..sz2]; |
|---|
| | 231 | } |
|---|
| | 232 | } |
|---|
| | 233 | else |
|---|
| | 234 | { |
|---|
| | 235 | static assert(0); |
|---|
| | 236 | } |
|---|
| 29 | 237 | } |
|---|
| 30 | | } |
|---|
| 31 | | |
|---|
| 32 | | template va_arg( T ) |
|---|
| 33 | | { |
|---|
| 34 | | T va_arg( ref va_list ap ) |
|---|
| | 238 | else |
|---|
| 35 | 239 | { |
|---|
| 36 | | T arg = *cast(T*) ap; |
|---|
| 37 | | ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); |
|---|
| 38 | | return arg; |
|---|
| | 240 | static assert(0, "not a valid argument type for va_arg"); |
|---|
| 39 | 241 | } |
|---|
| 40 | 242 | } |
|---|
| 41 | 243 | |
|---|
| 42 | | void va_end( va_list ap ) |
|---|
| 43 | | { |
|---|
| 44 | | |
|---|
| 45 | | } |
|---|
| 46 | | |
|---|
| 47 | | void va_copy( out va_list dest, va_list src ) |
|---|
| | 244 | void va_arg()(va_list apx, TypeInfo ti, void* parmn) |
|---|
| | 245 | { |
|---|
| | 246 | __va_list* ap = cast(__va_list*)apx; |
|---|
| | 247 | TypeInfo arg1, arg2; |
|---|
| | 248 | if (!ti.argTypes(arg1, arg2)) |
|---|
| | 249 | { |
|---|
| | 250 | if (arg1 && arg1.tsize() <= 8) |
|---|
| | 251 | { |
|---|
| | 252 | // Arg is passed in one register |
|---|
| | 253 | auto tsize = arg1.tsize(); |
|---|
| | 254 | void* p; |
|---|
| | 255 | auto s = arg1.toString(); |
|---|
| | 256 | if (s == "double" || s == "float" || s == "idouble" || s == "ifloat") |
|---|
| | 257 | { // Passed in XMM register |
|---|
| | 258 | if (ap.offset_fpregs < (6 * 8 + 16 * 8)) |
|---|
| | 259 | { |
|---|
| | 260 | p = ap.reg_args + ap.offset_fpregs; |
|---|
| | 261 | ap.offset_fpregs += 16; |
|---|
| | 262 | } |
|---|
| | 263 | else |
|---|
| | 264 | { |
|---|
| | 265 | p = ap.stack_args; |
|---|
| | 266 | ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 267 | } |
|---|
| | 268 | } |
|---|
| | 269 | else |
|---|
| | 270 | { // Passed in regular register |
|---|
| | 271 | if (ap.offset_regs < 6 * 8) |
|---|
| | 272 | { |
|---|
| | 273 | p = ap.reg_args + ap.offset_regs; |
|---|
| | 274 | ap.offset_regs += 8; |
|---|
| | 275 | } |
|---|
| | 276 | else |
|---|
| | 277 | { |
|---|
| | 278 | p = ap.stack_args; |
|---|
| | 279 | ap.stack_args += 8; |
|---|
| | 280 | } |
|---|
| | 281 | } |
|---|
| | 282 | parmn[0..tsize] = p[0..tsize]; |
|---|
| | 283 | |
|---|
| | 284 | if (arg2) |
|---|
| | 285 | { |
|---|
| | 286 | parmn += 8; |
|---|
| | 287 | tsize = arg2.tsize(); |
|---|
| | 288 | s = arg2.toString(); |
|---|
| | 289 | if (s == "double" || s == "float" || s == "idouble" || s == "ifloat") |
|---|
| | 290 | { // Passed in XMM register |
|---|
| | 291 | if (ap.offset_fpregs < (6 * 8 + 16 * 8)) |
|---|
| | 292 | { |
|---|
| | 293 | p = ap.reg_args + ap.offset_fpregs; |
|---|
| | 294 | ap.offset_fpregs += 16; |
|---|
| | 295 | } |
|---|
| | 296 | else |
|---|
| | 297 | { |
|---|
| | 298 | p = ap.stack_args; |
|---|
| | 299 | ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 300 | } |
|---|
| | 301 | } |
|---|
| | 302 | else |
|---|
| | 303 | { // Passed in regular register |
|---|
| | 304 | if (ap.offset_regs < 6 * 8) |
|---|
| | 305 | { |
|---|
| | 306 | p = ap.reg_args + ap.offset_regs; |
|---|
| | 307 | ap.offset_regs += 8; |
|---|
| | 308 | } |
|---|
| | 309 | else |
|---|
| | 310 | { |
|---|
| | 311 | p = ap.stack_args; |
|---|
| | 312 | ap.stack_args += 8; |
|---|
| | 313 | } |
|---|
| | 314 | } |
|---|
| | 315 | tsize = ti.tsize() - 8; |
|---|
| | 316 | parmn[0..tsize] = p[0..tsize]; |
|---|
| | 317 | } |
|---|
| | 318 | } |
|---|
| | 319 | else |
|---|
| | 320 | { |
|---|
| | 321 | // Always passed in memory |
|---|
| | 322 | // The arg may have more strict alignment than the stack |
|---|
| | 323 | auto talign = ti.talign(); |
|---|
| | 324 | auto tsize = ti.tsize(); |
|---|
| | 325 | |
|---|
| | 326 | |
|---|
| | 327 | auto p = cast(void*)((cast(size_t)ap.stack_args + talign - 1) & ~(talign - 1)); |
|---|
| | 328 | ap.stack_args = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); |
|---|
| | 329 | parmn[0..tsize] = p[0..tsize]; |
|---|
| | 330 | } |
|---|
| | 331 | } |
|---|
| | 332 | else |
|---|
| | 333 | { |
|---|
| | 334 | assert(0, "not a valid argument type for va_arg"); |
|---|
| | 335 | } |
|---|
| | 336 | } |
|---|
| | 337 | |
|---|
| | 338 | void va_end(va_list ap) |
|---|
| | 339 | { |
|---|
| | 340 | } |
|---|
| | 341 | |
|---|
| | 342 | void va_copy(out va_list dest, va_list src) |
|---|
| 48 | 343 | { |
|---|
| 49 | 344 | dest = src; |
|---|
| 50 | 345 | } |
|---|
| 51 | 346 | } |
|---|
| | 347 | else |
|---|
| | 348 | { |
|---|
| | 349 | static assert(0); |
|---|
| | 350 | } |
|---|
| | 351 | } |
|---|
| r5618 |
r5652 |
|
| 47 | 47 | } |
|---|
| 48 | 48 | |
|---|
| 49 | | version (Posix) |
|---|
| | 49 | version (Posix) |
|---|
| 50 | 50 | { |
|---|
| 51 | 51 | |
|---|
| … | … | |
| 78 | 78 | if it could not be expanded. |
|---|
| 79 | 79 | |
|---|
| 80 | | Throws: OutOfMemoryException if there is not enough memory to |
|---|
| | 80 | Throws: OutOfMemoryException if there is not enough memory to |
|---|
| 81 | 81 | perform the database lookup for the <i>~user</i> syntax. |
|---|
| 82 | 82 | |
|---|
| … | … | |
| 125 | 125 | |
|---|
| 126 | 126 | private char[] expandFromEnvironment(char[] path) |
|---|
| | 127 | in |
|---|
| 127 | 128 | { |
|---|
| 128 | 129 | assert(path.length >= 1); |
|---|
| 129 | 130 | assert(path[0] == '~'); |
|---|
| 130 | | |
|---|
| | 131 | } |
|---|
| | 132 | body |
|---|
| | 133 | { |
|---|
| 131 | 134 | // Get HOME and use that to replace the tilde. |
|---|
| 132 | 135 | char[] home = homeFolder; |
|---|
| … | … | |
| 134 | 137 | return path; |
|---|
| 135 | 138 | |
|---|
| | 139 | if (home[$-1] == '/') |
|---|
| | 140 | home = home[0..$-1]; |
|---|
| | 141 | |
|---|
| 136 | 142 | return Path.join(home, path[1..$]); |
|---|
| | 143 | |
|---|
| 137 | 144 | } |
|---|
| 138 | 145 | |
|---|
| … | … | |
| 154 | 161 | |
|---|
| 155 | 162 | if (last_char == path.length) |
|---|
| 156 | | { |
|---|
| | 163 | { |
|---|
| 157 | 164 | username = path[1..$] ~ '\0'; |
|---|
| 158 | | } |
|---|
| | 165 | } |
|---|
| 159 | 166 | else |
|---|
| 160 | | { |
|---|
| | 167 | { |
|---|
| 161 | 168 | username = path[1..last_char] ~ '\0'; |
|---|
| 162 | | } |
|---|
| | 169 | } |
|---|
| 163 | 170 | |
|---|
| 164 | 171 | assert(last_char > 1); |
|---|
| 165 | | |
|---|
| | 172 | |
|---|
| 166 | 173 | // Reserve C memory for the getpwnam_r() function. |
|---|
| 167 | 174 | passwd result; |
|---|
| … | … | |
| 169 | 176 | void* extra_memory; |
|---|
| 170 | 177 | |
|---|
| | 178 | scope (exit) if(extra_memory) tango.stdc.stdlib.free(extra_memory); |
|---|
| | 179 | |
|---|
| 171 | 180 | while (1) |
|---|
| 172 | | { |
|---|
| | 181 | { |
|---|
| 173 | 182 | extra_memory = tango.stdc.stdlib.malloc(extra_memory_size); |
|---|
| 174 | 183 | if (extra_memory is null) |
|---|
| 175 | | goto Lerror; |
|---|
| | 184 | throw new OutOfMemoryException("Not enough memory for user lookup in tilde expansion.", __LINE__); |
|---|
| 176 | 185 | |
|---|
| 177 | 186 | // Obtain info from database. |
|---|
| … | … | |
| 180 | 189 | if (getpwnam_r(username.ptr, &result, cast(char*)extra_memory, extra_memory_size, |
|---|
| 181 | 190 | &verify) == 0) |
|---|
| | 191 | { |
|---|
| | 192 | // Failure if verify doesn't point at result. |
|---|
| | 193 | if (verify == &result) |
|---|
| 182 | 194 | { |
|---|
| 183 | | // Failure if verify doesn't point at result. |
|---|
| 184 | | if (verify != &result) |
|---|
| 185 | | // username is not found, so return path[] |
|---|
| 186 | | goto Lnotfound; |
|---|
| 187 | | break; |
|---|
| | 195 | auto pwdirlen = strlen(result.pw_dir); |
|---|
| | 196 | |
|---|
| | 197 | path = Path.join(result.pw_dir[0..pwdirlen].dup, path[last_char..$]); |
|---|
| 188 | 198 | } |
|---|
| 189 | 199 | |
|---|
| | 200 | return path; |
|---|
| | 201 | } |
|---|
| | 202 | |
|---|
| 190 | 203 | if (tango.stdc.errno.errno() != ERANGE) |
|---|
| 191 | | goto Lerror; |
|---|
| | 204 | throw new OutOfMemoryException("Not enough memory for user lookup in tilde expansion.", __LINE__); |
|---|
| 192 | 205 | |
|---|
| 193 | 206 | // extra_memory isn't large enough |
|---|
| 194 | 207 | tango.stdc.stdlib.free(extra_memory); |
|---|
| 195 | 208 | extra_memory_size *= 2; |
|---|
| 196 | | } |
|---|
| 197 | | |
|---|
| 198 | | auto pwdirlen = strlen(result.pw_dir); |
|---|
| 199 | | path = Path.join(result.pw_dir[0..pwdirlen].dup, path[last_char..$]); |
|---|
| 200 | | |
|---|
| 201 | | Lnotfound: |
|---|
| 202 | | tango.stdc.stdlib.free(extra_memory); |
|---|
| 203 | | return path; |
|---|
| 204 | | |
|---|
| 205 | | Lerror: |
|---|
| 206 | | // Errors are going to be caused by running out of memory |
|---|
| 207 | | if (extra_memory) |
|---|
| 208 | | tango.stdc.stdlib.free(extra_memory); |
|---|
| 209 | | throw new OutOfMemoryException("Not enough memory for user lookup in tilde expansion.", __LINE__); |
|---|
| | 209 | } |
|---|
| 210 | 210 | } |
|---|
| 211 | 211 | |
|---|
| … | … | |
| 243 | 243 | if it could not be expanded. |
|---|
| 244 | 244 | |
|---|
| 245 | | Throws: OutOfMemoryException if there is not enough memory to |
|---|
| | 245 | Throws: OutOfMemoryException if there is not enough memory to |
|---|
| 246 | 246 | perform the database lookup for the <i>~user</i> syntax. |
|---|
| 247 | 247 | |
|---|
| … | … | |
| 309 | 309 | |
|---|
| 310 | 310 | debug(UnitTest) { |
|---|
| | 311 | |
|---|
| 311 | 312 | unittest |
|---|
| 312 | 313 | { |
|---|
| … | … | |
| 323 | 324 | // Testing when an environment variable is set. |
|---|
| 324 | 325 | Environment.set("HOME", "tango/test"); |
|---|
| | 326 | assert (Environment.get("HOME") == "tango/test"); |
|---|
| | 327 | |
|---|
| 325 | 328 | assert(expandTilde("~/") == "tango/test/"); |
|---|
| 326 | 329 | assert(expandTilde("~") == "tango/test"); |
|---|
| r5618 |
r5652 |
|
| 30 | 30 | extern (C) char*** _NSGetEnviron(); |
|---|
| 31 | 31 | private char** environ; |
|---|
| 32 | | |
|---|
| | 32 | |
|---|
| 33 | 33 | static this () |
|---|
| 34 | 34 | { |
|---|
| … | … | |
| 36 | 36 | } |
|---|
| 37 | 37 | } |
|---|
| 38 | | |
|---|
| | 38 | |
|---|
| 39 | 39 | else |
|---|
| 40 | 40 | private extern (C) extern char** environ; |
|---|
| … | … | |
| 126 | 126 | * cannot call the wait() method. Once the kill() method returns the process |
|---|
| 127 | 127 | * will be already dead. |
|---|
| 128 | | * |
|---|
| | 128 | * |
|---|
| 129 | 129 | * After calling either wait() or kill(), and no more data is expected on the |
|---|
| 130 | 130 | * pipes, you should call close() as this will clean the pipes. Not doing this |
|---|
| … | … | |
| 644 | 644 | * redirection from stdout to stderr and from stderr to stdout. If both |
|---|
| 645 | 645 | * of these are specified, an exception is thrown. |
|---|
| 646 | | * |
|---|
| | 646 | * |
|---|
| 647 | 647 | * If redirected to a pipe, once the process is executed successfully, its |
|---|
| 648 | 648 | * input and output can be manipulated through the stdin, stdout and |
|---|
| … | … | |
| 1016 | 1016 | } |
|---|
| 1017 | 1017 | } |
|---|
| 1018 | | |
|---|
| | 1018 | |
|---|
| 1019 | 1019 | // close the unused end of the pipes on scope exit |
|---|
| 1020 | 1020 | scope(exit) |
|---|
| … | … | |
| 1032 | 1032 | memset(_info, '\0', PROCESS_INFORMATION.sizeof); |
|---|
| 1033 | 1033 | |
|---|
| 1034 | | /* |
|---|
| | 1034 | /* |
|---|
| 1035 | 1035 | * quotes and backslashes in the command line are handled very |
|---|
| 1036 | 1036 | * strangely by Windows. Through trial and error, I believe that |
|---|
| … | … | |
| 1101 | 1101 | // rule 1 and be halved. |
|---|
| 1102 | 1102 | // |
|---|
| 1103 | | |
|---|
| | 1103 | |
|---|
| 1104 | 1104 | if(nextarg[$-1] == '\\') |
|---|
| 1105 | 1105 | { |
|---|
| … | … | |
| 1268 | 1268 | if(pin !is null) |
|---|
| 1269 | 1269 | { |
|---|
| 1270 | | dup2(pin.source.fileHandle(), STDIN_FILENO); |
|---|
| | 1270 | if (dup2(pin.source.fileHandle(), STDIN_FILENO) < 0) |
|---|
| | 1271 | throw new Exception("dup2 < 0"); |
|---|
| 1271 | 1272 | pin.sink().close(); |
|---|
| 1272 | 1273 | pin.source.close(); |
|---|
| … | … | |
| 1276 | 1277 | if(pout !is null) |
|---|
| 1277 | 1278 | { |
|---|
| 1278 | | dup2(pout.sink.fileHandle(), STDOUT_FILENO); |
|---|
| | 1279 | if (dup2(pout.sink.fileHandle(), STDOUT_FILENO) < 0) |
|---|
| | 1280 | throw new Exception("dup2 < 0"); |
|---|
| 1279 | 1281 | pout.source.close(); |
|---|
| 1280 | 1282 | pout.sink.close(); |
|---|
| … | … | |
| 1284 | 1286 | if(perr !is null) |
|---|
| 1285 | 1287 | { |
|---|
| 1286 | | dup2(perr.sink.fileHandle(), STDERR_FILENO); |
|---|
| | 1288 | if (dup2(perr.sink.fileHandle(), STDERR_FILENO) < 0) |
|---|
| | 1289 | throw new Exception("dup2 < 0"); |
|---|
| 1287 | 1290 | perr.source.close(); |
|---|
| 1288 | 1291 | perr.sink.close(); |
|---|
| … | … | |
| 1293 | 1296 | if(_redirect & Redirect.OutputToError) |
|---|
| 1294 | 1297 | { |
|---|
| 1295 | | dup2(STDERR_FILENO, STDOUT_FILENO); |
|---|
| | 1298 | if(dup2(STDERR_FILENO, STDOUT_FILENO) < 0) |
|---|
| | 1299 | throw new Exception("dup2 < 0"); |
|---|
| 1296 | 1300 | } |
|---|
| 1297 | 1301 | |
|---|
| 1298 | 1302 | if(_redirect & Redirect.ErrorToOutput) |
|---|
| 1299 | 1303 | { |
|---|
| 1300 | | dup2(STDOUT_FILENO, STDERR_FILENO); |
|---|
| | 1304 | if(dup2(STDOUT_FILENO, STDERR_FILENO) < 0) |
|---|
| | 1305 | throw new Exception("dup2 < 0"); |
|---|
| 1301 | 1306 | } |
|---|
| 1302 | 1307 | |
|---|
| … | … | |
| 1340 | 1345 | exit(errno); |
|---|
| 1341 | 1346 | } |
|---|
| | 1347 | exit(errno); |
|---|
| 1342 | 1348 | } |
|---|
| 1343 | 1349 | else |
|---|
| … | … | |
| 1579 | 1585 | * process may still want/need the remaining content. However, it is |
|---|
| 1580 | 1586 | * recommended to call close() on the process when it is no longer needed |
|---|
| 1581 | | * as this will clean the pipes. |
|---|
| | 1587 | * as this will clean the pipes. |
|---|
| 1582 | 1588 | */ |
|---|
| 1583 | 1589 | public void kill() |
|---|
| … | … | |
| 1927 | 1933 | char[][] pathList = delimit(str[0 .. strlen(str)], ":"); |
|---|
| 1928 | 1934 | |
|---|
| | 1935 | char[] path_buf; |
|---|
| | 1936 | |
|---|
| 1929 | 1937 | foreach (path; pathList) |
|---|
| 1930 | 1938 | { |
|---|
| 1931 | | if (path[path.length - 1] != FileConst.PathSeparatorChar) |
|---|
| 1932 | | { |
|---|
| 1933 | | path ~= FileConst.PathSeparatorChar; |
|---|
| 1934 | | } |
|---|
| 1935 | | |
|---|
| 1936 | | debug (Process) |
|---|
| 1937 | | Stdout.formatln("Trying execution of '{0}' in directory '{1}'", |
|---|
| 1938 | | filename, path); |
|---|
| 1939 | | |
|---|
| 1940 | | path ~= filename; |
|---|
| 1941 | | path ~= '\0'; |
|---|
| 1942 | | |
|---|
| 1943 | | rc = execve(path.ptr, argv.ptr, (envp.length == 0 ? environ : envp.ptr)); |
|---|
| | 1939 | if (path[$-1] != FileConst.PathSeparatorChar) |
|---|
| | 1940 | { |
|---|
| | 1941 | path_buf.length = path.length + 1 + filename.length + 1; |
|---|
| | 1942 | path_buf[] = path ~ FileConst.PathSeparatorChar ~ filename ~ '\0'; |
|---|
| | 1943 | } |
|---|
| | 1944 | else |
|---|
| | 1945 | { |
|---|
| | 1946 | path_buf.length = path.length +filename.length + 1; |
|---|
| | 1947 | path_buf[] = path ~ filename ~ '\0'; |
|---|
| | 1948 | } |
|---|
| | 1949 | |
|---|
| | 1950 | rc = execve(path_buf.ptr, argv.ptr, (envp.length == 0 ? environ : envp.ptr)); |
|---|
| | 1951 | |
|---|
| 1944 | 1952 | // If the process execution failed because of an error |
|---|
| 1945 | 1953 | // other than ENOENT (No such file or directory) we |
|---|
| 1946 | 1954 | // abort the loop. |
|---|
| 1947 | | if (rc == -1 && errno != ENOENT) |
|---|
| | 1955 | if (rc == -1 && SysError.lastCode !is ENOENT) |
|---|
| 1948 | 1956 | { |
|---|
| 1949 | 1957 | break; |
|---|
| … | … | |
| 2031 | 2039 | } |
|---|
| 2032 | 2040 | |
|---|
| 2033 | | |
|---|
| | 2041 | extern (C) uint sleep (uint s); |
|---|
| 2034 | 2042 | debug (UnitTest) |
|---|
| 2035 | 2043 | { |
|---|
| | 2044 | import tango.io.Stdout; |
|---|
| | 2045 | import tango.stdc.stdio : printf, fflush, stdout; |
|---|
| | 2046 | |
|---|
| 2036 | 2047 | unittest |
|---|
| 2037 | 2048 | { |
|---|
| … | … | |
| 2048 | 2059 | { |
|---|
| 2049 | 2060 | auto p = new Process(command, null); |
|---|
| 2050 | | |
|---|
| | 2061 | Stdout.flush; |
|---|
| 2051 | 2062 | p.execute(); |
|---|
| 2052 | | char[1024] buffer; |
|---|
| | 2063 | char[255] buffer; |
|---|
| | 2064 | |
|---|
| 2053 | 2065 | auto nread = p.stdout.read(buffer); |
|---|
| | 2066 | |
|---|
| 2054 | 2067 | assert(nread != p.stdout.Eof); |
|---|
| | 2068 | |
|---|
| 2055 | 2069 | version(Windows) |
|---|
| 2056 | 2070 | assert(buffer[0..nread] == message ~ "\r\n"); |
|---|
| 2057 | 2071 | else |
|---|
| 2058 | 2072 | assert(buffer[0..nread] == message ~ "\n"); |
|---|
| | 2073 | |
|---|
| 2059 | 2074 | nread = p.stdout.read(buffer); |
|---|
| 2060 | 2075 | assert(nread == p.stdout.Eof); |
|---|
| r5544 |
r5652 |
|
| 933 | 933 | cc.negate; |
|---|
| 934 | 934 | assert(cc.toString, "[(12)-(13)'e'-(ff)]"); |
|---|
| 935 | | |
|---|
| | 935 | |
|---|
| 936 | 936 | static CharClass!(char) cc2 = { parts: [] }; |
|---|
| 937 | 937 | assert(cc.toString, "[]"); |
|---|
| … | … | |
| 944 | 944 | cc2.negate; |
|---|
| 945 | 945 | assert(cc.toString, "[]"); |
|---|
| 946 | | |
|---|
| | 946 | |
|---|
| 947 | 947 | static CharClass!(char) cc3 = { parts: [{l_:0,r_:100},{l_:200,r_:0xff},] }; |
|---|
| 948 | 948 | assert(cc3.toString, "[(0)-'d'(c8)-(ff)]"); |
|---|
| … | … | |
| 951 | 951 | cc3.negate; |
|---|
| 952 | 952 | assert(cc.toString, "[(0)-'d'(c8)-(ff)]"); |
|---|
| 953 | | |
|---|
| | 953 | |
|---|
| 954 | 954 | static CharClass!(char) cc4 = { parts: [{l_:0,r_:200},{l_:100,r_:0xff},] }; |
|---|
| 955 | 955 | assert(cc.toString, "[(0)-(c8)'d'-(ff)]"); |
|---|
| 956 | 956 | cc4.optimize; |
|---|
| 957 | 957 | assert(cc.toString, "[(9)-(13)(20)-'~'(a0)-(ff)(100)-(17f)(180)-(24f)(20a3)-(20b5)]"); |
|---|
| 958 | | |
|---|
| | 958 | |
|---|
| 959 | 959 | static CharClass!(dchar) cc5 = { parts: [{l_:0x9,r_:0x13},{0x20,r_:'~'},{l_:0xa0,r_:0xff},{l_:0x100,r_:0x17f},{l_:0x180,r_:0x24f},{l_:0x20a3,r_:0x20b5}] }; |
|---|
| 960 | 960 | cc5.optimize; |
|---|
| … | … | |
| 1246 | 1246 | /****************************************************************************** |
|---|
| 1247 | 1247 | Move through states only going via epsilon transitions, and only choosing |
|---|
| 1248 | | the one with highest priority. If the highest priority transition from a |
|---|
| 1249 | | state isn't an epsilon transition, false is returned. |
|---|
| 1250 | | If the accepting NFA state can be reached in this manner, true is returned. |
|---|
| | 1248 | the one with highest priority. If the highest priority transition from a |
|---|
| | 1249 | state isn't an epsilon transition, false is returned. |
|---|
| | 1250 | If the accepting NFA state can be reached in this manner, true is returned. |
|---|
| 1251 | 1251 | |
|---|
| 1252 | 1252 | NOTE: This method does not look for cycles which should be kept in mind for |
|---|
| … | … | |
| 1264 | 1264 | if (!(highestPriTrans.predicate.type == Predicate!(char_t).Type.epsilon)) |
|---|
| 1265 | 1265 | return false; |
|---|
| 1266 | | |
|---|
| | 1266 | |
|---|
| 1267 | 1267 | t = highestPriTrans.target; |
|---|
| 1268 | 1268 | } |
|---|
| … | … | |
| 3499 | 3499 | // regressions have been discovered. larsivi 20090827 |
|---|
| 3500 | 3500 | TNFATransition!(char_t) highestPriTrans; |
|---|
| 3501 | | foreach ( trans; sorted_elms[$-1].nfa_state.transitions ) { |
|---|
| | 3501 | if (!(sorted_elms[$-1] && sorted_elms[$-1].nfa_state && |
|---|
| | 3502 | sorted_elms[$-1].nfa_state)) |
|---|
| | 3503 | throw new Exception ("Something is NULL that is expected to |
|---|
| | 3504 | be non-null", __FILE__, __LINE__); |
|---|
| | 3505 | |
|---|
| | 3506 | foreach ( trans; sorted_elms[$-1].nfa_state.transitions ) |
|---|
| | 3507 | { |
|---|
| 3502 | 3508 | if (trans.canFinish()) { |
|---|
| 3503 | 3509 | r.dfa_state.reluctant = true; |
|---|
| … | … | |
| 3935 | 3941 | goto Laccept; |
|---|
| 3936 | 3942 | |
|---|
| 3937 | | // if all input was consumed and we do not already accept, try to |
|---|
| | 3943 | // if all input was consumed and we do not already accept, try to |
|---|
| 3938 | 3944 | // add an explicit string/line end |
|---|
| 3939 | 3945 | if ( p >= inp.length ) |
|---|
| … | … | |
| 4361 | 4367 | |
|---|
| 4362 | 4368 | /********************************************************************************************* |
|---|
| 4363 | | Get the pattern with which this regex was constructed. |
|---|
| | 4369 | Get the pattern with which this regex was constructed. |
|---|
| 4364 | 4370 | **********************************************************************************************/ |
|---|
| 4365 | | public char_t[] pattern() |
|---|
| 4366 | | { |
|---|
| 4367 | | return pattern_; |
|---|
| | 4371 | public char_t[] pattern() |
|---|
| | 4372 | { |
|---|
| | 4373 | return pattern_; |
|---|
| 4368 | 4374 | } |
|---|
| 4369 | 4375 | |
|---|
| 4370 | 4376 | /********************************************************************************************* |
|---|
| 4371 | | Get the tag count of this regex, representing the number of sub-matches. |
|---|
| | 4377 | Get the tag count of this regex, representing the number of sub-matches. |
|---|
| 4372 | 4378 | |
|---|
| 4373 | 4379 | This value is the max valid value for match/opIndex. |
|---|
| r5499 |
r5652 |
|
| 126 | 126 | // reserve some space for inserts/additions |
|---|
| 127 | 127 | Text reserve (int extra); |
|---|
| 128 | | |
|---|
| | 128 | |
|---|
| 129 | 129 | // write content to stream |
|---|
| 130 | 130 | Text write (OutputStream sink); |
|---|
| … | … | |
| 214 | 214 | private import tango.stdc.string : memmove; |
|---|
| 215 | 215 | |
|---|
| | 216 | version(GNU) |
|---|
| | 217 | { |
|---|
| | 218 | private import tango.core.Vararg; |
|---|
| | 219 | } |
|---|
| | 220 | else version(DigitalMars) |
|---|
| | 221 | { |
|---|
| | 222 | private import tango.core.Vararg; |
|---|
| | 223 | version(X86_64) version=DigitalMarsX64; |
|---|
| | 224 | } |
|---|
| 216 | 225 | |
|---|
| 217 | 226 | /******************************************************************************* |
|---|
| … | … | |
| 286 | 295 | bool next () |
|---|
| 287 | 296 | { |
|---|
| 288 | | return locate (&engine.forward, text.slice, |
|---|
| | 297 | return locate (&engine.forward, text.slice, |
|---|
| 289 | 298 | text.selectPoint + text.selectLength); |
|---|
| 290 | 299 | } |
|---|
| … | … | |
| 292 | 301 | /*************************************************************** |
|---|
| 293 | 302 | |
|---|
| 294 | | Returns true if there is a match within the |
|---|
| | 303 | Returns true if there is a match within the |
|---|
| 295 | 304 | associated text |
|---|
| 296 | 305 | |
|---|
| … | … | |
| 298 | 307 | |
|---|
| 299 | 308 | bool within () |
|---|
| 300 | | { |
|---|
| | 309 | { |
|---|
| 301 | 310 | return engine.within (text.slice); |
|---|
| 302 | 311 | } |
|---|
| 303 | 312 | |
|---|
| 304 | 313 | /*************************************************************** |
|---|
| 305 | | |
|---|
| | 314 | |
|---|
| 306 | 315 | Returns number of matches within the associated |
|---|
| 307 | 316 | text |
|---|
| … | … | |
| 310 | 319 | |
|---|
| 311 | 320 | size_t count () |
|---|
| 312 | | { |
|---|
| | 321 | { |
|---|
| 313 | 322 | return engine.count (text.slice); |
|---|
| 314 | 323 | } |
|---|
| … | … | |
| 321 | 330 | |
|---|
| 322 | 331 | void replace (T chr) |
|---|
| 323 | | { |
|---|
| 324 | | replace ((&chr)[0..1]); |
|---|
| | 332 | { |
|---|
| | 333 | replace ((&chr)[0..1]); |
|---|
| 325 | 334 | } |
|---|
| 326 | 335 | |
|---|
| … | … | |
| 332 | 341 | |
|---|
| 333 | 342 | void replace (T[] sub = null) |
|---|
| 334 | | { |
|---|
| | 343 | { |
|---|
| 335 | 344 | auto dst = new T[text.length]; |
|---|
| 336 | 345 | dst.length = 0; |
|---|
| … | … | |
| 340 | 349 | text.set (dst, false); |
|---|
| 341 | 350 | } |
|---|
| 342 | | |
|---|
| | 351 | |
|---|
| 343 | 352 | /*************************************************************** |
|---|
| 344 | 353 | |
|---|
| … | … | |
| 380 | 389 | Note: A character like 'a' will be implicitly converted to |
|---|
| 381 | 390 | uint and thus will be accepted for this constructor, making |
|---|
| 382 | | it appear like you can initialize a Text instance with a |
|---|
| | 391 | it appear like you can initialize a Text instance with a |
|---|
| 383 | 392 | single character, something which is not supported. |
|---|
| 384 | 393 | |
|---|
| … | … | |
| 432 | 441 | "temporarily" with a stack-based Text. |
|---|
| 433 | 442 | |
|---|
| 434 | | Also resets the curent selection to null |
|---|
| | 443 | Also resets the curent selection to null |
|---|
| 435 | 444 | |
|---|
| 436 | 445 | ***********************************************************************/ |
|---|
| … | … | |
| 457 | 466 | "temporarily" with a stack-based Text. |
|---|
| 458 | 467 | |
|---|
| 459 | | Also resets the curent selection to null |
|---|
| | 468 | Also resets the curent selection to null |
|---|
| 460 | 469 | |
|---|
| 461 | 470 | ***********************************************************************/ |
|---|
| … | … | |
| 531 | 540 | |
|---|
| 532 | 541 | /*********************************************************************** |
|---|
| 533 | | |
|---|
| | 542 | |
|---|
| 534 | 543 | Return a search iterator for a given pattern. The iterator |
|---|
| 535 | 544 | sets the current text selection as appropriate. For example: |
|---|
| … | … | |
| 686 | 695 | uint emit (T[] s) |
|---|
| 687 | 696 | { |
|---|
| 688 | | append (s); |
|---|
| 689 | | return s.length; |
|---|
| | 697 | append (s); |
|---|
| | 698 | return s.length; |
|---|
| 690 | 699 | } |
|---|
| 691 | 700 | |
|---|
| 692 | | LayoutT.instance.convert (&emit, _arguments, _argptr, format); |
|---|
| | 701 | version (DigitalMarsX64) |
|---|
| | 702 | { |
|---|
| | 703 | va_list ap; |
|---|
| | 704 | |
|---|
| | 705 | va_start(ap, __va_argsave); |
|---|
| | 706 | |
|---|
| | 707 | scope(exit) va_end(ap); |
|---|
| | 708 | |
|---|
| | 709 | LayoutT.instance.convert (&emit, _arguments, ap, format); |
|---|
| | 710 | } |
|---|
| | 711 | else |
|---|
| | 712 | LayoutT.instance.convert (&emit, _arguments, _argptr, format); |
|---|
| | 713 | |
|---|
| 693 | 714 | return this; |
|---|
| 694 | 715 | } |
|---|
| … | … | |
| 696 | 717 | /*********************************************************************** |
|---|
| 697 | 718 | |
|---|
| 698 | | Append text to this Text |
|---|
| | 719 | Append text to this Text |
|---|
| 699 | 720 | |
|---|
| 700 | 721 | ***********************************************************************/ |
|---|
| … | … | |
| 736 | 757 | |
|---|
| 737 | 758 | ***********************************************************************/ |
|---|
| 738 | | |
|---|
| | 759 | |
|---|
| 739 | 760 | deprecated final Text append (int v, T[] fmt = null) |
|---|
| 740 | 761 | { |
|---|
| … | … | |
| 781 | 802 | { |
|---|
| 782 | 803 | T[8192/T.sizeof] tmp = void; |
|---|
| 783 | | while (true) |
|---|
| | 804 | while (true) |
|---|
| 784 | 805 | { |
|---|
| 785 | | auto len = source.read (tmp); |
|---|
| 786 | | if (len is source.Eof) |
|---|
| 787 | | break; |
|---|
| | 806 | auto len = source.read (tmp); |
|---|
| | 807 | if (len is source.Eof) |
|---|
| | 808 | break; |
|---|
| 788 | 809 | |
|---|
| 789 | 810 | // check to ensure UTF conversion is ok |
|---|
| … | … | |
| 1636 | 1657 | |
|---|
| 1637 | 1658 | debug (UnitTest) |
|---|
| 1638 | | { |
|---|
| | 1659 | { |
|---|
| 1639 | 1660 | import tango.io.device.Array; |
|---|
| 1640 | 1661 | |
|---|
| r5504 |
r5652 |
|
| 6 | 6 | |
|---|
| 7 | 7 | version: Jan 2005: initial release |
|---|
| 8 | | Mar 2009: extracted from locale, and |
|---|
| | 8 | Mar 2009: extracted from locale, and |
|---|
| 9 | 9 | converted to a struct |
|---|
| 10 | 10 | |
|---|
| … | … | |
| 12 | 12 | |
|---|
| 13 | 13 | Support for formatting date/time values, in a locale-specific |
|---|
| 14 | | manner. See DateTimeLocale.format() for a description on how |
|---|
| | 14 | manner. See DateTimeLocale.format() for a description on how |
|---|
| 15 | 15 | formatting is performed (below). |
|---|
| 16 | 16 | |
|---|
| … | … | |
| 42 | 42 | |
|---|
| 43 | 43 | O/S specifics |
|---|
| 44 | | |
|---|
| | 44 | |
|---|
| 45 | 45 | ******************************************************************************/ |
|---|
| 46 | 46 | |
|---|
| … | … | |
| 56 | 56 | |
|---|
| 57 | 57 | The default DateTimeLocale instance |
|---|
| 58 | | |
|---|
| | 58 | |
|---|
| 59 | 59 | ******************************************************************************/ |
|---|
| 60 | 60 | |
|---|
| … | … | |
| 62 | 62 | |
|---|
| 63 | 63 | static this() |
|---|
| 64 | | { |
|---|
| | 64 | { |
|---|
| 65 | 65 | DateTimeDefault = DateTimeLocale.create; |
|---|
| 66 | 66 | version (WithExtensions) |
|---|
| … | … | |
| 79 | 79 | |
|---|
| 80 | 80 | struct DateTimeLocale |
|---|
| 81 | | { |
|---|
| | 81 | { |
|---|
| 82 | 82 | static char[] rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"; |
|---|
| 83 | 83 | static char[] sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; |
|---|
| … | … | |
| 109 | 109 | /********************************************************************** |
|---|
| 110 | 110 | |
|---|
| 111 | | Format the given Time value into the provided output, |
|---|
| | 111 | Format the given Time value into the provided output, |
|---|
| 112 | 112 | using the specified layout. The layout can be a generic |
|---|
| 113 | 113 | variant or a custom one, where generics are indicated |
|---|
| 114 | 114 | via a single character: |
|---|
| 115 | | |
|---|
| | 115 | |
|---|
| 116 | 116 | <pre> |
|---|
| 117 | 117 | "t" = 7:04 |
|---|
| 118 | | "T" = 7:04:02 PM |
|---|
| | 118 | "T" = 7:04:02 PM |
|---|
| 119 | 119 | "d" = 3/30/2009 |
|---|
| 120 | 120 | "D" = Monday, March 30, 2009 |
|---|
| … | … | |
| 130 | 130 | "u" = 2009-03-30 19:04:02Z |
|---|
| 131 | 131 | </pre> |
|---|
| 132 | | |
|---|
| 133 | | For the US locale, these generic layouts are expanded in the |
|---|
| | 132 | |
|---|
| | 133 | For the US locale, these generic layouts are expanded in the |
|---|
| 134 | 134 | following manner: |
|---|
| 135 | | |
|---|
| | 135 | |
|---|
| 136 | 136 | <pre> |
|---|
| 137 | | "t" = "h:mm" |
|---|
| | 137 | "t" = "h:mm" |
|---|
| 138 | 138 | "T" = "h:mm:ss tt" |
|---|
| 139 | | "d" = "M/d/yyyy" |
|---|
| 140 | | "D" = "dddd, MMMM d, yyyy" |
|---|
| | 139 | "d" = "M/d/yyyy" |
|---|
| | 140 | "D" = "dddd, MMMM d, yyyy" |
|---|
| 141 | 141 | "f" = "dddd, MMMM d, yyyy h:mm tt" |
|---|
| 142 | 142 | "F" = "dddd, MMMM d, yyyy h:mm:ss tt" |
|---|
| … | … | |
| 144 | 144 | "G" = "M/d/yyyy h:mm:ss tt" |
|---|
| 145 | 145 | "y" |
|---|
| 146 | | "Y" = "MMMM, yyyy" |
|---|
| | 146 | "Y" = "MMMM, yyyy" |
|---|
| 147 | 147 | "r" |
|---|
| 148 | 148 | "R" = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'" |
|---|
| 149 | | "s" = "yyyy'-'MM'-'dd'T'HH':'mm':'ss" |
|---|
| 150 | | "u" = "yyyy'-'MM'-'dd' 'HH':'mm':'ss'Z'" |
|---|
| | 149 | "s" = "yyyy'-'MM'-'dd'T'HH':'mm':'ss" |
|---|
| | 150 | "u" = "yyyy'-'MM'-'dd' 'HH':'mm':'ss'Z'" |
|---|
| 151 | 151 | </pre> |
|---|
| 152 | 152 | |
|---|
| 153 | | Custom layouts are constructed using a combination of the |
|---|
| 154 | | character codes indicated on the right, above. For example, |
|---|
| 155 | | a layout of "dddd, dd MMM yyyy HH':'mm':'ss zzzz" will emit |
|---|
| | 153 | Custom layouts are constructed using a combination of the |
|---|
| | 154 | character codes indicated on the right, above. For example, |
|---|
| | 155 | a layout of "dddd, dd MMM yyyy HH':'mm':'ss zzzz" will emit |
|---|
| 156 | 156 | something like this: |
|---|
| 157 | 157 | --- |
|---|
| … | … | |
| 182 | 182 | // default to general format |
|---|
| 183 | 183 | if (layout.length is 0) |
|---|
| 184 | | layout = "G"; |
|---|
| | 184 | layout = "G"; |
|---|
| 185 | 185 | |
|---|
| 186 | 186 | // might be one of our shortcuts |
|---|
| 187 | | if (layout.length is 1) |
|---|
| | 187 | if (layout.length is 1) |
|---|
| 188 | 188 | layout = expandKnownFormat (layout); |
|---|
| 189 | | |
|---|
| | 189 | |
|---|
| 190 | 190 | auto res=Result(output); |
|---|
| 191 | 191 | return formatCustom (res, dateTime, layout); |
|---|
| … | … | |
| 235 | 235 | /********************************************************************** |
|---|
| 236 | 236 | |
|---|
| 237 | | Return a short day name |
|---|
| | 237 | Return a short day name |
|---|
| 238 | 238 | |
|---|
| 239 | 239 | **********************************************************************/ |
|---|
| … | … | |
| 254 | 254 | return dayNames [cast(int) dayOfWeek]; |
|---|
| 255 | 255 | } |
|---|
| 256 | | |
|---|
| | 256 | |
|---|
| 257 | 257 | /********************************************************************** |
|---|
| 258 | 258 | |
|---|
| … | … | |
| 289 | 289 | |
|---|
| 290 | 290 | static DateTimeLocale create () |
|---|
| 291 | | { |
|---|
| | 291 | { |
|---|
| 292 | 292 | static char[] toString (char[] dst, LCID id, LCTYPE type) |
|---|
| 293 | 293 | { |
|---|
| … | … | |
| 299 | 299 | GetLocaleInfoW (id, type, wide.ptr, wide.length); |
|---|
| 300 | 300 | len = WideCharToMultiByte (CP_UTF8, 0, wide.ptr, len-1, |
|---|
| 301 | | cast(PCHAR)dst.ptr, dst.length, |
|---|
| | 301 | cast(PCHAR)dst.ptr, dst.length, |
|---|
| 302 | 302 | null, null); |
|---|
| 303 | 303 | return dst [0..len].dup; |
|---|
| … | … | |
| 330 | 330 | dt.yearMonthPattern = toString (tmp, lcid, LOCALE_SYEARMONTH); |
|---|
| 331 | 331 | dt.longTimePattern = toString (tmp, lcid, LOCALE_STIMEFORMAT); |
|---|
| 332 | | |
|---|
| | 332 | |
|---|
| 333 | 333 | // synthesize a short time |
|---|
| 334 | 334 | auto s = dt.shortTimePattern = dt.longTimePattern; |
|---|
| … | … | |
| 340 | 340 | } |
|---|
| 341 | 341 | |
|---|
| 342 | | dt.fullDateTimePattern = dt.longDatePattern ~ " " ~ |
|---|
| | 342 | dt.fullDateTimePattern = dt.longDatePattern ~ " " ~ |
|---|
| 343 | 343 | dt.longTimePattern; |
|---|
| 344 | | dt.generalLongTimePattern = dt.shortDatePattern ~ " " ~ |
|---|
| | 344 | dt.generalLongTimePattern = dt.shortDatePattern ~ " " ~ |
|---|
| 345 | 345 | dt.longTimePattern; |
|---|
| 346 | | dt.generalShortTimePattern = dt.shortDatePattern ~ " " ~ |
|---|
| | 346 | dt.generalShortTimePattern = dt.shortDatePattern ~ " " ~ |
|---|
| 347 | 347 | dt.shortTimePattern; |
|---|
| 348 | 348 | return dt; |
|---|
| … | … | |
| 415 | 415 | |
|---|
| 416 | 416 | //extract shortTimePattern from longTimePattern |
|---|
| 417 | | for (auto i = dt.longTimePattern.length; i--;) |
|---|
| | 417 | for (auto i = dt.longTimePattern.length; i--;) |
|---|
| 418 | 418 | { |
|---|
| 419 | 419 | if (dt.longTimePattern[i] == dt.timeSeparator[$-1]) |
|---|
| … | … | |
| 473 | 473 | switch (c) |
|---|
| 474 | 474 | { |
|---|
| 475 | | case 'a': //locale's abbreviated weekday name. |
|---|
| | 475 | case 'a': //locale's abbreviated weekday name. |
|---|
| 476 | 476 | put("ddd"); //The abbreviated name of the day of the week, |
|---|
| 477 | 477 | break; |
|---|
| … | … | |
| 494 | 494 | break; |
|---|
| 495 | 495 | |
|---|
| 496 | | case 'D': //same as %m/%d/%y. |
|---|
| | 496 | case 'D': //same as %m/%d/%y. |
|---|
| 497 | 497 | put("MM/dd/yy"); |
|---|
| 498 | 498 | break; |
|---|
| … | … | |
| 504 | 504 | break; |
|---|
| 505 | 505 | |
|---|
| 506 | | case 'h': //same as %b. |
|---|
| | 506 | case 'h': //same as %b. |
|---|
| 507 | 507 | put("MMM"); |
|---|
| 508 | 508 | break; |
|---|
| … | … | |
| 567 | 567 | //If the week containing 1 January has four or more days |
|---|
| 568 | 568 | //in the new year, then it is considered week 1. |
|---|
| 569 | | //Otherwise, it is the last week of the previous year, and the next week is week 1. |
|---|
| | 569 | //Otherwise, it is the last week of the previous year, and the next week is week 1. |
|---|
| 570 | 570 | case 'w': //weekday as a decimal number [0,6], with 0 representing Sunday |
|---|
| 571 | 571 | case 'W': //week number of the year (Monday as the first day of the week) |
|---|
| 572 | 572 | //as a decimal number [00,53]. |
|---|
| 573 | 573 | //All days in a new year preceding the first Monday |
|---|
| 574 | | //are considered to be in week 0. |
|---|
| | 574 | //are considered to be in week 0. |
|---|
| 575 | 575 | case 'x': //locale's appropriate date representation |
|---|
| 576 | 576 | case 'X': //locale's appropriate time representation |
|---|
| … | … | |
| 671 | 671 | doy, |
|---|
| 672 | 672 | dow, |
|---|
| 673 | | era; |
|---|
| | 673 | era; |
|---|
| 674 | 674 | uint day, |
|---|
| 675 | 675 | year, |
|---|
| … | … | |
| 686 | 686 | { |
|---|
| 687 | 687 | char c = format[index]; |
|---|
| 688 | | |
|---|
| | 688 | |
|---|
| 689 | 689 | switch (c) |
|---|
| 690 | 690 | { |
|---|
| 691 | 691 | // day |
|---|
| 692 | | case 'd': |
|---|
| | 692 | case 'd': |
|---|
| 693 | 693 | len = parseRepeat (format, index, c); |
|---|
| 694 | 694 | if (len <= 2) |
|---|
| … | … | |
| 705 | 705 | { |
|---|
| 706 | 706 | result ~= num; |
|---|
| 707 | | |
|---|
| | 707 | |
|---|
| 708 | 708 | // append '0's |
|---|
| 709 | 709 | static char[8] zeros = '0'; |
|---|
| … | … | |
| 730 | 730 | |
|---|
| 731 | 731 | // month |
|---|
| 732 | | case 'M': |
|---|
| | 732 | case 'M': |
|---|
| 733 | 733 | len = parseRepeat (format, index, c); |
|---|
| 734 | 734 | if (len <= 2) |
|---|
| … | … | |
| 739 | 739 | |
|---|
| 740 | 740 | // year |
|---|
| 741 | | case 'y': |
|---|
| | 741 | case 'y': |
|---|
| 742 | 742 | len = parseRepeat (format, index, c); |
|---|
| 743 | 743 | |
|---|
| … | … | |
| 755 | 755 | |
|---|
| 756 | 756 | // hour (12-hour clock) |
|---|
| 757 | | case 'h': |
|---|
| | 757 | case 'h': |
|---|
| 758 | 758 | len = parseRepeat (format, index, c); |
|---|
| 759 | 759 | int hour = time.hours % 12; |
|---|
| … | … | |
| 764 | 764 | |
|---|
| 765 | 765 | // hour (24-hour clock) |
|---|
| 766 | | case 'H': |
|---|
| | 766 | case 'H': |
|---|
| 767 | 767 | len = parseRepeat (format, index, c); |
|---|
| 768 | 768 | result ~= formatInt (tmp, time.hours, len); |
|---|
| … | … | |
| 770 | 770 | |
|---|
| 771 | 771 | // minute |
|---|
| 772 | | case 'm': |
|---|
| | 772 | case 'm': |
|---|
| 773 | 773 | len = parseRepeat (format, index, c); |
|---|
| 774 | 774 | result ~= formatInt (tmp, time.minutes, len); |
|---|
| … | … | |
| 776 | 776 | |
|---|
| 777 | 777 | // second |
|---|
| 778 | | case 's': |
|---|
| | 778 | case 's': |
|---|
| 779 | 779 | len = parseRepeat (format, index, c); |
|---|
| 780 | 780 | result ~= formatInt (tmp, time.seconds, len); |
|---|
| … | … | |
| 782 | 782 | |
|---|
| 783 | 783 | // AM/PM |
|---|
| 784 | | case 't': |
|---|
| | 784 | case 't': |
|---|
| 785 | 785 | len = parseRepeat (format, index, c); |
|---|
| 786 | 786 | if (len is 1) |
|---|
| … | … | |
| 802 | 802 | |
|---|
| 803 | 803 | // timezone offset |
|---|
| 804 | | case 'z': |
|---|
| | 804 | case 'z': |
|---|
| 805 | 805 | len = parseRepeat (format, index, c); |
|---|
| 806 | 806 | auto minutes = cast(int) (WallClock.zone.minutes); |
|---|
| … | … | |
| 828 | 828 | |
|---|
| 829 | 829 | // time separator |
|---|
| 830 | | case ':': |
|---|
| | 830 | case ':': |
|---|
| 831 | 831 | len = 1; |
|---|
| 832 | 832 | result ~= timeSeparator; |
|---|
| … | … | |
| 834 | 834 | |
|---|
| 835 | 835 | // date separator |
|---|
| 836 | | case '/': |
|---|
| | 836 | case '/': |
|---|
| 837 | 837 | len = 1; |
|---|
| 838 | 838 | result ~= dateSeparator; |
|---|
| … | … | |
| 840 | 840 | |
|---|
| 841 | 841 | // string literal |
|---|
| 842 | | case '\"': |
|---|
| 843 | | case '\'': |
|---|
| | 842 | case '\"': |
|---|
| | 843 | case '\'': |
|---|
| 844 | 844 | len = parseQuote (result, format, index); |
|---|
| 845 | 845 | break; |
|---|
| … | … | |
| 947 | 947 | |
|---|
| 948 | 948 | /****************************************************************************** |
|---|
| 949 | | |
|---|
| | 949 | |
|---|
| 950 | 950 | An english/usa locale |
|---|
| 951 | 951 | Used as generic DateTimeLocale. |
|---|
| … | … | |
| 953 | 953 | ******************************************************************************/ |
|---|
| 954 | 954 | |
|---|
| 955 | | private DateTimeLocale EngUS = |
|---|
| | 955 | private DateTimeLocale EngUS = |
|---|
| 956 | 956 | { |
|---|
| 957 | 957 | shortDatePattern : "M/d/yyyy", |
|---|
| 958 | | shortTimePattern : "h:mm", |
|---|
| | 958 | shortTimePattern : "h:mm", |
|---|
| 959 | 959 | longDatePattern : "dddd, MMMM d, yyyy", |
|---|
| 960 | | longTimePattern : "h:mm:ss tt", |
|---|
| | 960 | longTimePattern : "h:mm:ss tt", |
|---|
| 961 | 961 | fullDateTimePattern : "dddd, MMMM d, yyyy h:mm:ss tt", |
|---|
| 962 | 962 | generalShortTimePattern : "M/d/yyyy h:mm", |
|---|
| … | … | |
| 968 | 968 | timeSeparator : ":", |
|---|
| 969 | 969 | dateSeparator : "/", |
|---|
| 970 | | dayNames : ["Sunday", "Monday", "Tuesday", "Wednesday", |
|---|
| | 970 | dayNames : ["Sunday", "Monday", "Tuesday", "Wednesday", |
|---|
| 971 | 971 | "Thursday", "Friday", "Saturday"], |
|---|
| 972 | | monthNames : ["January", "February", "March", "April", |
|---|
| 973 | | "May", "June", "July", "August", "September", |
|---|
| | 972 | monthNames : ["January", "February", "March", "April", |
|---|
| | 973 | "May", "June", "July", "August", "September", |
|---|
| 974 | 974 | "October" "November", "December"], |
|---|
| 975 | | abbreviatedDayNames : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], |
|---|
| 976 | | abbreviatedMonthNames : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", |
|---|
| | 975 | abbreviatedDayNames : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], |
|---|
| | 976 | abbreviatedMonthNames : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", |
|---|
| 977 | 977 | "Jul", "Aug", "Sep", "Oct" "Nov", "Dec"], |
|---|
| 978 | 978 | }; |
|---|
| r5618 |
r5652 |
|
| 46 | 46 | private import tango.time.Time; |
|---|
| 47 | 47 | private import tango.text.convert.DateTime; |
|---|
| 48 | | } |
|---|
| | 48 | } |
|---|
| 49 | 49 | |
|---|
| 50 | 50 | |
|---|
| … | … | |
| 66 | 66 | alias void* Arg; |
|---|
| 67 | 67 | alias va_list ArgList; |
|---|
| | 68 | } |
|---|
| | 69 | else version(DigitalMars) |
|---|
| | 70 | { |
|---|
| | 71 | private import tango.core.Vararg; |
|---|
| | 72 | alias void* Arg; |
|---|
| | 73 | alias va_list ArgList; |
|---|
| | 74 | |
|---|
| | 75 | version(X86_64) version = DigitalMarsX64; |
|---|
| 68 | 76 | } |
|---|
| 69 | 77 | else |
|---|
| … | … | |
| 84 | 92 | public alias convert opCall; |
|---|
| 85 | 93 | public alias uint delegate (T[]) Sink; |
|---|
| 86 | | |
|---|
| | 94 | |
|---|
| 87 | 95 | static if (is (DateTimeLocale)) |
|---|
| 88 | 96 | private DateTimeLocale* dateTime = &DateTimeDefault; |
|---|
| … | … | |
| 91 | 99 | |
|---|
| 92 | 100 | Return shared instance |
|---|
| 93 | | |
|---|
| | 101 | |
|---|
| 94 | 102 | Note that this is not threadsafe, and that static-ctor |
|---|
| 95 | 103 | usage doesn't get invoked appropriately (compiler bug) |
|---|
| … | … | |
| 112 | 120 | public final T[] sprint (T[] result, T[] formatStr, ...) |
|---|
| 113 | 121 | { |
|---|
| 114 | | return vprint (result, formatStr, _arguments, _argptr); |
|---|
| | 122 | version (DigitalMarsX64) |
|---|
| | 123 | { |
|---|
| | 124 | va_list ap; |
|---|
| | 125 | |
|---|
| | 126 | va_start(ap, __va_argsave); |
|---|
| | 127 | |
|---|
| | 128 | scope(exit) va_end(ap); |
|---|
| | 129 | |
|---|
| | 130 | return vprint (result, formatStr, _arguments, ap); |
|---|
| | 131 | } |
|---|
| | 132 | else |
|---|
| | 133 | return vprint (result, formatStr, _arguments, _argptr); |
|---|
| 115 | 134 | } |
|---|
| 116 | 135 | |
|---|
| … | … | |
| 176 | 195 | public final T[] convert (T[] formatStr, ...) |
|---|
| 177 | 196 | { |
|---|
| 178 | | return convert (_arguments, _argptr, formatStr); |
|---|
| | 197 | version (DigitalMarsX64) |
|---|
| | 198 | { |
|---|
| | 199 | va_list ap; |
|---|
| | 200 | |
|---|
| | 201 | va_start(ap, __va_argsave); |
|---|
| | 202 | |
|---|
| | 203 | scope(exit) va_end(ap); |
|---|
| | 204 | |
|---|
| | 205 | return convert (_arguments, ap, formatStr); |
|---|
| | 206 | } |
|---|
| | 207 | else |
|---|
| | 208 | return convert (_arguments, _argptr, formatStr); |
|---|
| 179 | 209 | } |
|---|
| 180 | 210 | |
|---|
| … | … | |
| 185 | 215 | public final uint convert (Sink sink, T[] formatStr, ...) |
|---|
| 186 | 216 | { |
|---|
| 187 | | return convert (sink, _arguments, _argptr, formatStr); |
|---|
| | 217 | version (DigitalMarsX64) |
|---|
| | 218 | { |
|---|
| | 219 | va_list ap; |
|---|
| | 220 | |
|---|
| | 221 | va_start(ap, __va_argsave); |
|---|
| | 222 | |
|---|
| | 223 | scope(exit) va_end(ap); |
|---|
| | 224 | |
|---|
| | 225 | return convert (sink, _arguments, ap, formatStr); |
|---|
| | 226 | } |
|---|
| | 227 | else |
|---|
| | 228 | return convert (sink, _arguments, _argptr, formatStr); |
|---|
| 188 | 229 | } |
|---|
| 189 | 230 | |
|---|
| … | … | |
| 204 | 245 | } |
|---|
| 205 | 246 | |
|---|
| 206 | | return convert (&sink, _arguments, _argptr, formatStr); |
|---|
| | 247 | |
|---|
| | 248 | version (DigitalMarsX64) |
|---|
| | 249 | { |
|---|
| | 250 | va_list ap; |
|---|
| | 251 | |
|---|
| | 252 | va_start(ap, __va_argsave); |
|---|
| | 253 | |
|---|
| | 254 | scope(exit) va_end(ap); |
|---|
| | 255 | |
|---|
| | 256 | return convert (&sink, _arguments, ap, formatStr); |
|---|
| | 257 | } |
|---|
| | 258 | else |
|---|
| | 259 | return convert (&sink, _arguments, _argptr, formatStr); |
|---|
| 207 | 260 | } |
|---|
| 208 | 261 | |
|---|
| … | … | |
| 225 | 278 | } |
|---|
| 226 | 279 | |
|---|
| 227 | | version (old) |
|---|
| 228 | | { |
|---|
| 229 | | /********************************************************************** |
|---|
| 230 | | |
|---|
| 231 | | **********************************************************************/ |
|---|
| 232 | | |
|---|
| 233 | | public final T[] convertOne (T[] result, TypeInfo ti, Arg arg) |
|---|
| | 280 | /********************************************************************** |
|---|
| | 281 | |
|---|
| | 282 | **********************************************************************/ |
|---|
| | 283 | |
|---|
| | 284 | version (old) public final T[] convertOne (T[] result, TypeInfo ti, Arg arg) |
|---|
| 234 | 285 | { |
|---|
| 235 | 286 | return dispatch (result, null, ti, arg); |
|---|
| 236 | 287 | } |
|---|
| 237 | | } |
|---|
| | 288 | |
|---|
| 238 | 289 | /********************************************************************** |
|---|
| 239 | 290 | |
|---|
| … | … | |
| 253 | 304 | Arg[64] arglist = void; |
|---|
| 254 | 305 | ArgU[64] storedArgs = void; |
|---|
| 255 | | |
|---|
| | 306 | |
|---|
| 256 | 307 | foreach (i, arg; arguments) |
|---|
| 257 | 308 | { |
|---|
| … | … | |
| 272 | 323 | converted = true; |
|---|
| 273 | 324 | break; |
|---|
| 274 | | |
|---|
| | 325 | |
|---|
| 275 | 326 | case TypeCode.CFLOAT: |
|---|
| 276 | 327 | storedArgs[i].cf = va_arg!(cfloat)(args); |
|---|
| … | … | |
| 278 | 329 | converted = true; |
|---|
| 279 | 330 | break; |
|---|
| 280 | | |
|---|
| | 331 | |
|---|
| 281 | 332 | case TypeCode.DOUBLE, TypeCode.IDOUBLE: |
|---|
| 282 | 333 | storedArgs[i].d = va_arg!(double)(args); |
|---|
| … | … | |
| 284 | 335 | converted = true; |
|---|
| 285 | 336 | break; |
|---|
| 286 | | |
|---|
| | 337 | |
|---|
| 287 | 338 | case TypeCode.CDOUBLE: |
|---|
| 288 | 339 | storedArgs[i].cd = va_arg!(cdouble)(args); |
|---|
| … | … | |
| 290 | 341 | converted = true; |
|---|
| 291 | 342 | break; |
|---|
| 292 | | |
|---|
| | 343 | |
|---|
| 293 | 344 | case TypeCode.REAL, TypeCode.IREAL: |
|---|
| 294 | 345 | storedArgs[i].r = va_arg!(real)(args); |
|---|
| … | … | |
| 302 | 353 | converted = true; |
|---|
| 303 | 354 | break; |
|---|
| 304 | | |
|---|
| | 355 | |
|---|
| 305 | 356 | default: |
|---|
| 306 | 357 | break; |
|---|
| … | … | |
| 337 | 388 | } |
|---|
| 338 | 389 | } |
|---|
| 339 | | else |
|---|
| | 390 | else version(DigitalMarsX64) |
|---|
| | 391 | { |
|---|
| | 392 | Arg[64] arglist = void; |
|---|
| | 393 | void[] buffer; |
|---|
| | 394 | uint len = 0; |
|---|
| | 395 | |
|---|
| | 396 | foreach(i, argType; arguments) |
|---|
| | 397 | len += (argType.tsize + size_t.sizeof - 1) & ~ (size_t.sizeof - 1); |
|---|
| | 398 | |
|---|
| | 399 | buffer.length = len; |
|---|
| | 400 | len = 0; |
|---|
| | 401 | foreach(i, argType; arguments) |
|---|
| 340 | 402 | { |
|---|
| | 403 | //printf("type: %s\n", argType.classinfo.name.ptr); |
|---|
| | 404 | |
|---|
| | 405 | va_arg(args, argType, buffer.ptr+len); |
|---|
| | 406 | |
|---|
| | 407 | if(argType.classinfo.name.length != 25 && argType.classinfo.name[9] == TypeCode.ARRAY && |
|---|
| | 408 | (argType.classinfo.name[10] == TypeCode.USHORT || |
|---|
| | 409 | argType.classinfo.name[10] == TypeCode.SHORT)) |
|---|
| | 410 | { |
|---|
| | 411 | printf("Warning: (u)short[] is broken for varargs in x86_64"); |
|---|
| | 412 | // simply disable the array for now |
|---|
| | 413 | (cast(short[]*) (buffer.ptr+len)).length = 0; |
|---|
| | 414 | } |
|---|
| | 415 | |
|---|
| | 416 | arglist[i] = &buffer[len]; |
|---|
| | 417 | |
|---|
| | 418 | len+= (argType.tsize + size_t.sizeof - 1) & ~ (size_t.sizeof - 1); |
|---|
| | 419 | } |
|---|
| | 420 | |
|---|
| | 421 | scope (exit) delete buffer; |
|---|
| | 422 | } |
|---|
| | 423 | else |
|---|
| | 424 | { |
|---|
| 341 | 425 | Arg[64] arglist = void; |
|---|
| 342 | 426 | foreach (i, arg; arguments) |
|---|
| … | … | |
| 345 | 429 | args += (arg.tsize + size_t.sizeof - 1) & ~ (size_t.sizeof - 1); |
|---|
| 346 | 430 | } |
|---|
| 347 | | } |
|---|
| | 431 | } |
|---|
| 348 | 432 | return parse (formatStr, arguments, arglist, sink); |
|---|
| 349 | 433 | } |
|---|
| … | … | |
| 525 | 609 | length += sink ("]"); |
|---|
| 526 | 610 | } |
|---|
| 527 | | else |
|---|
| | 611 | else |
|---|
| 528 | 612 | if (_ti.classinfo.name.length is 25 && _ti.classinfo.name[9..$] == "AssociativeArray") |
|---|
| 529 | 613 | { |
|---|
| … | … | |
| 531 | 615 | auto tiKey = tiAsso.key; |
|---|
| 532 | 616 | auto tiVal = tiAsso.next(); |
|---|
| | 617 | |
|---|
| 533 | 618 | // the knowledge of the internal k/v storage is used |
|---|
| 534 | 619 | // so this might break if, that internal storage changes |
|---|
| … | … | |
| 539 | 624 | length += sink ("{"); |
|---|
| 540 | 625 | bool first = true; |
|---|
| 541 | | |
|---|
| 542 | | size_t roundUp (size_t sz) |
|---|
| | 626 | |
|---|
| | 627 | size_t roundUp (size_t tsize) |
|---|
| 543 | 628 | { |
|---|
| 544 | | return (sz + (void*).sizeof -1) & ~((void*).sizeof - 1); |
|---|
| | 629 | //return (sz + (void*).sizeof -1) & ~((void*).sizeof - 1); |
|---|
| | 630 | |
|---|
| | 631 | version (X86_64) |
|---|
| | 632 | // Size of key needed to align value on 16 bytes |
|---|
| | 633 | return (tsize + 15) & ~(15); |
|---|
| | 634 | else |
|---|
| | 635 | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| 545 | 636 | } |
|---|
| 546 | 637 | |
|---|
| … | … | |
| 561 | 652 | length += sink ("}"); |
|---|
| 562 | 653 | } |
|---|
| 563 | | else |
|---|
| | 654 | else |
|---|
| 564 | 655 | if (_ti.classinfo.name[9] is TypeCode.ARRAY) |
|---|
| 565 | 656 | { |
|---|
| … | … | |
| 567 | 658 | emit (Utf.fromString8 (*cast(char[]*) _arg, result)); |
|---|
| 568 | 659 | else |
|---|
| 569 | | if (_ti is typeid(wchar[])) |
|---|
| | 660 | if (_ti is typeid(wchar[])) |
|---|
| 570 | 661 | emit (Utf.fromString16 (*cast(wchar[]*) _arg, result)); |
|---|
| 571 | 662 | else |
|---|
| … | … | |
| 597 | 688 | } |
|---|
| 598 | 689 | |
|---|
| 599 | | |
|---|
| | 690 | |
|---|
| 600 | 691 | // process this argument |
|---|
| 601 | 692 | if (index >= ti.length) |
|---|
| … | … | |
| 692 | 783 | case TypeCode.STRUCT: |
|---|
| 693 | 784 | auto s = cast(TypeInfo_Struct) type; |
|---|
| 694 | | if (s.xtoString) |
|---|
| | 785 | if (s.xtoString) |
|---|
| 695 | 786 | { |
|---|
| 696 | 787 | char[] delegate() toString; |
|---|
| … | … | |
| 735 | 826 | { |
|---|
| 736 | 827 | result = Extensions!(T).run (type, result, p, format); |
|---|
| 737 | | return (result) ? result : |
|---|
| | 828 | return (result) ? result : |
|---|
| 738 | 829 | "{unhandled argument type: " ~ Utf.fromString8 (type.toString, result) ~ "}"; |
|---|
| 739 | 830 | } |
|---|
| … | … | |
| 809 | 900 | break; |
|---|
| 810 | 901 | } |
|---|
| 811 | | |
|---|
| | 902 | |
|---|
| 812 | 903 | return Float.format (output, v, dec, exp, pad); |
|---|
| 813 | 904 | } |
|---|
| … | … | |
| 849 | 940 | return floatingTail (result, val.im, format, "*1i"); |
|---|
| 850 | 941 | } |
|---|
| 851 | | |
|---|
| | 942 | |
|---|
| 852 | 943 | /********************************************************************** |
|---|
| 853 | 944 | |
|---|
| … | … | |
| 860 | 951 | static bool signed (real x) |
|---|
| 861 | 952 | { |
|---|
| 862 | | static if (real.sizeof is 4) |
|---|
| | 953 | static if (real.sizeof is 4) |
|---|
| 863 | 954 | return ((*cast(uint *)&x) & 0x8000_0000) != 0; |
|---|
| 864 | 955 | else |
|---|
| 865 | | static if (real.sizeof is 8) |
|---|
| | 956 | static if (real.sizeof is 8) |
|---|
| 866 | 957 | return ((*cast(ulong *)&x) & 0x8000_0000_0000_0000) != 0; |
|---|
| 867 | 958 | else |
|---|
| … | … | |
| 936 | 1027 | IFLOAT = 'o', |
|---|
| 937 | 1028 | IDOUBLE = 'p', |
|---|
| 938 | | IREAL = 'j' |
|---|
| | 1029 | IREAL = 'j' |
|---|
| 939 | 1030 | } |
|---|
| 940 | 1031 | |
|---|
| … | … | |
| 944 | 1035 | |
|---|
| 945 | 1036 | *******************************************************************************/ |
|---|
| 946 | | |
|---|
| | 1037 | import tango.stdc.stdio : printf; |
|---|
| 947 | 1038 | debug (UnitTest) |
|---|
| 948 | 1039 | { |
|---|
| … | … | |
| 1087 | 1178 | assert( Formatter( "{:f.}", 1.000 ) == "1" ); |
|---|
| 1088 | 1179 | assert( Formatter( "{:f2.}", 200.001 ) == "200"); |
|---|
| 1089 | | |
|---|
| | 1180 | |
|---|
| 1090 | 1181 | // array output |
|---|
| 1091 | 1182 | int[] a = [ 51, 52, 53, 54, 55 ]; |
|---|
| … | … | |
| 1097 | 1188 | assert( Formatter( "{}", b ) == "[[51, 52], [53, 54, 55]]" ); |
|---|
| 1098 | 1189 | |
|---|
| 1099 | | ushort[3] c = [ cast(ushort)51, 52, 53 ]; |
|---|
| 1100 | | assert( Formatter( "{}", c ) == "[51, 52, 53]" ); |
|---|
| 1101 | | |
|---|
| 1102 | | // integer AA |
|---|
| | 1190 | char[1024] static_buffer; |
|---|
| | 1191 | static_buffer[0..10] = "1234567890"; |
|---|
| | 1192 | |
|---|
| | 1193 | assert (Formatter( "{}", static_buffer[0..10]) == "1234567890"); |
|---|
| | 1194 | |
|---|
| | 1195 | version(X86) |
|---|
| | 1196 | { |
|---|
| | 1197 | ushort[3] c = [ cast(ushort)51, 52, 53 ]; |
|---|
| | 1198 | assert( Formatter( "{}", c ) == "[51, 52, 53]" ); |
|---|
| | 1199 | } |
|---|
| | 1200 | |
|---|
| | 1201 | // integer AA |
|---|
| 1103 | 1202 | ushort[long] d; |
|---|
| 1104 | 1203 | d[234] = 2; |
|---|
| 1105 | 1204 | d[345] = 3; |
|---|
| | 1205 | |
|---|
| 1106 | 1206 | assert( Formatter( "{}", d ) == "{234 => 2, 345 => 3}" || |
|---|
| 1107 | 1207 | Formatter( "{}", d ) == "{345 => 3, 234 => 2}"); |
|---|
| 1108 | | |
|---|
| 1109 | | // bool/string AA |
|---|
| | 1208 | |
|---|
| | 1209 | // bool/string AA |
|---|
| 1110 | 1210 | bool[char[]] e; |
|---|
| 1111 | 1211 | e[ "key".dup ] = true; |
|---|
| … | … | |
| 1114 | 1214 | Formatter( "{}", e ) == "{value => false, key => true}"); |
|---|
| 1115 | 1215 | |
|---|
| 1116 | | // string/double AA |
|---|
| | 1216 | // string/double AA |
|---|
| 1117 | 1217 | char[][ double ] f; |
|---|
| 1118 | 1218 | f[ 1.0 ] = "one".dup; |
|---|
| … | … | |
| 1159 | 1259 | struct S |
|---|
| 1160 | 1260 | { |
|---|
| 1161 | | char[] toString () {return "foo";} |
|---|
| | 1261 | char[] toString () {return "foo";} |
|---|
| 1162 | 1262 | } |
|---|
| 1163 | 1263 | |
|---|
| r5446 |
r5652 |
|
| 4 | 4 | |
|---|
| 5 | 5 | license: BSD style: $(LICENSE) |
|---|
| 6 | | |
|---|
| | 6 | |
|---|
| 7 | 7 | version: May 2004 : Initial release |
|---|
| 8 | 8 | version: Oct 2004: Hierarchy moved due to circular dependencies |
|---|
| … | … | |
| 21 | 21 | Generic usage: |
|---|
| 22 | 22 | |
|---|
| 23 | | Loggers are named entities, sometimes shared, sometimes specific to |
|---|
| 24 | | a particular portion of code. The names are generally hierarchical in |
|---|
| 25 | | nature, using dot notation (with '.') to separate each named section. |
|---|
| | 23 | Loggers are named entities, sometimes shared, sometimes specific to |
|---|
| | 24 | a particular portion of code. The names are generally hierarchical in |
|---|
| | 25 | nature, using dot notation (with '.') to separate each named section. |
|---|
| 26 | 26 | For example, a typical name might be something like "mail.send.writer" |
|---|
| 27 | 27 | --- |
|---|
| 28 | 28 | import tango.util.log.Log; |
|---|
| 29 | | |
|---|
| | 29 | |
|---|
| 30 | 30 | auto log = Log.lookup ("mail.send.writer"); |
|---|
| 31 | 31 | |
|---|
| … | … | |
| 35 | 35 | etc ... |
|---|
| 36 | 36 | --- |
|---|
| 37 | | |
|---|
| 38 | | It is considered good form to pass a logger instance as a function or |
|---|
| 39 | | class-ctor argument, or to assign a new logger instance during static |
|---|
| 40 | | class construction. For example: if it were considered appropriate to |
|---|
| | 37 | |
|---|
| | 38 | It is considered good form to pass a logger instance as a function or |
|---|
| | 39 | class-ctor argument, or to assign a new logger instance during static |
|---|
| | 40 | class construction. For example: if it were considered appropriate to |
|---|
| 41 | 41 | have one logger instance per class, each might be constructed like so: |
|---|
| 42 | 42 | --- |
|---|
| 43 | 43 | private Logger log; |
|---|
| 44 | | |
|---|
| | 44 | |
|---|
| 45 | 45 | static this() |
|---|
| 46 | 46 | { |
|---|
| … | … | |
| 64 | 64 | --- |
|---|
| 65 | 65 | |
|---|
| 66 | | To avoid overhead when constructing arguments passed to formatted |
|---|
| | 66 | To avoid overhead when constructing arguments passed to formatted |
|---|
| 67 | 67 | messages, you should check to see whether a logger is active or not: |
|---|
| 68 | 68 | --- |
|---|
| … | … | |
| 70 | 70 | log.warn ("temperature is {} degrees!", complexFunction()); |
|---|
| 71 | 71 | --- |
|---|
| 72 | | |
|---|
| 73 | | tango.log closely follows both the API and the behaviour as documented |
|---|
| 74 | | at the official Log4J site, where you'll find a good tutorial. Those |
|---|
| 75 | | pages are hosted over |
|---|
| | 72 | |
|---|
| | 73 | tango.log closely follows both the API and the behaviour as documented |
|---|
| | 74 | at the official Log4J site, where you'll find a good tutorial. Those |
|---|
| | 75 | pages are hosted over |
|---|
| 76 | 76 | <A HREF="http://logging.apache.org/log4j/docs/documentation.html">here</A>. |
|---|
| 77 | 77 | |
|---|
| … | … | |
| 103 | 103 | alias void* Arg; |
|---|
| 104 | 104 | alias va_list ArgList; |
|---|
| | 105 | } |
|---|
| | 106 | else version (DigitalMars) |
|---|
| | 107 | { |
|---|
| | 108 | private import tango.core.Vararg; |
|---|
| | 109 | alias void* Arg; |
|---|
| | 110 | alias va_list ArgList; |
|---|
| | 111 | |
|---|
| | 112 | version(X86_64) version = DigitalMarsX64; |
|---|
| | 113 | |
|---|
| 105 | 114 | } |
|---|
| 106 | 115 | else |
|---|
| … | … | |
| 128 | 137 | |
|---|
| 129 | 138 | /******************************************************************************* |
|---|
| 130 | | |
|---|
| | 139 | |
|---|
| 131 | 140 | These represent the standard LOG4J event levels. Note that |
|---|
| 132 | 141 | Debug is called Trace here, because debug is a reserved word |
|---|
| 133 | | in D |
|---|
| | 142 | in D |
|---|
| 134 | 143 | |
|---|
| 135 | 144 | *******************************************************************************/ |
|---|
| 136 | 145 | |
|---|
| 137 | | alias ILogger.Level Level; |
|---|
| | 146 | alias ILogger.Level Level; |
|---|
| 138 | 147 | |
|---|
| 139 | 148 | |
|---|
| 140 | 149 | /******************************************************************************* |
|---|
| 141 | 150 | |
|---|
| 142 | | Manager for routing Logger calls to the default hierarchy. Note |
|---|
| | 151 | Manager for routing Logger calls to the default hierarchy. Note |
|---|
| 143 | 152 | that you may have multiple hierarchies per application, but must |
|---|
| 144 | | access the hierarchy directly for root() and lookup() methods within |
|---|
| | 153 | access the hierarchy directly for root() and lookup() methods within |
|---|
| 145 | 154 | each additional instance. |
|---|
| 146 | 155 | |
|---|
| … | … | |
| 168 | 177 | |
|---|
| 169 | 178 | private static Level [char[]] map; |
|---|
| 170 | | |
|---|
| 171 | | private static Pair[] Pairs = |
|---|
| | 179 | |
|---|
| | 180 | private static Pair[] Pairs = |
|---|
| 172 | 181 | [ |
|---|
| 173 | 182 | {"TRACE", Level.Trace}, |
|---|
| … | … | |
| 192 | 201 | |
|---|
| 193 | 202 | // logging-level names |
|---|
| 194 | | private static char[][] LevelNames = |
|---|
| | 203 | private static char[][] LevelNames = |
|---|
| 195 | 204 | [ |
|---|
| 196 | 205 | "Trace", "Info", "Warn", "Error", "Fatal", "None" |
|---|
| … | … | |
| 198 | 207 | |
|---|
| 199 | 208 | /*********************************************************************** |
|---|
| 200 | | |
|---|
| 201 | | Initialize the base hierarchy |
|---|
| 202 | | |
|---|
| | 209 | |
|---|
| | 210 | Initialize the base hierarchy |
|---|
| | 211 | |
|---|
| 203 | 212 | ***********************************************************************/ |
|---|
| 204 | 213 | |
|---|
| … | … | |
| 210 | 219 | map[p.name] = p.value; |
|---|
| 211 | 220 | |
|---|
| 212 | | version (Posix) |
|---|
| | 221 | version (Posix) |
|---|
| 213 | 222 | { |
|---|
| 214 | 223 | beginTime = Clock.now; |
|---|
| … | … | |
| 221 | 230 | if (! QueryPerformanceFrequency (&freq)) |
|---|
| 222 | 231 | throw new PlatformException ("high-resolution timer is not available"); |
|---|
| 223 | | |
|---|
| | 232 | |
|---|
| 224 | 233 | QueryPerformanceCounter (&timerStart); |
|---|
| 225 | | multiplier = cast(double) TimeSpan.TicksPerSecond / freq; |
|---|
| | 234 | multiplier = cast(double) TimeSpan.TicksPerSecond / freq; |
|---|
| 226 | 235 | beginTime = Clock.now; |
|---|
| 227 | 236 | } |
|---|
| … | … | |
| 229 | 238 | |
|---|
| 230 | 239 | /*********************************************************************** |
|---|
| 231 | | |
|---|
| | 240 | |
|---|
| 232 | 241 | Return the level of a given name |
|---|
| 233 | 242 | |
|---|
| … | … | |
| 243 | 252 | |
|---|
| 244 | 253 | /*********************************************************************** |
|---|
| 245 | | |
|---|
| | 254 | |
|---|
| 246 | 255 | Return the current time |
|---|
| 247 | 256 | |
|---|
| … | … | |
| 250 | 259 | static Time time () |
|---|
| 251 | 260 | { |
|---|
| 252 | | version (Posix) |
|---|
| | 261 | version (Posix) |
|---|
| 253 | 262 | { |
|---|
| 254 | 263 | return Clock.now; |
|---|
| … | … | |
| 267 | 276 | |
|---|
| 268 | 277 | Return the root Logger instance. This is the ancestor of |
|---|
| 269 | | all loggers and, as such, can be used to manipulate the |
|---|
| 270 | | entire hierarchy. For instance, setting the root 'level' |
|---|
| | 278 | all loggers and, as such, can be used to manipulate the |
|---|
| | 279 | entire hierarchy. For instance, setting the root 'level' |
|---|
| 271 | 280 | attribute will affect all other loggers in the tree. |
|---|
| 272 | 281 | |
|---|
| … | … | |
| 279 | 288 | |
|---|
| 280 | 289 | /*********************************************************************** |
|---|
| 281 | | |
|---|
| | 290 | |
|---|
| 282 | 291 | Return an instance of the named logger. Names should be |
|---|
| 283 | | hierarchical in nature, using dot notation (with '.') to |
|---|
| 284 | | separate each name section. For example, a typical name |
|---|
| | 292 | hierarchical in nature, using dot notation (with '.') to |
|---|
| | 293 | separate each name section. For example, a typical name |
|---|
| 285 | 294 | might be something like "tango.io.Stdout". |
|---|
| 286 | 295 | |
|---|
| … | … | |
| 298 | 307 | |
|---|
| 299 | 308 | /*********************************************************************** |
|---|
| 300 | | |
|---|
| | 309 | |
|---|
| 301 | 310 | Return text name for a log level |
|---|
| 302 | 311 | |
|---|
| … | … | |
| 310 | 319 | |
|---|
| 311 | 320 | /*********************************************************************** |
|---|
| 312 | | |
|---|
| | 321 | |
|---|
| 313 | 322 | Return the singleton hierarchy. |
|---|
| 314 | 323 | |
|---|
| … | … | |
| 321 | 330 | |
|---|
| 322 | 331 | /*********************************************************************** |
|---|
| 323 | | |
|---|
| | 332 | |
|---|
| 324 | 333 | Pedestrian usage support, as an alias for Log.root.info() |
|---|
| 325 | 334 | |
|---|
| … | … | |
| 328 | 337 | static void formatln (char[] fmt, ...) |
|---|
| 329 | 338 | { |
|---|
| | 339 | version (DigitalMarsX64) |
|---|
| | 340 | { |
|---|
| | 341 | va_list ap; |
|---|
| | 342 | |
|---|
| | 343 | version(GNU) {} else va_start(ap, __va_argsave); |
|---|
| | 344 | |
|---|
| | 345 | scope(exit) va_end(ap); |
|---|
| | 346 | |
|---|
| | 347 | root.format (Level.Info, fmt, _arguments, ap); |
|---|
| | 348 | } |
|---|
| | 349 | else |
|---|
| 330 | 350 | root.format (Level.Info, fmt, _arguments, _argptr); |
|---|
| 331 | 351 | } |
|---|
| … | … | |
| 337 | 357 | Adds a StreamAppender to the root node, and sets |
|---|
| 338 | 358 | the activity level to be everything enabled. |
|---|
| 339 | | |
|---|
| | 359 | |
|---|
| 340 | 360 | ***********************************************************************/ |
|---|
| 341 | 361 | |
|---|
| … | … | |
| 349 | 369 | /******************************************************************************* |
|---|
| 350 | 370 | |
|---|
| 351 | | Loggers are named entities, sometimes shared, sometimes specific to |
|---|
| 352 | | a particular portion of code. The names are generally hierarchical in |
|---|
| 353 | | nature, using dot notation (with '.') to separate each named section. |
|---|
| | 371 | Loggers are named entities, sometimes shared, sometimes specific to |
|---|
| | 372 | a particular portion of code. The names are generally hierarchical in |
|---|
| | 373 | nature, using dot notation (with '.') to separate each named section. |
|---|
| 354 | 374 | For example, a typical name might be something like "mail.send.writer" |
|---|
| 355 | 375 | --- |
|---|
| 356 | 376 | import tango.util.log.Log;format |
|---|
| 357 | | |
|---|
| | 377 | |
|---|
| 358 | 378 | auto log = Log.lookup ("mail.send.writer"); |
|---|
| 359 | 379 | |
|---|
| … | … | |
| 363 | 383 | etc ... |
|---|
| 364 | 384 | --- |
|---|
| 365 | | |
|---|
| 366 | | It is considered good form to pass a logger instance as a function or |
|---|
| 367 | | class-ctor argument, or to assign a new logger instance during static |
|---|
| 368 | | class construction. For example: if it were considered appropriate to |
|---|
| | 385 | |
|---|
| | 386 | It is considered good form to pass a logger instance as a function or |
|---|
| | 387 | class-ctor argument, or to assign a new logger instance during static |
|---|
| | 388 | class construction. For example: if it were considered appropriate to |
|---|
| 369 | 389 | have one logger instance per class, each might be constructed like so: |
|---|
| 370 | 390 | --- |
|---|
| 371 | 391 | private Logger log; |
|---|
| 372 | | |
|---|
| | 392 | |
|---|
| 373 | 393 | static this() |
|---|
| 374 | 394 | { |
|---|
| … | … | |
| 392 | 412 | --- |
|---|
| 393 | 413 | |
|---|
| 394 | | To avoid overhead when constructing argument passed to formatted |
|---|
| | 414 | To avoid overhead when constructing argument passed to formatted |
|---|
| 395 | 415 | messages, you should check to see whether a logger is active or not: |
|---|
| 396 | 416 | --- |
|---|
| … | … | |
| 398 | 418 | log.warn ("temperature is {} degrees!", complexFunction()); |
|---|
| 399 | 419 | --- |
|---|
| 400 | | |
|---|
| 401 | | The above will be handled implicitly by the logging system when |
|---|
| 402 | | macros are added to the language (used to be handled implicitly |
|---|
| | 420 | |
|---|
| | 421 | The above will be handled implicitly by the logging system when |
|---|
| | 422 | macros are added to the language (used to be handled implicitly |
|---|
| 403 | 423 | via lazy delegates, but usage of those turned out to be awkward). |
|---|
| 404 | 424 | |
|---|
| 405 | | tango.log closely follows both the API and the behaviour as documented |
|---|
| 406 | | at the official Log4J site, where you'll find a good tutorial. Those |
|---|
| 407 | | pages are hosted over |
|---|
| | 425 | tango.log closely follows both the API and the behaviour as documented |
|---|
| | 426 | at the official Log4J site, where you'll find a good tutorial. Those |
|---|
| | 427 | pages are hosted over |
|---|
| 408 | 428 | <A HREF="http://logging.apache.org/log4j/docs/documentation.html">here</A>. |
|---|
| 409 | 429 | |
|---|
| … | … | |
| 411 | 431 | |
|---|
| 412 | 432 | public class Logger : ILogger |
|---|
| 413 | | { |
|---|
| 414 | | |
|---|
| 415 | | alias Level.Trace Trace; // shortcut to Level values |
|---|
| | 433 | { |
|---|
| | 434 | |
|---|
| | 435 | alias Level.Trace Trace; // shortcut to Level values |
|---|
| 416 | 436 | alias Level.Info Info; // ... |
|---|
| 417 | 437 | alias Level.Warn Warn; // ... |
|---|
| … | … | |
| 422 | 442 | |
|---|
| 423 | 443 | /*********************************************************************** |
|---|
| 424 | | |
|---|
| | 444 | |
|---|
| 425 | 445 | Context for a hierarchy, used for customizing behaviour |
|---|
| 426 | 446 | of log hierarchies. You can use this to implement dynamic |
|---|
| … | … | |
| 433 | 453 | /// return a label for this context |
|---|
| 434 | 454 | char[] label (); |
|---|
| 435 | | |
|---|
| | 455 | |
|---|
| 436 | 456 | /// first arg is the setting of the logger itself, and |
|---|
| 437 | 457 | /// the second arg is what kind of message we're being |
|---|
| … | … | |
| 441 | 461 | |
|---|
| 442 | 462 | /*********************************************************************** |
|---|
| 443 | | |
|---|
| | 463 | |
|---|
| 444 | 464 | ***********************************************************************/ |
|---|
| 445 | 465 | |
|---|
| … | … | |
| 454 | 474 | |
|---|
| 455 | 475 | /*********************************************************************** |
|---|
| 456 | | |
|---|
| 457 | | Construct a LoggerInstance with the specified name for the |
|---|
| | 476 | |
|---|
| | 477 | Construct a LoggerInstance with the specified name for the |
|---|
| 458 | 478 | given hierarchy. By default, logger instances are additive |
|---|
| 459 | 479 | and are set to emit all events. |
|---|
| … | … | |
| 470 | 490 | |
|---|
| 471 | 491 | /*********************************************************************** |
|---|
| 472 | | |
|---|
| | 492 | |
|---|
| 473 | 493 | Is this logger enabed for the specified Level? |
|---|
| 474 | 494 | |
|---|
| … | … | |
| 499 | 519 | final void trace (char[] fmt, ...) |
|---|
| 500 | 520 | { |
|---|
| | 521 | version (DigitalMarsX64) |
|---|
| | 522 | { |
|---|
| | 523 | va_list ap; |
|---|
| | 524 | |
|---|
| | 525 | va_start(ap, __va_argsave); |
|---|
| | 526 | |
|---|
| | 527 | scope(exit) va_end(ap); |
|---|
| | 528 | |
|---|
| | 529 | format (Level.Trace, fmt, _arguments, ap); |
|---|
| | 530 | } |
|---|
| | 531 | else |
|---|
| 501 | 532 | format (Level.Trace, fmt, _arguments, _argptr); |
|---|
| 502 | 533 | } |
|---|
| … | … | |
| 521 | 552 | final void info (char[] fmt, ...) |
|---|
| 522 | 553 | { |
|---|
| | 554 | version (DigitalMarsX64) |
|---|
| | 555 | { |
|---|
| | 556 | va_list ap; |
|---|
| | 557 | |
|---|
| | 558 | va_start(ap, __va_argsave); |
|---|
| | 559 | |
|---|
| | 560 | scope(exit) va_end(ap); |
|---|
| | 561 | |
|---|
| | 562 | format (Level.Info, fmt, _arguments, ap); |
|---|
| | 563 | } |
|---|
| | 564 | else |
|---|
| 523 | 565 | format (Level.Info, fmt, _arguments, _argptr); |
|---|
| 524 | 566 | } |
|---|
| … | … | |
| 543 | 585 | final void warn (char[] fmt, ...) |
|---|
| 544 | 586 | { |
|---|
| | 587 | version (DigitalMarsX64) |
|---|
| | 588 | { |
|---|
| | 589 | va_list ap; |
|---|
| | 590 | |
|---|
| | 591 | va_start(ap, __va_argsave); |
|---|
| | 592 | |
|---|
| | 593 | scope(exit) va_end(ap); |
|---|
| | 594 | |
|---|
| | 595 | format (Level.Warn, fmt, _arguments, ap); |
|---|
| | 596 | } |
|---|
| | 597 | else |
|---|
| 545 | 598 | format (Level.Warn, fmt, _arguments, _argptr); |
|---|
| 546 | 599 | } |
|---|
| … | … | |
| 565 | 618 | final void error (char[] fmt, ...) |
|---|
| 566 | 619 | { |
|---|
| | 620 | version (DigitalMarsX64) |
|---|
| | 621 | { |
|---|
| | 622 | va_list ap; |
|---|
| | 623 | |
|---|
| | 624 | va_start(ap, __va_argsave); |
|---|
| | 625 | |
|---|
| | 626 | scope(exit) va_end(ap); |
|---|
| | 627 | |
|---|
| | 628 | format (Level.Error, fmt, _arguments, ap); |
|---|
| | 629 | } |
|---|
| | 630 | else |
|---|
| 567 | 631 | format (Level.Error, fmt, _arguments, _argptr); |
|---|
| 568 | 632 | } |
|---|
| … | … | |
| 587 | 651 | final void fatal (char[] fmt, ...) |
|---|
| 588 | 652 | { |
|---|
| | 653 | version (DigitalMarsX64) |
|---|
| | 654 | { |
|---|
| | 655 | va_list ap; |
|---|
| | 656 | |
|---|
| | 657 | va_start(ap, __va_argsave); |
|---|
| | 658 | |
|---|
| | 659 | scope(exit) va_end(ap); |
|---|
| | 660 | |
|---|
| | 661 | format (Level.Fatal, fmt, _arguments, ap); |
|---|
| | 662 | } |
|---|
| | 663 | else |
|---|
| 589 | 664 | format (Level.Fatal, fmt, _arguments, _argptr); |
|---|
| 590 | 665 | } |
|---|
| … | … | |
| 593 | 668 | |
|---|
| 594 | 669 | Return the name of this Logger (sans the appended dot). |
|---|
| 595 | | |
|---|
| | 670 | |
|---|
| 596 | 671 | ***********************************************************************/ |
|---|
| 597 | 672 | |
|---|
| … | … | |
| 601 | 676 | if (i > 0) |
|---|
| 602 | 677 | --i; |
|---|
| 603 | | return name_[0 .. i]; |
|---|
| 604 | | } |
|---|
| 605 | | |
|---|
| 606 | | /*********************************************************************** |
|---|
| 607 | | |
|---|
| | 678 | return name_[0 .. i]; |
|---|
| | 679 | } |
|---|
| | 680 | |
|---|
| | 681 | /*********************************************************************** |
|---|
| | 682 | |
|---|
| 608 | 683 | Return the Level this logger is set to |
|---|
| 609 | 684 | |
|---|
| … | … | |
| 612 | 687 | final Level level () |
|---|
| 613 | 688 | { |
|---|
| 614 | | return level_; |
|---|
| 615 | | } |
|---|
| 616 | | |
|---|
| 617 | | /*********************************************************************** |
|---|
| 618 | | |
|---|
| | 689 | return level_; |
|---|
| | 690 | } |
|---|
| | 691 | |
|---|
| | 692 | /*********************************************************************** |
|---|
| | 693 | |
|---|
| 619 | 694 | Set the current level for this logger (and only this logger). |
|---|
| 620 | 695 | |
|---|
| … | … | |
| 627 | 702 | |
|---|
| 628 | 703 | /*********************************************************************** |
|---|
| 629 | | |
|---|
| | 704 | |
|---|
| 630 | 705 | Set the current level for this logger, and (optionally) all |
|---|
| 631 | 706 | of its descendents. |
|---|
| … | … | |
| 635 | 710 | final Logger level (Level level, bool propagate) |
|---|
| 636 | 711 | { |
|---|
| 637 | | level_ = level; |
|---|
| 638 | | if (propagate) |
|---|
| | 712 | level_ = level; |
|---|
| | 713 | if (propagate) |
|---|
| 639 | 714 | foreach (log; host_) |
|---|
| 640 | 715 | if (log.isChildOf (name_)) |
|---|
| … | … | |
| 644 | 719 | |
|---|
| 645 | 720 | /*********************************************************************** |
|---|
| 646 | | |
|---|
| | 721 | |
|---|
| 647 | 722 | Is this logger additive? That is, should we walk ancestors |
|---|
| 648 | 723 | looking for more appenders? |
|---|
| … | … | |
| 656 | 731 | |
|---|
| 657 | 732 | /*********************************************************************** |
|---|
| 658 | | |
|---|
| | 733 | |
|---|
| 659 | 734 | Set the additive status of this logger. See bool additive(). |
|---|
| 660 | 735 | |
|---|
| … | … | |
| 663 | 738 | final Logger additive (bool enabled) |
|---|
| 664 | 739 | { |
|---|
| 665 | | additive_ = enabled; |
|---|
| | 740 | additive_ = enabled; |
|---|
| 666 | 741 | return this; |
|---|
| 667 | 742 | } |
|---|
| 668 | 743 | |
|---|
| 669 | 744 | /*********************************************************************** |
|---|
| 670 | | |
|---|
| | 745 | |
|---|
| 671 | 746 | Add (another) appender to this logger. Appenders are each |
|---|
| 672 | 747 | invoked for log events as they are produced. At most, one |
|---|
| … | … | |
| 684 | 759 | |
|---|
| 685 | 760 | /*********************************************************************** |
|---|
| 686 | | |
|---|
| | 761 | |
|---|
| 687 | 762 | Remove all appenders from this Logger |
|---|
| 688 | 763 | |
|---|
| … | … | |
| 691 | 766 | final Logger clear () |
|---|
| 692 | 767 | { |
|---|
| 693 | | appender_ = null; |
|---|
| | 768 | appender_ = null; |
|---|
| 694 | 769 | return this; |
|---|
| 695 | 770 | } |
|---|
| 696 | 771 | |
|---|
| 697 | 772 | /*********************************************************************** |
|---|
| 698 | | |
|---|
| | 773 | |
|---|
| 699 | 774 | Get time since this application started |
|---|
| 700 | 775 | |
|---|
| … | … | |
| 707 | 782 | |
|---|
| 708 | 783 | /*********************************************************************** |
|---|
| 709 | | |
|---|
| | 784 | |
|---|
| 710 | 785 | Send a message to this logger via its appender list. |
|---|
| 711 | 786 | |
|---|
| … | … | |
| 726 | 801 | |
|---|
| 727 | 802 | /*********************************************************************** |
|---|
| 728 | | |
|---|
| | 803 | |
|---|
| 729 | 804 | Send a message to this logger via its appender list. |
|---|
| 730 | 805 | |
|---|
| … | … | |
| 735 | 810 | // combine appenders from all ancestors |
|---|
| 736 | 811 | auto links = this; |
|---|
| 737 | | Appender.Mask masks = 0; |
|---|
| | 812 | Appender.Mask masks = 0; |
|---|
| 738 | 813 | do { |
|---|
| 739 | 814 | auto appender = links.appender_; |
|---|
| … | … | |
| 741 | 816 | // this level have an appender? |
|---|
| 742 | 817 | while (appender) |
|---|
| 743 | | { |
|---|
| | 818 | { |
|---|
| 744 | 819 | auto mask = appender.mask; |
|---|
| 745 | 820 | |
|---|
| … | … | |
| 768 | 843 | final char[] format (char[] buffer, char[] formatStr, ...) |
|---|
| 769 | 844 | { |
|---|
| | 845 | version (DigitalMarsX64) |
|---|
| | 846 | { |
|---|
| | 847 | va_list ap; |
|---|
| | 848 | |
|---|
| | 849 | va_start(ap, __va_argsave); |
|---|
| | 850 | |
|---|
| | 851 | scope(exit) va_end(ap); |
|---|
| | 852 | |
|---|
| | 853 | return Format.vprint (buffer, formatStr, _arguments, ap); |
|---|
| | 854 | } |
|---|
| | 855 | else |
|---|
| 770 | 856 | return Format.vprint (buffer, formatStr, _arguments, _argptr); |
|---|
| | 857 | |
|---|
| 771 | 858 | } |
|---|
| 772 | 859 | |
|---|
| … | … | |
| 778 | 865 | |
|---|
| 779 | 866 | final Logger format (Level level, char[] fmt, TypeInfo[] types, ArgList args) |
|---|
| 780 | | { |
|---|
| | 867 | { |
|---|
| 781 | 868 | char[2048] tmp = void; |
|---|
| 782 | | |
|---|
| | 869 | |
|---|
| 783 | 870 | if (types.length) |
|---|
| 784 | 871 | append (level, Format.vprint (tmp, fmt, types, args)); |
|---|
| 785 | 872 | else |
|---|
| 786 | | append (level, fmt); |
|---|
| | 873 | append (level, fmt); |
|---|
| 787 | 874 | return this; |
|---|
| 788 | 875 | } |
|---|
| 789 | 876 | |
|---|
| 790 | 877 | /*********************************************************************** |
|---|
| 791 | | |
|---|
| 792 | | See if the provided Logger name is a parent of this one. Note |
|---|
| 793 | | that each Logger name has a '.' appended to the end, such that |
|---|
| | 878 | |
|---|
| | 879 | See if the provided Logger name is a parent of this one. Note |
|---|
| | 880 | that each Logger name has a '.' appended to the end, such that |
|---|
| 794 | 881 | name segments will not partially match. |
|---|
| 795 | 882 | |
|---|
| … | … | |
| 802 | 889 | // possible parent if length is shorter |
|---|
| 803 | 890 | if (len < name_.length) |
|---|
| 804 | | // does the prefix match? Note we append a "." to each |
|---|
| | 891 | // does the prefix match? Note we append a "." to each |
|---|
| 805 | 892 | // (the root is a parent of everything) |
|---|
| 806 | | return (len is 0 || |
|---|
| | 893 | return (len is 0 || |
|---|
| 807 | 894 | memcmp (&candidate[0], &name_[0], len) is 0); |
|---|
| 808 | 895 | return false; |
|---|
| … | … | |
| 810 | 897 | |
|---|
| 811 | 898 | /*********************************************************************** |
|---|
| 812 | | |
|---|
| | 899 | |
|---|
| 813 | 900 | See if the provided Logger is a better match as a parent of |
|---|
| 814 | 901 | this one. This is used to restructure the hierarchy when a |
|---|
| … | … | |
| 829 | 916 | |
|---|
| 830 | 917 | /******************************************************************************* |
|---|
| 831 | | |
|---|
| | 918 | |
|---|
| 832 | 919 | The Logger hierarchy implementation. We keep a reference to each |
|---|
| 833 | 920 | logger in a hash-table for convenient lookup purposes, plus keep |
|---|
| 834 | 921 | each logger linked to the others in an ordered group. Ordering |
|---|
| 835 | | places shortest names at the head and longest ones at the tail, |
|---|
| | 922 | places shortest names at the head and longest ones at the tail, |
|---|
| 836 | 923 | making the job of identifying ancestors easier in an orderly |
|---|
| 837 | 924 | fashion. For example, when propagating levels across descendents |
|---|
| … | … | |
| 845 | 932 | private Logger root_; |
|---|
| 846 | 933 | private char[] name_, |
|---|
| 847 | | address_; |
|---|
| | 934 | address_; |
|---|
| 848 | 935 | private Logger.Context context_; |
|---|
| 849 | 936 | private Logger[char[]] loggers; |
|---|
| … | … | |
| 851 | 938 | |
|---|
| 852 | 939 | /*********************************************************************** |
|---|
| 853 | | |
|---|
| | 940 | |
|---|
| 854 | 941 | Construct a hierarchy with the given name. |
|---|
| 855 | 942 | |
|---|
| … | … | |
| 874 | 961 | return ""; |
|---|
| 875 | 962 | } |
|---|
| 876 | | |
|---|
| | 963 | |
|---|
| 877 | 964 | /********************************************************************** |
|---|
| 878 | 965 | |
|---|
| … | … | |
| 933 | 1020 | /********************************************************************** |
|---|
| 934 | 1021 | |
|---|
| 935 | | Return the diagnostic context. Useful for setting an |
|---|
| | 1022 | Return the diagnostic context. Useful for setting an |
|---|
| 936 | 1023 | override logging level. |
|---|
| 937 | 1024 | |
|---|
| 938 | 1025 | **********************************************************************/ |
|---|
| 939 | | |
|---|
| | 1026 | |
|---|
| 940 | 1027 | final Logger.Context context () |
|---|
| 941 | 1028 | { |
|---|
| 942 | 1029 | return context_; |
|---|
| 943 | 1030 | } |
|---|
| 944 | | |
|---|
| | 1031 | |
|---|
| 945 | 1032 | /********************************************************************** |
|---|
| 946 | 1033 | |
|---|
| 947 | | Set the diagnostic context. Not usually necessary, as a |
|---|
| 948 | | default was created. Useful when you need to provide a |
|---|
| | 1034 | Set the diagnostic context. Not usually necessary, as a |
|---|
| | 1035 | default was created. Useful when you need to provide a |
|---|
| 949 | 1036 | different implementation, such as a ThreadLocal variant. |
|---|
| 950 | 1037 | |
|---|
| 951 | 1038 | **********************************************************************/ |
|---|
| 952 | | |
|---|
| | 1039 | |
|---|
| 953 | 1040 | final void context (Logger.Context context) |
|---|
| 954 | 1041 | { |
|---|
| 955 | 1042 | context_ = context; |
|---|
| 956 | 1043 | } |
|---|
| 957 | | |
|---|
| 958 | | /*********************************************************************** |
|---|
| 959 | | |
|---|
| | 1044 | |
|---|
| | 1045 | /*********************************************************************** |
|---|
| | 1046 | |
|---|
| 960 | 1047 | Return the root node. |
|---|
| 961 | 1048 | |
|---|
| … | … | |
| 968 | 1055 | |
|---|
| 969 | 1056 | /*********************************************************************** |
|---|
| 970 | | |
|---|
| | 1057 | |
|---|
| 971 | 1058 | Return the instance of a Logger with the provided label. If |
|---|
| 972 | 1059 | the instance does not exist, it is created at this time. |
|---|
| … | … | |
| 1002 | 1089 | |
|---|
| 1003 | 1090 | /*********************************************************************** |
|---|
| 1004 | | |
|---|
| | 1091 | |
|---|
| 1005 | 1092 | Return the instance of a Logger with the provided label. If |
|---|
| 1006 | 1093 | the instance does not exist, it is created at this time. |
|---|
| … | … | |
| 1022 | 1109 | insert (li); |
|---|
| 1023 | 1110 | |
|---|
| 1024 | | // look for and adjust children. Don't force |
|---|
| | 1111 | // look for and adjust children. Don't force |
|---|
| 1025 | 1112 | // property inheritance on existing loggers |
|---|
| 1026 | 1113 | update (li); |
|---|
| … | … | |
| 1029 | 1116 | loggers [name] = li; |
|---|
| 1030 | 1117 | } |
|---|
| 1031 | | |
|---|
| | 1118 | |
|---|
| 1032 | 1119 | return *l; |
|---|
| 1033 | 1120 | } |
|---|
| 1034 | 1121 | |
|---|
| 1035 | 1122 | /*********************************************************************** |
|---|
| 1036 | | |
|---|
| 1037 | | Loggers are maintained in a sorted linked-list. The order |
|---|
| 1038 | | is maintained such that the shortest name is at the root, |
|---|
| | 1123 | |
|---|
| | 1124 | Loggers are maintained in a sorted linked-list. The order |
|---|
| | 1125 | is maintained such that the shortest name is at the root, |
|---|
| 1039 | 1126 | and the longest at the tail. |
|---|
| 1040 | 1127 | |
|---|
| … | … | |
| 1055 | 1142 | if (prev is null) |
|---|
| 1056 | 1143 | throw new IllegalElementException ("invalid hierarchy"); |
|---|
| 1057 | | else |
|---|
| | 1144 | else |
|---|
| 1058 | 1145 | { |
|---|
| 1059 | 1146 | l.next = prev.next; |
|---|
| … | … | |
| 1067 | 1154 | |
|---|
| 1068 | 1155 | // remember where insertion point should be |
|---|
| 1069 | | prev = curr; |
|---|
| 1070 | | curr = curr.next; |
|---|
| | 1156 | prev = curr; |
|---|
| | 1157 | curr = curr.next; |
|---|
| 1071 | 1158 | } |
|---|
| 1072 | 1159 | |
|---|
| … | … | |
| 1076 | 1163 | |
|---|
| 1077 | 1164 | /*********************************************************************** |
|---|
| 1078 | | |
|---|
| 1079 | | Propagate hierarchical changes across known loggers. |
|---|
| | 1165 | |
|---|
| | 1166 | Propagate hierarchical changes across known loggers. |
|---|
| 1080 | 1167 | This includes changes in the hierarchy itself, and to |
|---|
| 1081 | | the various settings of child loggers with respect to |
|---|
| 1082 | | their parent(s). |
|---|
| | 1168 | the various settings of child loggers with respect to |
|---|
| | 1169 | their parent(s). |
|---|
| 1083 | 1170 | |
|---|
| 1084 | 1171 | ***********************************************************************/ |
|---|
| … | … | |
| 1091 | 1178 | |
|---|
| 1092 | 1179 | /*********************************************************************** |
|---|
| 1093 | | |
|---|
| | 1180 | |
|---|
| 1094 | 1181 | Propagate changes in the hierarchy downward to child Loggers. |
|---|
| 1095 | | Note that while 'parent' is always changed, the adjustment of |
|---|
| | 1182 | Note that while 'parent' is always changed, the adjustment of |
|---|
| 1096 | 1183 | 'level' is selectable. |
|---|
| 1097 | 1184 | |
|---|
| … | … | |
| 1137 | 1224 | |
|---|
| 1138 | 1225 | /*********************************************************************** |
|---|
| 1139 | | |
|---|
| | 1226 | |
|---|
| 1140 | 1227 | Set the various attributes of this event. |
|---|
| 1141 | 1228 | |
|---|
| … | … | |
| 1152 | 1239 | |
|---|
| 1153 | 1240 | /*********************************************************************** |
|---|
| 1154 | | |
|---|
| | 1241 | |
|---|
| 1155 | 1242 | Return the message attached to this event. |
|---|
| 1156 | 1243 | |
|---|
| … | … | |
| 1163 | 1250 | |
|---|
| 1164 | 1251 | /*********************************************************************** |
|---|
| 1165 | | |
|---|
| | 1252 | |
|---|
| 1166 | 1253 | Return the name of the logger which produced this event |
|---|
| 1167 | 1254 | |
|---|
| … | … | |
| 1174 | 1261 | |
|---|
| 1175 | 1262 | /*********************************************************************** |
|---|
| 1176 | | |
|---|
| | 1263 | |
|---|
| 1177 | 1264 | Return the logger level of this event. |
|---|
| 1178 | 1265 | |
|---|
| … | … | |
| 1185 | 1272 | |
|---|
| 1186 | 1273 | /*********************************************************************** |
|---|
| 1187 | | |
|---|
| | 1274 | |
|---|
| 1188 | 1275 | Return the hierarchy where the event was produced from |
|---|
| 1189 | 1276 | |
|---|
| … | … | |
| 1196 | 1283 | |
|---|
| 1197 | 1284 | /*********************************************************************** |
|---|
| 1198 | | |
|---|
| 1199 | | Return the time this event was produced, relative to the |
|---|
| | 1285 | |
|---|
| | 1286 | Return the time this event was produced, relative to the |
|---|
| 1200 | 1287 | start of this executable |
|---|
| 1201 | 1288 | |
|---|
| … | … | |
| 1208 | 1295 | |
|---|
| 1209 | 1296 | /*********************************************************************** |
|---|
| 1210 | | |
|---|
| | 1297 | |
|---|
| 1211 | 1298 | Return the time this event was produced relative to Epoch |
|---|
| 1212 | 1299 | |
|---|
| … | … | |
| 1219 | 1306 | |
|---|
| 1220 | 1307 | /*********************************************************************** |
|---|
| 1221 | | |
|---|
| | 1308 | |
|---|
| 1222 | 1309 | Return time when the executable started |
|---|
| 1223 | 1310 | |
|---|
| … | … | |
| 1230 | 1317 | |
|---|
| 1231 | 1318 | /*********************************************************************** |
|---|
| 1232 | | |
|---|
| | 1319 | |
|---|
| 1233 | 1320 | Return the logger level name of this event. |
|---|
| 1234 | 1321 | |
|---|
| … | … | |
| 1241 | 1328 | |
|---|
| 1242 | 1329 | /*********************************************************************** |
|---|
| 1243 | | |
|---|
| | 1330 | |
|---|
| 1244 | 1331 | Convert a time value (in milliseconds) to ascii |
|---|
| 1245 | 1332 | |
|---|
| … | … | |
| 1256 | 1343 | ms /= 10; |
|---|
| 1257 | 1344 | } while (ms && len); |
|---|
| 1258 | | return s[len..s.length]; |
|---|
| | 1345 | return s[len..s.length]; |
|---|
| 1259 | 1346 | } |
|---|
| 1260 | 1347 | } |
|---|
| … | … | |
| 1267 | 1354 | than one appender attached to any logger. The actual message is |
|---|
| 1268 | 1355 | constructed by another class known as an EventLayout. |
|---|
| 1269 | | |
|---|
| | 1356 | |
|---|
| 1270 | 1357 | *******************************************************************************/ |
|---|
| 1271 | 1358 | |
|---|
| … | … | |
| 1283 | 1370 | Interface for all logging layout instances |
|---|
| 1284 | 1371 | |
|---|
| 1285 | | Implement this method to perform the formatting of |
|---|
| | 1372 | Implement this method to perform the formatting of |
|---|
| 1286 | 1373 | message content. |
|---|
| 1287 | 1374 | |
|---|
| … | … | |
| 1294 | 1381 | |
|---|
| 1295 | 1382 | /*********************************************************************** |
|---|
| 1296 | | |
|---|
| | 1383 | |
|---|
| 1297 | 1384 | Return the mask used to identify this Appender. The mask |
|---|
| 1298 | | is used to figure out whether an appender has already been |
|---|
| | 1385 | is used to figure out whether an appender has already been |
|---|
| 1299 | 1386 | invoked for a particular logger. |
|---|
| 1300 | 1387 | |
|---|
| … | … | |
| 1304 | 1391 | |
|---|
| 1305 | 1392 | /*********************************************************************** |
|---|
| 1306 | | |
|---|
| | 1393 | |
|---|
| 1307 | 1394 | Return the name of this Appender. |
|---|
| 1308 | 1395 | |
|---|
| … | … | |
| 1310 | 1397 | |
|---|
| 1311 | 1398 | abstract char[] name (); |
|---|
| 1312 | | |
|---|
| 1313 | | /*********************************************************************** |
|---|
| 1314 | | |
|---|
| | 1399 | |
|---|
| | 1400 | /*********************************************************************** |
|---|
| | 1401 | |
|---|
| 1315 | 1402 | Append a message to the output. |
|---|
| 1316 | 1403 | |
|---|
| … | … | |
| 1320 | 1407 | |
|---|
| 1321 | 1408 | /*********************************************************************** |
|---|
| 1322 | | |
|---|
| 1323 | | Create an Appender and default its layout to LayoutSimple. |
|---|
| | 1409 | |
|---|
| | 1410 | Create an Appender and default its layout to LayoutSimple. |
|---|
| 1324 | 1411 | |
|---|
| 1325 | 1412 | ***********************************************************************/ |
|---|
| … | … | |
| 1331 | 1418 | |
|---|
| 1332 | 1419 | /*********************************************************************** |
|---|
| 1333 | | |
|---|
| 1334 | | Create an Appender and default its layout to LayoutSimple. |
|---|
| | 1420 | |
|---|
| | 1421 | Create an Appender and default its layout to LayoutSimple. |
|---|
| 1335 | 1422 | |
|---|
| 1336 | 1423 | ***********************************************************************/ |
|---|
| … | … | |
| 1342 | 1429 | |
|---|
| 1343 | 1430 | /*********************************************************************** |
|---|
| 1344 | | |
|---|
| | 1431 | |
|---|
| 1345 | 1432 | Return the current Level setting |
|---|
| 1346 | 1433 | |
|---|
| … | … | |
| 1353 | 1440 | |
|---|
| 1354 | 1441 | /*********************************************************************** |
|---|
| 1355 | | |
|---|
| | 1442 | |
|---|
| 1356 | 1443 | Return the current Level setting |
|---|
| 1357 | 1444 | |
|---|
| … | … | |
| 1365 | 1452 | |
|---|
| 1366 | 1453 | /*********************************************************************** |
|---|
| 1367 | | |
|---|
| | 1454 | |
|---|
| 1368 | 1455 | Static method to return a mask for identifying the Appender. |
|---|
| 1369 | 1456 | Each Appender class should have a unique fingerprint so that |
|---|
| … | … | |
| 1395 | 1482 | |
|---|
| 1396 | 1483 | /*********************************************************************** |
|---|
| 1397 | | |
|---|
| | 1484 | |
|---|
| 1398 | 1485 | Set the current layout to be that of the argument, or the |
|---|
| 1399 | 1486 | generic layout where the argument is null |
|---|
| … | … | |
| 1407 | 1494 | |
|---|
| 1408 | 1495 | /*********************************************************************** |
|---|
| 1409 | | |
|---|
| | 1496 | |
|---|
| 1410 | 1497 | Return the current Layout |
|---|
| 1411 | 1498 | |
|---|
| … | … | |
| 1418 | 1505 | |
|---|
| 1419 | 1506 | /*********************************************************************** |
|---|
| 1420 | | |
|---|
| | 1507 | |
|---|
| 1421 | 1508 | Attach another appender to this one |
|---|
| 1422 | 1509 | |
|---|
| … | … | |
| 1429 | 1516 | |
|---|
| 1430 | 1517 | /*********************************************************************** |
|---|
| 1431 | | |
|---|
| | 1518 | |
|---|
| 1432 | 1519 | Return the next appender in the list |
|---|
| 1433 | 1520 | |
|---|
| … | … | |
| 1440 | 1527 | |
|---|
| 1441 | 1528 | /*********************************************************************** |
|---|
| 1442 | | |
|---|
| 1443 | | Close this appender. This would be used for file, sockets, |
|---|
| | 1529 | |
|---|
| | 1530 | Close this appender. This would be used for file, sockets, |
|---|
| 1444 | 1531 | and such like. |
|---|
| 1445 | 1532 | |
|---|
| … | … | |
| 1464 | 1551 | |
|---|
| 1465 | 1552 | /*********************************************************************** |
|---|
| 1466 | | |
|---|
| | 1553 | |
|---|
| 1467 | 1554 | Create with the given Layout |
|---|
| 1468 | 1555 | |
|---|
| … | … | |
| 1476 | 1563 | |
|---|
| 1477 | 1564 | /*********************************************************************** |
|---|
| 1478 | | |
|---|
| | 1565 | |
|---|
| 1479 | 1566 | Return the fingerprint for this class |
|---|
| 1480 | 1567 | |
|---|
| … | … | |
| 1487 | 1574 | |
|---|
| 1488 | 1575 | /*********************************************************************** |
|---|
| 1489 | | |
|---|
| | 1576 | |
|---|
| 1490 | 1577 | Return the name of this class |
|---|
| 1491 | 1578 | |
|---|
| … | … | |
| 1496 | 1583 | return this.classinfo.name; |
|---|
| 1497 | 1584 | } |
|---|
| 1498 | | |
|---|
| 1499 | | /*********************************************************************** |
|---|
| 1500 | | |
|---|
| | 1585 | |
|---|
| | 1586 | /*********************************************************************** |
|---|
| | 1587 | |
|---|
| 1501 | 1588 | Append an event to the output. |
|---|
| 1502 | | |
|---|
| | 1589 | |
|---|
| 1503 | 1590 | ***********************************************************************/ |
|---|
| 1504 | 1591 | |
|---|
| … | … | |
| 1523 | 1610 | |
|---|
| 1524 | 1611 | /*********************************************************************** |
|---|
| 1525 | | |
|---|
| | 1612 | |
|---|
| 1526 | 1613 | Create with the given stream and layout |
|---|
| 1527 | 1614 | |
|---|
| … | … | |
| 1539 | 1626 | |
|---|
| 1540 | 1627 | /*********************************************************************** |
|---|
| 1541 | | |
|---|
| | 1628 | |
|---|
| 1542 | 1629 | Return the fingerprint for this class |
|---|
| 1543 | 1630 | |
|---|
| … | … | |
| 1550 | 1637 | |
|---|
| 1551 | 1638 | /*********************************************************************** |
|---|
| 1552 | | |
|---|
| | 1639 | |
|---|
| 1553 | 1640 | Return the name of this class |
|---|
| 1554 | 1641 | |
|---|
| … | … | |
| 1559 | 1646 | return this.classinfo.name; |
|---|
| 1560 | 1647 | } |
|---|
| 1561 | | |
|---|
| 1562 | | /*********************************************************************** |
|---|
| 1563 | | |
|---|
| | 1648 | |
|---|
| | 1649 | /*********************************************************************** |
|---|
| | 1650 | |
|---|
| 1564 | 1651 | Append an event to the output. |
|---|
| 1565 | | |
|---|
| | 1652 | |
|---|
| 1566 | 1653 | ***********************************************************************/ |
|---|
| 1567 | 1654 | |
|---|
| … | … | |
| 1592 | 1679 | { |
|---|
| 1593 | 1680 | /*********************************************************************** |
|---|
| 1594 | | |
|---|
| | 1681 | |
|---|
| 1595 | 1682 | Subclasses should implement this method to perform the |
|---|
| 1596 | 1683 | formatting of the actual message content. |
|---|
| … | … | |
| 1622 | 1709 | { |
|---|
| 1623 | 1710 | import tango.io.Console; |
|---|
| 1624 | | |
|---|
| | 1711 | |
|---|
| 1625 | 1712 | void main() |
|---|
| 1626 | 1713 | { |
|---|
Download in other formats:
|
 |