Mercurial > projects > ddbg_continued
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 } |