 |
Changeset 3145
- Timestamp:
- 01/31/08 15:04:34
(10 months ago)
- Author:
- sean
- Message:
* Moved exception trace generation from tango.core.Exception into the runtime. This involved adding a TraceInfo? interface to the global Exception class, and moving the machinery to generate a trace into genobj.d.
* The new hook to attach a trace hander is as follows:
extern (C) void rt_setTraceHandler( void function( void* ptr = null ) h );
This feature is exposed in tango.core.Runtime as the new 'traceHandler' property.
* The change to tracing inspired me to similarly rewire the collection handler code to move that hook into the runtime as well. This was done to improve efficiency for collections, as each collected object can now simply test a pointer to see if a handler is set rather than calling into user-space to perform the same check. The new hook for this mechanism is:
extern (C) void rt_setCollectHandler( void function(Object) h );
And the feature is also exposed in the Runtime object as the new collectHandler property. I thought about the name 'collectHandler' being in Runtime rather than GC, but I think the accompanying explanation for the function justifies the decision.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r2913 |
r3145 |
|
| 13 | 13 | { |
|---|
| 14 | 14 | alias void function( char[] file, size_t line, char[] msg = null ) assertHandlerType; |
|---|
| 15 | | alias TracedExceptionInfo function( void* ptr = null ) traceHandlerType; |
|---|
| 16 | 15 | |
|---|
| 17 | 16 | assertHandlerType assertHandler = null; |
|---|
| 18 | | traceHandlerType traceHandler = null; |
|---|
| 19 | | } |
|---|
| 20 | | |
|---|
| 21 | | |
|---|
| 22 | | interface TracedExceptionInfo |
|---|
| 23 | | { |
|---|
| 24 | | int opApply( int delegate( inout char[] ) ); |
|---|
| 25 | 17 | } |
|---|
| 26 | 18 | |
|---|
| … | … | |
| 30 | 22 | - Exception |
|---|
| 31 | 23 | - OutOfMemoryException |
|---|
| 32 | | |
|---|
| 33 | | - TracedException |
|---|
| 34 | | - SwitchException |
|---|
| 35 | | - AssertException |
|---|
| 36 | | - ArrayBoundsException |
|---|
| 37 | | - FinalizeException |
|---|
| 38 | | |
|---|
| 39 | | - PlatformException |
|---|
| 40 | | - ProcessException |
|---|
| 41 | | - ThreadException |
|---|
| 42 | | - FiberException |
|---|
| 43 | | - SyncException |
|---|
| 44 | | - IOException |
|---|
| 45 | | - SocketException |
|---|
| 46 | | - SocketAcceptException |
|---|
| 47 | | - AddressException |
|---|
| 48 | | - HostException |
|---|
| 49 | | - VfsException |
|---|
| 50 | | - ClusterException |
|---|
| 51 | | |
|---|
| 52 | | - NoSuchElementException |
|---|
| 53 | | - CorruptedIteratorException |
|---|
| 54 | | |
|---|
| 55 | | - IllegalArgumentException |
|---|
| 56 | | - IllegalElementException |
|---|
| 57 | | |
|---|
| 58 | | - TextException |
|---|
| 59 | | - RegexException |
|---|
| 60 | | - LocaleException |
|---|
| 61 | | - UnicodeException |
|---|
| 62 | | |
|---|
| 63 | | - PayloadException |
|---|
| | 24 | - SwitchException |
|---|
| | 25 | - AssertException |
|---|
| | 26 | - ArrayBoundsException |
|---|
| | 27 | - FinalizeException |
|---|
| | 28 | |
|---|
| | 29 | - PlatformException |
|---|
| | 30 | - ProcessException |
|---|
| | 31 | - ThreadException |
|---|
| | 32 | - FiberException |
|---|
| | 33 | - SyncException |
|---|
| | 34 | - IOException |
|---|
| | 35 | - SocketException |
|---|
| | 36 | - SocketAcceptException |
|---|
| | 37 | - AddressException |
|---|
| | 38 | - HostException |
|---|
| | 39 | - VfsException |
|---|
| | 40 | - ClusterException |
|---|
| | 41 | |
|---|
| | 42 | - NoSuchElementException |
|---|
| | 43 | - CorruptedIteratorException |
|---|
| | 44 | |
|---|
| | 45 | - IllegalArgumentException |
|---|
| | 46 | - IllegalElementException |
|---|
| | 47 | |
|---|
| | 48 | - TextException |
|---|
| | 49 | - RegexException |
|---|
| | 50 | - LocaleException |
|---|
| | 51 | - UnicodeException |
|---|
| | 52 | |
|---|
| | 53 | - PayloadException |
|---|
| 64 | 54 | */ |
|---|
| 65 | 55 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| … | … | |
| 84 | 74 | |
|---|
| 85 | 75 | /** |
|---|
| 86 | | * Stores a stack trace when thrown. |
|---|
| 87 | | */ |
|---|
| 88 | | class TracedException : Exception |
|---|
| 89 | | { |
|---|
| 90 | | this( char[] msg ) |
|---|
| 91 | | { |
|---|
| 92 | | super( msg ); |
|---|
| 93 | | m_info = traceContext(); |
|---|
| 94 | | } |
|---|
| 95 | | |
|---|
| 96 | | this( char[] msg, Exception e ) |
|---|
| 97 | | { |
|---|
| 98 | | super( msg, e ); |
|---|
| 99 | | m_info = traceContext(); |
|---|
| | 76 | * Base class for operating system or library exceptions. |
|---|
| | 77 | */ |
|---|
| | 78 | class PlatformException : Exception |
|---|
| | 79 | { |
|---|
| | 80 | this( char[] msg ) |
|---|
| | 81 | { |
|---|
| | 82 | super( msg ); |
|---|
| | 83 | } |
|---|
| | 84 | } |
|---|
| | 85 | |
|---|
| | 86 | /** |
|---|
| | 87 | * Thrown on an assert error. |
|---|
| | 88 | */ |
|---|
| | 89 | class AssertException : Exception |
|---|
| | 90 | { |
|---|
| | 91 | this( char[] file, size_t line ) |
|---|
| | 92 | { |
|---|
| | 93 | super( "Assertion failure", file, line ); |
|---|
| 100 | 94 | } |
|---|
| 101 | 95 | |
|---|
| … | … | |
| 103 | 97 | { |
|---|
| 104 | 98 | super( msg, file, line ); |
|---|
| 105 | | m_info = traceContext(); |
|---|
| 106 | | } |
|---|
| 107 | | |
|---|
| 108 | | char[] toString() |
|---|
| 109 | | { |
|---|
| 110 | | if( m_info is null ) |
|---|
| 111 | | return super.toString(); |
|---|
| 112 | | char[] buf = super.toString(); |
|---|
| 113 | | buf ~= "\n----------------"; |
|---|
| 114 | | foreach( line; m_info ) |
|---|
| 115 | | buf ~= "\n" ~ line; |
|---|
| 116 | | return buf; |
|---|
| 117 | | } |
|---|
| 118 | | |
|---|
| 119 | | int opApply( int delegate( inout char[] buf ) dg ) |
|---|
| 120 | | { |
|---|
| 121 | | if( m_info is null ) |
|---|
| 122 | | return 0; |
|---|
| 123 | | return m_info.opApply( dg ); |
|---|
| 124 | | } |
|---|
| 125 | | |
|---|
| 126 | | private: |
|---|
| 127 | | TracedExceptionInfo m_info; |
|---|
| 128 | | } |
|---|
| 129 | | |
|---|
| 130 | | |
|---|
| 131 | | /** |
|---|
| 132 | | * Base class for operating system or library exceptions. |
|---|
| 133 | | */ |
|---|
| 134 | | class PlatformException : TracedException |
|---|
| 135 | | { |
|---|
| 136 | | this( char[] msg ) |
|---|
| 137 | | { |
|---|
| 138 | | super( msg ); |
|---|
| 139 | | } |
|---|
| 140 | | } |
|---|
| 141 | | |
|---|
| 142 | | /** |
|---|
| 143 | | * Thrown on an assert error. |
|---|
| 144 | | */ |
|---|
| 145 | | class AssertException : TracedException |
|---|
| | 99 | } |
|---|
| | 100 | } |
|---|
| | 101 | |
|---|
| | 102 | |
|---|
| | 103 | /** |
|---|
| | 104 | * Thrown on an array bounds error. |
|---|
| | 105 | */ |
|---|
| | 106 | class ArrayBoundsException : Exception |
|---|
| 146 | 107 | { |
|---|
| 147 | 108 | this( char[] file, size_t line ) |
|---|
| 148 | 109 | { |
|---|
| 149 | | super( "Assertion failure", file, line ); |
|---|
| 150 | | } |
|---|
| 151 | | |
|---|
| 152 | | this( char[] msg, char[] file, size_t line ) |
|---|
| 153 | | { |
|---|
| 154 | | super( msg, file, line ); |
|---|
| 155 | | } |
|---|
| 156 | | } |
|---|
| 157 | | |
|---|
| 158 | | |
|---|
| 159 | | /** |
|---|
| 160 | | * Thrown on an array bounds error. |
|---|
| 161 | | */ |
|---|
| 162 | | class ArrayBoundsException : TracedException |
|---|
| 163 | | { |
|---|
| 164 | | this( char[] file, size_t line ) |
|---|
| 165 | | { |
|---|
| 166 | 110 | super( "Array index out of bounds", file, line ); |
|---|
| 167 | 111 | } |
|---|
| … | … | |
| 172 | 116 | * Thrown on finalize error. |
|---|
| 173 | 117 | */ |
|---|
| 174 | | class FinalizeException : TracedException |
|---|
| | 118 | class FinalizeException : Exception |
|---|
| 175 | 119 | { |
|---|
| 176 | 120 | ClassInfo info; |
|---|
| … | … | |
| 192 | 136 | * Thrown on a switch error. |
|---|
| 193 | 137 | */ |
|---|
| 194 | | class SwitchException : TracedException |
|---|
| | 138 | class SwitchException : Exception |
|---|
| 195 | 139 | { |
|---|
| 196 | 140 | this( char[] file, size_t line ) |
|---|
| … | … | |
| 204 | 148 | * Represents a text processing error. |
|---|
| 205 | 149 | */ |
|---|
| 206 | | class TextException : TracedException |
|---|
| | 150 | class TextException : Exception |
|---|
| 207 | 151 | { |
|---|
| 208 | 152 | this( char[] msg ) |
|---|
| … | … | |
| 277 | 221 | |
|---|
| 278 | 222 | /** |
|---|
| 279 | | * The basic exception thrown by the tango.io.vfs package. |
|---|
| | 223 | * The basic exception thrown by the tango.io.vfs package. |
|---|
| 280 | 224 | */ |
|---|
| 281 | 225 | private class VfsException : IOException |
|---|
| … | … | |
| 288 | 232 | |
|---|
| 289 | 233 | /** |
|---|
| 290 | | * The basic exception thrown by the tango.io.cluster package. |
|---|
| | 234 | * The basic exception thrown by the tango.io.cluster package. |
|---|
| 291 | 235 | */ |
|---|
| 292 | 236 | private class ClusterException : IOException |
|---|
| … | … | |
| 387 | 331 | * guid. |
|---|
| 388 | 332 | */ |
|---|
| 389 | | class RegistryException : TracedException |
|---|
| | 333 | class RegistryException : Exception |
|---|
| 390 | 334 | { |
|---|
| 391 | 335 | this( char[] msg ) |
|---|
| … | … | |
| 399 | 343 | * Thrown when an illegal argument is encountered. |
|---|
| 400 | 344 | */ |
|---|
| 401 | | class IllegalArgumentException : TracedException |
|---|
| | 345 | class IllegalArgumentException : Exception |
|---|
| 402 | 346 | { |
|---|
| 403 | 347 | this( char[] msg ) |
|---|
| … | … | |
| 427 | 371 | * Thrown on past-the-end errors by iterators and containers. |
|---|
| 428 | 372 | */ |
|---|
| 429 | | class NoSuchElementException : TracedException |
|---|
| | 373 | class NoSuchElementException : Exception |
|---|
| 430 | 374 | { |
|---|
| 431 | 375 | this( char[] msg ) |
|---|
| … | … | |
| 462 | 406 | { |
|---|
| 463 | 407 | assertHandler = h; |
|---|
| 464 | | } |
|---|
| 465 | | |
|---|
| 466 | | |
|---|
| 467 | | /** |
|---|
| 468 | | * Overrides the default trace hander with a user-supplied version. |
|---|
| 469 | | * |
|---|
| 470 | | * Params: |
|---|
| 471 | | * h = The new trace handler. Set to null to use the default handler. |
|---|
| 472 | | */ |
|---|
| 473 | | void setTraceHandler( traceHandlerType h ) |
|---|
| 474 | | { |
|---|
| 475 | | traceHandler = h; |
|---|
| 476 | 408 | } |
|---|
| 477 | 409 | |
|---|
| … | … | |
| 517 | 449 | |
|---|
| 518 | 450 | |
|---|
| 519 | | /** |
|---|
| 520 | | * This function will be called when a TracedException is constructed. The |
|---|
| 521 | | * user-supplied trace handler will be called if one has been supplied, |
|---|
| 522 | | * otherwise no trace will be generated. |
|---|
| 523 | | * |
|---|
| 524 | | * Params: |
|---|
| 525 | | * ptr = A pointer to the location from which to generate the trace, or null |
|---|
| 526 | | * if the trace should be generated from within the trace handler |
|---|
| 527 | | * itself. |
|---|
| 528 | | * |
|---|
| 529 | | * Returns: |
|---|
| 530 | | * An object describing the current calling context or null if no handler is |
|---|
| 531 | | * supplied. |
|---|
| 532 | | */ |
|---|
| 533 | | TracedExceptionInfo traceContext( void* ptr = null ) |
|---|
| 534 | | { |
|---|
| 535 | | if( traceHandler is null ) |
|---|
| 536 | | return null; |
|---|
| 537 | | return traceHandler( ptr ); |
|---|
| 538 | | } |
|---|
| 539 | | |
|---|
| 540 | 451 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| 541 | 452 | // Internal Error Callbacks |
|---|
| r3073 |
r3145 |
|
| 47 | 47 | extern (C) void gc_removeRoot( void* p ); |
|---|
| 48 | 48 | extern (C) void gc_removeRange( void* p ); |
|---|
| 49 | | |
|---|
| 50 | | alias bool function( Object obj ) collectHandlerType; |
|---|
| 51 | 49 | } |
|---|
| 52 | 50 | |
|---|
| … | … | |
| 432 | 430 | gc_removeRange( p ); |
|---|
| 433 | 431 | } |
|---|
| 434 | | |
|---|
| 435 | | |
|---|
| 436 | | /** |
|---|
| 437 | | * Overrides the default collect hander with a user-supplied version. |
|---|
| 438 | | * |
|---|
| 439 | | * Params: |
|---|
| 440 | | * h = The new collect handler. Set to null to use the default handler. |
|---|
| 441 | | */ |
|---|
| 442 | | static void collectHandler( collectHandlerType h ) |
|---|
| 443 | | { |
|---|
| 444 | | sm_collectHandler = h; |
|---|
| 445 | | } |
|---|
| 446 | | |
|---|
| 447 | | |
|---|
| 448 | | private: |
|---|
| 449 | | static collectHandlerType sm_collectHandler = null; |
|---|
| 450 | 432 | } |
|---|
| 451 | | |
|---|
| 452 | | |
|---|
| 453 | | //////////////////////////////////////////////////////////////////////////////// |
|---|
| 454 | | // Overridable Callbacks |
|---|
| 455 | | //////////////////////////////////////////////////////////////////////////////// |
|---|
| 456 | | |
|---|
| 457 | | |
|---|
| 458 | | /** |
|---|
| 459 | | * This function will be called when resource objects (ie. objects with a dtor) |
|---|
| 460 | | * are finalized by the garbage collector. The user-supplied collect handler |
|---|
| 461 | | * will be called if one has been supplied, otherwise no action will be taken. |
|---|
| 462 | | * |
|---|
| 463 | | * Params: |
|---|
| 464 | | * obj = The object being collected. |
|---|
| 465 | | * |
|---|
| 466 | | * Returns: |
|---|
| 467 | | * true if the runtime should call this object's dtor and false if not. |
|---|
| 468 | | * Default behavior is to return true. |
|---|
| 469 | | */ |
|---|
| 470 | | extern (C) bool onCollectResource( Object obj ) |
|---|
| 471 | | { |
|---|
| 472 | | if( GC.sm_collectHandler is null ) |
|---|
| 473 | | return true; |
|---|
| 474 | | return GC.sm_collectHandler( obj ); |
|---|
| 475 | | } |
|---|
| r2465 |
r3145 |
|
| 13 | 13 | extern (C) bool rt_isHalting(); |
|---|
| 14 | 14 | |
|---|
| 15 | | alias bool function() moduleUnitTesterType; |
|---|
| | 15 | alias bool function() ModuleUnitTester; |
|---|
| | 16 | alias bool function(Object) CollectHandler; |
|---|
| | 17 | alias Exception.TraceInfo function( void* ptr = null ) TraceHandler; |
|---|
| | 18 | |
|---|
| | 19 | extern (C) void rt_setCollectHandler( CollectHandler h ); |
|---|
| | 20 | extern (C) void rt_setTraceHandler( TraceHandler h ); |
|---|
| 16 | 21 | } |
|---|
| 17 | 22 | |
|---|
| … | … | |
| 43 | 48 | |
|---|
| 44 | 49 | /** |
|---|
| | 50 | * Overrides the default trace mechanism with s user-supplied version. A |
|---|
| | 51 | * trace represents the context from which an exception was thrown, and the |
|---|
| | 52 | * trace handler will be called when this occurs. The pointer supplied to |
|---|
| | 53 | * this routine indicates the base address from which tracing should occur. |
|---|
| | 54 | * If the supplied pointer is null then the trace routine should determine |
|---|
| | 55 | * an appropriate calling context from which to begin the trace. |
|---|
| | 56 | * |
|---|
| | 57 | * Params: |
|---|
| | 58 | * h = The new trace handler. Set to null to use the default handler. |
|---|
| | 59 | */ |
|---|
| | 60 | static void traceHandler( TraceHandler h ) |
|---|
| | 61 | { |
|---|
| | 62 | rt_setTraceHandler( h ); |
|---|
| | 63 | } |
|---|
| | 64 | |
|---|
| | 65 | |
|---|
| | 66 | /** |
|---|
| | 67 | * Overrides the default collect hander with a user-supplied version. This |
|---|
| | 68 | * routine will be called for each resource object that is finalized in a |
|---|
| | 69 | * non-deterministic manner--typically during a garbage collection cycle. |
|---|
| | 70 | * If the supplied routine returns true then the object's dtor will called |
|---|
| | 71 | * as normal, but if the routine returns false than the dtor will not be |
|---|
| | 72 | * called. The default behavior is for all object dtors to be called. |
|---|
| | 73 | * |
|---|
| | 74 | * Params: |
|---|
| | 75 | * h = The new collect handler. Set to null to use the default handler. |
|---|
| | 76 | */ |
|---|
| | 77 | static void collectHandler( CollectHandler h ) |
|---|
| | 78 | { |
|---|
| | 79 | rt_setCollectHandler( h ); |
|---|
| | 80 | } |
|---|
| | 81 | |
|---|
| | 82 | |
|---|
| | 83 | /** |
|---|
| 45 | 84 | * Overrides the default module unit tester with a user-supplied version. |
|---|
| | 85 | * This routine will be called once on program initialization. The return |
|---|
| | 86 | * value of this routine indicates to the runtime whether the body of the |
|---|
| | 87 | * program will be executed. |
|---|
| 46 | 88 | * |
|---|
| 47 | 89 | * Params: |
|---|
| 48 | 90 | * h = The new unit tester. Set to null to use the default unit tester. |
|---|
| 49 | 91 | */ |
|---|
| 50 | | static void moduleUnitTester( moduleUnitTesterType h ) |
|---|
| | 92 | static void moduleUnitTester( ModuleUnitTester h ) |
|---|
| 51 | 93 | { |
|---|
| 52 | 94 | sm_moduleUnitTester = h; |
|---|
| … | … | |
| 55 | 97 | |
|---|
| 56 | 98 | private: |
|---|
| 57 | | static moduleUnitTesterType sm_moduleUnitTester = null; |
|---|
| | 99 | static ModuleUnitTester sm_moduleUnitTester = null; |
|---|
| 58 | 100 | } |
|---|
| 59 | 101 | |
|---|
| r2913 |
r3145 |
|
| 232 | 232 | { |
|---|
| 233 | 233 | // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg); |
|---|
| 234 | | console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n"); |
|---|
| | 234 | console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.toString)("\n"); |
|---|
| 235 | 235 | } |
|---|
| 236 | 236 | else |
|---|
| … | … | |
| 239 | 239 | console (e.classinfo.name)(": ")(e.toString)("\n"); |
|---|
| 240 | 240 | } |
|---|
| | 241 | if (e.info) |
|---|
| | 242 | { |
|---|
| | 243 | console ("----------------\n"); |
|---|
| | 244 | foreach (t; e.info) |
|---|
| | 245 | console (t)("\n"); |
|---|
| | 246 | } |
|---|
| | 247 | if (e.next) |
|---|
| | 248 | console ("\n"); |
|---|
| 241 | 249 | e = e.next; |
|---|
| 242 | 250 | } |
|---|
| r3088 |
r3145 |
|
| 887 | 887 | } |
|---|
| 888 | 888 | |
|---|
| | 889 | |
|---|
| | 890 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| | 891 | // Exception |
|---|
| | 892 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| | 893 | |
|---|
| | 894 | |
|---|
| 889 | 895 | class Exception : Object |
|---|
| 890 | 896 | { |
|---|
| | 897 | interface TraceInfo |
|---|
| | 898 | { |
|---|
| | 899 | int opApply( int delegate( inout char[] ) ); |
|---|
| | 900 | } |
|---|
| | 901 | |
|---|
| 891 | 902 | char[] msg; |
|---|
| 892 | 903 | char[] file; |
|---|
| 893 | 904 | size_t line; |
|---|
| | 905 | TraceInfo info; |
|---|
| 894 | 906 | Exception next; |
|---|
| 895 | 907 | |
|---|
| 896 | | this(char[] msg, Exception next = null) |
|---|
| | 908 | this( char[] msg, Exception next = null ) |
|---|
| 897 | 909 | { |
|---|
| 898 | 910 | this.msg = msg; |
|---|
| 899 | 911 | this.next = next; |
|---|
| 900 | | } |
|---|
| 901 | | |
|---|
| 902 | | this(char[] msg, char[] file, size_t line, Exception next = null) |
|---|
| | 912 | this.info = traceContext(); |
|---|
| | 913 | } |
|---|
| | 914 | |
|---|
| | 915 | this( char[] msg, char[] file, size_t line, Exception next = null ) |
|---|
| 903 | 916 | { |
|---|
| 904 | 917 | this(msg, next); |
|---|
| 905 | 918 | this.file = file; |
|---|
| 906 | 919 | this.line = line; |
|---|
| | 920 | this.info = traceContext(); |
|---|
| 907 | 921 | } |
|---|
| 908 | 922 | |
|---|
| … | … | |
| 911 | 925 | return msg; |
|---|
| 912 | 926 | } |
|---|
| | 927 | } |
|---|
| | 928 | |
|---|
| | 929 | |
|---|
| | 930 | alias Exception.TraceInfo function( void* ptr = null ) TraceHandler; |
|---|
| | 931 | private TraceHandler traceHandler = null; |
|---|
| | 932 | |
|---|
| | 933 | |
|---|
| | 934 | /** |
|---|
| | 935 | * Overrides the default trace hander with a user-supplied version. |
|---|
| | 936 | * |
|---|
| | 937 | * Params: |
|---|
| | 938 | * h = The new trace handler. Set to null to use the default handler. |
|---|
| | 939 | */ |
|---|
| | 940 | extern (C) void rt_setTraceHandler( TraceHandler h ) |
|---|
| | 941 | { |
|---|
| | 942 | traceHandler = h; |
|---|
| | 943 | } |
|---|
| | 944 | |
|---|
| | 945 | |
|---|
| | 946 | /** |
|---|
| | 947 | * This function will be called when an Exception is constructed. The |
|---|
| | 948 | * user-supplied trace handler will be called if one has been supplied, |
|---|
| | 949 | * otherwise no trace will be generated. |
|---|
| | 950 | * |
|---|
| | 951 | * Params: |
|---|
| | 952 | * ptr = A pointer to the location from which to generate the trace, or null |
|---|
| | 953 | * if the trace should be generated from within the trace handler |
|---|
| | 954 | * itself. |
|---|
| | 955 | * |
|---|
| | 956 | * Returns: |
|---|
| | 957 | * An object describing the current calling context or null if no handler is |
|---|
| | 958 | * supplied. |
|---|
| | 959 | */ |
|---|
| | 960 | Exception.TraceInfo traceContext( void* ptr = null ) |
|---|
| | 961 | { |
|---|
| | 962 | if( traceHandler is null ) |
|---|
| | 963 | return null; |
|---|
| | 964 | return traceHandler( ptr ); |
|---|
| 913 | 965 | } |
|---|
| 914 | 966 | |
|---|
| r2955 |
r3145 |
|
| 67 | 67 | extern (C) BlkInfo gc_query( void* p ); |
|---|
| 68 | 68 | |
|---|
| 69 | | extern (C) bool onCollectResource( Object o ); |
|---|
| 70 | 69 | extern (C) void onFinalizeError( ClassInfo c, Exception e ); |
|---|
| 71 | 70 | extern (C) void onOutOfMemoryError(); |
|---|
| … | … | |
| 77 | 76 | PAGESIZE = 4096 |
|---|
| 78 | 77 | } |
|---|
| | 78 | |
|---|
| | 79 | alias bool function(Object) CollectHandler; |
|---|
| | 80 | CollectHandler collectHandler = null; |
|---|
| 79 | 81 | } |
|---|
| 80 | 82 | |
|---|
| … | … | |
| 446 | 448 | * |
|---|
| 447 | 449 | */ |
|---|
| | 450 | extern (C) void rt_setCollectHandler(CollectHandler h) |
|---|
| | 451 | { |
|---|
| | 452 | collectHandler = h; |
|---|
| | 453 | } |
|---|
| | 454 | |
|---|
| | 455 | |
|---|
| | 456 | /** |
|---|
| | 457 | * |
|---|
| | 458 | */ |
|---|
| 448 | 459 | extern (C) void rt_finalize(void* p, bool det = true) |
|---|
| 449 | 460 | { |
|---|
| … | … | |
| 460 | 471 | try |
|---|
| 461 | 472 | { |
|---|
| 462 | | if (det || onCollectResource(cast(Object)p)) |
|---|
| | 473 | if (det || collectHandler is null || collectHandler(cast(Object)p)) |
|---|
| 463 | 474 | { |
|---|
| 464 | 475 | do |
|---|
| r2076 |
r3145 |
|
| 73 | 73 | size_t line; |
|---|
| 74 | 74 | |
|---|
| | 75 | struct Interface *info; |
|---|
| 75 | 76 | struct Exception *next; |
|---|
| 76 | 77 | } Exception; |
|---|
| r3095 |
r3145 |
|
| 240 | 240 | { |
|---|
| 241 | 241 | // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg); |
|---|
| 242 | | console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n"); |
|---|
| | 242 | console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.toString)("\n"); |
|---|
| 243 | 243 | } |
|---|
| 244 | 244 | else |
|---|
| … | … | |
| 247 | 247 | console (e.classinfo.name)(": ")(e.toString)("\n"); |
|---|
| 248 | 248 | } |
|---|
| | 249 | if (e.info) |
|---|
| | 250 | { |
|---|
| | 251 | console ("----------------\n"); |
|---|
| | 252 | foreach (t; e.info) |
|---|
| | 253 | console (t)("\n"); |
|---|
| | 254 | } |
|---|
| | 255 | if (e.next) |
|---|
| | 256 | console ("\n"); |
|---|
| 249 | 257 | e = e.next; |
|---|
| 250 | 258 | } |
|---|
| r3088 |
r3145 |
|
| 897 | 897 | } |
|---|
| 898 | 898 | |
|---|
| | 899 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| | 900 | // Exception |
|---|
| | 901 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| 899 | 902 | class Exception : Object |
|---|
| 900 | 903 | { |
|---|
| | 904 | interface TraceInfo |
|---|
| | 905 | { |
|---|
| | 906 | int opApply( int delegate( inout char[] ) ); |
|---|
| | 907 | } |
|---|
| 901 | 908 | char[] msg; |
|---|
| 902 | 909 | char[] file; |
|---|
| 903 | 910 | size_t line; |
|---|
| | 911 | TraceInfo info; |
|---|
| 904 | 912 | Exception next; |
|---|
| 905 | 913 | |
|---|
| … | … | |
| 908 | 916 | this.msg = msg; |
|---|
| 909 | 917 | this.next = next; |
|---|
| | 918 | this.info = traceContext(); |
|---|
| 910 | 919 | } |
|---|
| 911 | 920 | |
|---|
| … | … | |
| 915 | 924 | this.file = file; |
|---|
| 916 | 925 | this.line = line; |
|---|
| | 926 | this.info = traceContext(); |
|---|
| 917 | 927 | } |
|---|
| 918 | 928 | |
|---|
| … | … | |
| 921 | 931 | return msg; |
|---|
| 922 | 932 | } |
|---|
| | 933 | } |
|---|
| | 934 | |
|---|
| | 935 | |
|---|
| | 936 | alias Exception.TraceInfo function( void* ptr = null ) TraceHandler; |
|---|
| | 937 | private TraceHandler traceHandler = null; |
|---|
| | 938 | |
|---|
| | 939 | |
|---|
| | 940 | /** |
|---|
| | 941 | * Overrides the default trace hander with a user-supplied version. |
|---|
| | 942 | * |
|---|
| | 943 | * Params: |
|---|
| | 944 | * h = The new trace handler. Set to null to use the default handler. |
|---|
| | 945 | */ |
|---|
| | 946 | extern (C) void rt_setTraceHandler( TraceHandler h ) |
|---|
| | 947 | { |
|---|
| | 948 | traceHandler = h; |
|---|
| | 949 | } |
|---|
| | 950 | |
|---|
| | 951 | |
|---|
| | 952 | /** |
|---|
| | 953 | * This function will be called when an Exception is constructed. The |
|---|
| | 954 | * user-supplied trace handler will be called if one has been supplied, |
|---|
| | 955 | * otherwise no trace will be generated. |
|---|
| | 956 | * |
|---|
| | 957 | * Params: |
|---|
| | 958 | * ptr = A pointer to the location from which to generate the trace, or null |
|---|
| | 959 | * if the trace should be generated from within the trace handler |
|---|
| | 960 | * itself. |
|---|
| | 961 | * |
|---|
| | 962 | * Returns: |
|---|
| | 963 | * An object describing the current calling context or null if no handler is |
|---|
| | 964 | * supplied. |
|---|
| | 965 | */ |
|---|
| | 966 | Exception.TraceInfo traceContext( void* ptr = null ) |
|---|
| | 967 | { |
|---|
| | 968 | if( traceHandler is null ) |
|---|
| | 969 | return null; |
|---|
| | 970 | return traceHandler( ptr ); |
|---|
| 923 | 971 | } |
|---|
| 924 | 972 | |
|---|
| r2955 |
r3145 |
|
| 67 | 67 | extern (C) BlkInfo gc_query( void* p ); |
|---|
| 68 | 68 | |
|---|
| 69 | | extern (C) bool onCollectResource( Object o ); |
|---|
| 70 | 69 | extern (C) void onFinalizeError( ClassInfo c, Exception e ); |
|---|
| 71 | 70 | extern (C) void onOutOfMemoryError(); |
|---|
| … | … | |
| 77 | 76 | PAGESIZE = 4096 |
|---|
| 78 | 77 | } |
|---|
| | 78 | alias bool function(Object) CollectHandler; |
|---|
| | 79 | CollectHandler collectHandler = null; |
|---|
| 79 | 80 | } |
|---|
| 80 | 81 | |
|---|
| … | … | |
| 439 | 440 | * |
|---|
| 440 | 441 | */ |
|---|
| | 442 | extern (C) void rt_setCollectHandler(CollectHandler h) |
|---|
| | 443 | { |
|---|
| | 444 | collectHandler = h; |
|---|
| | 445 | } |
|---|
| | 446 | |
|---|
| | 447 | |
|---|
| | 448 | /** |
|---|
| | 449 | * |
|---|
| | 450 | */ |
|---|
| 441 | 451 | extern (C) void rt_finalize(void* p, bool det = true) |
|---|
| 442 | 452 | { |
|---|
| … | … | |
| 453 | 463 | try |
|---|
| 454 | 464 | { |
|---|
| 455 | | if (det || onCollectResource(cast(Object)p)) |
|---|
| | 465 | if (det || collectHandler is null || collectHandler(cast(Object)p)) |
|---|
| 456 | 466 | { |
|---|
| 457 | 467 | do |
|---|
| r2076 |
r3145 |
|
| 74 | 74 | size_t line; |
|---|
| 75 | 75 | |
|---|
| | 76 | struct Interface *info; |
|---|
| 76 | 77 | struct Exception *next; |
|---|
| 77 | 78 | } Exception; |
|---|
| r3028 |
r3145 |
|
| 156 | 156 | class Exception : Object |
|---|
| 157 | 157 | { |
|---|
| | 158 | interface TraceInfo |
|---|
| | 159 | { |
|---|
| | 160 | int opApply( int delegate( inout char[] ) ); |
|---|
| | 161 | char[] toString(); |
|---|
| | 162 | } |
|---|
| | 163 | |
|---|
| 158 | 164 | char[] msg; |
|---|
| 159 | 165 | char[] file; |
|---|
| 160 | 166 | size_t line; |
|---|
| | 167 | TraceInfo info; |
|---|
| 161 | 168 | Exception next; |
|---|
| 162 | 169 | |
|---|
| r3045 |
r3145 |
|
| 8 | 8 | module tango.core.Variant; |
|---|
| 9 | 9 | |
|---|
| 10 | | private import tango.core.Exception : TracedException; |
|---|
| 11 | 10 | private import tango.core.Vararg : va_list; |
|---|
| 12 | 11 | |
|---|
| … | … | |
| 198 | 197 | * without using a compatible type. |
|---|
| 199 | 198 | */ |
|---|
| 200 | | class VariantTypeMismatchException : TracedException |
|---|
| | 199 | class VariantTypeMismatchException : Exception |
|---|
| 201 | 200 | { |
|---|
| 202 | 201 | this(TypeInfo expected, TypeInfo got) |
|---|
| … | … | |
| 599 | 598 | assert( !v.isImplicitly!(float), v.type.toString ); |
|---|
| 600 | 599 | assert( v.get!(double) == 3.1413 ); |
|---|
| 601 | | |
|---|
| | 600 | |
|---|
| 602 | 601 | auto u = Variant(v); |
|---|
| 603 | 602 | assert( u.isA!(double), u.type.toString ); |
|---|
| … | … | |
| 657 | 656 | hash[v2] = 1; |
|---|
| 658 | 657 | hash[v3] = 2; |
|---|
| 659 | | |
|---|
| | 658 | |
|---|
| 660 | 659 | assert( hash[v1] == 0 ); |
|---|
| 661 | 660 | assert( hash[v2] == 1 ); |
|---|
| r3075 |
r3145 |
|
| 1 | | /******************************************************************************* |
|---|
| | 1 | /******************************************************************************* |
|---|
| 2 | 2 | * |
|---|
| 3 | | * copyright: Copyright © 2007 Daniel Keep. All rights reserved. |
|---|
| | 3 | * copyright: Copyright © 2007 Daniel Keep. All rights reserved. |
|---|
| 4 | 4 | * |
|---|
| 5 | 5 | * license: BSD style: $(LICENSE) |
|---|
| … | … | |
| 261 | 261 | Data* data; |
|---|
| 262 | 262 | static assert( Data.sizeof == 42 ); |
|---|
| 263 | | |
|---|
| | 263 | |
|---|
| 264 | 264 | char[] file_name; |
|---|
| 265 | 265 | ubyte[] extra_field; |
|---|
| … | … | |
| 319 | 319 | data.file_comment_length = file_comment.length; |
|---|
| 320 | 320 | |
|---|
| 321 | | // Ok; let's do this! |
|---|
| | 321 | // Ok; let's do this! |
|---|
| 322 | 322 | version( BigEndian ) swapAll(data); |
|---|
| 323 | 323 | writeExact(output, (&data)[0..1]); |
|---|
| … | … | |
| 406 | 406 | Data data; |
|---|
| 407 | 407 | static assert( data.sizeof == 18 ); |
|---|
| 408 | | |
|---|
| | 408 | |
|---|
| 409 | 409 | char[] file_comment; |
|---|
| 410 | 410 | |
|---|
| … | … | |
| 427 | 427 | Data data = this.data; |
|---|
| 428 | 428 | data.file_comment_length = file_comment.length; |
|---|
| 429 | | |
|---|
| | 429 | |
|---|
| 430 | 430 | version( BigEndian ) swapAll(data); |
|---|
| 431 | 431 | writeExact(output, (&data)[0..1]); |
|---|
| … | … | |
| 569 | 569 | * } |
|---|
| 570 | 570 | * ----- |
|---|
| 571 | | * |
|---|
| | 571 | * |
|---|
| 572 | 572 | * See the ZipEntry class for more information on the contents of entries. |
|---|
| 573 | 573 | * |
|---|
| … | … | |
| 611 | 611 | } |
|---|
| 612 | 612 | } |
|---|
| 613 | | |
|---|
| | 613 | |
|---|
| 614 | 614 | /** |
|---|
| 615 | 615 | * Creates a ZipBlockReader using the provided InputStream. Please note |
|---|
| … | … | |
| 660 | 660 | assert( state == State.Open ); |
|---|
| 661 | 661 | return more; |
|---|
| 662 | | |
|---|
| | 662 | |
|---|
| 663 | 663 | case State.Open: |
|---|
| 664 | 664 | return (current_index < headers.length); |
|---|
| … | … | |
| 681 | 681 | if( !more ) |
|---|
| 682 | 682 | ZipExhaustedException(); |
|---|
| 683 | | |
|---|
| | 683 | |
|---|
| 684 | 684 | return new ZipEntry(headers[current_index++], &open_file); |
|---|
| 685 | 685 | } |
|---|
| … | … | |
| 711 | 711 | { |
|---|
| 712 | 712 | entry = get(entry); |
|---|
| 713 | | |
|---|
| | 713 | |
|---|
| 714 | 714 | result = dg(entry); |
|---|
| 715 | 715 | if( result ) |
|---|
| … | … | |
| 949 | 949 | |
|---|
| 950 | 950 | LocalFileHeader lheader; lheader.fill(source); |
|---|
| 951 | | |
|---|
| | 951 | |
|---|
| 952 | 952 | if( !lheader.agrees_with(header) ) |
|---|
| 953 | 953 | ZipException.incons(header.file_name); |
|---|
| 954 | | |
|---|
| | 954 | |
|---|
| 955 | 955 | // Ok; get a slice stream for the file |
|---|
| 956 | 956 | return new SliceSeekInputStream( |
|---|
| … | … | |
| 983 | 983 | this(FilePath(path)); |
|---|
| 984 | 984 | } |
|---|
| 985 | | |
|---|
| | 985 | |
|---|
| 986 | 986 | /// ditto |
|---|
| 987 | 987 | this(PathView path) |
|---|
| … | … | |
| 1147 | 1147 | timeToDos(info.modified, lhdata.modification_file_time, |
|---|
| 1148 | 1148 | lhdata.modification_file_date); |
|---|
| 1149 | | |
|---|
| | 1149 | |
|---|
| 1150 | 1150 | put_local_header(lhdata, info.name); |
|---|
| 1151 | | |
|---|
| | 1151 | |
|---|
| 1152 | 1152 | // Store comment |
|---|
| 1153 | 1153 | entries[$-1].comment = info.comment; |
|---|
| … | … | |
| 1345 | 1345 | // Write out the header and the filename |
|---|
| 1346 | 1346 | auto header_pos = seeker.seek(0, IConduit.Seek.Anchor.Current); |
|---|
| 1347 | | |
|---|
| | 1347 | |
|---|
| 1348 | 1348 | write(output, LocalFileHeader.signature); |
|---|
| 1349 | 1349 | header.put(output); |
|---|
| … | … | |
| 1384 | 1384 | return header.data.uncompressed_size;; |
|---|
| 1385 | 1385 | } |
|---|
| 1386 | | |
|---|
| | 1386 | |
|---|
| 1387 | 1387 | /** |
|---|
| 1388 | 1388 | * Opens a stream for reading from the file. The contents of this stream |
|---|
| … | … | |
| 1525 | 1525 | // |
|---|
| 1526 | 1526 | |
|---|
| 1527 | | import tango.core.Exception : TracedException; |
|---|
| 1528 | | |
|---|
| 1529 | 1527 | /** |
|---|
| 1530 | 1528 | * This is the base class from which all exceptions generated by this module |
|---|
| 1531 | 1529 | * derive from. |
|---|
| 1532 | 1530 | */ |
|---|
| 1533 | | class ZipException : TracedException |
|---|
| | 1531 | class ZipException : Exception |
|---|
| 1534 | 1532 | { |
|---|
| 1535 | 1533 | this(char[] msg) { super(msg); } |
|---|
| … | … | |
| 1679 | 1677 | switch( m ) |
|---|
| 1680 | 1678 | { |
|---|
| 1681 | | case 0: |
|---|
| | 1679 | case 0: |
|---|
| 1682 | 1680 | case 8: assert(false); // supported |
|---|
| 1683 | 1681 | |
|---|
| … | … | |
| 2069 | 2067 | '\u00ea': '\x88', '\u00eb': '\x89', '\u00e8': '\x8a', '\u00ef': '\x8b', |
|---|
| 2070 | 2068 | '\u00ee': '\x8c', '\u00ec': '\x8d', '\u00c4': '\x8e', '\u00c5': '\x8f', |
|---|
| 2071 | | |
|---|
| | 2069 | |
|---|
| 2072 | 2070 | '\u00c9': '\x90', '\u00e6': '\x91', '\u00c6': '\x92', '\u00f4': '\x93', |
|---|
| 2073 | 2071 | '\u00f6': '\x94', '\u00f2': '\x95', '\u00fb': '\x96', '\u00f9': '\x97', |
|---|
| 2074 | 2072 | '\u00ff': '\x98', '\u00d6': '\x99', '\u00dc': '\x9a', '\u00f8': '\x9b', |
|---|
| 2075 | 2073 | '\u00a3': '\x9c', '\u00a5': '\x9d', '\u20a7': '\x9e', '\u0192': '\x9f', |
|---|
| 2076 | | |
|---|
| | 2074 | |
|---|
| 2077 | 2075 | '\u00e1': '\xa0', '\u00ed': '\xa1', '\u00f3': '\xa2', '\u00fa': '\xa3', |
|---|
| 2078 | 2076 | '\u00f1': '\xa4', '\u00d1': '\xa5', '\u00aa': '\xa6', '\u00ba': '\xa7', |
|---|
| 2079 | 2077 | '\u00bf': '\xa8', '\u2310': '\xa9', '\u00ac': '\xaa', '\u00bd': '\xab', |
|---|
| 2080 | 2078 | '\u00bc': '\xac', '\u00a1': '\xad', '\u00ab': '\xae', '\u00bb': '\xaf', |
|---|
| 2081 | | |
|---|
| | 2079 | |
|---|
| 2082 | 2080 | '\u2591': '\xb0', '\u2592': '\xb1', '\u2593': '\xb2', '\u2502': '\xb3', |
|---|
| 2083 | 2081 | '\u2524': '\xb4', '\u2561': '\xb5', '\u2562': '\xb6', '\u2556': '\xb7', |
|---|
| 2084 | 2082 | '\u2555': '\xb8', '\u2563': '\xb9', '\u2551': '\xba', '\u2557': '\xbb', |
|---|
| 2085 | 2083 | '\u255d': '\xbc', '\u255c': '\xbd', '\u255b': '\xbe', '\u2510': '\xbf', |
|---|
| 2086 | | |
|---|
| | 2084 | |
|---|
| 2087 | 2085 | '\u2514': '\xc0', '\u2534': '\xc1', '\u252c': '\xc2', '\u251c': '\xc3', |
|---|
| 2088 | 2086 | '\u2500': '\xc4', '\u253c': '\xc5', '\u255e': '\xc6', '\u255f': '\xc7', |
|---|
| 2089 | 2087 | '\u255a': '\xc8', '\u2554': '\xc9', '\u2569': '\xca', '\u2566': '\xcb', |
|---|
| 2090 | 2088 | '\u2560': '\xcc', '\u2550': '\xcd', '\u256c': '\xce', '\u2567': '\xcf', |
|---|
| 2091 | | |
|---|
| | 2089 | |
|---|
| 2092 | 2090 | '\u2568': '\xd0', '\u2564': '\xd1', '\u2565': '\xd2', '\u2559': '\xd3', |
|---|
| 2093 | 2091 | '\u2558': '\xd4', '\u2552': '\xd5', '\u2553': '\xd6', '\u256b': '\xd7', |
|---|
| … | … | |
| 2099 | 2097 | '\u03a6': '\xe8', '\u0398': '\xe9', '\u03a9': '\xea', '\u03b4': '\xeb', |
|---|
| 2100 | 2098 | '\u221e': '\xec', '\u03c6': '\xed', '\u03b5': '\xee', '\u2229': '\xef', |
|---|
| 2101 | | |
|---|
| | 2099 | |
|---|
| 2102 | 2100 | '\u2261': '\xf0', '\u00b1': '\xf1', '\u2265': '\xf2', '\u2264': '\xf3', |
|---|
| 2103 | 2101 | '\u2320': '\xf4', '\u2321': '\xf5', '\u00f7': '\xf6', '\u2248': '\xf7', |
|---|
| … | … | |
| 2125 | 2123 | if( 32 <= d && d <= 126 || d == 0 ) |
|---|
| 2126 | 2124 | r[k++] = d; |
|---|
| 2127 | | |
|---|
| | 2125 | |
|---|
| 2128 | 2126 | else if( d == '\u2302' ) |
|---|
| 2129 | 2127 | r[k++] = '\x7f'; |
|---|
| … | … | |
| 2131 | 2129 | else if( auto e_ptr = d in utf8_to_cp437_map ) |
|---|
| 2132 | 2130 | r[k++] = *e_ptr; |
|---|
| 2133 | | |
|---|
| | 2131 | |
|---|
| 2134 | 2132 | else |
|---|
| 2135 | 2133 | { |
|---|
| … | … | |
| 2227 | 2225 | // *muttering angrily* |
|---|
| 2228 | 2226 | scope cal = new Gregorian; |
|---|
| 2229 | | |
|---|
| | 2227 | |
|---|
| 2230 | 2228 | if( cal.getYear(time) < 1980 ) |
|---|
| 2231 | 2229 | ZipException.tooold; |
|---|
| … | … | |
| 2254 | 2252 | /******************************************************************************* |
|---|
| 2255 | 2253 | |
|---|
| 2256 | | copyright: Copyright © 2007 Daniel Keep. All rights reserved. |
|---|
| | 2254 | copyright: Copyright © 2007 Daniel Keep. All rights reserved. |
|---|
| 2257 | 2255 | |
|---|
| 2258 | 2256 | license: BSD style: $(LICENSE) |
|---|
| … | … | |
| 2377 | 2375 | /******************************************************************************* |
|---|
| 2378 | 2376 | |
|---|
| 2379 | | copyright: Copyright © |
|---|
|