Friday, December 31, 2010

The .NET Preprocessor - Part 2

NTSTATUS: STATUS_DOTNET_MACRO

The .NET Pre-Processor may be downloaded here.

The first debate was which language it should be written in. The candidates were C/C++, C# and Python. I really wanted to write it in C/C++, but the conveniences of C# and the .NET platform was just scoring too many points. No, I will not write managed C++ in Visual C++. I do not like the syntax. As for Python, the code would probably have been shorter, but it’s not a common install, and not as commonly used, I think. Related to that, Python got a boost when an actual Python came to my house a week ago. No, seriously. It’s the second one to come by in 6 months. I told my good friend Walter (Developer Security MVP) that it might have been a sign. But alas, it was C#.

DOTNETPP is a command-line tool that is largely designed to work with Visual Studio’s pre and post-build facilities. The settings are expected to be in an XML file, a sample of which is included in the download. Following is the usage:

Usage: DOTNETPP /p:"<config file path>" [/process|/cleanup]

/process: Process macro expansion

/cleanup: Cleanup expanded macro files

The config file path is specified by the /p: parameter. /process and /cleanup are actually mutually exclusive. If they both appear, /process will take priority. So basically, you will use /process in your Visual Studio .NET Project’s pre-build event, and /cleanup in your post-build event. Of course you can also manually run it to process and cleanup.

Macro Definition File

The macro definition file is basically a text file where you define your C Preprocessor macros. I will post some examples subsequent posts. DOTNETPP supports the following macro/preprocessor features:

- Non-parameterized macros

- Parameterized macros

- Token concatenation (##)

- Stringizing Operator (#)

- C++ style comments (//)

Since the macro definitions are in its own file, the line-continuation backslash ‘\’ is not required at the end of each line of the token list.

Source Files

In the source files which you want to use macros and have DOTNETPP process them, include the following syntax in said source file:

#include DOTNETPP

Since this syntax is not processed, it must be commented or excluded from compilation for the build to succeed. In the case of C#, you may use the following:

//#include DOTNETPP

Or

#if false

#include DOTNETPP

#endif

The Catch

There is a catch. This is because this tool is NOT integrated into Visual Studio. This is what the problem is… the way DOTNETPP works is that it (obviously) expands the macros, and then writes it back into the source file. So the catch is, if any of the source files that are processed by DOTNETPP are open when the build runs (with DOTNETPP running in the pre/post-build events), the build WILL FAIL.

Why? This is because Visual Studio will ask if you want to reload the file as it has been edited outside of the source editor. The compilation would have started way before you’re able to say you want to reload the files. So if you reload and save the changed files, you will LOSE all your macros, and have the expanded code instead. This would be equivalent to setting <RestoreMacrosInSource> to FALSE in the config file.

Here’s the scenario:

1. Build project/solution

2. Build fails

3. Visual Studio asks if you want to reload the files

4. Reload the files and save

5. Build project/solution (this time it will succeed assuming you did not screw up the macro definitions)

This is a clearly a serious inconvenience to have to close all the source files with the macros before doing a build every time. This is a major con. Well, it’s not part of Visual Studio, tough. So maybe there is a way to work around this if the tool is integrated into Visual Studio. That would be something to look into for the future.

However, having thought about it, this problem probably isn’t necessarily a bad thing. I probably don’t actually want the macros to remain in the source as it can be cryptic. So, as a potentially fortunate consequence of the way Visual Studio works, DOTNETPP could work as a one-time-no-return macro expander. After all, one of the config settings is <RestoreMacrosInSource>true/false</RestoreMacrosInSource>. OK, so maybe this is a less ‘evil’ way. Expand the macros so they become the source code, and no more macros in the source.

Next I will write about the config file, but the elements should be quite obvious.

Here’s one of the main reasons I started this project:

#define FOR(a) for (int i = 0; i < a.Count; i++)

Thursday, December 30, 2010

The .NET Preprocessor - Part 1

NTSTATUS: STATUS_DOTNET_MACRO

This is my only technical blog, so I’ll just put it here for now…

My favourite programming language is still C. One of the things I liked a lot about it is the C Preprocessor. There are people who love it, and then there are those who hate it. Some say that it is evil. Like they say, with C, you shoot yourself in the foot. I guess the C Preprocessor (CPP) is the same. It can be used for good, or evil. If used appropriately, boy, can it save you a load of tedious coding/keystrokes. If you screw it up, you shoot yourself in the foot.

So nowadays, I don’t use C/C++ as much as there is not all that much need for it, and better languages/platforms for certain jobs… Like web apps, and general Windows apps… Yes, that makes up most of the needs nowadays. I’ve always been Windows kinda guy, so naturally I’m using C# on .NET. Man, C# is sweet, and the .NET libraries are super sweet. OK, so at least C# has some basic compiler-directives, like symbol definition and conditional compilation. From a C background, that is very welcome indeed.

However, there is NO macro expansion!!! [Insert expletive here]. If you’ve used the CPP, you’ll soon start to miss it. I swear, man, I am so sick of typing tedious repetitive code. If you are one of those who would say to substitute the macros with functions, then forget it because I don’t want to create more overhead where it can be avoided. Besides, it just isn’t the same concept or in the same spirit.
So about a month ago, I started moaning about this again because I am so, so, so, did I say I was sooo sick of writing for-loops (for instance)? So I kindly asked someone (anyone) to add the CPP/Precompiler to C# on Facebook. OK, I know it was not included in C# for reasons unknown to me. But I believe Hejlsberg and co. had good reasons. But I know what I am doing, and I WANT IT!!! So how now brown cow?

So, having toyed with the idea for a couple of weeks, I spent another week or two actually thinking it out in my head how to build it, and which features it would include. Of course, I thought about how it could work with Visual Studio. Not surprisingly, after a few weeks of laying it all out in my head, I finally took some ‘time off’, sat down, and went about building it. Surprisingly, it took me just over half a day to finish the first complete app. So next time your boss catches you seemingly doing nothing, just tell ‘em that you’re laying it all out in your head first so the execution will be quicker and smoother.

Anyway, I will continue to write about how it works in subsequent posts and put the links up. Oh, I beg your pardon, I haven’t introduced it. I call it the ‘.NET Pre-Processor’, and it is DOTNETPP.EXE.