comparison src/util.d @ 1:4a9dcbd9e54f

-files of 0.13 beta -fixes so that it now compiles with the current dmd version
author marton@basel.hu
date Tue, 05 Apr 2011 20:44:01 +0200
parents
children
comparison
equal deleted inserted replaced
0:586e4a649642 1:4a9dcbd9e54f
1 /* Ddbg - Win32 Debugger for the D programming language
2 * Copyright (c) 2007 Jascha Wetzel
3 * All rights reserved. See LICENSE.TXT for details.
4 */
5
6 import std.ctype;
7 import std.stdio;
8 import std.string;
9 import std.c.string;
10 import std.c.stdio;
11 import std.format;
12 import std.date : getUTCtime, d_time, TicksPerSecond;
13 import std.demangle;
14
15 import win32.winbase;
16 import win32.windef;
17
18 import std.typeinfo.ti_AC;
19 import std.typeinfo.ti_Acdouble;
20 import std.typeinfo.ti_Acfloat;
21 import std.typeinfo.ti_Acreal;
22 import std.typeinfo.ti_Adouble;
23 import std.typeinfo.ti_Afloat;
24 import std.typeinfo.ti_Ag;
25 import std.typeinfo.ti_Aint;
26 import std.typeinfo.ti_Along;
27 import std.typeinfo.ti_Areal;
28 import std.typeinfo.ti_Ashort;
29 import std.typeinfo.ti_byte;
30 import std.typeinfo.ti_C;
31 import std.typeinfo.ti_cdouble;
32 import std.typeinfo.ti_cfloat;
33 import std.typeinfo.ti_char;
34 import std.typeinfo.ti_creal;
35 import std.typeinfo.ti_dchar;
36 import std.typeinfo.ti_delegate;
37 import std.typeinfo.ti_double;
38 import std.typeinfo.ti_float;
39 import std.typeinfo.ti_idouble;
40 import std.typeinfo.ti_ifloat;
41 import std.typeinfo.ti_int;
42 import std.typeinfo.ti_ireal;
43 import std.typeinfo.ti_long;
44 import std.typeinfo.ti_ptr;
45 import std.typeinfo.ti_real;
46 import std.typeinfo.ti_short;
47 import std.typeinfo.ti_ubyte;
48 import std.typeinfo.ti_uint;
49 import std.typeinfo.ti_ulong;
50 import std.typeinfo.ti_ushort;
51 import std.typeinfo.ti_void;
52 import std.typeinfo.ti_wchar;
53
54 /**************************************************************************************************
55
56 **************************************************************************************************/
57 T dmax(T)(T a, T b)
58 {
59 return a<b?b:a;
60 }
61
62 T dmin(T)(T a, T b)
63 {
64 return a>b?b:a;
65 }
66
67 /**************************************************************************************************
68
69 **************************************************************************************************/
70 uint intFromStr(string str)
71 {
72 uint i;
73 foreach_reverse ( c; str )
74 i = i<<8 | c;
75 return i;
76 }
77
78 /**************************************************************************************************
79
80 **************************************************************************************************/
81 string itoa(uint i)
82 {
83 if ( i == 0 )
84 return "0";
85 string str;
86 for ( ; i > 0; i /= 10 )
87 str = "0123456789"[i%10] ~ str;
88 return str;
89 }
90
91 /**************************************************************************************************
92
93 **************************************************************************************************/
94 string TODO(string file, uint line, string msg)
95 {
96 return "TODO - "~file~"("~itoa(line)~"): "~msg~"";
97 }
98
99 /**************************************************************************************************
100
101 **************************************************************************************************/
102 string formatTicks(ulong ticks)
103 {
104 SYSTEMTIME stime;
105 if ( !FileTimeToSystemTime(cast(FILETIME*)&ticks, &stime) )
106 return "invalid";
107 string str = format("%02d:%02d:%02d.%03d", stime.wHour, stime.wMinute, stime.wSecond, stime.wMilliseconds);
108 return str;
109 }
110
111 /**************************************************************************************************
112 Name lookup for win32 DebugEventCodes.
113 **************************************************************************************************/
114 string getEventName(uint event)
115 {
116 switch ( event )
117 {
118 case EXCEPTION_DEBUG_EVENT : return "EXCEPTION_DEBUG_EVENT";
119 case CREATE_THREAD_DEBUG_EVENT : return "CREATE_THREAD_DEBUG_EVENT";
120 case CREATE_PROCESS_DEBUG_EVENT : return "CREATE_PROCESS_DEBUG_EVENT";
121 case EXIT_THREAD_DEBUG_EVENT : return "EXIT_THREAD_DEBUG_EVENT";
122 case EXIT_PROCESS_DEBUG_EVENT : return "EXIT_PROCESS_DEBUG_EVENT";
123 case LOAD_DLL_DEBUG_EVENT : return "LOAD_DLL_DEBUG_EVENT";
124 case UNLOAD_DLL_DEBUG_EVENT : return "UNLOAD_DLL_DEBUG_EVENT";
125 case OUTPUT_DEBUG_STRING_EVENT : return "OUTPUT_DEBUG_STRING_EVENT";
126 case RIP_EVENT: return "RIP_EVENT";
127 default : break;
128 }
129 return "";
130 }
131
132 /**************************************************************************************************
133 Name lookup for win32 ExceptionCodes.
134 **************************************************************************************************/
135 string getExceptionName(uint excpt)
136 {
137 switch ( excpt )
138 {
139 case EXCEPTION_ACCESS_VIOLATION : return "EXCEPTION_ACCESS_VIOLATION";
140 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED : return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
141 case EXCEPTION_BREAKPOINT : return "EXCEPTION_BREAKPOINT";
142 case EXCEPTION_DATATYPE_MISALIGNMENT : return "EXCEPTION_DATATYPE_MISALIGNMENT";
143 case EXCEPTION_FLT_DENORMAL_OPERAND : return "EXCEPTION_FLT_DENORMAL_OPERAND";
144 case EXCEPTION_FLT_DIVIDE_BY_ZERO : return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
145 case EXCEPTION_FLT_INEXACT_RESULT : return "EXCEPTION_FLT_INEXACT_RESULT";
146 case EXCEPTION_FLT_INVALID_OPERATION : return "EXCEPTION_FLT_INVALID_OPERATION";
147 case EXCEPTION_FLT_OVERFLOW : return "EXCEPTION_FLT_OVERFLOW";
148 case EXCEPTION_FLT_STACK_CHECK : return "EXCEPTION_FLT_STACK_CHECK";
149 case EXCEPTION_FLT_UNDERFLOW : return "EXCEPTION_FLT_UNDERFLOW";
150 case EXCEPTION_ILLEGAL_INSTRUCTION : return "EXCEPTION_ILLEGAL_INSTRUCTION";
151 case EXCEPTION_IN_PAGE_ERROR : return "EXCEPTION_IN_PAGE_ERROR";
152 case EXCEPTION_INT_DIVIDE_BY_ZERO : return "EXCEPTION_INT_DIVIDE_BY_ZERO";
153 case EXCEPTION_INT_OVERFLOW : return "EXCEPTION_INT_OVERFLOW";
154 case EXCEPTION_INVALID_DISPOSITION : return "EXCEPTION_INVALID_DISPOSITION";
155 case EXCEPTION_NONCONTINUABLE_EXCEPTION : return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
156 case EXCEPTION_PRIV_INSTRUCTION : return "EXCEPTION_PRIV_INSTRUCTION";
157 case EXCEPTION_SINGLE_STEP : return "EXCEPTION_SINGLE_STEP";
158 case EXCEPTION_STACK_OVERFLOW : return "EXCEPTION_STACK_OVERFLOW";
159 default : break;
160 }
161 return "";
162 }
163
164 /**************************************************************************************************
165 Wrapper for Win32 GetLastError.
166 **************************************************************************************************/
167 string lastError()
168 {
169 char[4096] msg;
170 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, null, GetLastError(), 0, msg.ptr, msg.length, null);
171 return msg[0..strlen(msg.ptr)];
172 }
173
174 /**************************************************************************************************
175 Simplified number parser for prefixes.
176 Returns: number represented by the prefix of name, 0 else
177 **************************************************************************************************/
178 uint parseNumber(inout string name)
179 {
180 uint res;
181 int i;
182 while ( name.length > 0 )
183 {
184 if ( !isdigit(name[0]) )
185 break;
186 res = res*10+(name[0]-'0');
187 name = name[1..$];
188 }
189 return res;
190 }
191
192 /**************************************************************************************************
193
194 **************************************************************************************************/
195 string typeFromMangled(string mangled)
196 {
197 if ( mangled is null || mangled.length < 4 || mangled[0..2] != "_D" || !isdigit(mangled[2]) )
198 return null;
199 string type = mangled[1..$];
200 // skip symbol name
201 while ( type.length > 1 && type[0] == 'D' && isdigit(type[1]) ) {
202 type = type[1..$];
203 uint len = parseNumber(type);
204 type = type[len..$];
205 }
206 return type;
207 }
208
209 /**************************************************************************************************
210
211 **************************************************************************************************/
212 string mangleName(string name)
213 {
214 string mangled;
215 string[] idents = split(name, ".");
216 foreach ( string id; idents )
217 mangled ~= .toString(id.length)~id;
218 return mangled;
219 }
220
221 /**************************************************************************************************
222
223 **************************************************************************************************/
224 string demangleType(string mangled)
225 {
226 return demangle("_D0"~mangled);
227 }
228
229 /**************************************************************************************************
230
231 **************************************************************************************************/
232 string demangleNameSkip(inout string mangled)
233 {
234 string name;
235 do {
236 uint len = parseNumber(mangled);
237 if ( len <= 0 || len > mangled.length )
238 return null;
239 if ( name.length > 0 )
240 name ~= ".";
241 name ~= mangled[0..len];
242 mangled = mangled[len..$];
243 } while ( mangled.length > 0 );
244 return name;
245 }
246
247 /**************************************************************************************************
248
249 **************************************************************************************************/
250 string demangleName(string mangled)
251 {
252 string name;
253 if ( mangled.length > 2 && mangled[0..2] == "_D" && isNumeric(mangled[2]) )
254 mangled = mangled[2..$];
255 else
256 return mangled;
257 do {
258 uint len = parseNumber(mangled);
259 while ( len <= 0 && mangled.length > 0 ) {
260 mangled = mangled[1..$];
261 len = parseNumber(mangled);
262 }
263 if ( len <= 0 || len > mangled.length )
264 return name;
265 if ( name.length > 0 )
266 name ~= ".";
267 name ~= mangled[0..len];
268 mangled = mangled[len..$];
269 } while ( mangled.length > 0 );
270 return name;
271 }
272
273 /**************************************************************************************************
274 Wraps win32 stdio functions. Respects io redirection into pipes.
275 **************************************************************************************************/
276 class DbgIO
277 {
278 static HANDLE ddb_read, ddb_write;
279 static string buffer;
280
281 /**********************************************************************************************
282
283 **********************************************************************************************/
284 static this()
285 {
286 ddb_read = GetStdHandle(STD_INPUT_HANDLE);
287 ddb_write = GetStdHandle(STD_OUTPUT_HANDLE);
288 }
289
290 /**********************************************************************************************
291
292 **********************************************************************************************/
293 static string readln()
294 {
295 char[128] buf;
296 uint read;
297
298 int nl_index;
299 do
300 {
301 ReadFile(ddb_read, buf.ptr, buf.length, &read, null);
302 buffer ~= buf[0..read];
303 nl_index = find(buffer, '\n');
304 } while ( nl_index < 0 );
305 string ret = buffer[0..nl_index];
306 buffer = buffer[nl_index+1..$];
307 return ret;
308 }
309
310 /**********************************************************************************************
311
312 **********************************************************************************************/
313 static void print(...)
314 {
315 string str;
316
317 void putc(dchar c)
318 {
319 str ~= c;
320 }
321
322 doFormat(&putc, _arguments, _argptr);
323 uint written;
324 WriteFile(ddb_write, str.ptr, str.length, &written, null);
325 }
326
327 /**********************************************************************************************
328
329 **********************************************************************************************/
330 static void println(...)
331 {
332 string str;
333
334 void putc(dchar c)
335 {
336 str ~= c;
337 }
338
339 doFormat(&putc, _arguments, _argptr);
340 uint written;
341 str ~= '\n';
342 WriteFile(ddb_write, str.ptr, str.length, &written, null);
343 }
344
345 /**********************************************************************************************
346
347 **********************************************************************************************/
348 static void write(string str)
349 {
350 uint written;
351 WriteFile(ddb_write, str.ptr, str.length, &written, null);
352 }
353
354 /**********************************************************************************************
355
356 **********************************************************************************************/
357 static void writeln(string str)
358 {
359 uint written;
360 str ~= "\n";
361 WriteFile(ddb_write, str.ptr, str.length, &written, null);
362 }
363 }
364
365 /**************************************************************************************************
366
367 **************************************************************************************************/
368 TypeInfo TypeInfoFromMangled(string mangled)
369 {
370 TypeInfo res;
371 TypeInfo* ti = &res;
372
373 for ( uint i=0; ti !is null && i < mangled.length; ++i )
374 {
375 switch ( mangled[i] )
376 {
377 case 'C':
378 debug DbgIO.println("TypeInfoFromMangled: classinfos not supported, yet");
379 return null;
380 case 'P':
381 TypeInfo_Pointer tip = new TypeInfo_Pointer;
382 *ti = tip;
383 ti = &tip.m_next;
384 break;
385 case 'G':
386 TypeInfo_StaticArray tia = new TypeInfo_StaticArray;
387 *ti = tia;
388 ti = &tia.value;
389 break;
390 case 'A':
391 switch ( mangled[i+1] )
392 {
393 case 'v': *ti = new TypeInfo_Av; ti = null; break;
394 case 'x':
395 case 'b': *ti = new TypeInfo_Ab; ti = null; break;
396 case 'g': *ti = new TypeInfo_Ag; ti = null; break;
397 case 'h': *ti = new TypeInfo_Ah; ti = null; break;
398 case 's': *ti = new TypeInfo_As; ti = null; break;
399 case 't': *ti = new TypeInfo_At; ti = null; break;
400 case 'i': *ti = new TypeInfo_Ai; ti = null; break;
401 case 'k': *ti = new TypeInfo_Ak; ti = null; break;
402 case 'l': *ti = new TypeInfo_Al; ti = null; break;
403 case 'm': *ti = new TypeInfo_Am; ti = null; break;
404 case 'f': *ti = new TypeInfo_Af; ti = null; break;
405 case 'd': *ti = new TypeInfo_Ad; ti = null; break;
406 case 'e': *ti = new TypeInfo_Ae; ti = null; break;
407 case 'o': *ti = new TypeInfo_Ao; ti = null; break;
408 case 'p': *ti = new TypeInfo_Ap; ti = null; break;
409 case 'j': *ti = new TypeInfo_Aj; ti = null; break;
410 case 'q': *ti = new TypeInfo_Aq; ti = null; break;
411 case 'r': *ti = new TypeInfo_Ar; ti = null; break;
412 case 'c': *ti = new TypeInfo_Ac; ti = null; break;
413 case 'a': *ti = new TypeInfo_Aa; ti = null; break;
414 case 'u': *ti = new TypeInfo_Au; ti = null; break;
415 case 'w': *ti = new TypeInfo_Aw; ti = null; break;
416 default:
417 TypeInfo_Array tia = new TypeInfo_Array;
418 *ti = tia;
419 ti = &tia.value;
420 }
421 break;
422 case 'v': *ti = new TypeInfo_v; ti = null; break;
423 case 'x':
424 case 'b': *ti = new TypeInfo_b; ti = null; break;
425 case 'g': *ti = new TypeInfo_g; ti = null; break;
426 case 'h': *ti = new TypeInfo_h; ti = null; break;
427 case 's': *ti = new TypeInfo_s; ti = null; break;
428 case 't': *ti = new TypeInfo_t; ti = null; break;
429 case 'i': *ti = new TypeInfo_i; ti = null; break;
430 case 'k': *ti = new TypeInfo_k; ti = null; break;
431 case 'l': *ti = new TypeInfo_l; ti = null; break;
432 case 'm': *ti = new TypeInfo_m; ti = null; break;
433 case 'f': *ti = new TypeInfo_f; ti = null; break;
434 case 'd': *ti = new TypeInfo_d; ti = null; break;
435 case 'e': *ti = new TypeInfo_e; ti = null; break;
436 case 'o': *ti = new TypeInfo_o; ti = null; break;
437 case 'p': *ti = new TypeInfo_p; ti = null; break;
438 case 'j': *ti = new TypeInfo_j; ti = null; break;
439 case 'q': *ti = new TypeInfo_q; ti = null; break;
440 case 'r': *ti = new TypeInfo_r; ti = null; break;
441 case 'c': *ti = new TypeInfo_c; ti = null; break;
442 case 'a': *ti = new TypeInfo_a; ti = null; break;
443 case 'u': *ti = new TypeInfo_u; ti = null; break;
444 case 'w': *ti = new TypeInfo_w; ti = null; break;
445 default:
446 debug DbgIO.println("unknown mangled type "~mangled[i]);
447 assert(0);
448 }
449 }
450
451 return res;
452 }
453
454 /**************************************************************************************************
455
456 **************************************************************************************************/
457 class DataReader
458 {
459 ubyte[] data;
460 uint cursor;
461
462 /**********************************************************************************************
463
464 **********************************************************************************************/
465 this(ubyte[] d)
466 {
467 data = d;
468 }
469
470 /**********************************************************************************************
471
472 **********************************************************************************************/
473 void alignCursor(ubyte num)
474 {
475 cursor += (num + cursor) % num;
476 assert(cursor<=data.length);
477 }
478
479 /**********************************************************************************************
480
481 **********************************************************************************************/
482 bool available()
483 {
484 return cursor<data.length;
485 }
486
487 /**********************************************************************************************
488
489 **********************************************************************************************/
490 void seek(uint offset)
491 {
492 cursor=offset;
493 if ( cursor > data.length )
494 throw new Exception("DataReader.seek beyond end of data offset="~.toString(cursor)~", $="~.toString(data.length));
495 }
496
497 /**********************************************************************************************
498
499 **********************************************************************************************/
500 void relseek(int offset)
501 {
502 cursor+=offset;
503 if ( cursor > data.length )
504 throw new Exception("DataReader.seek beyond end of data offset="~.toString(cursor)~", $="~.toString(data.length));
505 }
506
507 /**********************************************************************************************
508
509 **********************************************************************************************/
510 void peek(out ubyte val)
511 {
512 assert(cursor<data.length);
513 val = data[cursor];
514 }
515
516 /**********************************************************************************************
517
518 **********************************************************************************************/
519 void read(out ubyte val)
520 {
521 assert(cursor<data.length);
522 val = data[cursor];
523 ++cursor;
524 }
525 void read(out char val) { read(*cast(ubyte*)&val); }
526
527 /**********************************************************************************************
528
529 **********************************************************************************************/
530 void read(out ushort val)
531 {
532 assert(cursor+1<data.length);
533 val = (cast(ushort[])(data[cursor..cursor+2]))[0];
534 cursor+=2;
535 }
536 void read(out short val) { read(*cast(ushort*)&val); }
537
538 /**********************************************************************************************
539
540 **********************************************************************************************/
541 void read(out uint val)
542 {
543 assert(cursor+3<data.length);
544 val = (cast(uint[])(data[cursor..cursor+4]))[0];
545 cursor+=4;
546 }
547 void read(out int val) { read(*cast(uint*)&val); }
548 void read(out float val) { read(*cast(uint*)&val); }
549
550 /**********************************************************************************************
551
552 **********************************************************************************************/
553 void read(out ulong val)
554 {
555 assert(cursor+7<data.length);
556 val = (cast(ulong[])(data[cursor..cursor+8]))[0];
557 cursor+=8;
558 }
559 void read(out long val) { read(*cast(ulong*)&val); }
560 void read(out double val) { read(*cast(ulong*)&val); }
561 void read(out cfloat val) { read(*cast(ulong*)&val); }
562
563 /**********************************************************************************************
564
565 **********************************************************************************************/
566 void read(out real val)
567 {
568 assert(cursor+9<data.length);
569 val = (cast(real[])(data[cursor..cursor+10]))[0];
570 cursor+=10;
571 }
572
573 /**********************************************************************************************
574
575 **********************************************************************************************/
576 void read(out string str)
577 {
578 assert(cursor<data.length);
579 ushort len = data[cursor++];
580 if ( len >= 0xff && data[cursor] == 0 ) {
581 ++cursor;
582 read(len);
583 }
584
585 assert(cursor+len<=data.length, "dr cursor="~.toString(cursor)~" len="~.toString(len));
586 str = (cast(string)data)[cursor..cursor+len];
587 cursor+=len;
588 }
589
590 /**********************************************************************************************
591
592 **********************************************************************************************/
593 void readA(T)(out T[] array, uint length)
594 {
595 uint size = length*T.sizeof;
596 assert(cursor<=data.length-size);
597 array = cast(T[])(data[cursor..cursor+size]);
598 cursor+=size;
599 }
600 }
601
602 /**************************************************************************************************
603
604 **************************************************************************************************/
605 string getFullPath(string filename)
606 {
607 char[] fullpath;
608 char* filepart;
609 fullpath.length = 4096;
610 int len = GetFullPathName(
611 toStringz(filename),
612 fullpath.length,
613 fullpath.ptr,
614 &filepart
615 );
616 if ( len <= 0 )
617 return null;
618 fullpath.length = len;
619
620 char[] longfullpath;
621 longfullpath.length = 4096;
622 len = GetLongPathName(
623 toStringz(fullpath),
624 longfullpath.ptr,
625 longfullpath.length
626 );
627 longfullpath.length = len;
628 return longfullpath;
629 }
630
631 /**************************************************************************************************
632
633 **************************************************************************************************/
634 struct DbgTimer
635 {
636 d_time time;
637
638 void start()
639 {
640 time = getUTCtime;
641 }
642
643 string finish()
644 {
645 time = getUTCtime - time;
646 return format("%d'%03d", time / TicksPerSecond, time % TicksPerSecond);
647 }
648 }