From 2fd7d60c13de12ba99db45b6216d29ec399d6aed Mon Sep 17 00:00:00 2001 From: Brad Roberts Date: Mon, 10 Sep 2007 04:05:01 +0000 Subject: [PATCH] phobos 0.96 --- internal/adi.d | 8 +- internal/cast.d | 14 +- internal/obj.d | 2 +- internal/object.d | 4 +- linux.mak | 6 +- std/c/linux/linux.d | 6 +- std/c/time.d | 5 + std/c/windows/windows.d | 7 +- std/compiler.d | 5 + std/date.d | 7 +- std/dateparse.d | 59 +- std/format.d | 11 +- std/loader.d | 24 +- std/perf.d | 1148 +++++++++++++++++++++++++++++++++++++++ std/process.d | 84 ++- std/recls.d | 1 + std/regexp.d | 2 +- std/stdint.d | 5 + std/stdio.d | 2 +- std/system.d | 5 + std/thread.d | 33 +- std/typeinfo/ti_AC.d | 6 +- std/uri.d | 21 + std/utf.d | 33 +- std/windows/registry.d | 74 +-- win32.mak | 10 +- 26 files changed, 1475 insertions(+), 107 deletions(-) create mode 100644 std/perf.d diff --git a/internal/adi.d b/internal/adi.d index e2e549710..83edaf100 100644 --- a/internal/adi.d +++ b/internal/adi.d @@ -28,7 +28,7 @@ struct Array extern (C) Array _adReverse(Array a, int szelem) out (result) { - assert(result === a); + assert(result is a); } body { @@ -81,7 +81,7 @@ unittest for (i = 0; i < 5; i++) a[i] = i; b = a.reverse; - assert(b === a); + assert(b is a); for (i = 0; i < 5; i++) assert(a[i] == 4 - i); @@ -99,7 +99,7 @@ unittest c[i].e = 10; } d = c.reverse; - assert(d === c); + assert(d is c); for (i = 0; i < 5; i++) { assert(c[i].a == 4 - i); @@ -114,7 +114,7 @@ unittest extern (C) bit[] _adReverseBit(bit[] a) out (result) { - assert(result === a); + assert(result is a); } body { diff --git a/internal/cast.d b/internal/cast.d index 58c1b44c3..3b61ac538 100644 --- a/internal/cast.d +++ b/internal/cast.d @@ -48,18 +48,18 @@ Object _d_dynamic_cast(Object o, ClassInfo c) int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset) { int i; - if (oc === c) + if (oc is c) return 1; do { - if (oc.base === c) + if (oc.base is c) return 1; for (i = 0; i < oc.interfaces.length; i++) { ClassInfo ic; ic = oc.interfaces[i].classinfo; - if (ic === c) + if (ic is c) { offset = oc.interfaces[i].offset; return 1; } @@ -82,18 +82,18 @@ int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset) int _d_isbaseof(ClassInfo oc, ClassInfo c) { int i; - if (oc === c) + if (oc is c) return 1; do { - if (oc.base === c) + if (oc.base is c) return 1; for (i = 0; i < oc.interfaces.length; i++) { ClassInfo ic; ic = oc.interfaces[i].classinfo; - if (ic === c || _d_isbaseof(ic, c)) + if (ic is c || _d_isbaseof(ic, c)) return 1; } oc = oc.base; @@ -119,7 +119,7 @@ void *_d_interface_vtbl(ClassInfo ic, Object o) ClassInfo oic; oic = oc.interfaces[i].classinfo; - if (oic === ic) + if (oic is ic) { return cast(void *)oc.interfaces[i].vtbl; } diff --git a/internal/obj.d b/internal/obj.d index 74b0633f0..035b1d80d 100644 --- a/internal/obj.d +++ b/internal/obj.d @@ -13,7 +13,7 @@ extern (C): int _d_obj_eq(Object o1, Object o2) { - return o1 === o2 || (o1 && o1.opEquals(o2)); + return o1 is o2 || (o1 && o1.opEquals(o2)); } diff --git a/internal/object.d b/internal/object.d index 4d63a96d7..f194d1359 100644 --- a/internal/object.d +++ b/internal/object.d @@ -45,7 +45,7 @@ class Object int opEquals(Object o) { - return this === o; + return this is o; } } @@ -93,7 +93,7 @@ class TypeInfo * across DLL's. Therefore, comparing for a name match is * sufficient. */ - return this === o || this.classinfo.name == o.classinfo.name; + return this is o || this.classinfo.name == o.classinfo.name; } uint getHash(void *p) { return cast(uint)p; } diff --git a/linux.mak b/linux.mak index 3247c4762..c28352901 100644 --- a/linux.mak +++ b/linux.mak @@ -56,6 +56,7 @@ OBJS= asserterror.o deh2.o switch.o complex.o gcstats.o \ crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ + perf.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -95,7 +96,7 @@ SRC_STD= std/zlib.d std/zip.d std/stdint.d std/conv.d std/utf.d std/uri.d \ std/intrinsic.d std/array.d std/switcherr.d std/syserror.d \ std/regexp.d std/random.d std/stream.d std/process.d std/recls.d \ std/socket.d std/socketstream.d std/loader.d std/stdarg.d \ - std/stdio.d std/format.d + std/stdio.d std/format.d std/perf.d SRC_STD_C= std/c/process.d std/c/stdlib.d std/c/time.d std/c/stdio.d \ std/c/math.d std/c/stdarg.d @@ -398,6 +399,9 @@ outofmemory.o : std/outofmemory.d path.o : std/path.d $(DMD) -c $(DFLAGS) std/path.d +perf.o : std/perf.d + $(DMD) -c $(DFLAGS) std/perf.d + process.o : std/process.d $(DMD) -c $(DFLAGS) std/process.d diff --git a/std/c/linux/linux.d b/std/c/linux/linux.d index 20d5dc804..9256b40be 100644 --- a/std/c/linux/linux.d +++ b/std/c/linux/linux.d @@ -1,9 +1,13 @@ +/* Written by Walter Bright + * www.digitalmars.com + * Placed into public domain. + */ + module std.c.linux.linux; import std.c.linux.linuxextern; -alias int time_t; alias int off_t; enum : int diff --git a/std/c/time.d b/std/c/time.d index 96e165b78..8b587eb9e 100644 --- a/std/c/time.d +++ b/std/c/time.d @@ -1,4 +1,9 @@ +/* Written by Walter Bright + * www.digitalmars.com + * Placed into public domain. + */ + module std.c.time; extern (C): diff --git a/std/c/windows/windows.d b/std/c/windows/windows.d index 074532ae5..0766aec35 100644 --- a/std/c/windows/windows.d +++ b/std/c/windows/windows.d @@ -285,7 +285,7 @@ struct FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; } -alias FILETIME* PFILETIME; +alias FILETIME* PFILETIME, LPFILETIME; struct WIN32_FIND_DATA { DWORD dwFileAttributes; @@ -872,6 +872,7 @@ enum } export HANDLE GetCurrentThread(); +export BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); export HANDLE GetCurrentProcess(); export BOOL DuplicateHandle (HANDLE sourceProcess, HANDLE sourceThread, HANDLE targetProcessHandle, HANDLE *targetHandle, DWORD access, @@ -880,6 +881,7 @@ export DWORD GetCurrentThreadId(); export BOOL SetThreadPriority(HANDLE hThread, int nPriority); export BOOL SetThreadPriorityBoost(HANDLE hThread, BOOL bDisablePriorityBoost); export BOOL GetThreadPriorityBoost(HANDLE hThread, PBOOL pDisablePriorityBoost); +export BOOL GetThreadTimes(HANDLE hThread, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); export int GetThreadPriority(HANDLE hThread); export BOOL GetThreadContext(HANDLE hThread, CONTEXT* lpContext); export BOOL SetThreadContext(HANDLE hThread, CONTEXT* lpContext); @@ -889,6 +891,9 @@ export DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); export DWORD WaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds); export void Sleep(DWORD dwMilliseconds); +export BOOL QueryPerformanceCounter(long* lpPerformanceCount); +export BOOL QueryPerformanceFrequency(long* lpFrequency); + enum { WM_NOTIFY = 0x004E, diff --git a/std/compiler.d b/std/compiler.d index 4b75e4cbb..89dd568a0 100644 --- a/std/compiler.d +++ b/std/compiler.d @@ -1,4 +1,9 @@ +/* Written by Walter Bright + * www.digitalmars.com + * Placed into Public Domain + */ + // Identify the compiler used and its various features. module std.compiler; diff --git a/std/date.d b/std/date.d index d0c6519bc..9df5468e2 100644 --- a/std/date.d +++ b/std/date.d @@ -25,7 +25,7 @@ struct Date int ms; // 0..999 int weekday; // 0: not specified // 1..7: Sunday..Saturday - int tzcorrection = int.min; // -12..12 correction in hours + int tzcorrection = int.min; // -1200..1200 correction in hours void parse(char[] s) { @@ -562,7 +562,10 @@ d_time parse(char[] s) if (dp.tzcorrection == Date.tzcorrection.init) time -= LocalTZA; else - time += cast(d_time)dp.tzcorrection * msPerHour; + { + time += cast(d_time)(dp.tzcorrection / 100) * msPerHour + + cast(d_time)(dp.tzcorrection % 100) * msPerMinute; + } day = MakeDay(dp.year, dp.month - 1, dp.day); n = MakeDate(day,time); n = TimeClip(n); diff --git a/std/dateparse.d b/std/dateparse.d index da00dafd3..95cc8ab77 100644 --- a/std/dateparse.d +++ b/std/dateparse.d @@ -1,8 +1,26 @@ -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com +/* + * Copyright (C) 1999-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + module std.dateparse; @@ -13,7 +31,7 @@ private import std.date; } -//debug=log; +//debug=dateparse; class DateParseError : Error { @@ -34,7 +52,7 @@ struct DateParse //else //buffer = new char[s.length]; - debug(log) printf("DateParse.parse('%.*s')\n", s); + debug(dateparse) printf("DateParse.parse('%.*s')\n", s); if (!parseString(s)) { goto Lerror; @@ -45,7 +63,7 @@ struct DateParse year = 0; else +/ - debug(log) + debug(dateparse) printf("year = %d, month = %d, day = %d\n%02d:%02d:%02d.%03d\nweekday = %d, tzcorrection = %d\n", year, month, day, hours, minutes, seconds, ms, @@ -59,7 +77,7 @@ struct DateParse (seconds < 0 || seconds > 59) || (tzcorrection != tzcorrection.init && ((tzcorrection < -1200 || tzcorrection > 1200) || - (tzcorrection % 100))) + (tzcorrection % 10))) ) { Lerror: @@ -80,8 +98,8 @@ struct DateParse } } - if (tzcorrection != tzcorrection.init) - tzcorrection /= 100; +// if (tzcorrection != tzcorrection.init) +// tzcorrection /= 100; if (year >= 0 && year <= 99) year += 1900; @@ -110,7 +128,7 @@ private: int ampm; // 0: not specified // 1: AM // 2: PM - int tzcorrection = int.min; // -12..12 correction in hours + int tzcorrection = int.min; // -1200..1200 correction in hours char[] s; int si; @@ -518,7 +536,7 @@ private: int n3; int dp; - debug(log) printf("DateParse.parseCalendarDate(%d)\n", n1); + debug(dateparse) printf("DateParse.parseCalendarDate(%d)\n", n1); dp = nextToken(); if (dp == DP.month) // day/month { @@ -670,7 +688,7 @@ unittest assert(d.second == 0); assert(d.ms == 0); assert(d.weekday == 0); - assert(d.tzcorrection == 8); + assert(d.tzcorrection == 800); dp.parse("Tue Apr 02 02:04:57 GMT-0800 1996", d); assert(d.year == 1996); @@ -681,7 +699,7 @@ unittest assert(d.second == 57); assert(d.ms == 0); assert(d.weekday == 3); - assert(d.tzcorrection == 8); + assert(d.tzcorrection == 800); dp.parse("March 14, -1980 21:14:50", d); assert(d.year == 1980); @@ -749,7 +767,18 @@ unittest assert(d.weekday == 0); assert(d.tzcorrection == int.min); - debug(log) printf("year = %d, month = %d, day = %d\n%02d:%02d:%02d.%03d\nweekday = %d, tzcorrection = %d\n", + dp.parse("Tue, 20 May 2003 15:38:58 +0530", d); + assert(d.year == 2003); + assert(d.month == 5); + assert(d.day == 20); + assert(d.hour == 15); + assert(d.minute == 38); + assert(d.second == 58); + assert(d.ms == 0); + assert(d.weekday == 3); + assert(d.tzcorrection == -530); + + debug(dateparse) printf("year = %d, month = %d, day = %d\n%02d:%02d:%02d.%03d\nweekday = %d, tzcorrection = %d\n", d.year, d.month, d.day, d.hour, d.minute, d.second, d.ms, d.weekday, d.tzcorrection); diff --git a/std/format.d b/std/format.d index 686d79d73..e9706724e 100644 --- a/std/format.d +++ b/std/format.d @@ -399,7 +399,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr) dchar[] sd = va_arg!(dchar[])(argptr); s = toUTF8(sd); Lputstr: - if (flags & FLprecision && precision > s.length) + if (flags & FLprecision && precision < s.length) s = s[0 .. precision]; putstr(s); break; @@ -788,5 +788,14 @@ unittest s = std.string.format("%0.0008f", 1e-05); assert(s == "0.00001000"); + + s = "helloworld"; + char[] r; + r = std.string.format("%.2s", s[0..5]); + assert(r == "he"); + r = std.string.format("%.20s", s[0..5]); + assert(r == "hello"); + r = std.string.format("%8s", s[0..5]); + assert(r == " hello"); } diff --git a/std/loader.d b/std/loader.d index a00d6ba43..eeff42563 100644 --- a/std/loader.d +++ b/std/loader.d @@ -214,7 +214,7 @@ version(Windows) { HXModule hmod = cast(HXModule)LoadLibraryA(toStringz(moduleName)); - if(null === hmod) + if(null is hmod) { record_error_(); } @@ -255,7 +255,7 @@ version(Windows) { void *symbol = GetProcAddress(cast(HModule_)hModule, toStringz(symbolName)); - if(null === symbol) + if(null is symbol) { record_error_(); } @@ -306,7 +306,7 @@ else version(Linux) private void record_error_() { char *err = dlerror(); - s_lastError = (null === err) ? "" : err[0 .. std.string.strlen(err)]; + s_lastError = (null is err) ? "" : err[0 .. std.string.strlen(err)]; } private int ExeModule_Init_() @@ -344,7 +344,7 @@ else version(Linux) { HModule_ hmod = dlopen(toStringz(moduleName), RTLD_NOW); - if(null === hmod) + if(null is hmod) { record_error_(); @@ -372,7 +372,7 @@ else version(Linux) assert(null !== mi.m_hmod); assert(null !== mi.m_name); assert(null !== s_modules[mi.m_name]); - assert(mi === s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); } body { @@ -399,7 +399,7 @@ else version(Linux) assert(null !== mi.m_hmod); assert(null !== mi.m_name); assert(null !== s_modules[mi.m_name]); - assert(mi === s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); } body { @@ -431,7 +431,7 @@ else version(Linux) assert(null !== mi.m_hmod); assert(null !== mi.m_name); assert(null !== s_modules[mi.m_name]); - assert(mi === s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); } body { @@ -462,7 +462,7 @@ else version(Linux) assert(null !== mi.m_hmod); assert(null !== mi.m_name); assert(null !== s_modules[mi.m_name]); - assert(mi === s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); } body { @@ -543,13 +543,13 @@ public: version (Windows) { m_hModule = cast(HXModule)LoadLibraryA(toStringz(moduleName)); - if (null === m_hModule) + if (null is m_hModule) throw new ExeModuleException(GetLastError()); } else version (linux) { m_hModule = ExeModule_Load(moduleName); - if (null === m_hModule) + if (null is m_hModule) throw new ExeModuleException(ExeModule_Error()); } else @@ -602,7 +602,7 @@ public: version (Windows) { void *symbol = GetProcAddress(cast(HModule_)m_hModule, toStringz(symbolName)); - if(null === symbol) + if(null is symbol) { throw new ExeModuleException(GetLastError()); } @@ -611,7 +611,7 @@ public: { void *symbol = ExeModule_GetSymbol(m_hModule, symbolName); - if(null === symbol) + if(null is symbol) { throw new ExeModuleException(ExeModule_Error()); } diff --git a/std/perf.d b/std/perf.d new file mode 100644 index 000000000..84704f8a9 --- /dev/null +++ b/std/perf.d @@ -0,0 +1,1148 @@ +/* ///////////////////////////////////////////////////////////////////////////// + * File: perf.d + * + * Purpose: Performance measurement classes. These classes were ported + * over to D from the STLSoft (http://stlsoft.org/) C++ libraries, + * which were documented in the article "Win32 Performance + * Measurement Option", May 2003 issue of Windows Develper Network + * (http://www.windevnet.com/documents/win0305a/). + * + * Created 19th March 2004 + * Updated: 18th July 2004 + * + * www: http://www.digitalmars.com/ + * + * Copyright (C) 2004 by Digital Mars + * All Rights Reserved + * Written by Matthew Wilson + * www.digitalmars.com + * License for redistribution is by either the Artistic License in artistic.txt, + * or the LGPL + * + * ////////////////////////////////////////////////////////////////////////// */ + + +/** \file std/perf.d This file contains platform-independent performance classes */ + +module std.perf; + +/// \brief Performance counter scope class generating template +/// +/// This template declares the class PerformanceCounterScope which manages a +/// performance counter instance, scoping its measurement interval by virtue of +/// its supporting the RAII mechanism. + +auto class PerformanceCounterScope(T) +{ + /// \name Construction + /// @{ + public: + /// Constructs an instance of the PerformanceCounterScope using a reference + /// to the parameterising performance counter class, whose measurement is + /// to be scoped. The measurement interval is commenced with a call to + /// start() on the managed counter instance. + this(T counter) + in + { + assert(null !== counter); + } + body + { + m_counter = counter; + + m_counter.start(); + } + /// The measurement interval is completed with a call to stop() on the + /// managed counter instance. + ~this() + { + m_counter.stop(); + } + + /// Calls stop() on the managed counter instance, so that intermediate + /// timings can be taken. + void stop() + { + m_counter.stop(); + } + + /// Returns a reference to the managed counter instance. + T counter() + { + return m_counter; + } + /// @} + + /// \name Members + /// @{ + private: + T m_counter; + /// @} + + // Not to be implemented + private: + this(PerformanceCounterScope rhs); +} + +version(linux) +{ + + extern (C) + { + private struct timeval + { + int tv_sec; /*!< The number of seconds, since Jan. 1, 1970, in the time value. */ + int tv_usec; /*!< The number of microseconds in the time value. */ + }; + private struct timezone + { + int tz_minuteswest; /*!< minutes west of Greenwich. */ + int tz_dsttime; /*!< type of dst corrections to apply. */ + }; + private void gettimeofday(timeval *tv, timezone *tz); + } + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \brief A performance counter that uses the most accurate measurement APIs available on the host machine + /// + /// This class attempts to use the high performance hardware counter as its measurement resource, but failing + /// that it defaults to less accurate resources in order to guarantee that meaningful measurements are always + /// available to application code + /// + /// \ingroup group_synsoft_linux_perf + class PerformanceCounter + { + /// \name Types + /// @{ + private: + alias timeval epoch_type; + public: + /// \brief The interval type + /// + /// The type of the interval measurement, a 64-bit signed integer + alias long interval_type; + + /// \brief The scope type + /// + /// The type with which instances of the counter class can be subject to the RAII mechanism in order + /// to scope particular measurement intervals + alias PerformanceCounterScope!(PerformanceCounter) scope_type; + /// @} + + /// \name Operations + /// @{ + public: + /// \brief Starts measurement + /// + /// Begins the measurement period + void start() + { + timezone tz; + + gettimeofday(&m_start, &tz); + } + + /// \brief Ends measurement + /// + /// Ends the measurement period + void stop() + { + timezone tz; + + gettimeofday(&m_end, &tz); + } + /// @} + + /// \name Attributes + /// @{ + public: + /// \brief The elapsed count in the measurement period + /// + /// This represents the extent, in machine-specific increments, of the measurement period + interval_type periodCount() + { + return microseconds; + } + + /// \brief The number of whole seconds in the measurement period + /// + /// This represents the extent, in whole seconds, of the measurement period + interval_type seconds() + { + interval_type start = cast(interval_type)m_start.tv_sec + cast(interval_type)m_start.tv_usec / (1000 * 1000); + interval_type end = cast(interval_type)m_end.tv_sec + cast(interval_type)m_end.tv_usec / (1000 * 1000); + + return end - start; + } + + /// \brief The number of whole milliseconds in the measurement period + /// + /// This represents the extent, in whole milliseconds, of the measurement period + interval_type milliseconds() + { + interval_type start = cast(interval_type)m_start.tv_sec * 1000 + cast(interval_type)m_start.tv_usec / 1000; + interval_type end = cast(interval_type)m_end.tv_sec * 1000 + cast(interval_type)m_end.tv_usec / 1000; + + return end - start; + } + + /// \brief The number of whole microseconds in the measurement period + /// + /// This represents the extent, in whole microseconds, of the measurement period + interval_type microseconds() + { + interval_type start = cast(interval_type)m_start.tv_sec * 1000 * 1000 + cast(interval_type)m_start.tv_usec; + interval_type end = cast(interval_type)m_end.tv_sec * 1000 * 1000 + cast(interval_type)m_end.tv_usec; + + return end - start; + } + /// @} + + /// \name Members + /// @{ + private: + epoch_type m_start; // start of measurement period + epoch_type m_end; // End of measurement period + /// @} + } + + unittest + { + alias PerformanceCounter counter_type; + + counter_type counter = new counter_type(); + + counter.start(); + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us1 = counter.microseconds(); + counter_type.interval_type ms1 = counter.milliseconds(); + counter_type.interval_type s1 = counter.seconds(); + + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us2 = counter.microseconds(); + counter_type.interval_type ms2 = counter.milliseconds(); + counter_type.interval_type s2 = counter.seconds(); + + assert(us2 >= us1); + assert(ms2 >= ms1); + assert(s2 >= s1); + } + + /* ////////////////////////////////////////////////////////////////////////// */ +} +else version(Windows) +{ + + private import std.c.windows.windows; + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \defgroup group_synsoft_win32_perf synsoft.win32.perf + /// \ingroup group_synsoft_win32 + /// \brief This library provides Win32 Performance facilities + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \brief A performance counter that uses the high performance hardware counter on the host machine + /// + /// This class provides high-resolution performance monitoring using the host machine's high performance + /// hardware counter. This class does not provide meaningful timing information on operating systems + /// that do not provide a high performance hardware counter. + /// + /// \ingroup group_synsoft_win32_perf + class HighPerformanceCounter + { + /// \name Types + /// @{ + private: + alias long epoch_type; + public: + /// \brief The interval type + /// + /// The type of the interval measurement, a 64-bit signed integer + alias long interval_type; + + /// \brief The scope type + /// + /// The type with which instances of the counter class can be subject to the RAII mechanism in order + /// to scope particular measurement intervals + alias PerformanceCounterScope!(HighPerformanceCounter) scope_type; + /// @} + + /// \name Construction + /// @{ + private: + static this() + { + if(!QueryPerformanceFrequency(&sm_freq)) + { + sm_freq = 0x7fffffffffffffffL; + } + } + /// @} + + /// \name Operations + /// @{ + public: + /// \brief Starts measurement + /// + /// Begins the measurement period + void start() + { + QueryPerformanceCounter(&m_start); + } + + /// \brief Ends measurement + /// + /// Ends the measurement period + void stop() + { + QueryPerformanceCounter(&m_end); + } + /// @} + + /// \name Attributes + /// @{ + public: + /// \brief The elapsed count in the measurement period + /// + /// This represents the extent, in machine-specific increments, of the measurement period + interval_type periodCount() + { + return m_end - m_start; + } + + /// \brief The number of whole seconds in the measurement period + /// + /// This represents the extent, in whole seconds, of the measurement period + interval_type seconds() + { + return periodCount() / sm_freq; + } + + /// \brief The number of whole milliseconds in the measurement period + /// + /// This represents the extent, in whole milliseconds, of the measurement period + interval_type milliseconds() + { + interval_type result; + interval_type count = periodCount(); + + if(count < 0x20C49BA5E353F7L) + { + result = (count * 1000) / sm_freq; + } + else + { + result = (count / sm_freq) * 1000; + } + + return result; + } + + /// \brief The number of whole microseconds in the measurement period + /// + /// This represents the extent, in whole microseconds, of the measurement period + interval_type microseconds() + { + interval_type result; + interval_type count = periodCount(); + + if(count < 0x8637BD05AF6L) + { + result = (count * 1000000) / sm_freq; + } + else + { + result = (count / sm_freq) * 1000000; + } + + return result; + } + /// @} + + /// \name Members + /// @{ + private: + epoch_type m_start; // start of measurement period + epoch_type m_end; // End of measurement period + static interval_type sm_freq; // Frequency + /// @} + } + + unittest + { + alias HighPerformanceCounter counter_type; + + counter_type counter = new counter_type(); + + counter.start(); + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us1 = counter.microseconds(); + counter_type.interval_type ms1 = counter.milliseconds(); + counter_type.interval_type s1 = counter.seconds(); + + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us2 = counter.microseconds(); + counter_type.interval_type ms2 = counter.milliseconds(); + counter_type.interval_type s2 = counter.seconds(); + + assert(us2 >= us1); + assert(ms2 >= ms1); + assert(s2 >= s1); + } + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \brief A low-cost, low-resolution performance counter + /// + /// This class provides low-resolution, but low-latency, performance monitoring + /// and is guaranteed to be meaningful on all operating systems. + /// + /// \ingroup group_synsoft_win32_perf + class TickCounter + { + /// \name Types + /// @{ + private: + alias long epoch_type; + public: + /// \brief The interval type + /// + /// The type of the interval measurement, a 64-bit signed integer + alias long interval_type; + + /// \brief The scope type + /// + /// The type with which instances of the counter class can be subject to the RAII mechanism in order + /// to scope particular measurement intervals + alias PerformanceCounterScope!(TickCounter) scope_type; + /// @} + + /// \name Construction + /// @{ + public: + /// @} + + /// \name Operations + /// @{ + public: + /// \brief Starts measurement + /// + /// Begins the measurement period + void start() + { + m_start = GetTickCount(); + } + + /// \brief Ends measurement + /// + /// Ends the measurement period + void stop() + { + m_end = GetTickCount(); + } + /// @} + + /// \name Attributes + /// @{ + public: + /// \brief The elapsed count in the measurement period + /// + /// This represents the extent, in machine-specific increments, of the measurement period + interval_type periodCount() + { + return m_end - m_start; + } + + /// \brief The number of whole seconds in the measurement period + /// + /// This represents the extent, in whole seconds, of the measurement period + interval_type seconds() + { + return periodCount() / 1000; + } + + /// \brief The number of whole milliseconds in the measurement period + /// + /// This represents the extent, in whole milliseconds, of the measurement period + interval_type milliseconds() + { + return periodCount(); + } + + /// \brief The number of whole microseconds in the measurement period + /// + /// This represents the extent, in whole microseconds, of the measurement period + interval_type microseconds() + { + return periodCount() * 1000; + } + /// @} + + /// \name Members + /// @{ + private: + uint m_start; // start of measurement period + uint m_end; // End of measurement period + /// @} + } + + unittest + { + alias TickCounter counter_type; + + counter_type counter = new counter_type(); + + counter.start(); + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us1 = counter.microseconds(); + counter_type.interval_type ms1 = counter.milliseconds(); + counter_type.interval_type s1 = counter.seconds(); + + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us2 = counter.microseconds(); + counter_type.interval_type ms2 = counter.milliseconds(); + counter_type.interval_type s2 = counter.seconds(); + + assert(us2 >= us1); + assert(ms2 >= ms1); + assert(s2 >= s1); + } + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \brief A performance counter that provides thread-specific performance timings + /// + /// This class uses the operating system's performance monitoring facilities to provide timing + /// information pertaining to the calling thread only, irrespective of the activities of other + /// threads on the system. This class does not provide meaningful timing information on operating + /// systems that do not provide thread-specific monitoring. + /// + /// \ingroup group_synsoft_win32_perf + class ThreadTimesCounter + { + /// \name Types + /// @{ + private: + alias long epoch_type; + public: + /// \brief The interval type + /// + /// The type of the interval measurement, a 64-bit signed integer + alias long interval_type; + + /// \brief The scope type + /// + /// The type with which instances of the counter class can be subject to the RAII mechanism in order + /// to scope particular measurement intervals + alias PerformanceCounterScope!(ThreadTimesCounter) scope_type; + /// @} + + /// \name Construction + /// @{ + public: + /// \brief Constructor + /// + /// Creates an instance of the class, and caches the thread token so that measurements will + /// be taken with respect to the thread in which the class was created. + this() + { + m_thread = GetCurrentThread(); + } + /// @} + + /// \name Operations + /// @{ + public: + /// \brief Starts measurement + /// + /// Begins the measurement period + void start() + { + FILETIME creationTime; + FILETIME exitTime; + + GetThreadTimes(m_thread, &creationTime, &exitTime, cast(FILETIME*)&m_kernelStart, cast(FILETIME*)&m_userStart); + } + + /// \brief Ends measurement + /// + /// Ends the measurement period + void stop() + { + FILETIME creationTime; + FILETIME exitTime; + + GetThreadTimes(m_thread, &creationTime, &exitTime, cast(FILETIME*)&m_kernelEnd, cast(FILETIME*)&m_userEnd); + } + /// @} + + /// \name Attributes + /// @{ + public: + /// \name Kernel + /// @{ + + /// \brief The elapsed count in the measurement period for kernel mode activity + /// + /// This represents the extent, in machine-specific increments, of the measurement period for kernel mode activity + interval_type kernelPeriodCount() + { + return m_kernelEnd - m_kernelStart; + } + /// \brief The number of whole seconds in the measurement period for kernel mode activity + /// + /// This represents the extent, in whole seconds, of the measurement period for kernel mode activity + interval_type kernelSeconds() + { + return kernelPeriodCount() / 10000000; + } + /// \brief The number of whole milliseconds in the measurement period for kernel mode activity + /// + /// This represents the extent, in whole milliseconds, of the measurement period for kernel mode activity + interval_type kernelMilliseconds() + { + return kernelPeriodCount() / 10000; + } + /// \brief The number of whole microseconds in the measurement period for kernel mode activity + /// + /// This represents the extent, in whole microseconds, of the measurement period for kernel mode activity + interval_type kernelMicroseconds() + { + return kernelPeriodCount() / 10; + } + /// @} + + /// \name User + /// @{ + + /// \brief The elapsed count in the measurement period for user mode activity + /// + /// This represents the extent, in machine-specific increments, of the measurement period for user mode activity + interval_type userPeriodCount() + { + return m_userEnd - m_userStart; + } + /// \brief The number of whole seconds in the measurement period for user mode activity + /// + /// This represents the extent, in whole seconds, of the measurement period for user mode activity + interval_type userSeconds() + { + return userPeriodCount() / 10000000; + } + /// \brief The number of whole milliseconds in the measurement period for user mode activity + /// + /// This represents the extent, in whole milliseconds, of the measurement period for user mode activity + interval_type userMilliseconds() + { + return userPeriodCount() / 10000; + } + /// \brief The number of whole microseconds in the measurement period for user mode activity + /// + /// This represents the extent, in whole microseconds, of the measurement period for user mode activity + interval_type userMicroseconds() + { + return userPeriodCount() / 10; + } + /// @} + + /// \name Total + /// @{ + + /// \brief The elapsed count in the measurement period + /// + /// This represents the extent, in machine-specific increments, of the measurement period + interval_type periodCount() + { + return kernelPeriodCount() + userPeriodCount(); + } + + /// \brief The number of whole seconds in the measurement period + /// + /// This represents the extent, in whole seconds, of the measurement period + interval_type seconds() + { + return periodCount() / 10000000; + } + + /// \brief The number of whole milliseconds in the measurement period + /// + /// This represents the extent, in whole milliseconds, of the measurement period + interval_type milliseconds() + { + return periodCount() / 10000; + } + + /// \brief The number of whole microseconds in the measurement period + /// + /// This represents the extent, in whole microseconds, of the measurement period + interval_type microseconds() + { + return periodCount() / 10; + } + /// @} + /// @} + + /// \name Members + /// @{ + private: + epoch_type m_kernelStart; + epoch_type m_kernelEnd; + epoch_type m_userStart; + epoch_type m_userEnd; + HANDLE m_thread; + /// @} + } + + unittest + { + alias ThreadTimesCounter counter_type; + + counter_type counter = new counter_type(); + + counter.start(); + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us1 = counter.microseconds(); + counter_type.interval_type ms1 = counter.milliseconds(); + counter_type.interval_type s1 = counter.seconds(); + + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us2 = counter.microseconds(); + counter_type.interval_type ms2 = counter.milliseconds(); + counter_type.interval_type s2 = counter.seconds(); + + assert(us2 >= us1); + assert(ms2 >= ms1); + assert(s2 >= s1); + } + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \brief A performance counter that provides process-specific performance timings + /// + /// This class uses the operating system's performance monitoring facilities to provide timing + /// information pertaining to the calling process only, irrespective of the activities of other + /// processes on the system. This class does not provide meaningful timing information on operating + /// systems that do not provide process-specific monitoring. + /// + /// \ingroup group_synsoft_win32_perf + class ProcessTimesCounter + { + /// \name Types + /// @{ + private: + alias long epoch_type; + public: + /// \brief The interval type + /// + /// The type of the interval measurement, a 64-bit signed integer + alias long interval_type; + + /// \brief The scope type + /// + /// The type with which instances of the counter class can be subject to the RAII mechanism in order + /// to scope particular measurement intervals + alias PerformanceCounterScope!(ProcessTimesCounter) scope_type; + /// @} + + /// \name Construction + /// @{ + private: + /// \brief Class constructor + /// + /// Detects availability of the high performance hardware counter, and if + /// not available adjusts + static this() + { + sm_process = GetCurrentProcess(); + } + /// @} + + /// \name Operations + /// @{ + public: + /// \brief Starts measurement + /// + /// Begins the measurement period + void start() + { + FILETIME creationTime; + FILETIME exitTime; + + GetProcessTimes(sm_process, &creationTime, &exitTime, cast(FILETIME*)&m_kernelStart, cast(FILETIME*)&m_userStart); + } + + /// \brief Ends measurement + /// + /// Ends the measurement period + void stop() + { + FILETIME creationTime; + FILETIME exitTime; + + GetProcessTimes(sm_process, &creationTime, &exitTime, cast(FILETIME*)&m_kernelEnd, cast(FILETIME*)&m_userEnd); + } + /// @} + + /// \name Attributes + /// @{ + public: + /// \name Kernel + /// @{ + + /// \brief The elapsed count in the measurement period for kernel mode activity + /// + /// This represents the extent, in machine-specific increments, of the measurement period for kernel mode activity + interval_type kernelPeriodCount() + { + return m_kernelEnd - m_kernelStart; + } + /// \brief The number of whole seconds in the measurement period for kernel mode activity + /// + /// This represents the extent, in whole seconds, of the measurement period for kernel mode activity + interval_type kernelSeconds() + { + return kernelPeriodCount() / 10000000; + } + /// \brief The number of whole milliseconds in the measurement period for kernel mode activity + /// + /// This represents the extent, in whole milliseconds, of the measurement period for kernel mode activity + interval_type kernelMilliseconds() + { + return kernelPeriodCount() / 10000; + } + /// \brief The number of whole microseconds in the measurement period for kernel mode activity + /// + /// This represents the extent, in whole microseconds, of the measurement period for kernel mode activity + interval_type kernelMicroseconds() + { + return kernelPeriodCount() / 10; + } + /// @} + + /// \name User + /// @{ + + /// \brief The elapsed count in the measurement period for user mode activity + /// + /// This represents the extent, in machine-specific increments, of the measurement period for user mode activity + interval_type userPeriodCount() + { + return m_userEnd - m_userStart; + } + /// \brief The number of whole seconds in the measurement period for user mode activity + /// + /// This represents the extent, in whole seconds, of the measurement period for user mode activity + interval_type userSeconds() + { + return userPeriodCount() / 10000000; + } + /// \brief The number of whole milliseconds in the measurement period for user mode activity + /// + /// This represents the extent, in whole milliseconds, of the measurement period for user mode activity + interval_type userMilliseconds() + { + return userPeriodCount() / 10000; + } + /// \brief The number of whole microseconds in the measurement period for user mode activity + /// + /// This represents the extent, in whole microseconds, of the measurement period for user mode activity + interval_type userMicroseconds() + { + return userPeriodCount() / 10; + } + /// @} + + /// \name Total + /// @{ + + /// \brief The elapsed count in the measurement period + /// + /// This represents the extent, in machine-specific increments, of the measurement period + interval_type periodCount() + { + return kernelPeriodCount() + userPeriodCount(); + } + + /// \brief The number of whole seconds in the measurement period + /// + /// This represents the extent, in whole seconds, of the measurement period + interval_type seconds() + { + return periodCount() / 10000000; + } + + /// \brief The number of whole milliseconds in the measurement period + /// + /// This represents the extent, in whole milliseconds, of the measurement period + interval_type milliseconds() + { + return periodCount() / 10000; + } + + /// \brief The number of whole microseconds in the measurement period + /// + /// This represents the extent, in whole microseconds, of the measurement period + interval_type microseconds() + { + return periodCount() / 10; + } + /// @} + /// @} + + /// \name Members + /// @{ + private: + epoch_type m_kernelStart; + epoch_type m_kernelEnd; + epoch_type m_userStart; + epoch_type m_userEnd; + static HANDLE sm_process; + /// @} + } + + unittest + { + alias ProcessTimesCounter counter_type; + + counter_type counter = new counter_type(); + + counter.start(); + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us1 = counter.microseconds(); + counter_type.interval_type ms1 = counter.milliseconds(); + counter_type.interval_type s1 = counter.seconds(); + + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us2 = counter.microseconds(); + counter_type.interval_type ms2 = counter.milliseconds(); + counter_type.interval_type s2 = counter.seconds(); + + assert(us2 >= us1); + assert(ms2 >= ms1); + assert(s2 >= s1); + } + + /* ////////////////////////////////////////////////////////////////////////// */ + + /// \brief A performance counter that uses the most accurate measurement APIs available on the host machine + /// + /// This class attempts to use the high performance hardware counter as its measurement resource, but failing + /// that it defaults to less accurate resources in order to guarantee that meaningful measurements are always + /// available to application code + /// + /// \ingroup group_synsoft_win32_perf + class PerformanceCounter + { + /// \name Types + /// @{ + private: + alias long epoch_type; + public: + /// \brief The interval type + /// + /// The type of the interval measurement, a 64-bit signed integer + alias long interval_type; + + /// \brief The scope type + /// + /// The type with which instances of the counter class can be subject to the RAII mechanism in order + /// to scope particular measurement intervals + alias PerformanceCounterScope!(PerformanceCounter) scope_type; + /// @} + + /// \name Constructors + /// @{ + private: + /// \brief Class constructor + /// + /// Detects availability of the high performance hardware counter, and if + /// not available adjusts + static this() + { + if(QueryPerformanceFrequency(&sm_freq)) + { + sm_fn = &_qpc; + } + else + { + sm_freq = 1000; + sm_fn = &_qtc; + } + } + /// @} + + /// \name Operations + /// @{ + public: + /// \brief Starts measurement + /// + /// Begins the measurement period + void start() + { + sm_fn(m_start); + } + + /// \brief Ends measurement + /// + /// Ends the measurement period + void stop() + { + sm_fn(m_end); + } + /// @} + + /// \name Attributes + /// @{ + public: + /// \brief The elapsed count in the measurement period + /// + /// This represents the extent, in machine-specific increments, of the measurement period + interval_type periodCount() + { + return m_end - m_start; + } + + /// \brief The number of whole seconds in the measurement period + /// + /// This represents the extent, in whole seconds, of the measurement period + interval_type seconds() + { + return periodCount() / sm_freq; + } + + /// \brief The number of whole milliseconds in the measurement period + /// + /// This represents the extent, in whole milliseconds, of the measurement period + interval_type milliseconds() + { + interval_type result; + interval_type count = periodCount(); + + if(count < 0x20C49BA5E353F7L) + { + result = (count * 1000) / sm_freq; + } + else + { + result = (count / sm_freq) * 1000; + } + + return result; + } + + /// \brief The number of whole microseconds in the measurement period + /// + /// This represents the extent, in whole microseconds, of the measurement period + interval_type microseconds() + { + interval_type result; + interval_type count = periodCount(); + + if(count < 0x8637BD05AF6L) + { + result = (count * 1000000) / sm_freq; + } + else + { + result = (count / sm_freq) * 1000000; + } + + return result; + } + /// @} + + /// \name Implementation + /// @{ + private: + alias void function(out epoch_type interval) measure_func; + + static void _qpc(out epoch_type interval) + { + QueryPerformanceCounter(&interval); + } + + static void _qtc(out epoch_type interval) + { + interval = GetTickCount(); + } + /// @} + + /// \name Members + /// @{ + private: + epoch_type m_start; // start of measurement period + epoch_type m_end; // End of measurement period + static interval_type sm_freq; // Frequency + static measure_func sm_fn; // Measurement function + /// @} + } + + unittest + { + alias PerformanceCounter counter_type; + + counter_type counter = new counter_type(); + + counter.start(); + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us1 = counter.microseconds(); + counter_type.interval_type ms1 = counter.milliseconds(); + counter_type.interval_type s1 = counter.seconds(); + + volatile for(int i = 0; i < 10000000; ++i) + { } + counter.stop(); + + counter_type.interval_type us2 = counter.microseconds(); + counter_type.interval_type ms2 = counter.milliseconds(); + counter_type.interval_type s2 = counter.seconds(); + + assert(us2 >= us1); + assert(ms2 >= ms1); + assert(s2 >= s1); + } + + /* ////////////////////////////////////////////////////////////////////////// */ +} +else +{ + const int platform_not_supported = 0; + + static assert(platform_not_supported); +} diff --git a/std/process.d b/std/process.d index 3387ded03..58c931e1e 100644 --- a/std/process.d +++ b/std/process.d @@ -1,11 +1,30 @@ -// Copyright (c) 2003 by Digital Mars -// All Rights Reserved -// www.digitalmars.com +/* + * Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com + * Written by Matthew Wilson and Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ module std.process; +private import std.c.stdlib; private import std.string; private import std.c.process; @@ -13,3 +32,62 @@ int system(char[] command) { return std.c.process.system(toStringz(command)); } + +private void toAStringz(char[][] a, char**az) +{ + foreach(char[] s; a) + { + *az++ = toStringz(s); + } + *az = null; +} + +int execv(char[] pathname, char[][] argv) +{ + char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); + + toAStringz(argv, argv_); + return std.c.process.execv(toStringz(pathname), argv_); +} + +int execve(char[] pathname, char[][] argv, char[][] envp) +{ + char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); + char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length)); + + + toAStringz(argv, argv_); + toAStringz(envp, envp_); + return std.c.process.execve(toStringz(pathname), argv_, envp_); +} + +int execvp(char[] pathname, char[][] argv) +{ + char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); + toAStringz(argv, argv_); + return std.c.process.execvp(toStringz(pathname), argv_); +} + +int execvpe(char[] pathname, char[][] argv, char[][] envp) +{ + char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); + char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length)); + toAStringz(argv, argv_); + toAStringz(envp, envp_); + return std.c.process.execvpe(toStringz(pathname), argv_, envp_); +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +version(MainTest) +{ + int main(char[][] args) + { +// int i = execv(args[1], args[2 .. args.length]); + int i = execvp(args[1], args[2 .. args.length]); + + printf("exec??() has returned! Error code: %d; errno: %d\n", i, /* errno */0); + + return 0; + } +} diff --git a/std/recls.d b/std/recls.d index 44141371d..ac6c1e534 100644 --- a/std/recls.d +++ b/std/recls.d @@ -74,6 +74,7 @@ import std.string; version (linux) { + private import std.c.time; private import std.c.linux.linux; } diff --git a/std/regexp.d b/std/regexp.d index 7e56e4870..16954186c 100644 --- a/std/regexp.d +++ b/std/regexp.d @@ -227,7 +227,7 @@ void compile(tchar[] pattern, tchar[] attributes) if (re_nsub > oldre_nsub) { - if (pmatch === &gmatch) + if (pmatch is &gmatch) pmatch = null; pmatch.length = re_nsub + 1; } diff --git a/std/stdint.d b/std/stdint.d index 2d1a1c805..7d1f268a6 100644 --- a/std/stdint.d +++ b/std/stdint.d @@ -1,4 +1,9 @@ +/* Written by Walter Bright + * www.digitalmars.com + * Placed into Public Domain + */ + module std.stdint; /* Exact sizes */ diff --git a/std/stdio.d b/std/stdio.d index b078d67c9..2a452133e 100644 --- a/std/stdio.d +++ b/std/stdio.d @@ -6,7 +6,7 @@ module std.stdio; -private import std.c.stdio; +import std.c.stdio; private import std.format; private import std.utf; diff --git a/std/system.d b/std/system.d index 86fa84382..79b6e2413 100644 --- a/std/system.d +++ b/std/system.d @@ -1,4 +1,9 @@ +/* Written by Walter Bright + * www.digitalmars.com + * Placed into Public Domain + */ + // Information about the target operating system, environment, and CPU module std.system; diff --git a/std/thread.d b/std/thread.d index ea2ba6ab8..2c6b15469 100644 --- a/std/thread.d +++ b/std/thread.d @@ -1,7 +1,24 @@ -// Copyright (c) 2002-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com +/* + * Copyright (C) 2002-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ module std.thread; @@ -97,7 +114,7 @@ class Thread void wait() { - if (this === getThis()) + if (this is getThis()) error("wait on self"); if (state == TS.RUNNING) { DWORD dw; @@ -108,7 +125,7 @@ class Thread void wait(uint milliseconds) { - if (this === getThis()) + if (this is getThis()) error("wait on self"); if (state == TS.RUNNING) { DWORD dw; @@ -500,7 +517,7 @@ class Thread void wait() { - if (this === getThis()) + if (this is getThis()) error("wait on self"); if (state == TS.RUNNING) { int result; @@ -516,7 +533,7 @@ class Thread { wait(); /+ not implemented - if (this === getThis()) + if (this is getThis()) error("wait on self"); if (state == TS.RUNNING) { DWORD dw; diff --git a/std/typeinfo/ti_AC.d b/std/typeinfo/ti_AC.d index 127678933..e910d825e 100644 --- a/std/typeinfo/ti_AC.d +++ b/std/typeinfo/ti_AC.d @@ -29,8 +29,8 @@ class TypeInfo_AC : TypeInfo Object o2 = s2[u]; // Do not pass null's to Object.opEquals() - if (o1 === o2 || - (o1 !== null && o2 !== null && o1.opEquals(o2))) + if (o1 is o2 || + (!(o1 is null) && !(o2 is null) && o1.opEquals(o2))) continue; return 0; } @@ -52,7 +52,7 @@ class TypeInfo_AC : TypeInfo { Object o1 = s1[u]; Object o2 = s2[u]; - if (o1 === o2) + if (o1 is o2) continue; // Regard null references as always being "less than" diff --git a/std/uri.d b/std/uri.d index a0579b1e0..07e6336a1 100644 --- a/std/uri.d +++ b/std/uri.d @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2000-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ module std.uri; diff --git a/std/utf.d b/std/utf.d index 77ba6ffeb..2172302ed 100644 --- a/std/utf.d +++ b/std/utf.d @@ -1,8 +1,26 @@ // utf.d -// Written by Walter Bright -// Copyright (c) 2003-2004 Digital Mars -// All Rights Reserved -// www.digitalmars.com + +/* + * Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ // Description of UTF-8 at: // http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 @@ -25,6 +43,13 @@ class UtfError : Error bit isValidDchar(dchar c) { + /* Note: FFFE and FFFF are specifically permitted by the + * Unicode standard for application internal use, but are not + * allowed for interchange. + * (thanks to Arcane Jill) + * However, we still mark them as invalid. + */ + return c < 0xD800 || (c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF); } diff --git a/std/windows/registry.d b/std/windows/registry.d index 761fae513..a00113591 100644 --- a/std/windows/registry.d +++ b/std/windows/registry.d @@ -418,7 +418,7 @@ private uint swap(in uint i) private char[] expand_environment_strings(in char[] value) in { - assert(null !== value); + assert(!(null is value)); } body { @@ -445,7 +445,7 @@ body private LONG Reg_CloseKey_(in HKEY hkey) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -480,7 +480,7 @@ body private LONG Reg_FlushKey_(in HKEY hkey) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -493,8 +493,8 @@ private LONG Reg_CreateKeyExA_( in HKEY hkey, in char[] subKey , out HKEY hkeyResult, out DWORD disposition) in { - assert(null !== hkey); - assert(null !== subKey); + assert(!(null is hkey)); + assert(!(null is subKey)); } body { @@ -506,8 +506,8 @@ body private LONG Reg_DeleteKeyA_(in HKEY hkey, in char[] subKey) in { - assert(null !== hkey); - assert(null !== subKey); + assert(!(null is hkey)); + assert(!(null is subKey)); } body { @@ -517,8 +517,8 @@ body private LONG Reg_DeleteValueA_(in HKEY hkey, in char[] valueName) in { - assert(null !== hkey); - assert(null !== valueName); + assert(!(null is hkey)); + assert(!(null is valueName)); } body { @@ -528,7 +528,7 @@ body private HKEY Reg_Dup_(HKEY hkey) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -573,8 +573,8 @@ private LONG Reg_EnumKeyName_( in HKEY hkey, in DWORD index, inout char [] name , out DWORD cchName) in { - assert(null !== hkey); - assert(null !== name); + assert(!(null is hkey)); + assert(!(null is name)); assert(0 < name.length); } body @@ -609,7 +609,7 @@ private LONG Reg_EnumValueName_(in HKEY hkey, in DWORD dwIndex, in LPSTR lpName , inout DWORD cchName) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -620,7 +620,7 @@ private LONG Reg_GetNumSubKeys_(in HKEY hkey, out DWORD cSubKeys , out DWORD cchSubKeyMaxLen) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -632,7 +632,7 @@ private LONG Reg_GetNumValues_( in HKEY hkey, out DWORD cValues , out DWORD cchValueMaxLen) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -644,7 +644,7 @@ private LONG Reg_GetValueType_( in HKEY hkey, in char[] name , out REG_VALUE_TYPE type) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -664,8 +664,8 @@ private LONG Reg_OpenKeyExA_( in HKEY hkey, in char[] subKey , in REGSAM samDesired, out HKEY hkeyResult) in { - assert(null !== hkey); - assert(null !== subKey); + assert(!(null is hkey)); + assert(!(null is subKey)); } body { @@ -676,7 +676,7 @@ private void Reg_QueryValue_( in HKEY hkey, in char[] name, out char[] value , out REG_VALUE_TYPE type) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -745,7 +745,7 @@ private void Reg_QueryValue_( in HKEY hkey, in char[] name, out char[][] value , out REG_VALUE_TYPE type) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -789,7 +789,7 @@ private void Reg_QueryValue_( in HKEY hkey, in char[] name, out uint value , out REG_VALUE_TYPE type) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -832,7 +832,7 @@ private void Reg_QueryValue_( in HKEY hkey, in char[] name, out ulong value , out REG_VALUE_TYPE type) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -861,7 +861,7 @@ private void Reg_QueryValue_( in HKEY hkey, in char[] name, out byte[] value , out REG_VALUE_TYPE type) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -901,7 +901,7 @@ private void Reg_SetValueExA_( in HKEY hkey, in char[] subKey , in DWORD cbData) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -993,7 +993,7 @@ public class Key { invariant { - assert(null !== m_hkey); + assert(!(null is m_hkey)); } /// \name Construction @@ -1002,7 +1002,7 @@ private: this(HKEY hkey, char[] name, boolean created) in { - assert(null !== hkey); + assert(!(null is hkey)); } body { @@ -1102,7 +1102,7 @@ public: /// \note If the key cannot be created, a RegistryException is thrown. Key createKey(char[] name, REGSAM access) { - if( null === name || + if( null is name || 0 == name.length) { throw new RegistryException("Key name is invalid"); @@ -1120,7 +1120,7 @@ public: throw new RegistryException("Failed to create requested key: \"" ~ name ~ "\"", lRes); } - assert(null !== hkey); + assert(!(null is hkey)); // Potential resource leak here!! // @@ -1164,7 +1164,7 @@ public: /// \note This function never returns null. If a key corresponding to the requested name is not found, a RegistryException is thrown Key getKey(char[] name, REGSAM access) { - if( null === name || + if( null is name || 0 == name.length) { return new Key(Reg_Dup_(m_hkey), m_name, false); @@ -1179,7 +1179,7 @@ public: throw new RegistryException("Failed to open requested key: \"" ~ name ~ "\"", lRes); } - assert(null !== hkey); + assert(!(null is hkey)); // Potential resource leak here!! // @@ -1220,7 +1220,7 @@ public: /// \param name The name of the key to delete. May not be null void deleteKey(char[] name) { - if( null === name || + if( null is name || 0 == name.length) { throw new RegistryException("Key name is invalid"); @@ -1408,14 +1408,14 @@ public class Value { invariant { - assert(null !== m_key); + assert(!(null is m_key)); } private: this(Key key, char[] name, REG_VALUE_TYPE type) in { - assert(key !== null); + assert(!(key is null)); } body { @@ -1675,7 +1675,7 @@ public class KeyNameSequence { invariant { - assert(null !== m_key); + assert(!(null is m_key)); } /// Construction @@ -1808,7 +1808,7 @@ public class KeySequence { invariant { - assert(null !== m_key); + assert(!(null is m_key)); } /// Construction @@ -1954,7 +1954,7 @@ public class ValueNameSequence { invariant { - assert(null !== m_key); + assert(!(null is m_key)); } /// Construction @@ -2081,7 +2081,7 @@ public class ValueSequence { invariant { - assert(null !== m_key); + assert(!(null is m_key)); } /// Construction diff --git a/win32.mak b/win32.mak index 1674cc7ed..3230926db 100644 --- a/win32.mak +++ b/win32.mak @@ -19,8 +19,8 @@ DFLAGS=-O -release #DFLAGS=-unittest -g CC=sc -#DMD=\dmd\bin\dmd -DMD=..\dmd +DMD=\dmd\bin\dmd +#DMD=..\dmd .c.obj: $(CC) -c $(CFLAGS) $* @@ -62,6 +62,7 @@ OBJS= asserterror.obj deh.obj switch.obj complex.obj gcstats.obj \ iunknown.obj crc32.obj conv.obj arraycast.obj utf.obj uri.obj \ Czlib.obj Dzlib.obj zip.obj process.obj registry.obj recls.obj \ socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \ + perf.obj \ ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ @@ -84,7 +85,7 @@ SRC_STD= std\zlib.d std\zip.d std\stdint.d std\conv.d std\utf.d std\uri.d \ std\intrinsic.d std\array.d std\switcherr.d std\syserror.d \ std\regexp.d std\random.d std\stream.d std\process.d std\recls.d \ std\socket.d std\socketstream.d std\loader.d std\stdarg.d std\format.d \ - std\stdio.d + std\stdio.d std\perf.d SRC_STD_C= std\c\process.d std\c\stdlib.d std\c\time.d std\c\stdio.d \ std\c\math.d std\c\stdarg.d @@ -369,6 +370,9 @@ outofmemory.obj : std\outofmemory.d path.obj : std\path.d $(DMD) -c $(DFLAGS) std\path.d +perf.obj : std\perf.d + $(DMD) -c $(DFLAGS) std\perf.d + process.obj : std\process.d $(DMD) -c $(DFLAGS) std\process.d