diff --git a/README.md b/README.md index 5155c9b..2be7f6c 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,8 @@ Some individual functions have been moved here rather than full Phobos modules. * undead.doformat: Contains the `doFormat` function from std.format * undead.string: Contains regex style pattern matching functions from std.string + +The dmdsamples folder contains a list of code samples which used to be located +in the dmd installation directory, but which have not been kept up to date, so +they are now located here as well. + diff --git a/dmdsamples/.gitignore b/dmdsamples/.gitignore new file mode 100644 index 0000000..898af9a --- /dev/null +++ b/dmdsamples/.gitignore @@ -0,0 +1,15 @@ +*.d.htm +*.exe +chello +dclient +dserver +d2html +dhry +hello +htmlget +listener +pi +sieve +wc +wc2 +winsamp diff --git a/dmdsamples/all.sh b/dmdsamples/all.sh new file mode 100644 index 0000000..eb7f50c --- /dev/null +++ b/dmdsamples/all.sh @@ -0,0 +1,49 @@ + +# Little shell script to compile, link, and run all the samples. +# Use dmd\windows\bin\shell.exe to execute. + +DMD=..\..\windows\bin\dmd +DFLAGS= +CLEAN=clean.bat + + + +#~ $(DMD) chello $(DFLAGS) # which compilation flags? +#~ chello + +$(DMD) d2html $(DFLAGS) +d2html d2html.d + +$(DMD) dhry $(DFLAGS) +dhry + +$(DMD) hello $(DFLAGS) +hello + +#~ $(DMD) htmlget $(DFLAGS) # broken + +#~ $(DMD) listener $(DFLAGS) # broken + + +$(DMD) pi $(DFLAGS) +pi 1000 + +$(DMD) sieve $(DFLAGS) +sieve + +$(DMD) wc $(DFLAGS) +wc wc.d + +$(DMD) wc2 $(DFLAGS) +wc2 wc2.d + +$(DMD) winsamp gdi32.lib winsamp.def +winsamp + +# COM client/server example +$(DMD) dserver.d chello.d dserver.def advapi32.lib ole32.lib user32.lib +# dclient will fail unless run with administrator rights +$(DMD) dclient $(DFLAGS) ole32.lib uuid.lib +dclient + +$(CLEAN) diff --git a/dmdsamples/build.bat b/dmdsamples/build.bat new file mode 100644 index 0000000..3cf2ea5 --- /dev/null +++ b/dmdsamples/build.bat @@ -0,0 +1 @@ +..\..\windows\bin\shell all.sh diff --git a/dmdsamples/chello.d b/dmdsamples/chello.d new file mode 100644 index 0000000..d1f3fed --- /dev/null +++ b/dmdsamples/chello.d @@ -0,0 +1,124 @@ + +/* Server for IHello + * Heavily modified from: + */ +/* + * SELFREG.CPP + * Server Self-Registrtation Utility, Chapter 5 + * + * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Microsoft + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + +// From an example from "Inside OLE" Copyright Microsoft + +import core.stdc.stdio; +import core.stdc.stdlib; +import std.string; +import core.sys.windows.com; +import core.sys.windows.windef; + +GUID CLSID_Hello = { 0x30421140, 0, 0, [0xC0, 0, 0, 0, 0, 0, 0, 0x46] }; +GUID IID_IHello = { 0x00421140, 0, 0, [0xC0, 0, 0, 0, 0, 0, 0, 0x46] }; + +interface IHello : IUnknown +{ + extern (Windows) : + int Print(); +} + +// Type for an object-destroyed callback +alias void function() PFNDESTROYED; + +/* + * The class definition for an object that singly implements + * IHello in D. + */ +class CHello : ComObject, IHello +{ +protected: + IUnknown m_pUnkOuter; // Controlling unknown + + PFNDESTROYED m_pfnDestroy; // To call on closure + + /* + * pUnkOuter LPUNKNOWN of a controlling unknown. + * pfnDestroy PFNDESTROYED to call when an object + * is destroyed. + */ + public this(IUnknown pUnkOuter, PFNDESTROYED pfnDestroy) + { + m_pUnkOuter = pUnkOuter; + m_pfnDestroy = pfnDestroy; + } + + ~this() + { + printf("CHello.~this()\n"); + } + + extern (Windows) : + /* + * Performs any initialization of a CHello that's prone to failure + * that we also use internally before exposing the object outside. + * Return Value: + * BOOL true if the function is successful, + * false otherwise. + */ + +public: + BOOL Init() + { + printf("CHello.Init()\n"); + return true; + } + +public: + override HRESULT QueryInterface(const (IID)*riid, LPVOID *ppv) + { + printf("CHello.QueryInterface()\n"); + + if (IID_IUnknown == *riid) + *ppv = cast(void*) cast(IUnknown) this; + else if (IID_IHello == *riid) + *ppv = cast(void*) cast(IHello) this; + else + { + *ppv = null; + return E_NOINTERFACE; + } + + AddRef(); + return NOERROR; + } + + override ULONG Release() + { + printf("CHello.Release()\n"); + + if (0 != --count) + return count; + + /* + * Tell the housing that an object is going away so it can + * shut down if appropriate. + */ + printf("CHello Destroy()\n"); + + if (m_pfnDestroy) + (*m_pfnDestroy)(); + + // delete this; + return 0; + } + + // IHello members + override HRESULT Print() + { + printf("CHello.Print()\n"); + return NOERROR; + } +} diff --git a/dmdsamples/clean.bat b/dmdsamples/clean.bat new file mode 100644 index 0000000..434850e --- /dev/null +++ b/dmdsamples/clean.bat @@ -0,0 +1,4 @@ +@echo off +setlocal EnableDelayedExpansion +del *.obj +del *.res diff --git a/dmdsamples/d2html.d b/dmdsamples/d2html.d new file mode 100644 index 0000000..235ab9e --- /dev/null +++ b/dmdsamples/d2html.d @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2001 + * Pavel "EvilOne" Minayev + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Author makes no representations about + * the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + */ + +import core.stdc.stdio; + +import std.conv; +import std.string; +import std.stdio; +import std.ascii; +import std.file; + +// colors for syntax highlighting, default values are +// my preferences in Microsoft Visual Studio editor +enum Colors +{ + keyword = "0000FF", + number = "008000", + astring = "000080", + comment = "808080" +} + +enum tabsize = 4; // number of spaces in tab +bool[string] keywords; + + +void main(string[] args) +{ + // need help? + if (args.length < 2 || args.length > 3) + { + printf("D to HTML converter\n" ~ + "Usage: D2HTML .d [.htm]\n"); + return; + } + + // auto-name output file + if (args.length == 2) + args ~= args[1] ~ ".htm"; + + // load keywords + assert("d2html.kwd".exists, "file d2html.kwd does not exist"); + auto kwd = File("d2html.kwd"); + foreach (word; kwd.byLine()) + keywords[word.idup] = true; + kwd.close(); + + // open input and output files + auto src = File(args[1]); + auto dst = File(args[2], "w"); + + // write HTML header + dst.writeln("" ~ args[1] ~ ""); + dst.writeln("
");
+
+    // the main part is wrapped into try..catch block because
+    // when end of file is reached, an exception is raised;
+    // so we can omit any checks for EOF inside this block...
+    try
+    {
+        static char readc(ref File src)
+        {
+            while (true)
+            {
+                if (src.eof())
+                    throw new Exception("");
+                char c;
+                src.readf("%c", &c);
+                if (c != '\r' && c != 0xFF)
+                    return c;
+            }
+        }
+
+        ulong linestart = 0;             // for tabs
+        char c;
+
+        c = readc(src);
+
+        while (true)
+        {
+            if (isWhite(c))                     // whitespace
+            {
+                do
+                {
+                    if (c == 9)
+                    {
+                        // expand tabs to spaces
+                        immutable spaces = tabsize -
+                                     (src.tell() - linestart) % tabsize;
+
+                        for (int i = 0; i < spaces; i++)
+                            dst.write(" ");
+
+                        linestart = src.tell() - tabsize + 1;
+                    }
+                    else
+                    {
+                        // reset line start on newline
+                        if (c == 10 || c == 13)
+                            linestart = src.tell() + 1;
+
+                        dst.write(c);
+                    }
+
+                    c = readc(src);
+                } while (isWhite(c));
+            }
+            else if (isAlpha(c))                // keyword or identifier
+            {
+                string token;
+
+                do
+                {
+                    token ~= c;
+                    c = readc(src);
+                } while (isAlpha(c) || isDigit(c));
+
+                if (token in keywords)                   // keyword
+                    dst.write("" ~ token ~ "");
+                else                    // simple identifier
+                    dst.write(token);
+            }
+            else if (c == '0')                  // binary, octal or hexadecimal number
+            {
+                dst.write("");
+                dst.write(c);
+                c = readc(src);
+
+                if (c == 'X' || c == 'x')                       // hexadecimal
+                {
+                    dst.write(c);
+                    c = readc(src);
+
+                    while (isHexDigit(c)) {
+                        dst.write(c);
+                        c = readc(src);
+                    }
+
+                    // TODO: add support for hexadecimal floats
+                }
+                else if (c == 'B' || c == 'b')                  // binary
+                {
+                    dst.write(c);
+                    c = readc(src);
+
+                    while (c == '0' || c == '1') {
+                        dst.write(c);
+                        c = readc(src);
+                    }
+                }
+                else                    // octal
+                {
+                    do
+                    {
+                        dst.write(c);
+                        c = readc(src);
+                    } while (isOctalDigit(c));
+                }
+
+                dst.write("");
+            }
+            else if (c == '#')                // hash
+            {
+                dst.write(c);
+                c = readc(src);
+            }
+            else if (c == '\\')                // backward slash
+            {
+                dst.write(c);
+                c = readc(src);
+            }
+            else if (isDigit(c))                // decimal number
+            {
+                dst.write("");
+
+                // integral part
+                do
+                {
+                    dst.write(c);
+                    c = readc(src);
+                } while (isDigit(c));
+
+                // fractional part
+                if (c == '.')
+                {
+                    dst.write(c);
+                    c = readc(src);
+
+                    while (isDigit(c))
+                    {
+                        dst.write(c);
+                        c = readc(src);
+                    }
+                }
+
+                // scientific notation
+                if (c == 'E' || c == 'e')
+                {
+                    dst.write(c);
+                    c = readc(src);
+
+                    if (c == '+' || c == '-')
+                    {
+                        dst.write(c);
+                        c = readc(src);
+                    }
+
+                    while (isDigit(c))
+                    {
+                        dst.write(c);
+                        c = readc(src);
+                    }
+                }
+
+                // suffices
+                while (c == 'U' || c == 'u' || c == 'L' ||
+                       c == 'l' || c == 'F' || c == 'f')
+                {
+                    dst.write(c);
+                    c = readc(src);
+                }
+
+                dst.write("");
+            }
+            else if (c == '\'')                 // string without escape sequences
+            {
+                dst.write("");
+
+                do
+                {
+                    if (c == '<')                       // special symbol in HTML
+                        dst.write("<");
+                    else
+                        dst.write(c);
+
+                    c = readc(src);
+                } while (c != '\'');
+                dst.write(c);
+                c = readc(src);
+                dst.write("");
+            }
+            else if (c == 34)                   // string with escape sequences
+            {
+                dst.write("");
+                char prev;                      // used to handle \" properly
+
+                do
+                {
+                    if (c == '<')                       // special symbol in HTML
+                        dst.write("<");
+                    else
+                        dst.write(c);
+
+                    prev = c;
+                    c = readc(src);
+                } while (!(c == 34 && prev != '\\'));                   // handle \"
+                dst.write(c);
+                c = readc(src);
+                dst.write("");
+            }
+            else if (isPunctuation(c))          // either operator or comment
+            {
+                if (c == '<')                   // special symbol in HTML
+                {
+                    dst.write("<");
+                    c = readc(src);
+                }
+                else if (c == '/')                      // could be a comment...
+                {
+                    c = readc(src);
+
+                    if (c == '/')                       // single-line one
+                    {
+                        dst.write("/");
+
+                        while (c != 10)
+                        {
+                            if (c == '<')                               // special symbol in HTML
+                                dst.write("<");
+                            else if (c == 9)
+                            {
+                                // expand tabs
+                                immutable spaces2 = tabsize -
+                                              (src.tell() - linestart) % tabsize;
+
+                                for (int i2 = 0; i2 < spaces2; i2++)
+                                    dst.write(" ");
+
+                                linestart = src.tell() - tabsize + 1;
+                            }
+                            else
+                                dst.write(c);
+
+                            c = readc(src);
+                        }
+
+                        dst.write("");
+                    }
+                    else if (c == '*')                          // multi-line one
+                    {
+                        dst.write("/");
+                        char prev2;
+
+                        do
+                        {
+                            if (c == '<')                               // special symbol in HTML
+                                dst.write("<");
+                            else if (c == 9)
+                            {
+                                // expand tabs
+                                immutable spaces3 = tabsize -
+                                              (src.tell() - linestart) % tabsize;
+
+                                for (int i3 = 0; i3 < spaces3; i3++)
+                                    dst.write(" ");
+
+                                linestart = src.tell() - tabsize + 1;
+                            }
+                            else
+                            {
+                                // reset line start on newline
+                                if (c == 10 || c == 13)
+                                    linestart = src.tell() + 1;
+
+                                dst.write(c);
+                            }
+
+                            prev2 = c;
+                            c = readc(src);
+                        } while (!(c == '/' && prev2 == '*'));
+                        dst.write(c);
+                        dst.write("");
+                        c = readc(src);
+                    }
+                    else                        // just an operator
+                        dst.write(cast(char) '/');
+                }
+                else                    // just an operator
+                {
+                    dst.write(c);
+                    c = readc(src);
+                }
+            }
+            else
+            {
+                // whatever it is, it's not a valid D token
+                throw new Error("unrecognized token " ~ c);
+                //~ break;
+            }
+        }
+    }
+
+    // if end of file is reached and we try to read something
+    // with typed read(), a ReadError is thrown; in our case,
+    // this means that job is successfully done
+    catch (Exception e)
+    {
+        // write HTML footer
+        dst.writeln("
"); + } + + return; +} diff --git a/dmdsamples/d2html.kwd b/dmdsamples/d2html.kwd new file mode 100644 index 0000000..4a42206 --- /dev/null +++ b/dmdsamples/d2html.kwd @@ -0,0 +1,179 @@ +property +abstract +alias +align +asm +assert +auto +body +bool +break +byte +case +cast +catch +cdouble +cent +cfloat +char +class +const +continue +creal +dchar +dstring +debug +default +delegate +delete +deprecated +do +double +else +enum +export +extern +false +final +finally +float +for +foreach +foreach_reverse +function +goto +idouble +if +ifloat +immutable +import +in +inout +int +interface +invariant +ireal +is +lazy +long +macro +mixin +module +new +nothrow +null +out +override +package +pragma +private +protected +public +pure +real +ref +return +scope +shared +short +size_t +static +string +struct +super +switch +synchronized +template +this +throw +true +try +typedef +typeid +typeof +ubyte +ucent +uint +ulong +union +unittest +ushort +version +void +volatile +wchar +wstring +while +with +__FILE__ +__LINE__ +__gshared +__thread +__traits +const_cast +dynamic_cast +explicit +friend +inline +mutable +namespace +operator +register +reinterpret_cast +restrict +signed +sizeof +static_cast +typename +unsigned +using +virtual +int8_t +uint8_t +int16_t +uint16_t +int32_t +uint32_t +int64_t +uint64_t +int_least8_t +uint_least8_t +int_least16_t +uint_least16_t +int_least32_t +uint_least32_t +int_least64_t +uint_least64_t +int_fast8_t +uint_fast8_t +int_fast16_t +uint_fast16_t +int_fast32_t +uint_fast32_t +int_fast64_t +uint_fast64_t +intptr_t +uintptr_t +intmax_t +uintmax_t +wint_t +wchar_t +wctrans_t +time_t +and +and_eq +bitand +bitor +compl +not +not_eq +or +or_eq +xor +xor_eq +wctype_tcomplex +imaginary +_Complex +_Imaginary +_Bool +_Pragma diff --git a/dmdsamples/dclient.d b/dmdsamples/dclient.d new file mode 100644 index 0000000..1cc4286 --- /dev/null +++ b/dmdsamples/dclient.d @@ -0,0 +1,132 @@ + +/* Client for IHello + * Heavily modified from: + */ +/* + * SELFREG.CPP + * Server Self-Registrtation Utility, Chapter 5 + * + * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Microsoft + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + +import core.stdc.stdio; +import core.stdc.stdlib; +import core.sys.windows.com; +import core.sys.windows.winbase; +import core.sys.windows.windef; + +GUID CLSID_Hello = { 0x30421140, 0, 0, [0xC0, 0, 0, 0, 0, 0, 0, 0x46] }; +GUID IID_IHello = { 0x00421140, 0, 0, [0xC0, 0, 0, 0, 0, 0, 0, 0x46] }; + +interface IHello : IUnknown +{ + extern (Windows) : + int Print(); +} + +int main() +{ + DWORD dwVer; + HRESULT hr; + IHello pIHello; + + // Make sure COM is the right version + dwVer = CoBuildVersion(); + + if (rmm != HIWORD(dwVer)) + { + printf("Incorrect OLE 2 version number\n"); + return EXIT_FAILURE; + } + + hr=CoInitialize(null); // Initialize OLE + + if (FAILED(hr)) + { + printf("OLE 2 failed to initialize\n"); + return EXIT_FAILURE; + } + + printf("OLE 2 initialized\n"); + + if (dll_regserver("dserver.dll", 1) == 0) + { + printf("server registered\n"); + hr=CoCreateInstance(&CLSID_Hello, null, CLSCTX_ALL, &IID_IHello, cast(void**)&pIHello); + + if (FAILED(hr)) + { + printf("Failed to create object x%x\n", hr); + } + else + { + printf("Object created, calling IHello.Print(), IHello = %p\n", pIHello); + + // fflush(stdout); + pIHello.Print(); + pIHello.Release(); + } + + CoFreeUnusedLibraries(); + + if (dll_regserver("dserver.dll", 0)) + printf("server unregister failed\n"); + } + else + printf("server registration failed\n"); + + // Only call this if CoInitialize worked + CoUninitialize(); + return EXIT_SUCCESS; +} + +/************************************** + * Register/unregister a DLL server. + * Input: + * flag !=0: register + * ==0: unregister + * Returns: + * 0 success + * !=0 failure + */ + +extern (Windows) alias HRESULT function() pfn_t; + +int dll_regserver(const (char) *dllname, int flag) +{ + char *fn = flag ? cast(char*) "DllRegisterServer" + : cast(char*) "DllUnregisterServer"; + int result = 1; + pfn_t pfn; + HINSTANCE hMod; + + if (SUCCEEDED(CoInitialize(null))) + { + hMod=LoadLibraryA(dllname); + printf("hMod = %p\n", hMod); + + if (hMod) + { + printf("LoadLibraryA() %s\n", (flag ? "registered".ptr : "unregistered".ptr)); + pfn = cast(pfn_t) GetProcAddress(hMod, fn); + printf("pfn = %p, fn = '%s'\n", pfn, fn); + + if (pfn && SUCCEEDED((*pfn)())) + { + printf("successfully called %s\n", fn); + result = 0; + } + + printf("CoFreeLibrary()\n"); + CoFreeLibrary(hMod); + printf("CoUninitialize()\n"); + CoUninitialize(); + } + } + + return result; +} diff --git a/dmdsamples/dhry.d b/dmdsamples/dhry.d new file mode 100644 index 0000000..f990b1a --- /dev/null +++ b/dmdsamples/dhry.d @@ -0,0 +1,939 @@ + +/* + ************************************************************************* + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry.h (part 1 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * Siemens Nixdorf Inf. Syst. + * STM OS 32 + * Otto-Hahn-Ring 6 + * W-8000 Muenchen 83 + * Germany + * Phone: [+49]-89-636-42436 + * (8-17 Central European Time) + * UUCP: weicker@ztivax.uucp@unido.uucp + * Internet: weicker@ztivax.siemens.com + * + * Original Version (in Ada) published in + * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), + * pp. 1013 - 1030, together with the statistics + * on which the distribution of statements etc. is based. + * + * In this C version, the following C library functions are + * used: + * - strcpy, strcmp (inside the measurement loop) + * - printf, scanf (outside the measurement loop) + * + * Collection of Results: + * Reinhold Weicker (address see above) and + * + * Rick Richardson + * PC Research. Inc. + * 94 Apple Orchard Drive + * Tinton Falls, NJ 07724 + * Phone: (201) 834-1378 (9-17 EST) + * UUCP: ...!uunet!pcrat!rick + * + * Please send results to Rick Richardson and/or Reinhold Weicker. + * Complete information should be given on hardware and software + * used. Hardware information includes: Machine type, CPU, type and + * size of caches; for microprocessors: clock frequency, memory speed + * (number of wait states). Software information includes: Compiler + * (and runtime library) manufacturer and version, compilation + * switches, OS version. The Operating System version may give an + * indication about the compiler; Dhrystone itself performs no OS + * calls in the measurement loop. + * + * The complete output generated by the program should be mailed + * such that at least some checks for correctness can be made. + * + ************************************************************************* + * + * History: This version C/2.1 has been made for two reasons: + * + * 1) There is an obvious need for a common C version of + * Dhrystone, since C is at present the most popular system + * programming language for the class of processors + * (microcomputers, minicomputers) where Dhrystone is used + * most. There should be, as far as possible, only one C + * version of Dhrystone such that results can be compared + * without restrictions. In the past, the C versions + * distributed by Rick Richardson (Version 1.1) and by + * Reinhold Weicker had small (though not significant) + * differences. + * + * 2) As far as it is possible without changes to the + * Dhrystone statistics, optimizing compilers should be + * prevented from removing significant statements. + * + * This C version has been developed in cooperation with + * Rick Richardson (Tinton Falls, NJ), it incorporates many + * ideas from the "Version 1.1" distributed previously by + * him over the UNIX network Usenet. + * I also thank Chaim Benedelac (National Semiconductor), + * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), + * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) + * for their help with comments on earlier versions of the + * benchmark. + * + * Changes: In the initialization part, this version follows mostly + * Rick Richardson's version distributed via Usenet, not the + * version distributed earlier via floppy disk by Reinhold + * Weicker. As a concession to older compilers, names have + * been made unique within the first 8 characters. Inside the + * measurement loop, this version follows the version + * previously distributed by Reinhold Weicker. + * + * At several places in the benchmark, code has been added, + * but within the measurement loop only in branches that + * are not executed. The intention is that optimizing + * compilers should be prevented from moving code out of the + * measurement loop, or from removing code altogether. Since + * the statements that are executed within the measurement + * loop have NOT been changed, the numbers defining the + * "Dhrystone distribution" (distribution of statements, + * operand types and locality) still hold. Except for + * sophisticated optimizing compilers, execution times for + * this version should be the same as for previous versions. + * + * Since it has proven difficult to subtract the time for the + * measurement loop overhead in a correct way, the loop check + * has been made a part of the benchmark. This does have + * an impact - though a very minor one - on the distribution + * statistics which have been updated for this version. + * + * All changes within the measurement loop are described + * and discussed in the companion paper "Rationale for + * Dhrystone version 2". + * + * Because of the self-imposed limitation that the order and + * distribution of the executed statements should not be + * changed, there are still cases where optimizing compilers + * may not generate code for some statements. To a certain + * degree, this is unavoidable for small synthetic + * benchmarks. Users of the benchmark are advised to check + * code listings whether code is generated for all statements + * of Dhrystone. + * + * Version 2.1 is identical to version 2.0 distributed via + * the UNIX network Usenet in March 1988 except that it + * corrects some minor deficiencies that were found by users + * of version 2.0. The only change within the measurement + * loop is that a non-executed "else" part was added to the + * "if" statement in Func_3, and a non-executed "else" part + * removed from Proc_3. + * + ************************************************************************* + * + * Defines: The following "Defines" are possible: + * -DROPT (default: Not defined) + * As an approximation to what an average C + * programmer might do, the "register" storage class + * is applied (if enabled by -DROPT) + * - for local variables, if they are used + * (dynamically) five or more times + * - for parameters if they are used (dynamically) + * six or more times + * Note that an optimal "register" strategy is + * compiler-dependent, and that "register" + * declarations do not necessarily lead to faster + * execution. + * -DNOSTRUCTASSIGN (default: Not defined) + * Define if the C compiler does not support + * assignment of structures. + * -DNOENUMS (default: Not defined) + * Define if the C compiler does not support + * enumeration types. + * + ************************************************************************* + * + * Compilation model and measurement (IMPORTANT): + * + * This C version of Dhrystone consists of three files: + * - dhry.h (this file, containing global definitions and comments) + * - dhry_1.c (containing the code corresponding to Ada package Pack_1) + * - dhry_2.c (containing the code corresponding to Ada package Pack_2) + * + * The following "ground rules" apply for measurements: + * - Separate compilation + * - No procedure merging + * - Otherwise, compiler optimizations are allowed but should be + * indicated + * - Default results are those without register declarations + * See the companion paper "Rationale for Dhrystone Version 2" for a more + * detailed discussion of these ground rules. + * + * For 16-Bit processors (e.g. 80186, 80286), times for all compilation + * models ("small", "medium", "large" etc.) should be given if possible, + * together with a definition of these models for the compiler system + * used. + * + ************************************************************************* + * + * Dhrystone (C version) statistics: + * + * [Comment from the first distribution, updated for version 2. + * Note that because of language differences, the numbers are slightly + * different from the Ada version.] + * + * The following program contains statements of a high level programming + * language (here: C) in a distribution considered representative: + * + * assignments 52 (51.0 %) + * control statements 33 (32.4 %) + * procedure, function calls 17 (16.7 %) + * + * 103 statements are dynamically executed. The program is balanced with + * respect to the three aspects: + * + * - statement type + * - operand type + * - operand locality + * operand global, local, parameter, or constant. + * + * The combination of these three aspects is balanced only approximately. + * + * 1. Statement Type: + * ----------------- number + * + * V1 = V2 9 + * (incl. V1 = F(..) + * V = Constant 12 + * Assignment, 7 + * with array element + * Assignment, 6 + * with record component + * -- + * 34 34 + * + * X = Y +|-|"&&"|"|" Z 5 + * X = Y +|-|"==" Constant 6 + * X = X +|- 1 3 + * X = Y *|/ Z 2 + * X = Expression, 1 + * two operators + * X = Expression, 1 + * three operators + * -- + * 18 18 + * + * if .... 14 + * with "else" 7 + * without "else" 7 + * executed 3 + * not executed 4 + * for ... 7 | counted every time + * while ... 4 | the loop condition + * do ... while 1 | is evaluated + * switch ... 1 + * break 1 + * declaration with 1 + * initialization + * -- + * 34 34 + * + * P (...) procedure call 11 + * user procedure 10 + * library procedure 1 + * X = F (...) + * function call 6 + * user function 5 + * library function 1 + * -- + * 17 17 + * --- + * 103 + * + * The average number of parameters in procedure or function calls + * is 1.82 (not counting the function values as implicit parameters). + * + * + * 2. Operators + * ------------ + * number approximate + * percentage + * + * Arithmetic 32 50.8 + * + * + 21 33.3 + * - 7 11.1 + * * 3 4.8 + * / (int div) 1 1.6 + * + * Comparison 27 42.8 + * + * == 9 14.3 + * /= 4 6.3 + * > 1 1.6 + * < 3 4.8 + * >= 1 1.6 + * <= 9 14.3 + * + * Logic 4 6.3 + * + * && (AND-THEN) 1 1.6 + * | (OR) 1 1.6 + * ! (NOT) 2 3.2 + * + * -- ----- + * 63 100.1 + * + * + * 3. Operand Type (counted once per operand reference): + * --------------- + * number approximate + * percentage + * + * Integer 175 72.3 % + * Character 45 18.6 % + * Pointer 12 5.0 % + * String30 6 2.5 % + * Array 2 0.8 % + * Record 2 0.8 % + * --- ------- + * 242 100.0 % + * + * When there is an access path leading to the final operand (e.g. a + * record component), only the final data type on the access path is + * counted. + * + * + * 4. Operand Locality: + * ------------------- + * number approximate + * percentage + * + * local variable 114 47.1 % + * global variable 22 9.1 % + * parameter 45 18.6 % + * value 23 9.5 % + * reference 22 9.1 % + * function result 6 2.5 % + * constant 55 22.7 % + * --- ------- + * 242 100.0 % + * + * + * The program does not compute anything meaningful, but it is + * syntactically and semantically correct. All variables have a value + * assigned to them before they are used as a source operand. + * + * There has been no explicit effort to account for the effects of a + * cache, or to balance the use of long or short displacements for code + * or data. + * + ************************************************************************* + */ + +import core.stdc.stdio; +import core.stdc.string; +import core.stdc.stdlib; +import std.string; + +/* Compiler and system dependent definitions: */ + +const double Mic_secs_Per_Second = 1000000.0; + +/* Berkeley UNIX C returns process times in seconds/HZ */ + +enum { Ident_1, Ident_2, Ident_3, Ident_4, Ident_5 } +alias int Enumeration; + +/* for boolean and enumeration types in Ada, Pascal */ + +/* General definitions: */ + +const int StrLen = 30; + +alias int One_Thirty; +alias int One_Fifty; +alias char Capital_Letter; +alias bool Boolean; +alias char[StrLen] Str_30; +alias int[50] Arr_1_Dim; +alias int[50][50] Arr_2_Dim; + +struct record +{ + record *Ptr_Comp; + Enumeration Discr; + union V + { + struct V1 + { + Enumeration Enum_Comp; + int Int_Comp; + char[StrLen] Str_Comp; + } + V1 var_1; + struct V2 + { + Enumeration E_Comp_2; + char[StrLen] Str_2_Comp; + } + V2 var_2; + struct V3 + { + char Ch_1_Comp; + char Ch_2_Comp; + } + V3 var_3; + } + V variant; +} + +alias record Rec_Type; +alias record *Rec_Pointer; + +/* Global Variables: */ + +Rec_Pointer Ptr_Glob, + Next_Ptr_Glob; +int Int_Glob; +Boolean Bool_Glob; +char Ch_1_Glob, + Ch_2_Glob; +int[50] Arr_1_Glob; +int[50][50] Arr_2_Glob; + +char[StrLen] Reg_Define = "Register option selected."; + +/* variables for time measurement: */ + +const int Too_Small_Time = 2; + +/* Measurements should last at least 2 seconds */ + +double Begin_Time, + End_Time, + User_Time; + +double Microseconds, + Dhrystones_Per_Second, + Vax_Mips; + +/* end of variables for time measurement */ +void main() + +/*****/ + +/* main program, corresponds to procedures */ +/* Main and Proc_0 in the Ada version */ +{ + One_Fifty Int_1_Loc; + One_Fifty Int_2_Loc; + One_Fifty Int_3_Loc; + char Ch_Index; + Enumeration Enum_Loc; + Str_30 Str_1_Loc; + Str_30 Str_2_Loc; + int Run_Index; + int Number_Of_Runs; + + FILE *Ap; + + /* Initializations */ + + if ((Ap = fopen("dhry.res", "a+")) == null) + { + printf("Can not open dhry.res\n\n"); + exit(1); + } + + Next_Ptr_Glob = cast(Rec_Pointer) malloc (Rec_Type.sizeof); + Ptr_Glob = cast(Rec_Pointer) malloc (Rec_Type.sizeof); + + Ptr_Glob.Ptr_Comp = Next_Ptr_Glob; + Ptr_Glob.Discr = Ident_1; + Ptr_Glob.variant.var_1.Enum_Comp = Ident_3; + Ptr_Glob.variant.var_1.Int_Comp = 40; + + // strcpy (Ptr_Glob.variant.var_1.Str_Comp, + // "DHRYSTONE PROGRAM, SOME STRING"); + // strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); + Ptr_Glob.variant.var_1.Str_Comp[] = "DHRYSTONE PROGRAM, SOME STRING"; + Str_1_Loc[] = "DHRYSTONE PROGRAM, 1'ST STRING"; + + Arr_2_Glob [8][7] = 10; + + /* Was missing in published program. Without this statement, */ + /* Arr_2_Glob [8][7] would have an undefined value. */ + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ + /* overflow may occur for this array element. */ + + printf ("\n"); + printf ("Dhrystone Benchmark, Version 2.1 (Language: D)\n"); + printf ("\n"); + printf ("Please give the number of runs through the benchmark: "); + { + int n; + + // scanf ("%d", &n); + n = 10000000; + Number_Of_Runs = n; + } + printf ("\n"); + + printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); + + /***************/ + /* Start timer */ + /***************/ + + Begin_Time = dtime(); + + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) + { + Proc_5(); + Proc_4(); + + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ + Int_1_Loc = 2; + Int_2_Loc = 3; + + // strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); + Str_2_Loc[] = "DHRYSTONE PROGRAM, 2'ND STRING"; + Enum_Loc = Ident_2; + Bool_Glob = !Func_2 (Str_1_Loc, Str_2_Loc); + + /* Bool_Glob == 1 */ + while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ + { + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; + + /* Int_3_Loc == 7 */ + Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); + + /* Int_3_Loc == 7 */ + Int_1_Loc += 1; + } /* while */ + + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); + + /* Int_Glob == 5 */ + Proc_1 (Ptr_Glob); + + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) + { + /* loop body executed twice */ + if (Enum_Loc == Func_1 (Ch_Index, 'C')) + { + /* then, not executed */ + Proc_6 (Ident_1, &Enum_Loc); + + // strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); + Str_2_Loc[] = "DHRYSTONE PROGRAM, 3'RD STRING"; + Int_2_Loc = Run_Index; + Int_Glob = Run_Index; + } + } + + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Int_2_Loc = Int_2_Loc * Int_1_Loc; + Int_1_Loc = Int_2_Loc / Int_3_Loc; + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; + + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ + Proc_2 (&Int_1_Loc); + + /* Int_1_Loc == 5 */ + } /* loop "for Run_Index" */ + + /**************/ + /* Stop timer */ + /**************/ + + End_Time = dtime(); + + printf ("Execution ends\n"); + printf ("\n"); + printf ("Final values of the variables used in the benchmark:\n"); + printf ("\n"); + printf ("Int_Glob: %d\n", Int_Glob); + printf (" should be: %d\n", 5); + printf ("Bool_Glob: %d\n", Bool_Glob); + printf (" should be: %d\n", 1); + printf ("Ch_1_Glob: %c\n", Ch_1_Glob); + printf (" should be: %c\n", cast(int) 'A'); + printf ("Ch_2_Glob: %c\n", Ch_2_Glob); + printf (" should be: %c\n", cast(int) 'B'); + printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + printf (" should be: %d\n", 7); + printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + printf (" should be: Number_Of_Runs + 10\n"); + printf ("Ptr_Glob.\n"); + printf (" Ptr_Comp: %d\n", cast(int) Ptr_Glob.Ptr_Comp); + printf (" should be: (implementation-dependent)\n"); + printf (" Discr: %d\n", Ptr_Glob.Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Ptr_Glob.variant.var_1.Enum_Comp); + printf (" should be: %d\n", 2); + printf (" Int_Comp: %d\n", Ptr_Glob.variant.var_1.Int_Comp); + printf (" should be: %d\n", 17); + printf (" Str_Comp: %.*s\n", cast(int) Ptr_Glob.variant.var_1.Str_Comp.length, + Ptr_Glob.variant.var_1.Str_Comp.ptr); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Next_Ptr_Glob.\n"); + printf (" Ptr_Comp: %d\n", cast(int) Next_Ptr_Glob.Ptr_Comp); + printf (" should be: (implementation-dependent), same as above\n"); + printf (" Discr: %d\n", Next_Ptr_Glob.Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Next_Ptr_Glob.variant.var_1.Enum_Comp); + printf (" should be: %d\n", 1); + printf (" Int_Comp: %d\n", Next_Ptr_Glob.variant.var_1.Int_Comp); + printf (" should be: %d\n", 18); + printf (" Str_Comp: %.*s\n", cast(int) Next_Ptr_Glob.variant.var_1.Str_Comp.length, + Next_Ptr_Glob.variant.var_1.Str_Comp.ptr); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Int_1_Loc: %d\n", Int_1_Loc); + printf (" should be: %d\n", 5); + printf ("Int_2_Loc: %d\n", Int_2_Loc); + printf (" should be: %d\n", 13); + printf ("Int_3_Loc: %d\n", Int_3_Loc); + printf (" should be: %d\n", 7); + printf ("Enum_Loc: %d\n", Enum_Loc); + printf (" should be: %d\n", 1); + printf ("Str_1_Loc: %.*s\n", cast(int) Str_1_Loc.length, Str_1_Loc.ptr); + printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + printf ("Str_2_Loc: %.*s\n", cast(int) Str_2_Loc.length, Str_2_Loc.ptr); + printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + printf ("\n"); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + printf ("Measured time too small to obtain meaningful results\n"); + printf ("Please increase number of runs\n"); + printf ("\n"); + } + else + { + Microseconds = User_Time * Mic_secs_Per_Second + / cast(double) Number_Of_Runs; + Dhrystones_Per_Second = cast(double) Number_Of_Runs / User_Time; + Vax_Mips = Dhrystones_Per_Second / 1757.0; + + printf ("Register option selected? NO\n"); + strcpy(Reg_Define.ptr, "Register option not selected."); + printf ("Microseconds for one run through Dhrystone: "); + printf ("%7.1lf \n", Microseconds); + printf ("Dhrystones per Second: "); + printf ("%10.1lf \n", Dhrystones_Per_Second); + printf ("VAX MIPS rating = %10.3lf \n", Vax_Mips); + printf ("\n"); + + fprintf(Ap, "\n"); + fprintf(Ap, "Dhrystone Benchmark, Version 2.1 (Language: D)\n"); + fprintf(Ap, "%*s\n", Reg_Define.ptr); + fprintf(Ap, "Microseconds for one loop: %7.1lf\n", Microseconds); + fprintf(Ap, "Dhrystones per second: %10.1lf\n", Dhrystones_Per_Second); + fprintf(Ap, "VAX MIPS rating: %10.3lf\n", Vax_Mips); + fclose(Ap); + } +} + +void Proc_1(Rec_Pointer Ptr_Val_Par) + +/******************/ + +/* executed once */ +{ + Rec_Pointer Next_Record = Ptr_Val_Par.Ptr_Comp; + + /* == Ptr_Glob_Next */ + /* Local variable, initialized with Ptr_Val_Par.Ptr_Comp, */ + /* corresponds to "rename" in Ada, "with" in Pascal */ + + *Ptr_Val_Par.Ptr_Comp = *Ptr_Glob; + Ptr_Val_Par.variant.var_1.Int_Comp = 5; + Next_Record.variant.var_1.Int_Comp + = Ptr_Val_Par.variant.var_1.Int_Comp; + Next_Record.Ptr_Comp = Ptr_Val_Par.Ptr_Comp; + Proc_3 (&Next_Record.Ptr_Comp); + + /* Ptr_Val_Par.Ptr_Comp.Ptr_Comp + == Ptr_Glob.Ptr_Comp */ + if (Next_Record.Discr == Ident_1) + { + /* then, executed */ + Next_Record.variant.var_1.Int_Comp = 6; + Proc_6 (Ptr_Val_Par.variant.var_1.Enum_Comp, + &Next_Record.variant.var_1.Enum_Comp); + Next_Record.Ptr_Comp = Ptr_Glob.Ptr_Comp; + Proc_7 (Next_Record.variant.var_1.Int_Comp, 10, + &Next_Record.variant.var_1.Int_Comp); + } + else /* not executed */ + *Ptr_Val_Par = *Ptr_Val_Par.Ptr_Comp; +} /* Proc_1 */ +void Proc_2(One_Fifty *Int_Par_Ref) + +/******************/ +/* executed once */ +/* *Int_Par_Ref == 1, becomes 4 */ +{ + One_Fifty Int_Loc; + Enumeration Enum_Loc; + + Int_Loc = *Int_Par_Ref + 10; + + do /* executed once */ + if (Ch_1_Glob == 'A') + { + /* then, executed */ + Int_Loc -= 1; + *Int_Par_Ref = Int_Loc - Int_Glob; + Enum_Loc = Ident_1; + } + + /* if */ + while (Enum_Loc != Ident_1); /* true */ +} /* Proc_2 */ +void Proc_3(Rec_Pointer *Ptr_Ref_Par) + +/******************/ +/* executed once */ +/* Ptr_Ref_Par becomes Ptr_Glob */ +{ + if (Ptr_Glob != null) + /* then, executed */ + *Ptr_Ref_Par = Ptr_Glob.Ptr_Comp; + + Proc_7 (10, Int_Glob, &Ptr_Glob.variant.var_1.Int_Comp); +} /* Proc_3 */ +void Proc_4() /* without parameters */ +/*******/ +/* executed once */ +{ + Boolean Bool_Loc; + + Bool_Loc = Ch_1_Glob == 'A'; + Bool_Glob = Bool_Loc | Bool_Glob; + Ch_2_Glob = 'B'; +} /* Proc_4 */ +void Proc_5() /* without parameters */ +/*******/ +/* executed once */ +{ + Ch_1_Glob = 'A'; + Bool_Glob = false; +} /* Proc_5 */ +void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par) + +/*********************************/ +/* executed once */ +/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ +{ + *Enum_Ref_Par = Enum_Val_Par; + + if (!Func_3 (Enum_Val_Par)) + /* then, not executed */ + *Enum_Ref_Par = Ident_4; + + switch (Enum_Val_Par) + { + case Ident_1: + *Enum_Ref_Par = Ident_1; + break; + + case Ident_2: + + if (Int_Glob > 100) + /* then */ + *Enum_Ref_Par = Ident_1; + else *Enum_Ref_Par = Ident_4; + + break; + + case Ident_3: /* executed */ + *Enum_Ref_Par = Ident_2; + break; + + case Ident_4: + break; + + case Ident_5: + *Enum_Ref_Par = Ident_3; + break; + + default: + } /* switch */ + +} /* Proc_6 */ +void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref) + +/**********************************************/ +/* executed three times */ +/* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ +/* Int_Par_Ref becomes 7 */ +/* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ +/* Int_Par_Ref becomes 17 */ +/* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ +/* Int_Par_Ref becomes 18 */ +{ + One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 2; + *Int_Par_Ref = Int_2_Par_Val + Int_Loc; +} /* Proc_7 */ +void Proc_8(ref Arr_1_Dim Arr_1_Par_Ref, ref Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val) + +/*********************************************************************/ +/* executed once */ +/* Int_Par_Val_1 == 3 */ +/* Int_Par_Val_2 == 7 */ +{ + One_Fifty Int_Index; + One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 5; + Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; + Arr_1_Par_Ref [Int_Loc + 1] = Arr_1_Par_Ref [Int_Loc]; + Arr_1_Par_Ref [Int_Loc + 30] = Int_Loc; + + for (Int_Index = Int_Loc; Int_Index <= Int_Loc + 1; ++Int_Index) + Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; + + Arr_2_Par_Ref [Int_Loc] [Int_Loc - 1] += 1; + Arr_2_Par_Ref [Int_Loc + 20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; + Int_Glob = 5; +} /* Proc_8 */ +Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val) + +/*************************************************/ +/* executed three times */ +/* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ +/* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ +/* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ +{ + Capital_Letter Ch_1_Loc; + Capital_Letter Ch_2_Loc; + + Ch_1_Loc = Ch_1_Par_Val; + Ch_2_Loc = Ch_1_Loc; + + if (Ch_2_Loc != Ch_2_Par_Val) + /* then, executed */ + return (Ident_1); + else /* not executed */ + { + Ch_1_Glob = Ch_1_Loc; + return (Ident_2); + } +} /* Func_1 */ +Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref) + +/*************************************************/ +/* executed once */ +/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ +/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ +{ + One_Thirty Int_Loc; + Capital_Letter Ch_Loc; + + Int_Loc = 2; + + while (Int_Loc <= 2) /* loop body executed once */ + if (Func_1 (Str_1_Par_Ref[Int_Loc], + Str_2_Par_Ref[Int_Loc + 1]) == Ident_1) + { + /* then, executed */ + Ch_Loc = 'A'; + Int_Loc += 1; + } + + /* if, while */ + + if (Ch_Loc >= 'W' && Ch_Loc < 'Z') + /* then, not executed */ + Int_Loc = 7; + + if (Ch_Loc == 'R') + /* then, not executed */ + return (true); + else /* executed */ + { + // if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) + // if (memcmp (Str_1_Par_Ref, Str_2_Par_Ref, 30) > 0) + if (Str_1_Par_Ref > Str_2_Par_Ref) + { + /* then, not executed */ + Int_Loc += 7; + Int_Glob = Int_Loc; + return (true); + } + else /* executed */ + return (false); + } /* if Ch_Loc */ + +} /* Func_2 */ +Boolean Func_3(Enumeration Enum_Par_Val) + +/***************************/ +/* executed once */ +/* Enum_Par_Val == Ident_3 */ +{ + Enumeration Enum_Loc; + + Enum_Loc = Enum_Par_Val; + + if (Enum_Loc == Ident_3) + /* then, executed */ + return (true); + else /* not executed */ + return (false); +} /* Func_3 */ + +version (Windows) +{ + import core.sys.windows.winbase; + + double dtime() + { + double q; + + q = cast(double) GetTickCount() * 1.0e-03; + + return q; + } +} + +version (linux) +{ + import core.stdc.time; + + double dtime() + { + double q; + + q = cast(double) time(null); + + return q; + } +} + +version (OSX) // supplied by Anders F Bjorklund +{ + import core.sys.posix.sys.time; + + double dtime() + { + double q; + timeval tv; + + gettimeofday(&tv, null); + q = cast(double) tv.tv_sec + cast(double) tv.tv_usec * 1.0e-6; + + return q; + } +} diff --git a/dmdsamples/dserver.d b/dmdsamples/dserver.d new file mode 100644 index 0000000..bc811ba --- /dev/null +++ b/dmdsamples/dserver.d @@ -0,0 +1,399 @@ + +/* + * Hello Object DLL Self-Registering Server + * Heavily modified from: + */ +/* + * SELFREG.CPP + * Server Self-Registrtation Utility, Chapter 5 + * + * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Microsoft + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + +import core.stdc.stdio; +import core.stdc.stdlib; +import core.stdc.string; +import std.string; +import core.sys.windows.com; +import core.sys.windows.winbase; +import core.sys.windows.windef; +import core.sys.windows.winreg; + +import chello; + +// This class factory object creates Hello objects. + +class CHelloClassFactory : ComObject, IClassFactory +{ +public: + this() + { + printf("CHelloClassFactory()\n"); + } + + ~this() + { + printf("~CHelloClassFactory()"); + } + + extern (Windows) : + + // IUnknown members + override HRESULT QueryInterface(const (IID)*riid, LPVOID *ppv) + { + printf("CHelloClassFactory.QueryInterface()\n"); + + if (IID_IUnknown == *riid) + { + printf("IUnknown\n"); + *ppv = cast(void*) cast(IUnknown) this; + } + else if (IID_IClassFactory == *riid) + { + printf("IClassFactory\n"); + *ppv = cast(void*) cast(IClassFactory) this; + } + else + { + *ppv = null; + return E_NOINTERFACE; + } + + AddRef(); + return NOERROR; + } + + // IClassFactory members + override HRESULT CreateInstance(IUnknown pUnkOuter, IID*riid, LPVOID *ppvObj) + { + CHello pObj; + HRESULT hr; + + printf("CHelloClassFactory.CreateInstance()\n"); + *ppvObj = null; + hr = E_OUTOFMEMORY; + + // Verify that a controlling unknown asks for IUnknown + if (null !is pUnkOuter && memcmp(&IID_IUnknown, riid, IID.sizeof)) + return CLASS_E_NOAGGREGATION; + + // Create the object passing function to notify on destruction. + pObj = new CHello(pUnkOuter, &ObjectDestroyed); + + if (!pObj) + return hr; + + if (pObj.Init()) + { + hr = pObj.QueryInterface(riid, ppvObj); + } + + // Kill the object if initial creation or Init failed. + if (FAILED(hr)) + delete pObj; + else + g_cObj++; + + return hr; + } + + HRESULT LockServer(BOOL fLock) + { + printf("CHelloClassFactory.LockServer(%d)\n", fLock); + + if (fLock) + g_cLock++; + else + g_cLock--; + + return NOERROR; + } +}; + +// Count number of objects and number of locks. +ULONG g_cObj =0; +ULONG g_cLock=0; + +import core.sys.windows.dll; +HINSTANCE g_hInst; + +extern (Windows): + +BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) +{ + switch (ulReason) + { + case DLL_PROCESS_ATTACH: + g_hInst = hInstance; + dll_process_attach( hInstance, true ); + printf("ATTACH\n"); + break; + + case DLL_PROCESS_DETACH: + printf("DETACH\n"); + dll_process_detach( hInstance, true ); + break; + + case DLL_THREAD_ATTACH: + dll_thread_attach( true, true ); + printf("THREAD_ATTACH\n"); + break; + + case DLL_THREAD_DETACH: + dll_thread_detach( true, true ); + printf("THREAD_DETACH\n"); + break; + + default: + assert(0); + } + return true; +} + +/* + * DllGetClassObject + * + * Purpose: + * Provides an IClassFactory for a given CLSID that this DLL is + * registered to support. This DLL is placed under the CLSID + * in the registration database as the InProcServer. + * + * Parameters: + * clsID REFCLSID that identifies the class factory + * desired. Since this parameter is passed this + * DLL can handle any number of objects simply + * by returning different class factories here + * for different CLSIDs. + * + * riid REFIID specifying the interface the caller wants + * on the class object, usually IID_ClassFactory. + * + * ppv LPVOID * in which to return the interface + * pointer. + * + * Return Value: + * HRESULT NOERROR on success, otherwise an error code. + */ +HRESULT DllGetClassObject(CLSID*rclsid, IID*riid, LPVOID *ppv) +{ + HRESULT hr; + CHelloClassFactory pObj; + + printf("DllGetClassObject()\n"); + + if (CLSID_Hello != *rclsid) + return E_FAIL; + + pObj = new CHelloClassFactory(); + + if (!pObj) + return E_OUTOFMEMORY; + + hr = pObj.QueryInterface(riid, ppv); + + if (FAILED(hr)) + delete pObj; + + return hr; +} + +/* + * Answers if the DLL can be freed, that is, if there are no + * references to anything this DLL provides. + * + * Return Value: + * BOOL true if nothing is using us, false otherwise. + */ +HRESULT DllCanUnloadNow() +{ + SCODE sc; + + printf("DllCanUnloadNow()\n"); + + // Any locks or objects? + sc = (0 == g_cObj && 0 == g_cLock) ? S_OK : S_FALSE; + return sc; +} + +/* + * Instructs the server to create its own registry entries + * + * Return Value: + * HRESULT NOERROR if registration successful, error + * otherwise. + */ +HRESULT DllRegisterServer() +{ + char[128] szID; + char[128] szCLSID; + char[512] szModule; + + printf("DllRegisterServer()\n"); + + // Create some base key strings. + StringFromGUID2(&CLSID_Hello, cast(LPOLESTR) szID, 128); + unicode2ansi(szID.ptr); + strcpy(szCLSID.ptr, "CLSID\\"); + strcat(szCLSID.ptr, szID.ptr); + + // Create ProgID keys + SetKeyAndValue("Hello1.0", null, "Hello Object"); + SetKeyAndValue("Hello1.0", "CLSID", szID.ptr); + + // Create VersionIndependentProgID keys + SetKeyAndValue("Hello", null, "Hello Object"); + SetKeyAndValue("Hello", "CurVer", "Hello1.0"); + SetKeyAndValue("Hello", "CLSID", szID.ptr); + + // Create entries under CLSID + SetKeyAndValue(szCLSID.ptr, null, "Hello Object"); + SetKeyAndValue(szCLSID.ptr, "ProgID", "Hello1.0"); + SetKeyAndValue(szCLSID.ptr, "VersionIndependentProgID", "Hello"); + SetKeyAndValue(szCLSID.ptr, "NotInsertable", null); + + GetModuleFileNameA(g_hInst, szModule.ptr, szModule.length); + + SetKeyAndValue(szCLSID.ptr, "InprocServer32", szModule.ptr); + return NOERROR; +} + +/* + * Purpose: + * Instructs the server to remove its own registry entries + * + * Return Value: + * HRESULT NOERROR if registration successful, error + * otherwise. + */ +HRESULT DllUnregisterServer() +{ + char[128] szID; + char[128] szCLSID; + char[256] szTemp; + + printf("DllUnregisterServer()\n"); + + // Create some base key strings. + StringFromGUID2(&CLSID_Hello, cast(LPOLESTR) szID, 128); + unicode2ansi(szID.ptr); + strcpy(szCLSID.ptr, "CLSID\\"); + strcat(szCLSID.ptr, szID.ptr); + + RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello\\CurVer"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello\\CLSID"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello"); + + RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello1.0\\CLSID"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello1.0"); + + strcpy(szTemp.ptr, szCLSID.ptr); + strcat(szTemp.ptr, "\\"); + strcat(szTemp.ptr, "ProgID"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr); + + strcpy(szTemp.ptr, szCLSID.ptr); + strcat(szTemp.ptr, "\\"); + strcat(szTemp.ptr, "VersionIndependentProgID"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr); + + strcpy(szTemp.ptr, szCLSID.ptr); + strcat(szTemp.ptr, "\\"); + strcat(szTemp.ptr, "NotInsertable"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr); + + strcpy(szTemp.ptr, szCLSID.ptr); + strcat(szTemp.ptr, "\\"); + strcat(szTemp.ptr, "InprocServer32"); + RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr); + + RegDeleteKeyA(HKEY_CLASSES_ROOT, szCLSID.ptr); + return NOERROR; +} + +/* + * SetKeyAndValue + * + * Purpose: + * Private helper function for DllRegisterServer that creates + * a key, sets a value, and closes that key. + * + * Parameters: + * pszKey LPTSTR to the name of the key + * pszSubkey LPTSTR ro the name of a subkey + * pszValue LPTSTR to the value to store + * + * Return Value: + * BOOL true if successful, false otherwise. + */ +BOOL SetKeyAndValue(LPCSTR pszKey, LPCSTR pszSubkey, LPCSTR pszValue) +{ + HKEY hKey; + char[256] szKey; + BOOL result; + + strcpy(szKey.ptr, pszKey); + + if (pszSubkey) + { + strcat(szKey.ptr, "\\"); + strcat(szKey.ptr, pszSubkey); + } + + result = true; + + int regresult = RegCreateKeyExA(HKEY_CLASSES_ROOT, + szKey.ptr, 0, null, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, null, &hKey, null); + if (ERROR_SUCCESS != regresult) + { + result = false; + // If the value is 5, you'll need to run the program with Administrator privileges + printf("RegCreateKeyExA() failed with 0x%x\n", regresult); + } + else + { + if (null != pszValue) + { + if (RegSetValueExA(hKey, null, 0, REG_SZ, cast(BYTE *) pszValue, + cast(int)((strlen(pszValue) + 1) * char.sizeof)) != ERROR_SUCCESS) + result = false; + } + + if (RegCloseKey(hKey) != ERROR_SUCCESS) + result = false; + } + + if (!result) + printf("SetKeyAndValue() failed\n"); + + return result; +} + +/* + * ObjectDestroyed + * + * Purpose: + * Function for the Hello object to call when it gets destroyed. + * Since we're in a DLL we only track the number of objects here, + * letting DllCanUnloadNow take care of the rest. + */ + +extern (D) void ObjectDestroyed() +{ + printf("ObjectDestroyed()\n"); + g_cObj--; +} + +void unicode2ansi(char *s) +{ + wchar *w; + + for (w = cast(wchar *) s; *w; w++) + *s++ = cast(char)*w; + + *s = 0; +} diff --git a/dmdsamples/dserver64.def b/dmdsamples/dserver64.def new file mode 100644 index 0000000..b4b885c --- /dev/null +++ b/dmdsamples/dserver64.def @@ -0,0 +1,5 @@ +EXPORTS + DllGetClassObject + DllCanUnloadNow + DllRegisterServer + DllUnregisterServer diff --git a/dmdsamples/hello.d b/dmdsamples/hello.d new file mode 100644 index 0000000..d0446af --- /dev/null +++ b/dmdsamples/hello.d @@ -0,0 +1,13 @@ + +import std.stdio; + +void main(string[] args) +{ + writeln("hello world"); + writefln("args.length = %d", args.length); + + foreach (index, arg; args) + { + writefln("args[%d] = '%s'", index, arg); + } +} diff --git a/dmdsamples/htmlget.d b/dmdsamples/htmlget.d new file mode 100644 index 0000000..8b15ed6 --- /dev/null +++ b/dmdsamples/htmlget.d @@ -0,0 +1,111 @@ + +/* + HTMLget written by Christopher E. Miller + This code is public domain. + You may use it for any purpose. + This code has no warranties and is provided 'as-is'. + */ + +debug = HTMLGET; + +import std.string, std.conv, std.stdio; +import std.socket; + +int main(string[] args) +{ + if (args.length < 2) + { + writeln("Usage:"); + writeln(" htmlget "); + return 0; + } + + string url = args[1]; + auto i = indexOf(url, "://"); + + if (i != -1) + { + if (icmp(url[0 .. i], "http")) + throw new Exception("http:// expected"); + url = url[i + 3 .. $]; + } + + i = indexOf(url, '#'); + + if (i != -1) // Remove anchor ref. + url = url[0 .. i]; + + i = indexOf(url, '/'); + string domain; + + if (i == -1) + { + domain = url; + url = "/"; + } + else + { + domain = url[0 .. i]; + url = url[i .. $]; + } + + ushort port; + i = indexOf(domain, ':'); + + if (i == -1) + { + port = 80; // Default HTTP port. + } + else + { + port = to!ushort(domain[i + 1 .. $]); + domain = domain[0 .. i]; + } + + debug (HTMLGET) + writefln("Connecting to %s on port %d...", domain, port); + + Socket sock = new TcpSocket(new InternetAddress(domain, port)); + scope(exit) sock.close(); + + debug (HTMLGET) + writefln("Connected! Requesting URL \"%s\"...", url); + + if (port != 80) + domain = domain ~ ":" ~ to!string(port); + + sock.send("GET " ~ url ~ " HTTP/1.0\r\n" ~ + "Host: " ~ domain ~ "\r\n" ~ + "\r\n"); + + // Skip HTTP header. + while (true) + { + char[] line; + char[1] buf; + while(sock.receive(buf)) + { + line ~= buf; + if (buf[0] == '\n') + break; + } + + if (!line.length) + break; + + write(line); + + enum CONTENT_TYPE_NAME = "Content-Type: "; + + if (line.length > CONTENT_TYPE_NAME.length && + !icmp(CONTENT_TYPE_NAME, line[0 .. CONTENT_TYPE_NAME.length])) + { + auto type = line[CONTENT_TYPE_NAME.length .. $]; + + if (type.length <= 5 || icmp("text/", type[0 .. 5])) + throw new Exception("URL is not text"); + } + } + + return 0; +} diff --git a/dmdsamples/listener.d b/dmdsamples/listener.d new file mode 100644 index 0000000..1917960 --- /dev/null +++ b/dmdsamples/listener.d @@ -0,0 +1,113 @@ +/* + D listener written by Christopher E. Miller + Modified by Orvid King + This code is public domain. + You may use it for any purpose. + This code has no warranties and is provided 'as-is'. + */ + +import std.algorithm : remove; +import std.conv : to; +import std.socket : InternetAddress, Socket, SocketException, SocketSet, TcpSocket; +import std.stdio : writeln, writefln; + +void main(string[] args) +{ + ushort port; + + if (args.length >= 2) + port = to!ushort(args[1]); + else + port = 4444; + + auto listener = new TcpSocket(); + assert(listener.isAlive); + listener.blocking = false; + listener.bind(new InternetAddress(port)); + listener.listen(10); + writefln("Listening on port %d.", port); + + enum MAX_CONNECTIONS = 60; + // Room for listener. + auto socketSet = new SocketSet(MAX_CONNECTIONS + 1); + Socket[] reads; + + while (true) + { + socketSet.add(listener); + + foreach (sock; reads) + socketSet.add(sock); + + Socket.select(socketSet, null, null); + + for (size_t i = 0; i < reads.length; i++) + { + if (socketSet.isSet(reads[i])) + { + char[1024] buf; + auto datLength = reads[i].receive(buf[]); + + if (datLength == Socket.ERROR) + writeln("Connection error."); + else if (datLength != 0) + { + writefln("Received %d bytes from %s: \"%s\"", datLength, reads[i].remoteAddress().toString(), buf[0..datLength]); + continue; + } + else + { + try + { + // if the connection closed due to an error, remoteAddress() could fail + writefln("Connection from %s closed.", reads[i].remoteAddress().toString()); + } + catch (SocketException) + { + writeln("Connection closed."); + } + } + + // release socket resources now + reads[i].close(); + + reads = reads.remove(i); + // i will be incremented by the for, we don't want it to be. + i--; + + writefln("\tTotal connections: %d", reads.length); + } + } + + if (socketSet.isSet(listener)) // connection request + { + Socket sn = null; + scope (failure) + { + writefln("Error accepting"); + + if (sn) + sn.close(); + } + sn = listener.accept(); + assert(sn.isAlive); + assert(listener.isAlive); + + if (reads.length < MAX_CONNECTIONS) + { + writefln("Connection from %s established.", sn.remoteAddress().toString()); + reads ~= sn; + writefln("\tTotal connections: %d", reads.length); + } + else + { + writefln("Rejected connection from %s; too many connections.", sn.remoteAddress().toString()); + sn.close(); + assert(!sn.isAlive); + assert(listener.isAlive); + } + } + + socketSet.reset(); + } +} diff --git a/dmdsamples/mydll/build.bat b/dmdsamples/mydll/build.bat new file mode 100644 index 0000000..8e6f29a --- /dev/null +++ b/dmdsamples/mydll/build.bat @@ -0,0 +1,2 @@ +..\..\..\windows\bin\dmd -ofmydll.dll -L/IMPLIB mydll.d dll.d mydll.def +..\..\..\windows\bin\dmd test.d mydll.lib diff --git a/dmdsamples/mydll/dll.d b/dmdsamples/mydll/dll.d new file mode 100644 index 0000000..7d85381 --- /dev/null +++ b/dmdsamples/mydll/dll.d @@ -0,0 +1,36 @@ + +// Public Domain + +import core.sys.windows.windef; +import core.sys.windows.dll; + +__gshared HINSTANCE g_hInst; + +extern (Windows) +BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) +{ + switch (ulReason) + { + case DLL_PROCESS_ATTACH: + g_hInst = hInstance; + dll_process_attach( hInstance, true ); + break; + + case DLL_PROCESS_DETACH: + dll_process_detach( hInstance, true ); + break; + + case DLL_THREAD_ATTACH: + dll_thread_attach( true, true ); + break; + + case DLL_THREAD_DETACH: + dll_thread_detach( true, true ); + break; + + default: + assert(0); + } + + return true; +} diff --git a/dmdsamples/mydll/mydll.d b/dmdsamples/mydll/mydll.d new file mode 100644 index 0000000..91ee32d --- /dev/null +++ b/dmdsamples/mydll/mydll.d @@ -0,0 +1,5 @@ + +module mydll; +import core.stdc.stdio; + +export void dllprint() { printf("hello dll world\n"); } diff --git a/dmdsamples/mydll/mydll.def b/dmdsamples/mydll/mydll.def new file mode 100644 index 0000000..3a83c13 --- /dev/null +++ b/dmdsamples/mydll/mydll.def @@ -0,0 +1,5 @@ +LIBRARY "mydll.dll" +EXETYPE NT +SUBSYSTEM WINDOWS +CODE SHARED EXECUTE +DATA WRITE diff --git a/dmdsamples/mydll/mydll.di b/dmdsamples/mydll/mydll.di new file mode 100644 index 0000000..b943b88 --- /dev/null +++ b/dmdsamples/mydll/mydll.di @@ -0,0 +1 @@ +export void dllprint(); diff --git a/dmdsamples/mydll/test.d b/dmdsamples/mydll/test.d new file mode 100644 index 0000000..0054e8b --- /dev/null +++ b/dmdsamples/mydll/test.d @@ -0,0 +1,8 @@ + +import mydll; + +int main() +{ + mydll.dllprint(); + return 0; +} diff --git a/dmdsamples/pi.d b/dmdsamples/pi.d new file mode 100644 index 0000000..5c787a1 --- /dev/null +++ b/dmdsamples/pi.d @@ -0,0 +1,187 @@ +import std.stdio; +import std.conv; +import core.stdc.stdlib; +import core.stdc.time; + +const int LONG_TIME = 4000; + +byte[] p; +byte[] t; +int q; + +int main(string[] args) +{ + time_t startime, endtime; + int i; + + if (args.length == 2) + { + q = to!int(args[1]); + } + else + { + writeln("Usage: pi [precision]"); + exit(55); + } + + if (q < 0) + { + writeln("Precision was too low, running with precision of 0."); + q = 0; + } + + if (q > LONG_TIME) + { + writeln("Be prepared to wait a while..."); + } + + // Compute one more digit than we display to compensate for rounding + q++; + + p.length = q + 1; + t.length = q + 1; + + /* compute pi */ + core.stdc.time.time(&startime); + arctan(2); + arctan(3); + mul4(); + core.stdc.time.time(&endtime); + + // Return to the number of digits we want to display + q--; + + /* print pi */ + + writef("pi = %d.", cast(int) (p[0])); + + for (i = 1; i <= q; i++) + writef("%d", cast(int) (p[i])); + + writeln(); + writefln("%s seconds to compute pi with a precision of %s digits.", endtime - startime, q); + + return 0; +} + +void arctan(int s) +{ + int n; + + t[0] = 1; + div(s); /* t[] = 1/s */ + add(); + n = 1; + + do + { + mul(n); + div(s * s); + div(n += 2); + + if (((n - 1) / 2) % 2 == 0) + add(); + else + sub(); + } while (!tiszero()); +} + +void add() +{ + int j; + + for (j = q; j >= 0; j--) + { + if (t[j] + p[j] > 9) + { + p[j] += t[j] - 10; + p[j - 1] += 1; + } + else + p[j] += t[j]; + } +} + +void sub() +{ + int j; + + for (j = q; j >= 0; j--) + { + if (p[j] < t[j]) + { + p[j] -= t[j] - 10; + p[j - 1] -= 1; + } + else + p[j] -= t[j]; + } + +} + +void mul(int multiplier) +{ + int b; + int i; + int carry = 0, digit = 0; + + for (i = q; i >= 0; i--) + { + b = (t[i] * multiplier + carry); + digit = b % 10; + carry = b / 10; + t[i] = cast(byte) digit; + } +} + +/* t[] /= l */ +void div(int divisor) +{ + int i, b; + int quotient, remainder = 0; + + foreach (ref x; t) + { + b = (10 * remainder + x); + quotient = b / divisor; + remainder = b % divisor; + x = cast(byte) quotient; + } +} + +void div4() +{ + int i, c, d = 0; + + for (i = 0; i <= q; i++) + { + c = (10 * d + p[i]) / 4; + d = (10 * d + p[i]) % 4; + p[i] = cast(byte) c; + } +} + +void mul4() +{ + int i, c, d; + + d = c = 0; + + for (i = q; i >= 0; i--) + { + d = (p[i] * 4 + c) % 10; + c = (p[i] * 4 + c) / 10; + p[i] = cast(byte) d; + } +} + +int tiszero() +{ + int k; + + for (k = 0; k <= q; k++) + if (t[k] != 0) + return false; + + return true; +} diff --git a/dmdsamples/posix.mak b/dmdsamples/posix.mak new file mode 100644 index 0000000..bbb1f8d --- /dev/null +++ b/dmdsamples/posix.mak @@ -0,0 +1,108 @@ +## +# Example Makefile for the D programming language +## +TARGETS= \ + d2html \ + dhry \ + hello \ + htmlget \ + listener \ + pi \ + sieve \ + wc \ + wc2 + +## Those examples are Windows specific: +# chello +# dserver +# dclient +# winsamp + +SRC = \ + chello.d \ + d2html.d \ + dclient.d \ + dhry.d \ + dserver.d \ + hello.d \ + htmlget.d \ + listener.d \ + pi.d \ + sieve.d \ + wc.d \ + wc2.d \ + winsamp.d +DFLAGS = +LFLAGS = + + +## +## Those values are immutables +## For languages such as C and C++, builtin rules are provided. +## But for D, you had to had to do everything by hand. +## Basically, if you had some Makefile knowledge, this is all you need. +## +## For explanation / more advanced use, see: +## https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html +.SUFFIXES: .d +.d.o: + $(DMD) $(DFLAGS) -c $< -of$@ +## + +LINK = dmd +DMD = dmd +RM = rm -rf +OBJS = $(SRC:.d=.o) + +all: $(TARGETS) + +clean: + $(RM) $(OBJS) + +fclean: clean + $(RM) $(TARGETS) + $(RM) *.d.htm + +re: fclean all + +chello: $(OBJS) + $(LINK) $(LFLAGS) $(OBJS) -of$@ + +.PHONY: all clean fclean re +.NOTPARALLEL: clean + +d2html: d2html.o + $(LINK) $(LFLAGS) $< -of$@ + +dclient: dclient.o + $(LINK) $(LFLAGS) $< -of$@ + +dhry: dhry.o + $(LINK) $(LFLAGS) $< -of$@ + +dserver: dserver.o + $(LINK) $(LFLAGS) $< -of$@ + +hello: hello.o + $(LINK) $(LFLAGS) $< -of$@ + +htmlget: htmlget.o + $(LINK) $(LFLAGS) $< -of$@ + +listener: listener.o + $(LINK) $(LFLAGS) $< -of$@ + +pi: pi.o + $(LINK) $(LFLAGS) $< -of$@ + +sieve: sieve.o + $(LINK) $(LFLAGS) $< -of$@ + +wc2: wc2.o + $(LINK) $(LFLAGS) $< -of$@ + +wc: wc.o + $(LINK) $(LFLAGS) $< -of$@ + +winsamp: winsamp.o + $(LINK) $(LFLAGS) $< -of$@ diff --git a/dmdsamples/sieve.d b/dmdsamples/sieve.d new file mode 100644 index 0000000..4fc2454 --- /dev/null +++ b/dmdsamples/sieve.d @@ -0,0 +1,28 @@ +/* Eratosthenes Sieve prime number calculation. */ + +import std.conv; +import std.stdio; +import std.range; + +void main(string[] args) +{ + immutable max = (1 < args.length) + ? args[1].to!size_t + : 0x4000; + size_t count = 1; // we have 2. + // flags[i] = isPrime(2 * i + 3) + auto flags = new bool[(max - 1) / 2]; + flags[] = true; + + foreach (i; 0..flags.length) + { + if (!flags[i]) + continue; + auto prime = i + i + 3; + foreach (k; iota(i + prime, flags.length, prime)) + flags[k] = false; + + count++; + } + writefln("%d primes", count); +} diff --git a/dmdsamples/wc.d b/dmdsamples/wc.d new file mode 100644 index 0000000..e11f584 --- /dev/null +++ b/dmdsamples/wc.d @@ -0,0 +1,49 @@ +import std.stdio; +import std.file; + +void main(string[] args) +{ + int w_total; + int l_total; + int c_total; + + writeln(" lines words bytes file"); + + foreach (arg; args[1 .. $]) + { + int w_cnt, l_cnt, c_cnt; + bool inword; + + string input = readText(arg); + + foreach (char c; input) + { + if (c == '\n') + ++l_cnt; + + if (c != ' ') + { + if (!inword) + { + inword = true; + ++w_cnt; + } + } + else + inword = false; + + ++c_cnt; + } + + writefln("%8s%8s%8s %s\n", l_cnt, w_cnt, c_cnt, arg); + l_total += l_cnt; + w_total += w_cnt; + c_total += c_cnt; + } + + if (args.length > 2) + { + writefln("--------------------------------------\n%8s%8s%8s total", + l_total, w_total, c_total); + } +} diff --git a/dmdsamples/wc2.d b/dmdsamples/wc2.d new file mode 100644 index 0000000..78169e7 --- /dev/null +++ b/dmdsamples/wc2.d @@ -0,0 +1,117 @@ +import std.stdio; +import std.file; +import std.algorithm.sorting; + +void main (string[] args) +{ + int w_total; + int l_total; + ulong c_total; + size_t[string] dictionary; + + writefln(" lines words bytes file"); + foreach (arg; args[1 .. $]) + { + int w_cnt, l_cnt; + bool inword; + auto c_cnt = std.file.getSize(arg); + + if (c_cnt < 10_000_000) + { + size_t wstart; + auto input = readText(arg); + + foreach (j, c; input) + { + if (c == '\n') + ++l_cnt; + if (c >= '0' && c <= '9') + { + } + else if (c >= 'a' && c <= 'z' || + c >= 'A' && c <= 'Z') + { + if (!inword) + { + wstart = j; + inword = true; + ++w_cnt; + } + } + else if (inword) + { + auto word = input[wstart .. j]; + dictionary[word]++; + inword = false; + } + } + if (inword) + { + auto w = input[wstart .. $]; + dictionary[w]++; + } + } + else + { + auto f = std.stdio.File(arg); + string buf; + + while (!f.eof()) + { + char c; + f.readf("%c", &c); + + if (c == '\n') + ++l_cnt; + + if (c >= '0' && c <= '9') + { + if (inword) + buf ~= c; + } + else if (c >= 'a' && c <= 'z' || + c >= 'A' && c <= 'Z') + { + if (!inword) + { + buf.length = 0; + buf ~= c; + inword = 1; + ++w_cnt; + } + else + buf ~= c; + } + else if (inword) + { + if (++dictionary[buf] == 1) + buf = null; + inword = 0; + } + } + + if (inword) + { + dictionary[buf]++; + } + } + + writefln("%8s%8s%8s %s\n", l_cnt, w_cnt, c_cnt, arg); + l_total += l_cnt; + w_total += w_cnt; + c_total += c_cnt; + } + + if (args.length > 2) + { + writefln("--------------------------------------\n%8s%8s%8s total", + l_total, w_total, c_total); + } + + writefln("--------------------------------------"); + + foreach (word1; dictionary.keys.sort()) + { + writefln("%3s %s", dictionary[word1], word1); + } +} diff --git a/dmdsamples/win32.mak b/dmdsamples/win32.mak new file mode 100644 index 0000000..ba8e642 --- /dev/null +++ b/dmdsamples/win32.mak @@ -0,0 +1,64 @@ +MODEL=32 +DMD=..\..\windows\bin\dmd +DFLAGS=-m$(MODEL) + +EXAMPLES = hello d2html dhry pi sieve wc wc2 \ + winsamp dserver mydll htmlget listener + +all: $(EXAMPLES) + echo done + +d2html: + $(DMD) d2html $(DFLAGS) + .\d2html.exe d2html.d + +dhry: + $(DMD) dhry $(DFLAGS) + .\dhry.exe + +hello: + $(DMD) hello $(DFLAGS) + .\hello.exe + +htmlget: + $(DMD) htmlget $(DFLAGS) + .\htmlget.exe www.dlang.org/index.html + +listener: + $(DMD) listener $(DFLAGS) + # .\listener.exe + +pi: + $(DMD) pi $(DFLAGS) + .\pi.exe 1000 + +sieve: + $(DMD) sieve $(DFLAGS) + .\sieve.exe + +wc: + $(DMD) wc $(DFLAGS) + .\wc.exe wc.d + +wc2: + $(DMD) wc2 $(DFLAGS) + .\wc2.exe wc2.d + +winsamp: + $(DMD) winsamp $(DFLAGS) gdi32.lib user32.lib winsamp.def + # .\winsamp.exe + +# COM client/server example +# dclient will fail unless run with administrator rights +dserver: + $(DMD) dserver.d chello.d $(DFLAGS) -L/DLL dserver64.def advapi32.lib ole32.lib user32.lib + $(DMD) dclient $(DFLAGS) ole32.lib uuid.lib + .\dclient.exe + +mydll: + $(DMD) $(DFLAGS) -ofmydll.dll mydll\mydll.d mydll\dll.d -L/DLL + $(DMD) $(DFLAGS) -ofdlltest.exe mydll\test.d mydll\mydll.di mydll.lib + .\dlltest.exe + +clean: + clean.bat diff --git a/dmdsamples/winsamp.d b/dmdsamples/winsamp.d new file mode 100644 index 0000000..82dff93 --- /dev/null +++ b/dmdsamples/winsamp.d @@ -0,0 +1,169 @@ +module winsamp; + +/+ Compile with: + + dmd winsamp winsamp.def + + or: + + dmd winsamp -L-Subsystem:Windows + + + + 64 bit version: + + dmd -m64 winsamp -L-Subsystem:Windows user32.lib + +/ + +pragma(lib, "gdi32.lib"); +import core.runtime; +import core.sys.windows.windef; +import core.sys.windows.wingdi; +import core.sys.windows.winuser; +import std.string; + +enum IDC_BTNCLICK = 101; +enum IDC_BTNDONTCLICK = 102; + +extern(Windows) +int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) +{ + int result; + + try + { + Runtime.initialize(); + result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow); + Runtime.terminate(); + } + catch (Throwable e) + { + MessageBoxA(null, e.toString().toStringz, "Error", MB_OK | MB_ICONEXCLAMATION); + result = 0; + } + + return result; +} + +int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) +{ + wstring caption = "The Hello Program"; + wstring className = "DWndClass"; + HWND hWnd, btnClick, btnDontClick; + MSG msg; + WNDCLASSW wndclass; + + wndclass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = &WindowProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIconW(null, IDI_APPLICATION); + wndclass.hCursor = LoadCursorW(null, IDC_CROSS); + wndclass.hbrBackground = cast(HBRUSH)GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = null; + wndclass.lpszClassName = className.ptr; + + if (!RegisterClassW(&wndclass)) + { + MessageBoxW(null, "Couldn't register Window Class!", caption.ptr, MB_ICONERROR); + return 0; + } + + hWnd = CreateWindowW(className.ptr, // window class name + caption.ptr, // window caption + WS_THICKFRAME | + WS_MAXIMIZEBOX | + WS_MINIMIZEBOX | + WS_SYSMENU | + WS_VISIBLE, // window style + CW_USEDEFAULT, // initial x position + CW_USEDEFAULT, // initial y position + 600, // initial x size + 400, // initial y size + HWND_DESKTOP, // parent window handle + null, // window menu handle + hInstance, // program instance handle + null); // creation parameters + + if (hWnd is null) + { + MessageBoxW(null, "Couldn't create window.", caption.ptr, MB_ICONERROR); + return 0; + } + + btnClick = CreateWindowW("BUTTON", "Click Me", WS_CHILD | WS_VISIBLE, + 0, 0, 100, 25, hWnd, cast(HMENU)IDC_BTNCLICK, hInstance, null); + + btnDontClick = CreateWindowW("BUTTON", "DON'T CLICK!", WS_CHILD | WS_VISIBLE, + 110, 0, 100, 25, hWnd, cast(HMENU)IDC_BTNDONTCLICK, hInstance, null); + + ShowWindow(hWnd, iCmdShow); + UpdateWindow(hWnd); + + while (GetMessageW(&msg, null, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + return cast(int) msg.wParam; +} + +int* p; +extern(Windows) +LRESULT WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow +{ + switch (message) + { + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_BTNCLICK: + if (HIWORD(wParam) == BN_CLICKED) + MessageBoxW(hWnd, "Hello, world!", "Greeting", + MB_OK | MB_ICONINFORMATION); + + break; + + case IDC_BTNDONTCLICK: + if (HIWORD(wParam) == BN_CLICKED) + { + MessageBoxW(hWnd, "You've been warned...", "Prepare to GP fault", + MB_OK | MB_ICONEXCLAMATION); + *p = 1; + } + + break; + + default: + } + + break; + } + + case WM_PAINT: + { + enum text = "D Does Windows"; + PAINTSTRUCT ps; + + HDC dc = BeginPaint(hWnd, &ps); + scope(exit) EndPaint(hWnd, &ps); + RECT r; + GetClientRect(hWnd, &r); + HFONT font = CreateFontW(80, 0, 0, 0, FW_EXTRABOLD, FALSE, FALSE, + FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); + HGDIOBJ old = SelectObject(dc, cast(HGDIOBJ) font); + SetTextAlign(dc, TA_CENTER | TA_BASELINE); + TextOutA(dc, r.right / 2, r.bottom / 2, text.ptr, text.length); + DeleteObject(SelectObject(dc, old)); + + break; + } + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + break; + } + + return DefWindowProcW(hWnd, message, wParam, lParam); +} diff --git a/dmdsamples/winsamp.def b/dmdsamples/winsamp.def new file mode 100644 index 0000000..40b796c --- /dev/null +++ b/dmdsamples/winsamp.def @@ -0,0 +1,2 @@ +EXETYPE NT +SUBSYSTEM WINDOWS