Discussion:
Programming Windows D Examples are now Online!
Andrej Mitrovic
2011-06-21 04:14:22 UTC
Permalink
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.

Currently over 120 code samples have been translated into D, with only
a few modules remaining.

Everything else you need to know is in the Readme file:
https://github.com/AndrejMitrovic/DWindowsProgramming

The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
Walter Bright
2011-06-21 04:46:52 UTC
Permalink
Post by Andrej Mitrovic
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.
Currently over 120 code samples have been translated into D, with only
a few modules remaining.
https://github.com/AndrejMitrovic/DWindowsProgramming
The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
This is nice work. When you're done, let's post a link on Reddit!
Andrej Mitrovic
2011-06-21 05:11:41 UTC
Permalink
Post by Walter Bright
This is nice work. When you're done, let's post a link on Reddit!
Let's shake the bees nest? :p

I'll have to make some kind of workaround for D DLLs for a few
examples. I'll see about doing this these days. There's a few audio
examples I'll finish tomorrow (I just need to plug my guitar to see if
it records anything), and then I'm almost done with making all
examples compile. After that some polishing can be done gradually.

Btw, would it be good idea to link this somewhere on the homepage?
Maybe a page like this: http://d-programming-language.org/windows.html

I've already linked it from the dwiki.
Walter Bright
2011-06-21 17:38:31 UTC
Permalink
Post by Andrej Mitrovic
Btw, would it be good idea to link this somewhere on the homepage?
Sure! Wanna generate a pull request?
Andrej Mitrovic
2011-06-21 18:32:55 UTC
Permalink
Post by Walter Bright
Post by Andrej Mitrovic
Btw, would it be good idea to link this somewhere on the homepage?
Sure! Wanna generate a pull request?
Yeah I'll cook something up and make a pull.

Btw, std.c.windows.windows and the WindowsAPI bindings clash when used
together. The root of the problem is type definitions like these:

typedef void* HINSTANCE;

The problem is that both bindings create this typedef, and the
compiler treats them as separate types. From what I recall I've tried
to compile something like this before (this is just a snippet):

import win32.windef;
import core.sys.windows.dll;

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:
}

return true;
}

However this won't work. dll_process_attach() can't be called with the
`hInstance` argument because it's defined as a typedef in
`win32.windef`, while dll_process_attach has the parameter defined as
a typedef somewhere in `core.windows` or a similar module.

I don't know whether it is planned to incorporate the WinAPI bindings
into Phobos/Druntime, there's at least 2.5 megs of code in prototypes
and I'm not sure about the license (it's based on the MinGW headers).

std.c.windows.windows is already growing as people need to call more
API functions (just recently a bunch of prototypes were added for
std.registry). It seems odd having to waste time writing function
prototypes when this was already done long ago in the WinAPI bindings.
Trass3r
2011-06-21 21:29:47 UTC
Permalink
Am 21.06.2011, 20:32 Uhr, schrieb Andrej Mitrovic
Post by Andrej Mitrovic
I don't know whether it is planned to incorporate the WinAPI bindings
into Phobos/Druntime, there's at least 2.5 megs of code in prototypes
and I'm not sure about the license (it's based on the MinGW headers).
That is indeed long overdue!
Jimmy Cao
2011-06-21 21:48:19 UTC
Permalink
Am 21.06.2011, 20:32 Uhr, schrieb Andrej Mitrovic <
I don't know whether it is planned to incorporate the WinAPI bindings
Post by Andrej Mitrovic
into Phobos/Druntime, there's at least 2.5 megs of code in prototypes
and I'm not sure about the license (it's based on the MinGW headers).
That is indeed long overdue!
I feel like I cannot express how immensely helpful such an addition would
be.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110621/c315ccdb/attachment.html>
Brad Anderson
2011-06-21 06:08:13 UTC
Permalink
On Mon, Jun 20, 2011 at 10:14 PM, Andrej Mitrovic <
Post by Andrej Mitrovic
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.
Currently over 120 code samples have been translated into D, with only
a few modules remaining.
https://github.com/AndrejMitrovic/DWindowsProgramming
The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
Awesome. If only I hadn't sold my copy a month ago :(. It's great that
Petzold was OK with you doing this. He's a great author. Code is probably
the most interesting technical book I've ever read (sorry, Andrei).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110621/daab9dbe/attachment.html>
Andrei Alexandrescu
2011-06-21 14:06:17 UTC
Permalink
Post by Brad Anderson
On Mon, Jun 20, 2011 at 10:14 PM, Andrej Mitrovic
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.
Currently over 120 code samples have been translated into D, with only
a few modules remaining.
https://github.com/AndrejMitrovic/DWindowsProgramming
The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
Awesome. If only I hadn't sold my copy a month ago :(. It's great that
Petzold was OK with you doing this. He's a great author. Code is
probably the most interesting technical book I've ever read (sorry, Andrei).
There are comparisons I love to lose.

Andrei
Walter Bright
2011-06-21 17:37:42 UTC
Permalink
Post by Andrei Alexandrescu
Post by Brad Anderson
He's a great author. Code is
probably the most interesting technical book I've ever read (sorry, Andrei).
There are comparisons I love to lose.
It's true. There's no shame in losing to Petzold!
bearophile
2011-06-21 14:41:18 UTC
Permalink
Post by Andrej Mitrovic
https://github.com/AndrejMitrovic/DWindowsProgramming
It looks like a lot of work!
I have not tried to compile the code yet.

I am not asking you to modify the code, but D with() was designed to reduce noise in code like:

wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = &WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = appName.toUTF16z;
wndclass.lpszClassName = appName.toUTF16z;


The code in those examples is generally very noisy (I presume about as much as the original code). I have mixed feelings about it.

Sometimes final switches are not easy to retrofit.

Bye,
bearophile
Andrej Mitrovic
2011-06-21 15:58:57 UTC
Permalink
Post by bearophile
I am not asking you to modify the code, but D with() was designed to reduce
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = &WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = appName.toUTF16z;
wndclass.lpszClassName = appName.toUTF16z;
Yes, the original code is quite noisy, especially considering that a
lot of code uses pointers and state variables for strcpy calls and
things like that.
Post by bearophile
The code in those examples is generally very noisy (I presume about as much
as the original code). I have mixed feelings about it.
Yes, it's noisy because of a couple of things:

1. I haven't worked a lot on actually using D idioms. My main concern
was making the examples compile and work in the exact way as the
original examples. Having a 1-to-1 translation helps in catching bugs
(and I've had quite a few of those).

2. Generally calling into GDI is going to be much more noisy than
using some 3rd party GUI library, the same goes for various other
WinAPI functions as well. You have to manually acquire and release GDI
resources so this complicates things.

3. I've added some excessive noise in some code since I've used a lot
of to!string() and duplication workarounds to get the examples
compiling. This will be replaced with better code.

The examples will be continued to be improved and refactored, but I
had to start hosting them otherwise I'd never finish the project.
Walter Bright
2011-06-21 17:40:13 UTC
Permalink
Post by Andrej Mitrovic
The examples will be continued to be improved and refactored, but I
had to start hosting them otherwise I'd never finish the project.
I'm glad you decided to host them on github. Github has been a great boon for D
in crowdsourcing improvements!
bearophile
2011-06-21 17:54:56 UTC
Permalink
Post by Andrej Mitrovic
Having a 1-to-1 translation helps in catching bugs
(and I've had quite a few of those).
After translating so much code have you seen some recurring patterns in your code conversion bugs?
Time ago I have suggested a -cstyle compiler switch to DMD that activates some C-isms like C-style array declarations, and activates warnings useful to catch common conversion bugs, like a warning against passing by value large fixed-static arrays, having large static arrays of floating point values (that are initialized with NaN, so they cause quite large binaries), and so on.
Post by Andrej Mitrovic
2. Generally calling into GDI is going to be much more noisy than
using some 3rd party GUI library,
Right. I'd like the standard D distribution to have a little graphics module like simplegraphics, that I use now and then (not written by me) :-)

Bye,
bearophile
Andrej Mitrovic
2011-06-21 19:35:13 UTC
Permalink
Post by bearophile
After translating so much code have you seen some recurring patterns in your
code conversion bugs?
A lot of C code is missing default labels. I've used the github 2.054
clone to compile all examples in order to catch missing labels at
compile time. I've missed many of them before this feature became
available.

Float/Doubles are initialized to NaN in D, however I don't know what
they're initialized to in C. But it seems none of the examples had
floating point variables initialized. This causes halts/exceptions in
D, and without ddbg it's really hard to track down what went wrong. I
don't think the stack traces helped me in this regard. Generally
forgetting to initialize floats seems to be common in other C code as
well.

C struct initializer syntax is used for static arrays of structs in
the C code. I think this could easily be a source of bugs if you add
or remove fields from a struct. I'm not sure if that syntax works in D
but I've used explicit ctor calls instead, such as:

struct Foo { int x, y; }
Foo[5] foo = [Foo(1, 2), Foo(1, 2), Foo(1, 2), Foo(1, 2), Foo(1, 2)];

It's verbose but it's safer.

In some code a variable would be defined as an int, and returned as a
short. There are other cases where it's defined as an int, and then
casted to a ubyte (BYTE is an alias for ubyte there). I have to fix
some of these.

I did notice an annoying thing with D, for example:
ubyte val = min(0, 128);
Error: cannot implicitly convert expression (min(0,128)) of type int to ubyte

The problem with this is I have to add a cast or a safer to!() call.
to!() can only do a runtime check:
ubyte val = to!ubyte(min(1024, 2048)); // overflow exception at runtime

And a cast is completely unsafe:
ubyte val = cast(ubyte)(min(1024, 2048)); // no error, bugs introduced!

Of course the compiler doesn't know what min does, only that it
returns an int, so I don't know whether it could ever figure out that
a function would never return a value that overflows the assignment
variable (maybe this feature could be implemented for pure
functions..).

C Globals become an instant source of bugs as soon as you fire up a
new thread. This is due to D's thread-local storage by default
feature. I like D's approach, and C globals should be replaced with
messaging or some other technique. I've used __gshared in various
modules to make the examples compile and work properly, but this
should be replaced.
This isn't unique to these examples. I've seen globals used everywhere
for messaging purposes in C code, e.g. some audio processing examples
in a different library.

A weird thing I've seen in the examples was a pointer to a static
variable was passed to a newly spawned thread's function. And via this
static variable the original thread and the work thread communicated
together. How this can work is beyond me, but it can't work in D.
Luckily D's spawn() function does offer protection for this kind of
code.

These examples used implicit fallbacks a lot, with only a comment
explicitly mentioning that there is a fallback in play. I think it's
good that we've abandoned implicit fallbacks, they could easily cause
bugs.
But, on the other hand someone might get an error about an implicit
fallback and think they forgot to add a "break" when porting C code.
So they add that, but now they've introduced a bug because the
fallback was actually necessary. I had this happen to me in one
example because the fallback wasn't explicitly mentioned.

There are issues with calling format() and writef(). This is not just
for this translation project. Most C code uses some form of
printf/wsprintf to either store a string to a variable or print it
out. But the format specifiers often do not translate into D. I think
what is probably causing this is that C types are not the same as D
types, so when you see this in C code:
printf("Note Count %ld, (long) notescount);

This might not translate into D and you could easily get an exception
at runtime (a pity that this doesn't get caught at compile-time). The
root of the problem is that the format specifiers explicitly name the
type, while you inadvertently change the actual type in D (maybe you
were fixing a conversion bug), and then you randomly get an exception
thrown at runtime.

The #1 problem with these exceptions is that you get no error line
whatsoever. You just get back "Invalid format specifier" or something
like that. This is of no help, and I always have to fire up ddbg or
manually hunt down each format specifier and replace it with D's safe
"%s", which works great.
The exceptions with no error line problem is common for most Phobos
functions, I absolutely hate getting back an error message such as:
std.exception.ErrnoException at std\stdio.d(286): Cannot open file
`blablabla' in mode `r' (No such file or directory)

No stack trace, no error line except the error line in Phobos. I
*don't care* about error lines in Phobos, the error is in my code not
in Phobos, and I really think this needs to improve.

Many functions assume ASCII or USC2, both of which are wrong to assume
these days. I have some examples I still have to fix, because I've
used code like:
string buffer;
TextOut(buffer.toUTF16z, buffer.length);
This is incorrect code. TextOut takes the number of characters, not
code units when issuing the call. The code will compile and run fine
for the majority of cases because most characters will fit into
wchar's code point, and you will have a 1to1 code-point to code-unit
ratio. But add a Japanese character and you will see garbage being
printed out to the screen. The correct workaround for this is to
either:
1) Store everything as a dchar[]:
dstring buffer;
TextOut(buffer.toUTF16z, buffer.length); // correct as long as
UTF never has more than 4 code units
2) Use some Phobos code-point counting function
string buffer;
TextOut(buffer.toUTF16z, std.utf.count(buffer));

The second option might cause performance issues, while using UTF32
dchars might cause excessive use of memory. Other solutions might be
to wrap strings and cache the count of code points. It's a balancing
act between memory and performance.

Some API functions take char* as a parameter when expecting some
pointer to a data buffer which can but doesn't necessarily store text.
I don't know why char* is used instead of void*, perhaps char* are
more often used with these functions so they've decided to type it
like that.

There are many cases of implicit 0 to void* casts, but D catches this
at compile time.

A big issue with porting is that D's character arrays are always
initialized to invalid values. This wreaks havoc in code, in
particular with static arrays. For example:

char[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(buffer[]); // <- buggy code

The problem is twofold. First, the API call might not work because it
could easily expect a null terminator to be present as a first
character:
char[100] buffer;
APIWriteToBuffer(buffer.ptr); // Might not work!

So I've had to do this:
char[100] buffer;
buffer[] = '\0'; // or buffer[0] = '\0', depending on the function
APIWriteToBuffer(buffer.ptr);

Second, after the call you will have a buffer that has some valid text
stored into it, and then either null terminators to the length of the
array (if you did buffer[] = '\0'), OR you will have a null terminator
followed by a series of char.init invalid UTF values.

So when you finally call a D function with such a static array, it
could print out garbage or throw an exception:
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(buffer[]); // what will this function do when
stumbles on '\0' or char.init?

Behind the scense that D function might in turn call a C function, so
continued from the last example:
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(buffer[]);

void myDStringFunction(char[] buffer)
{
// huge mess, the API function might write nonsense like ['f',
'o', 'o', '\0', char.init, char.init..]
APIPrintToScreen(buffer.ptr, buffer.length);
}

So you have to do conversion and duplication all the time. You have to do:

char[100] buffer;
APIWriteToBuffer(buffer.ptr); // buffer might now be ['f', 'o',
'o', '\0', char.init, char.init..];
myDStringFunction(to!string(buffer.ptr.toStringz));

How it works: First, you need to treat the buffer as a C
null-terminated char array, hence using .ptr. Then, you have to call a
Phobos function so it can retrieve a string until the first null
terminator.

But it gets worse when UTF is in play because in v2.043 conv.to
doesn't know how to convert wchar*'s. I've made a request on github
and I think this feature will be incorporated, but for now you can't
do this:

wchar[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(to!string(buffer.ptr)); // error, to!() can't
convert wchar*

So I've had to create my own function which converts a wchar* to
wchar[], which can then be used for whatever purpose:

wchar[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(to!string(fromWStringz(buffer.ptr)));

So generally static arrays of characters and string handling between C
and D can be painful.
Walter Bright
2011-06-21 20:22:11 UTC
Permalink
[...]
This is interesting and valuable information. Please add it to your repository
as a readme, or even as a blog post!
Walter Bright
2011-06-21 20:30:46 UTC
Permalink
Post by Andrej Mitrovic
Float/Doubles are initialized to NaN in D, however I don't know what
they're initialized to in C.
In C they're initialized to 0 for globals, and garbage for locals and allocated
data.
Post by Andrej Mitrovic
A big issue with porting is that D's character arrays are always
initialized to invalid values. This wreaks havoc in code, in
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(buffer[]); //<- buggy code
In C buffer is not initialized to 0, if it is not global, it is initialized to
garbage.
Post by Andrej Mitrovic
The problem is twofold. First, the API call might not work because it
could easily expect a null terminator to be present as a first
char[100] buffer;
APIWriteToBuffer(buffer.ptr); // Might not work!
Fix:

char[100] buffer = 0;
Post by Andrej Mitrovic
So when you finally call a D function with such a static array, it
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
myDStringFunction(buffer[]); // what will this function do when
stumbles on '\0' or char.init?
Fix:
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
auto p = buffer[0 .. strlen(buffer.ptr)];
myDStringFunction(p);
Andrej Mitrovic
2011-06-21 20:46:04 UTC
Permalink
Post by Walter Bright
char[100] buffer = 0;
I didn't know about this syntax! I've been under a rock apparently.
Post by Walter Bright
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
auto p = buffer[0 .. strlen(buffer.ptr)];
myDStringFunction(p);
Yeah I was going to suggest that. My only problem was I didn't know
where to look for an strlen equivalent for UTF, but I found it in
std.utf and it's called stride().

I'll fix these examples soon. I'll give a thought or two about that
blogging idea as well, thanks.
Jonathan M Davis
2011-06-21 21:02:57 UTC
Permalink
Post by Andrej Mitrovic
Post by Walter Bright
char[100] buffer = 0;
I didn't know about this syntax! I've been under a rock apparently.
Post by Walter Bright
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
auto p = buffer[0 .. strlen(buffer.ptr)];
myDStringFunction(p);
Yeah I was going to suggest that. My only problem was I didn't know
where to look for an strlen equivalent for UTF, but I found it in
std.utf and it's called stride().
stride isn't a UTF version of strlen. stride returns how many code units it is
to the beginning of the next code point. You can use it to get the number of
characters in a string by calling it in a loop, but it isn't a UTF version of
strlen.

- Jonathan M Davis
Andrej Mitrovic
2011-06-21 21:04:39 UTC
Permalink
Post by Jonathan M Davis
stride isn't a UTF version of strlen.
Brain misshap, I meant std.utf.count.
Andrej Mitrovic
2011-06-21 21:24:21 UTC
Permalink
Walter, would it be possible to make .map file generation follow the
-od flag? It's odd when a build script fills a directory with map
files while executables and object files are properly in their own
directories as specified via -od and -of flags.

Btw, I have just pushed a changeset and made the build script
parallel. I turned this:
foreach (dir; dirs)

into this:
foreach (dir; taskPool.parallel(dirs, 1))

And added other small cosmetic changes, but the above is the only real change.

Here's my timings:
Serial build: 1min, 3sec
Parallel build: 22sec
Brad Roberts
2011-06-21 21:33:52 UTC
Permalink
Post by Andrej Mitrovic
Walter, would it be possible to make .map file generation follow the
-od flag? It's odd when a build script fills a directory with map
files while executables and object files are properly in their own
directories as specified via -od and -of flags.
Btw, I have just pushed a changeset and made the build script
foreach (dir; dirs)
foreach (dir; taskPool.parallel(dirs, 1))
And added other small cosmetic changes, but the above is the only real change.
Serial build: 1min, 3sec
Parallel build: 22sec
Fixed in 2.053. See also bug 4833.
Andrej Mitrovic
2011-06-21 21:39:28 UTC
Permalink
Post by Brad Roberts
Fixed in 2.053. See also bug 4833.
Well that's odd because the script still generates map files in the
root directory of the script file even though I'm using -od and -of,
and I'm using 2.053. I've added a cleanup call after each sample is
built so every map file is deleted from the root dir.
Andrej Mitrovic
2011-06-21 21:45:30 UTC
Permalink
Wait, I'm using 2.054 from github. This might be a regression. I'll investigate.
Andrej Mitrovic
2011-06-21 21:46:36 UTC
Permalink
No I've tested with 2.053 and it still generates a map file. I'll
reopen that report.
Brad Roberts
2011-06-21 21:47:51 UTC
Permalink
Post by Andrej Mitrovic
Wait, I'm using 2.054 from github. This might be a regression. I'll investigate.
I just checked the source for dmd's link.c (where the changes were) and it hasn't changed. I just ran some quick tests
on linux and it appears to be working correctly still. Testing on windows is a tad more painful for me, so I haven't
re-tested it there. Take a look at the pull request listed in the ticket for the test cases that were run.

Something you're doing is different than the test cases (which were tested on win32 as well as linux at the time).
Robert Clipsham
2011-06-21 21:56:02 UTC
Permalink
Post by Andrej Mitrovic
Walter, would it be possible to make .map file generation follow the
-od flag? It's odd when a build script fills a directory with map
files while executables and object files are properly in their own
directories as specified via -od and -of flags.
Btw, I have just pushed a changeset and made the build script
foreach (dir; dirs)
foreach (dir; taskPool.parallel(dirs, 1))
And added other small cosmetic changes, but the above is the only real change.
Serial build: 1min, 3sec
Parallel build: 22sec
I use D as a build script for my project too, it's awesome how easy it
is to make the build parallel, and how much compilation time it saves!

Side note: parallel() works as an alias for taskPool.parallel, saves you
some characters and looks nicer!
--
Robert
http://octarineparrot.com/
Andrej Mitrovic
2011-06-21 22:09:10 UTC
Permalink
Post by Robert Clipsham
I use D as a build script for my project too, it's awesome how easy it
is to make the build parallel, and how much compilation time it saves!
Yeah, true words right there. RDMD is what makes everything run so
smooth, it feels like coding in Python.
Post by Robert Clipsham
Side note: parallel() works as an alias for taskPool.parallel, saves you
some characters and looks nicer!
Right you are. Fixed!

I can't believe how easy it is to just fix and push something online.
It's quite exciting.
Andrej Mitrovic
2011-06-21 23:01:49 UTC
Permalink
Ok I've made most of the examples unicode safe now by using
std.utf.count instead of .length. The changesets are online.
Andrej Mitrovic
2011-06-21 23:17:58 UTC
Permalink
Post by Andrej Mitrovic
Post by Jonathan M Davis
stride isn't a UTF version of strlen.
Brain misshap, I meant std.utf.count.
Double brain misshap. I wasn't looking for code-point count of a D
string, but of a zero-terminated wchar*.
Walter Bright
2011-06-22 00:34:17 UTC
Permalink
Post by Andrej Mitrovic
Walter, would it be possible to make .map file generation follow the
-od flag? It's odd when a build script fills a directory with map
files while executables and object files are properly in their own
directories as specified via -od and -of flags.
I think it's a good idea. Please post to bugzilla!
Post by Andrej Mitrovic
Btw, I have just pushed a changeset and made the build script
foreach (dir; dirs)
foreach (dir; taskPool.parallel(dirs, 1))
And added other small cosmetic changes, but the above is the only real change.
Serial build: 1min, 3sec
Parallel build: 22sec
Awesome!
Walter Bright
2011-06-22 00:57:31 UTC
Permalink
Post by Andrej Mitrovic
Post by Andrej Mitrovic
Post by Jonathan M Davis
stride isn't a UTF version of strlen.
Brain misshap, I meant std.utf.count.
Double brain misshap. I wasn't looking for code-point count of a D
string, but of a zero-terminated wchar*.
wcslen()
Walter Bright
2011-06-22 00:28:01 UTC
Permalink
Post by Andrej Mitrovic
Post by Andrej Mitrovic
char[100] buffer;
APIWriteToBuffer(buffer.ptr);
auto p = buffer[0 .. strlen(buffer.ptr)];
myDStringFunction(p);
Yeah I was going to suggest that. My only problem was I didn't know
where to look for an strlen equivalent for UTF, but I found it in
std.utf and it's called stride().
I think there's a misunderstanding somewhere. strlen() works just fine on UTF-8
code.
Andrej Mitrovic
2011-06-22 00:41:37 UTC
Permalink
Post by Walter Bright
I think there's a misunderstanding somewhere. strlen() works just fine on UTF-8
code.
I need a UTF16 strlen function for wchar*.
Walter Bright
2011-06-22 00:58:17 UTC
Permalink
Post by Andrej Mitrovic
I need a UTF16 strlen function for wchar*.
wcslen()
Andrej Mitrovic
2011-06-22 01:08:17 UTC
Permalink
Post by Walter Bright
Post by Andrej Mitrovic
I need a UTF16 strlen function for wchar*.
wcslen()
You, sir, are a gentleman and a scholar.
Walter Bright
2011-06-22 01:15:05 UTC
Permalink
Post by Andrej Mitrovic
You, sir, are a gentleman and a scholar.
I've been called worse :-)
Andrej Mitrovic
2011-06-22 01:24:28 UTC
Permalink
Now on YC too: http://news.ycombinator.com/item?id=2681216
zsxxsz
2011-06-21 14:55:17 UTC
Permalink
Excellent! I've build and run it all ok.
zhang
2011-06-21 10:45:00 UTC
Permalink
That's great!
I'm porting the Scintilla which is an editor library. I think I can get benefit from your works greatly.
----------
Zhang <bitworld at qq.com>
Andrej Mitrovic
2011-06-21 15:47:30 UTC
Permalink
I completey forgot about single-project compilation yesterday.

I've pushed a new changeset which allows you to build each project
alone by CD-ing to the directory and building, e.g.:

$ cd "C:\Documents and Settings\Andrej\Desktop\WinAPI\Samples\Chap01\HelloMsg"
$ rdmd ..\..\..\build.d "%cd%"

The quotes are important for CD in order for paths with spaces to
work. The build script will warn you if you passed an incorrect path
though. :)
Andrej Mitrovic
2011-06-21 15:53:16 UTC
Permalink
Post by zhang
That's great!
I'm porting the Scintilla which is an editor library. I think I can get
benefit from your works greatly.
----------
Zhang <bitworld at qq.com>
Nice! Btw, I have DSciteWin in my projects too:
https://github.com/AndrejMitrovic/dscitewin
But that simply uses the DLL via D.
Andrej Mitrovic
2011-06-21 16:13:07 UTC
Permalink
Post by zhang
That's great!
I'm porting the Scintilla which is an editor library. I think I can get
benefit from your works greatly.
----------
Zhang <bitworld at qq.com>
Btw, I'd like to know more about this. Is it an open-source project?
Will it be hosted somewhere? And what additions/changes are you
planning to make in the D version?

I'm sure there's at least a couple of people interested in this,
including me, and probably Nick too (I've seen him mention he wanted
to do this if he had the time).
zhang
2011-06-22 12:01:03 UTC
Permalink
The whole porting works have being done almost by hand.
It is still too early for real using.
When all things done, I'll make it open-source.
I'm just busy with porting the modules about winapi.
----------
Zhang <bitworld at qq.com>
Andrej Mitrovic
2011-06-22 19:01:35 UTC
Permalink
I just ran into some odd stdout corruption issue while doing parallel
builds, take a look:

Loading Image...

I've tried building again and it was gone, it looks like an appearance
of a heisenbug. There might be some bug lurking somewhere in
std.parallelism, but it's hard to say when I can't recreate it.
Dmitry Olshansky
2011-06-22 20:07:28 UTC
Permalink
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
http://i.imgur.com/pgC4o.png
I've tried building again and it was gone, it looks like an appearance
of a heisenbug. There might be some bug lurking somewhere in
std.parallelism, but it's hard to say when I can't recreate it.
I'd say that is to be expected, e.g. when multiple processes (in this
case two resource compilers) output to the same stream (console) and
has nothing to do with std.parallelism. One cure for that is to have
them output to a unique temporary files or pipes.
The only thing that's strange is that I'd expect it to happen in blocks
as there should be buffering, but maybe they doesn't use it at all.
--
Dmitry Olshansky
Andrej Mitrovic
2011-06-22 20:26:32 UTC
Permalink
Post by Dmitry Olshansky
I'd say that is to be expected, e.g. when multiple processes (in this
case two resource compilers) output to the same stream (console) and
has nothing to do with std.parallelism. One cure for that is to have
them output to a unique temporary files or pipes.
The only thing that's strange is that I'd expect it to happen in blocks
as there should be buffering, but maybe they doesn't use it at all.
But stdout is marked as shared. I would think that would solve the
issue of outputting from multiple threads?
Johannes Pfau
2011-06-22 20:46:51 UTC
Permalink
Post by Andrej Mitrovic
Post by Dmitry Olshansky
I'd say that is to be expected, e.g. when multiple processes (in this
case two resource compilers) output to the same stream (console) and
has nothing to do with std.parallelism. One cure for that is to have
them output to a unique temporary files or pipes.
The only thing that's strange is that I'd expect it to happen in
blocks as there should be buffering, but maybe they doesn't use it
at all.
But stdout is marked as shared. I would think that would solve the
issue of outputting from multiple threads?
That's only true for D functions based on D stdout (D writeln, etc.).
It doesn't apply to C printf, or different processes using the same
console handle. I guess you use the std.process system function which
afaik doesn't redirect the spawned processes output.
--
Johannes Pfau
Andrej Mitrovic
2011-06-22 21:28:25 UTC
Permalink
Post by Johannes Pfau
Post by Andrej Mitrovic
Post by Dmitry Olshansky
I'd say that is to be expected, e.g. when multiple processes (in this
case two resource compilers) output to the same stream (console) and
has nothing to do with std.parallelism. One cure for that is to have
them output to a unique temporary files or pipes.
The only thing that's strange is that I'd expect it to happen in
blocks as there should be buffering, but maybe they doesn't use it
at all.
But stdout is marked as shared. I would think that would solve the
issue of outputting from multiple threads?
That's only true for D functions based on D stdout (D writeln, etc.).
It doesn't apply to C printf, or different processes using the same
console handle. I guess you use the std.process system function which
afaik doesn't redirect the spawned processes output.
--
Johannes Pfau
Ah you're right, I'm using system and writeln() calls, so that might
be causing it.
Andrej Mitrovic
2011-06-23 01:36:07 UTC
Permalink
Ok here's a little challenge for you fokes:

Write a D script that removes extra parens from strings like these:
("Acoustic Bass Drum"), ("Bass Drum 1"),
("Side Stick"), ("Acoustic Snare"),
("Hand Clap"), ("Electric Snare"),
("Low Floor Tom"), ("Closed High Hat"),
("High Floor Tom"), ("Pedal High Hat"),

and replaces it with:
"Acoustic Bass Drum", "Bass Drum 1",
"Side Stick", "Acoustic Snare",
"Hand Clap", "Electric Snare",
"Low Floor Tom", "Closed High Hat",
"High Floor Tom", "Pedal High Hat",

I can't figure std.regex out. Every time I try to use the hit()
property of a RegexMatch object I get back some weird internal error:

core.exception.AssertError at D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\regex.d(1861):
4294967295 .. 4294967295 vs. 2

The parens are leftover from code like this:
TEXT ("Acoustic Bass Drum"), TEXT ("Bass Drum 1"),
TEXT ("Side Stick"), TEXT ("Acoustic Snare"),
TEXT ("Hand Clap"), TEXT ("Electric Snare"),
TEXT ("Low Floor Tom"), TEXT ("Closed High Hat"),
TEXT ("High Floor Tom"), TEXT ("Pedal High Hat"),

TEXT was just a macro that would probably add a function call if the C
code was compiled with unicode support. I did a global search and
replace of TEXT but that left me with a minefield of parens. :)

Maybe this will help:
http://www.txt2re.com/index.php3?s=%28%22Acoustic+Bass+Drum%22%29&submit=Show+Matches
bearophile
2011-06-23 03:01:50 UTC
Permalink
Post by Andrej Mitrovic
("Acoustic Bass Drum"), ("Bass Drum 1"),
("Side Stick"), ("Acoustic Snare"),
("Hand Clap"), ("Electric Snare"),
("Low Floor Tom"), ("Closed High Hat"),
("High Floor Tom"), ("Pedal High Hat"),
"Acoustic Bass Drum", "Bass Drum 1",
"Side Stick", "Acoustic Snare",
"Hand Clap", "Electric Snare",
"Low Floor Tom", "Closed High Hat",
"High Floor Tom", "Pedal High Hat",
I can't figure std.regex out. Every time I try to use the hit()
4294967295 .. 4294967295 vs. 2
I suggest to minimize the case and submit a bug report for Phobos.

Regarding your problem, I have written this Python code, probably it's not too much hard to translate it to D:

import re

lines = """
Post by Andrej Mitrovic
TEXT ("Acoustic Bass Drum"), TEXT ("Bass Drum 1"),
TEXT ("Side Stick"), TEXT ("Acoustic Snare"),
TEXT ("Hand Clap"), TEXT ("Electric Snare"),
TEXT ("Low Floor Tom"), TEXT ("Closed High Hat"),
TEXT ("High Floor Tom"), TEXT ("Pedal High Hat"),
""".splitlines()

patt = re.compile(r"""
TEXT \s* \(
\s*
(".*?")
\s*
\) """, re.VERBOSE)

def replacer(m):
return str(m.group(1))

for line in lines:
print patt.sub(replacer, line)


I have used redemo2.pyw

Bye,
bearophile
Andrej Mitrovic
2011-06-23 04:23:38 UTC
Permalink
What am I doing wrong here?

f1 = open('Drum.d', 'r')
lines = f1.readlines()
f1.close()

f2 = open('Drum.w', 'w')
for line in lines:
#~ print(patt.sub(replacer, line)) # This replaces the parens correctly
f2.write(patt.sub(replacer, line)) # But the file ends up being
the same..
f2.close()
Jimmy Cao
2011-06-23 05:18:55 UTC
Permalink
On Wed, Jun 22, 2011 at 11:23 PM, Andrej Mitrovic <
Post by Andrej Mitrovic
What am I doing wrong here?
f1 = open('Drum.d', 'r')
lines = f1.readlines()
f1.close()
f2 = open('Drum.w', 'w')
#~ print(patt.sub(replacer, line)) # This replaces the parens correctly
f2.write(patt.sub(replacer, line)) # But the file ends up being
the same..
f2.close()
That looks 100% right.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/ac5bb1fc/attachment.html>
Andrej Mitrovic
2011-06-23 05:25:37 UTC
Permalink
It works when I write to a different file:

f1 = open('Drum.d', 'r')
lines = f1.readlines()
f1.close()

f2 = open('Drum2.w', 'w')
for line in lines:
#~ print(patt.sub(replacer, line)) # This replaces the parens correctly
f2.write(patt.sub(replacer, line)) # But the file ends up being
the same..
f2.close()

Looks like some kind of file handling bug in Python?
Andrej Mitrovic
2011-06-23 05:26:44 UTC
Permalink
Eh what the heck now it works again. LOL. Ok, well thanks bear for the script!
Jimmy Cao
2011-06-23 05:32:35 UTC
Permalink
On Thu, Jun 23, 2011 at 12:25 AM, Andrej Mitrovic <
Post by Andrej Mitrovic
Looks like some kind of file handling bug in Python?
On Thu, Jun 23, 2011 at 12:26 AM, Andrej Mitrovic <
Post by Andrej Mitrovic
Eh what the heck now it works again. LOL. Ok, well thanks bear for the
script!
LOL. It's not that easy to find a bug in Python :P
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/f021ce5d/attachment-0001.html>
Andrej Mitrovic
2011-06-23 05:36:56 UTC
Permalink
Hmm it's a bit problematic though:

szLabel.indexOf("(")
szLabel.indexOf""

Well I'll just have to manually merge these changes then one by one.
Well it's better than nothing.
Andrej Mitrovic
2011-06-23 05:39:14 UTC
Permalink
This is why we need language-aware tools, it killed this:

throw new Exception("Can't allocate buffer.");

Woops:
throw new Exception"Can't allocate buffer.";
Andrej Mitrovic
2011-06-23 05:58:24 UTC
Permalink
Fixed: https://github.com/AndrejMitrovic/DWindowsProgramming/commit/42228c9012c2c75d2638fab52277f21427b2ed01

Quite a huge list of stray parens. Good thing I had Beyond Compare for
the diffs.
Dmitry Olshansky
2011-06-23 16:44:04 UTC
Permalink
Post by Andrej Mitrovic
Fixed: https://github.com/AndrejMitrovic/DWindowsProgramming/commit/42228c9012c2c75d2638fab52277f21427b2ed01
Quite a huge list of stray parens. Good thing I had Beyond Compare for
the diffs.
Seems like I'm late for regex party :(
Still, this works in D2, and is somewhat intelligent ;)

import std.regex, std.file;

void main(string[] args)
{
auto r = regex(`(\W\s*)\(("(?:[^"]|\\")*")\)`,"g");
foreach(arg; args[1..$])
{
auto data = cast(string)read(arg);
auto replaced = replace(data, r, `$1$2`);
std.file.write(arg, replaced);
}
}
--
Dmitry Olshansky
Andrej Mitrovic
2011-06-23 17:04:48 UTC
Permalink
Post by Dmitry Olshansky
Post by Andrej Mitrovic
https://github.com/AndrejMitrovic/DWindowsProgramming/commit/42228c9012c2c75d2638fab52277f21427b2ed01
Quite a huge list of stray parens. Good thing I had Beyond Compare for
the diffs.
Seems like I'm late for regex party :(
Still, this works in D2, and is somewhat intelligent ;)
import std.regex, std.file;
void main(string[] args)
{
auto r = regex(`(\W\s*)\(("(?:[^"]|\\")*")\)`,"g");
foreach(arg; args[1..$])
{
auto data = cast(string)read(arg);
auto replaced = replace(data, r, `$1$2`);
std.file.write(arg, replaced);
}
}
--
Dmitry Olshansky
Thanks, goes into my d_tips.txt file. :)
Jacob Carlborg
2011-06-23 06:25:51 UTC
Permalink
Post by Andrej Mitrovic
szLabel.indexOf("(")
szLabel.indexOf""
Well I'll just have to manually merge these changes then one by one.
Well it's better than nothing.
If every string looks like this:

TEXT ("Acoustic Bass Drum")

Then you can use a regexp like this:

TEXT \("(.+?)"\)

And replace with:

"$1"

You don't need a script for this, just put it in an editor with search &
replace with support for regexp.
--
/Jacob Carlborg
Walter Bright
2011-06-22 20:37:17 UTC
Permalink
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
stdout is shared, but the atomic units of output are where the calls to it are,
and are interleaved otherwise. For example, a single call to printf locks stdout
for the duration of the printf.
Johannes Pfau
2011-06-22 20:49:52 UTC
Permalink
Post by Walter Bright
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
stdout is shared, but the atomic units of output are where the calls
to it are, and are interleaved otherwise. For example, a single call
to printf locks stdout for the duration of the printf.
C printf is atomic? Didn't know that.
What happens when multiple processes are spawned with system()? Is
their IO output still synchronized?
--
Johannes Pfau
Walter Bright
2011-06-22 21:20:01 UTC
Permalink
Post by Johannes Pfau
Post by Walter Bright
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
stdout is shared, but the atomic units of output are where the calls
to it are, and are interleaved otherwise. For example, a single call
to printf locks stdout for the duration of the printf.
C printf is atomic? Didn't know that.
What happens when multiple processes are spawned with system()? Is
their IO output still synchronized?
I'm sure that Windows does discrete write's atomically, but it's up to the
individual apps to bundle things together into discrete writes.
Andrei Alexandrescu
2011-06-22 21:20:18 UTC
Permalink
Post by Johannes Pfau
Post by Walter Bright
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
stdout is shared, but the atomic units of output are where the calls
to it are, and are interleaved otherwise. For example, a single call
to printf locks stdout for the duration of the printf.
C printf is atomic? Didn't know that.
What happens when multiple processes are spawned with system()? Is
their IO output still synchronized?
No, printf is atomic across threads. Spilling buffers to disk is a
distinct issue.

Andrei
Kagamin
2011-06-23 07:56:07 UTC
Permalink
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
http://i.imgur.com/pgC4o.png
I've tried building again and it was gone, it looks like an appearance
of a heisenbug. There might be some bug lurking somewhere in
std.parallelism, but it's hard to say when I can't recreate it.
console output is unbuffered and stdio loves to call putch. Usually this is ok since one doesn't run multiple applications on the same console simultaneously. And if it does, a program usually makes it in time. It's strange to see interwined characters as if it can't write a character in a context switch time frame. May be a bug in console2?
Jimmy Cao
2011-06-23 08:04:55 UTC
Permalink
Post by Kagamin
Post by Andrej Mitrovic
I just ran into some odd stdout corruption issue while doing parallel
http://i.imgur.com/pgC4o.png
I've tried building again and it was gone, it looks like an appearance
of a heisenbug. There might be some bug lurking somewhere in
std.parallelism, but it's hard to say when I can't recreate it.
console output is unbuffered and stdio loves to call putch. Usually this is
ok since one doesn't run multiple applications on the same console
simultaneously. And if it does, a program usually makes it in time. It's
strange to see interwined characters as if it can't write a character in a
context switch time frame. May be a bug in console2?
I don't think console output is unbuffered. I think it's line-buffered by
default. Although it does differ and vary; I think on Windows
std.stdio.write("hello\n") doesn't flush but on Linux it does.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/28283b5c/attachment.html>
Kagamin
2011-06-23 11:06:03 UTC
Permalink
Post by Jimmy Cao
I don't think console output is unbuffered. I think it's line-buffered by
default. Although it does differ and vary; I think on Windows
std.stdio.write("hello\n") doesn't flush but on Linux it does.
LOL, MS resource compiler doesn't use symantec C runtime.
In fact sc runtime didn't flush, but this was fixed, though I don't remember where, in phobos or in sc.
Jimmy Cao
2011-06-23 11:27:34 UTC
Permalink
Post by Kagamin
Post by Jimmy Cao
I don't think console output is unbuffered. I think it's line-buffered
by
Post by Jimmy Cao
default. Although it does differ and vary; I think on Windows
std.stdio.write("hello\n") doesn't flush but on Linux it does.
LOL, MS resource compiler doesn't use symantec C runtime.
In fact sc runtime didn't flush, but this was fixed, though I don't
remember where, in phobos or in sc.
I've tested it out with DMD 2.053 on Windows XP.

import std.stdio;
import core.thread;


void main()
{
version(WIDE) // Will flush during write
wstring mystr = "Hello\n"w;
else // Will not flush
string mystr = "Hello\n";

write(mystr);

Thread.sleep( 70_000_000 ); // 7 sec
stdout.flush();
}


Also, there's nothing in the C standard that says, stdout must be buffered
this way or that way or even buffered at all. I believe you can safely
assume that stdout is line-buffered in Linux, though, but I'm not sure.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/c2ead91b/attachment.html>
Walter Bright
2011-06-23 17:46:31 UTC
Permalink
Also, there's nothing in the C standard that says, stdout must be buffered this
way or that way or even buffered at all. I believe you can safely assume that
stdout is line-buffered in Linux, though, but I'm not sure.
Even so, stdout buffering is done on a global, shared basis. There is not a
per-thread buffer.

DMC++ buffers stdout by line if the output is a tty. This is normal practice.
Jimmy Cao
2011-06-23 18:48:28 UTC
Permalink
On Thu, Jun 23, 2011 at 12:46 PM, Walter Bright
Post by Walter Bright
Also, there's nothing in the C standard that says, stdout must be buffered this
way or that way or even buffered at all. I believe you can safely assume that
stdout is line-buffered in Linux, though, but I'm not sure.
DMC++ buffers stdout by line if the output is a tty. This is normal practice.
But that's not possible (to set it to line-buffering) on Windows, right?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/08649c11/attachment.html>
Walter Bright
2011-06-23 19:52:50 UTC
Permalink
Post by Jimmy Cao
But that's not possible (to set it to line-buffering) on Windows, right?
Sure it is, using the usual C functions. This is not a Windows thing, it's a C
runtime library thing.
Jimmy Cao
2011-06-23 20:03:34 UTC
Permalink
On Thu, Jun 23, 2011 at 2:52 PM, Walter Bright
Post by Walter Bright
Post by Jimmy Cao
But that's not possible (to set it to line-buffering) on Windows, right?
Sure it is, using the usual C functions. This is not a Windows thing, it's
a C runtime library thing.
How do you make it have line-buffering?
It's not possible to set line-buffering in Windows using setvbuf, it seems:
http://msdn.microsoft.com/en-us/library/86cebhfs(v=vs.71).aspx
_IOFBF and _IOLBF are the same.

I think this is the cause of the strange flushing inconsistencies with
stdio.d from my earlier example on Windows.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/46a940c7/attachment.html>
Walter Bright
2011-06-23 20:16:54 UTC
Permalink
On Thu, Jun 23, 2011 at 2:52 PM, Walter Bright <newshound2 at digitalmars.com
But that's not possible (to set it to line-buffering) on Windows, right?
Sure it is, using the usual C functions. This is not a Windows thing, it's a
C runtime library thing.
How do you make it have line-buffering?
http://msdn.microsoft.com/en-us/library/86cebhfs(v=vs.71).aspx
_IOFBF and _IOLBF are the same.
I think this is the cause of the strange flushing inconsistencies with stdio.d
from my earlier example on Windows.
I can't say anything about VC++, but dmd on Windows is designed to work with DMC++.

http://www.digitalmars.com/rtl/stdio.html#setvbuf
Jimmy Cao
2011-06-23 20:30:42 UTC
Permalink
On Thu, Jun 23, 2011 at 3:16 PM, Walter Bright
Post by Walter Bright
On Thu, Jun 23, 2011 at 2:52 PM, Walter Bright <
newshound2 at digitalmars.com
But that's not possible (to set it to line-buffering) on Windows, right?
Sure it is, using the usual C functions. This is not a Windows thing, it's a
C runtime library thing.
How do you make it have line-buffering?
http://msdn.microsoft.com/en-**us/library/86cebhfs(v=vs.71).**aspx<http://msdn.microsoft.com/en-us/library/86cebhfs(v=vs.71).aspx>
_IOFBF and _IOLBF are the same.
I think this is the cause of the strange flushing inconsistencies with stdio.d
from my earlier example on Windows.
I can't say anything about VC++, but dmd on Windows is designed to work with DMC++.
http://www.digitalmars.com/**rtl/stdio.html#setvbuf<http://www.digitalmars.com/rtl/stdio.html#setvbuf>
On Windows:

import std.stdio;

extern(C) int getch();

void main()
{
stdout.setvbuf(100, _IOLBUF);
string mystr = "Hello\n";
fwrite(mystr.ptr, mystr[0].sizeof, mystr.length, stdout.getFP);

// FPUTC('\n', cast(_iobuf*)stdout.getFP);

getch();
}

Am I doing anything wrong there? That code as it is does not flush until
after a keypress (when the program terminates). Uncomment the FPUTC call
and it does flush before the keypress.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/cb1f1393/attachment.html>
Walter Bright
2011-06-23 20:59:50 UTC
Permalink
Post by Jimmy Cao
stdout.setvbuf(100, _IOLBUF);
You're mixing up D and C stdio. Try using std.c.stdio.setvbuf().
Jimmy Cao
2011-06-23 21:05:40 UTC
Permalink
On Thu, Jun 23, 2011 at 3:59 PM, Walter Bright
Post by Walter Bright
Post by Jimmy Cao
stdout.setvbuf(100, _IOLBUF);
You're mixing up D and C stdio. Try using std.c.stdio.setvbuf().
It gives me the same result.

import std.stdio;

extern(C) int getch();

void main()
{
std.c.stdio.setvbuf(stdout.getFP, null, std.c.stdio._IOLBF, 100);
string mystr = "Hello\n";
fwrite(mystr.ptr, mystr[0].sizeof, mystr.length, stdout.getFP);

// FPUTC('\n', cast(_iobuf*)stdout.getFP);

getch();
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110623/3e463114/attachment.html>
Walter Bright
2011-06-23 22:24:00 UTC
Permalink
Post by Jimmy Cao
It gives me the same result.
It seems to be an issue with fwrite(). With fprintf, it works as expected.
Kagamin
2011-06-24 12:45:44 UTC
Permalink
Post by Jimmy Cao
void main()
{
std.c.stdio.setvbuf(stdout.getFP, null, std.c.stdio._IOLBF, 100);
string mystr = "Hello\n";
fwrite(mystr.ptr, mystr[0].sizeof, mystr.length, stdout.getFP);
// FPUTC('\n', cast(_iobuf*)stdout.getFP);
getch();
}
fwrite is from so called low-level file API supposed to write binary data without extra processing.
Steven Schveighoffer
2011-06-24 14:11:01 UTC
Permalink
Post by Kagamin
Post by Jimmy Cao
void main()
{
std.c.stdio.setvbuf(stdout.getFP, null, std.c.stdio._IOLBF, 100);
string mystr = "Hello\n";
fwrite(mystr.ptr, mystr[0].sizeof, mystr.length, stdout.getFP);
// FPUTC('\n', cast(_iobuf*)stdout.getFP);
getch();
}
fwrite is from so called low-level file API supposed to write binary
data without extra processing.
As stated in a previous post, it does flush on newline in Linux (just
tested it). I don't know if flushing-on-newline-if-console is part of the
C standard, so both implementations are likely compliant. But it is an
inconsistency.

-Steve
Jimmy Cao
2011-06-24 16:41:05 UTC
Permalink
Post by Kagamin
Post by Jimmy Cao
void main()
{
std.c.stdio.setvbuf(stdout.getFP, null, std.c.stdio._IOLBF, 100);
string mystr = "Hello\n";
fwrite(mystr.ptr, mystr[0].sizeof, mystr.length, stdout.getFP);
// FPUTC('\n', cast(_iobuf*)stdout.getFP);
getch();
}
fwrite is from so called low-level file API supposed to write binary data
without extra processing.
No, it writes to stdout which (in this case) is line-buffered. Whenever
there's a newline character, it is supposed to flush.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110624/ac8d7d59/attachment.html>
Walter Bright
2011-06-24 18:48:53 UTC
Permalink
No, it writes to stdout which (in this case) is line-buffered. Whenever there's
a newline character, it is supposed to flush.
Please file a bug report!

http://bugzilla.digitalmars.com/issues/buglist.cgi?quicksearch=.
Kagamin
2011-06-24 20:03:53 UTC
Permalink
Post by Jimmy Cao
No, it writes to stdout which (in this case) is line-buffered. Whenever
there's a newline character, it is supposed to flush.
There're no characters in binary data. This is low-level API. If you want the library to care about characters and do various things, maybe you need a high-level text API like printf or even better phobos std.stdio.write?
Jimmy Cao
2011-06-24 20:19:51 UTC
Permalink
Post by Kagamin
Post by Jimmy Cao
No, it writes to stdout which (in this case) is line-buffered. Whenever
there's a newline character, it is supposed to flush.
There're no characters in binary data. This is low-level API. If you want
the library to care about characters and do various things, maybe you need a
high-level text API like printf or even better phobos std.stdio.write?
Actually, low-level is like using cputs from conio.h.
http://www.digitalmars.com/rtl/conio.html
Post by Kagamin
"They bypass the stdin and stdout buffers and access the console
directly."
Anyways, I was using to write an array of characters to stdout. Since
stdout was buffered, when the newline character was encountered, flushing
should have occured.
Also, you do realize that std.stdio.write uses fwrite, right? It's the same
thing, except when writing wider chars or when fwide doesn't return 0, in
that case something else is used.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20110624/a775072c/attachment.html>
Steven Schveighoffer
2011-06-23 21:22:23 UTC
Permalink
Post by Jimmy Cao
Thread.sleep( 70_000_000 ); // 7 sec
Gah!

Here, let me fix that for you:

Thread.sleep(dur!"seconds"(7));

:)

-Steve
Andrej Mitrovic
2011-06-23 21:50:38 UTC
Permalink
Post by Steven Schveighoffer
Post by Jimmy Cao
Thread.sleep( 70_000_000 ); // 7 sec
Gah!
Thread.sleep(dur!"seconds"(7));
:)
-Steve
I find it very odd that for seconds we use "seconds", but for
everything else we use "msec", "usec", "hnsecs" abbreviations.
Jonathan M Davis
2011-06-23 22:02:02 UTC
Permalink
Post by Andrej Mitrovic
Post by Steven Schveighoffer
Thread.sleep( 70_000_000 ); // 7 sec
Gah!
Thread.sleep(dur!"seconds"(7));
:)
-Steve
I find it very odd that for seconds we use "seconds", but for
everything else we use "msec", "usec", "hnsecs" abbreviations.
Because it makes sense to use the full names up to seconds. After that,
they're too long, so they get abbreviated.

- Jonathan M Davis
Steven Schveighoffer
2011-06-23 22:10:53 UTC
Permalink
On Thu, 23 Jun 2011 18:02:02 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by Andrej Mitrovic
On Thu, 23 Jun 2011 07:27:34 -0400, Jimmy Cao <jcao219 at gmail.com>
Thread.sleep( 70_000_000 ); // 7 sec
Gah!
Thread.sleep(dur!"seconds"(7));
:)
-Steve
I find it very odd that for seconds we use "seconds", but for
everything else we use "msec", "usec", "hnsecs" abbreviations.
Because it makes sense to use the full names up to seconds. After that,
they're too long, so they get abbreviated.
You could argue that mseconds is not much longer than seconds. It's still
an abbreviation.

You could also argue that seconds is too long, couldn't it be secs? One
thing that sucks about having inconsistent abbreviations, I have to look
them up, even when I know what I'm typing makes sense to a reader, it just
may not be what the function expects. For instance, before I sent this
message, I had to look it up to make sure it was valid.

But here's an idea -- milliseconds, msecs, and mseconds could all map to
the same template function.

hectonanoseconds, hm.. that's a long one :)

-Steve
Andrej Mitrovic
2011-06-23 22:20:57 UTC
Permalink
Why don't we use unicode for microseconds then? :p

duration!"?s"(10);

Personally I'd be fine with:
"sec"
"ms"
"ns"
"us"

If you're dealing with time you know what those are. But the existing
names are ok, except seconds because I always put "sec" by accident.
Jonathan M Davis
2011-06-23 22:42:45 UTC
Permalink
Post by Steven Schveighoffer
On Thu, 23 Jun 2011 18:02:02 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by Andrej Mitrovic
On Thu, 23 Jun 2011 07:27:34 -0400, Jimmy Cao <jcao219 at gmail.com>
Thread.sleep( 70_000_000 ); // 7 sec
Gah!
Thread.sleep(dur!"seconds"(7));
:)
-Steve
I find it very odd that for seconds we use "seconds", but for
everything else we use "msec", "usec", "hnsecs" abbreviations.
Because it makes sense to use the full names up to seconds. After that,
they're too long, so they get abbreviated.
You could argue that mseconds is not much longer than seconds. It's still
an abbreviation.
You could also argue that seconds is too long, couldn't it be secs? One
thing that sucks about having inconsistent abbreviations, I have to look
them up, even when I know what I'm typing makes sense to a reader, it just
may not be what the function expects. For instance, before I sent this
message, I had to look it up to make sure it was valid.
Unfortunately, there are so many variations on what they could be that there's
no way to make them so that everyone is going to remember them correctly. So,
no matter what I picked, someone would have been unhapy with it.
Post by Steven Schveighoffer
But here's an idea -- milliseconds, msecs, and mseconds could all map to
the same template function.
hectonanoseconds, hm.. that's a long one :)
I thought about doing that (though it _never_ occurred to me to use mseconds,
since that feels to me like you abbreviated half of it, which is just weird to
me). The problem is that that feels a bit too much like the inconsistent
horror that is html where it accepts just about anything. I generally prefer
things to be strict and consistent over trying to guess what was meant. It
also makes the template constraints uglier. I'm not completely against the
idea, but I'm not convinced that it's a good one either.

As it stands, all units seconds and greater are completely unabbreviated, and
all of the sub-second units are abbreviated, which if you're going to
abbreviate some but not all feels very consistent to me (though again, what
seems perfectly logical to one person may not seem that way to another). I
_don't_ want to change them to something else at this point. There's enough in
core.time and std.datetime to get used to already, and that's a pretty
heavily-used feature in those modules. It _might_ be worth making it so that
other variants of the units' names work, but I'm not convinced that being lax
about it is necessarily a good idea.

- Jonathan M Davis
Steven Schveighoffer
2011-06-23 23:06:34 UTC
Permalink
On Thu, 23 Jun 2011 18:42:45 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by Steven Schveighoffer
On Thu, 23 Jun 2011 18:02:02 -0400, Jonathan M Davis
<jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by Andrej Mitrovic
On Thu, 23 Jun 2011 07:27:34 -0400, Jimmy Cao <jcao219 at gmail.com>
Thread.sleep( 70_000_000 ); // 7 sec
Gah!
Thread.sleep(dur!"seconds"(7));
:)
-Steve
I find it very odd that for seconds we use "seconds", but for
everything else we use "msec", "usec", "hnsecs" abbreviations.
Because it makes sense to use the full names up to seconds. After
that,
Post by Jonathan M Davis
they're too long, so they get abbreviated.
You could argue that mseconds is not much longer than seconds. It's
still
an abbreviation.
You could also argue that seconds is too long, couldn't it be secs? One
thing that sucks about having inconsistent abbreviations, I have to look
them up, even when I know what I'm typing makes sense to a reader, it just
may not be what the function expects. For instance, before I sent this
message, I had to look it up to make sure it was valid.
Unfortunately, there are so many variations on what they could be that
there's
no way to make them so that everyone is going to remember them
correctly. So,
no matter what I picked, someone would have been unhapy with it.
Right. I totally agree, if you have to have one, you just have to choose
and be done with it. The only reason we can have this conversation is
because it's really easy to just add another "overload". :)
Post by Jonathan M Davis
Post by Steven Schveighoffer
But here's an idea -- milliseconds, msecs, and mseconds could all map to
the same template function.
hectonanoseconds, hm.. that's a long one :)
I thought about doing that (though it _never_ occurred to me to use
mseconds,
since that feels to me like you abbreviated half of it, which is just
weird to
me). The problem is that that feels a bit too much like the inconsistent
horror that is html where it accepts just about anything. I generally
prefer
things to be strict and consistent over trying to guess what was meant.
It
also makes the template constraints uglier. I'm not completely against
the
idea, but I'm not convinced that it's a good one either.
I'm not completely for it either, it was just a thought. Personally, I
think super-abbreviated and fully-spelled-out would be the two best
options to have. Since you are already sticking it in a namespace (dur),
it should be rather obvious what each is:

hns or hectonanoseconds
us or microseconds
ms or milliseconds
s or seconds
m or minutes
h or hours
d or days
w or weeks
mo or months (yeah, this one is sucky)
y or years
Post by Jonathan M Davis
As it stands, all units seconds and greater are completely
unabbreviated, and
all of the sub-second units are abbreviated, which if you're going to
abbreviate some but not all feels very consistent to me (though again,
what
seems perfectly logical to one person may not seem that way to another).
It would be good to highlight this pattern in the documentation. It makes
it easier to remember which ones are abbreviated!
Post by Jonathan M Davis
I
_don't_ want to change them to something else at this point. There's
enough in
core.time and std.datetime to get used to already, and that's a pretty
heavily-used feature in those modules. It _might_ be worth making it so
that
other variants of the units' names work, but I'm not convinced that
being lax
about it is necessarily a good idea.
To me, an optimal API is one you don't have to look up. It just makes
sense. There are various ways to achieve this, and it's probably
achievable with your scheme as long as you give an easy rule to remember
(i.e. subseconds are abbreviated, everything else is not).

One thing that would be good to have is to have a more defined error
message when you type the wrong term. i.e.:

Error: millis is not a valid unit, try hnsecs, usecs, msecs, ...

-Steve
Mike James
2011-06-24 14:24:56 UTC
Permalink
"Steven Schveighoffer" <schveiguy at yahoo.com> wrote in message
Post by Steven Schveighoffer
On Thu, 23 Jun 2011 18:42:45 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by Steven Schveighoffer
On Thu, 23 Jun 2011 18:02:02 -0400, Jonathan M Davis
<jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by Andrej Mitrovic
On Thu, 23 Jun 2011 07:27:34 -0400, Jimmy Cao <jcao219 at gmail.com>
Thread.sleep( 70_000_000 ); // 7 sec
Gah!
Thread.sleep(dur!"seconds"(7));
:)
-Steve
I find it very odd that for seconds we use "seconds", but for
everything else we use "msec", "usec", "hnsecs" abbreviations.
Because it makes sense to use the full names up to seconds. After
that,
Post by Jonathan M Davis
they're too long, so they get abbreviated.
You could argue that mseconds is not much longer than seconds. It's
still
an abbreviation.
You could also argue that seconds is too long, couldn't it be secs? One
thing that sucks about having inconsistent abbreviations, I have to look
them up, even when I know what I'm typing makes sense to a reader, it just
may not be what the function expects. For instance, before I sent this
message, I had to look it up to make sure it was valid.
Unfortunately, there are so many variations on what they could be that
there's
no way to make them so that everyone is going to remember them
correctly. So,
no matter what I picked, someone would have been unhapy with it.
Right. I totally agree, if you have to have one, you just have to choose
and be done with it. The only reason we can have this conversation is
because it's really easy to just add another "overload". :)
Post by Jonathan M Davis
Post by Steven Schveighoffer
But here's an idea -- milliseconds, msecs, and mseconds could all map to
the same template function.
hectonanoseconds, hm.. that's a long one :)
I thought about doing that (though it _never_ occurred to me to use
mseconds,
since that feels to me like you abbreviated half of it, which is just
weird to
me). The problem is that that feels a bit too much like the inconsistent
horror that is html where it accepts just about anything. I generally
prefer
things to be strict and consistent over trying to guess what was meant.
It
also makes the template constraints uglier. I'm not completely against
the
idea, but I'm not convinced that it's a good one either.
I'm not completely for it either, it was just a thought. Personally, I
think super-abbreviated and fully-spelled-out would be the two best
options to have. Since you are already sticking it in a namespace (dur),
hns or hectonanoseconds
us or microseconds
ms or milliseconds
s or seconds
m or minutes
h or hours
d or days
w or weeks
mo or months (yeah, this one is sucky)
y or years
Post by Jonathan M Davis
As it stands, all units seconds and greater are completely
unabbreviated, and
all of the sub-second units are abbreviated, which if you're going to
abbreviate some but not all feels very consistent to me (though again,
what
seems perfectly logical to one person may not seem that way to another).
It would be good to highlight this pattern in the documentation. It makes
it easier to remember which ones are abbreviated!
Post by Jonathan M Davis
I
_don't_ want to change them to something else at this point. There's
enough in
core.time and std.datetime to get used to already, and that's a pretty
heavily-used feature in those modules. It _might_ be worth making it so
that
other variants of the units' names work, but I'm not convinced that
being lax
about it is necessarily a good idea.
To me, an optimal API is one you don't have to look up. It just makes
sense. There are various ways to achieve this, and it's probably
achievable with your scheme as long as you give an easy rule to remember
(i.e. subseconds are abbreviated, everything else is not).
One thing that would be good to have is to have a more defined error
Error: millis is not a valid unit, try hnsecs, usecs, msecs, ...
-Steve
Yeh. Use the SI prefixes for units of time, where applicable (and no unicode
:-) )

-=mike=-
Kagamin
2011-06-24 12:50:16 UTC
Permalink
Post by Steven Schveighoffer
But here's an idea -- milliseconds, msecs, and mseconds could all map to
the same template function.
BTW, why it's not opDispatch?
Jonathan M Davis
2011-06-24 15:44:55 UTC
Permalink
Post by Kagamin
Post by Steven Schveighoffer
But here's an idea -- milliseconds, msecs, and mseconds could all map to
the same template function.
BTW, why it's not opDispatch?
It's not a function call. It's a template parameter to a variety of functions
- some of which are not member functions (e.g. core.time.dur).

- Jonathan M Davis
Nick Sabalausky
2011-06-21 19:33:08 UTC
Permalink
"zhang" <bitworld at qq.com> wrote in message
Post by zhang
That's great!
I'm porting the Scintilla which is an editor library. I think I can get
benefit from your works greatly.
That sounds great, I'd love to see the result when you're done. I've wanted
to make some modifications to Scintilla, but I didn't really feel like
dealing with C/C++.
Andrei Alexandrescu
2011-06-21 21:28:34 UTC
Permalink
Post by Andrej Mitrovic
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.
Currently over 120 code samples have been translated into D, with only
a few modules remaining.
https://github.com/AndrejMitrovic/DWindowsProgramming
The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
Now on reddit:

http://www.reddit.com/r/programming/comments/i5m0c/petzolds_windows_programming_5th_ed_code_samples/


Andrei
Andrei Alexandrescu
2011-06-22 02:51:26 UTC
Permalink
Post by Andrei Alexandrescu
Post by Andrej Mitrovic
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.
Currently over 120 code samples have been translated into D, with only
a few modules remaining.
https://github.com/AndrejMitrovic/DWindowsProgramming
The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
http://www.reddit.com/r/programming/comments/i5m0c/petzolds_windows_programming_5th_ed_code_samples/
And now approved.

Andrei
Daniel Gibson
2011-06-21 21:33:41 UTC
Permalink
Post by Andrej Mitrovic
This is a translation project of Charles Petzold's Programming Windows
(5th edition) book code samples.
Currently over 120 code samples have been translated into D, with only
a few modules remaining.
https://github.com/AndrejMitrovic/DWindowsProgramming
The examples were tested on fresh installs of XP and Win7 with the
only dependency being DMD v2.053 and an NT operating system. I hope
everyone will be able to build these examples without too much
trouble. *crosses fingers*
The README mentions 2.043 instead of 2.053.

Cheers,
- Daniel
Andrej Mitrovic
2011-06-21 21:37:58 UTC
Permalink
Post by Daniel Gibson
The README mentions 2.043 instead of 2.053.
Fixed, thanks.
Loading...