Monday, 4 June 2012

Being lied to. For 20+ years

About 20+ years ago, CRiSP for Windows was written (or, more correctly, ported).
Back in early 1990's, a new operating system - Windows NT 3.0 was arriving. I remember
it - I had to buy a new machine - a fabulous 486DX2, running at 50MHz.

At last, a version of Windows which didnt crash. Windows NT 3.0 was a 32-bit operating
system. CRiSP has been compiled for Windows 3.1 - a 16-bit operating system. Porting and debugging
CRiSP was painful - any bad behavior would likely require a machine reboot - Windows 3.x was
too unstable; errant applications could write anywhere.

NT 3.0 was protected from this nonsense. CRiSP exists as two main versions - a console
version, and the GUI application. (This is true today, not only for Windows, but for Unix/Linux
and MacOS).

Whats the difference between a GUI application and a console application? "main(int argc, char **argv)".

Well, Windows has a different startup function - WinMain. WinMain is a bit like the function invoked
before main() is invoked. It doesnt get an array of command line arguments. It gets a single
argument for the command line, and its up to the application to parse the command line.

All the CRiSP tools (and all tools, even non-Foxtrot ones), parse that command line.

An annoying problem is that CRiSP relies on printf() for debugging and for some of the macro
commands. When you link a Windows application, you use a different command line - to signify its
a GUI applications ("link -subsystem:windows,4.x" or equivalent, depending on the version of Windows
you are targetting).

By contrast, a console application is very POSIX like in its behavior. printf() writes to the
console (cmd.exe) you invoked from and you can pipe the output.

I recently started using MINGW (http://www.mingw.org/) - a port of the GNU compiler collection
to Windows. MINGW is different from CYGWIN which provides a Unix/POSIX like system under Windows.
MINGW can generate Windows applications - so, no need for the SDK. (MINGW is simply brilliant;
I'll explain why, below).

In porting CRiSP to run under MINGW, I ended up building a "premake" like build tool,
because the Windows and Unix makefiles had grown too long in the tooth to easily adapt. After
building CRiSP under MINGW, I did something *wrong*. I built crisp.exe as a console application.
I didnt realise this. And was surprised that printf() was writing to the console.

Up until now, CRiSP has had to emulate the console, and writes to a popup dialog. Its not a bad
way of debugging, but a nuisance, despite some nice little features which help me.

But why was MINGW crisp.exe writing to stdout quite happily, yet the Win32 version of CRiSP.EXE
did not? I had attempted to solve this problem many years ago, and found that somewhere in the
Windows startup code, the STDIN/STDOUT/STDERR handles are closed and not available - by the time
WinMain() is called, it is game over.

But when crisp.exe is linked as a console application, this does not happen. stdin/stdout/stderr
are left intact. So, a GUI application can read/write to stdin/stdout !

I dont know why all the Windows documentation makes a big play about the linking "subsystem", but if
you ignore it, life is more palatable.

Why is MINGW so good? Because "gdb" just *works*. I can use gdb on Linux, MacOS and Windows and have
the same debug environment. Even hardware watchpoints work. gdb may not be everyones favorite debugger,
but it is might powerful.

Prior to this I was using the free Visual C++ Express edition. (I had purchased the Professional
Visual Studio a long time back, but Visual Studio, despite being a very powerful product, just
changes too often with whatever current flavour of technology is current, and its not cost effective
for software which runs cross-platform). With the advent of Windows-8, its not clear whether
Microsoft is trying more to create a walled garden, like Apple is/has done.

So, the GNU compiler collection is great - providing a consistent compiler platform across
many operating systems. MINGW fills in a gap - which was how to use GCC to create Windows applications.

Currently CRiSP is being built via Visual Studio, and MINGW is only being used for internal
debugging, but this may likely change in the near future.




Post created by CRiSP v11.0.4a-b6356


1 comment:

  1. Well, one issue I found (thanks Pierre) is that making it a console app, and then doing "start crisp.exe" causes an additional cmd.exe console to be launched.

    Back to the drawing board. I really want it to be a console app if launched from the console, but a windows app if not launched with a stdin.

    ReplyDelete