X-Code .NET

writing code with code (specifically, with JScript .NET code)

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[This is prerelease software -- it is new and subject to change.
Your comments and suggestions would be much appreciated.]

Download it! (version: 2002.12.18)


X-Code .NET is a successor to the popular "X-Code" codegen language, which was included as part of the excellent-but-now-defunct product from DevelopMentor known as Gen<X>.  X-Code .NET is like classic X-Code, except that it's based on JScript .NET instead of classic JScript.

The idea of X-Code is simple but powerful:  using templates with script embedded inside (ala ASP) to emit not just HTML, but any code or text or data that is representable in a standard text format.  Some examples of what you can generate with X-Code: C/C++/C# source files, Java code, HTML and XML files, Visual Studio project files, source files for the Win32 RC and MC (resource- and message-compiler), batch files, and ... the list goes on an on.

The benefits of using JScript .NET as the driving language for X-Code, instead of classic JScript, are vast and numerous.  With the addition of strong typing, plus access to the entire .NET Common Language Runtime environment, and a vastly improved debugging experience... it's really a whole new ball game!

However, the original X-Code supported not just JScript, but all of the Active Scripting languages (like VBScript).  X-Code .NET currently supports only JScript .NET, none of the other .NET languages.  Why?

What's New:

bug fix: the encoding of the source template is now preserved in the output file; in the absence of /out, the template's output is written to stdout in the system default encoding

bug fix: stdout is only used to emit the template's output (all diagnostic info is written to stderr) -- this allows the template output to be cleanly piped/redirected, and also allows template code to write its own diagnostic info, via Console.Error.Write()

bug fix: don't output duplicate compiler errors

bug fix: cleanup of temp files needed to support /debug


Simply copy XCC.exe into your path somewhere, and you're good to go.  XCC requires the .NET runtime, version 1.0.3705.


XCC <sourceTemplate> [<options...>] [<arguments...>]

Where <options...> is zero or more of the following:

[/out=<outFile>] [/debug] [/legacy] [/noautoref] [/ref=<assemblyName>]

And <arguments...> is a list of name/type/value triplets passed on to the X-Code program. The syntax for each argument is:


Note the double-slashes:  it's not a typo -- they help to avoid confusion/collision with the /out= and /ref= switches, and any other such switches that may be defined in the future. The <type> specifier is optional ("string" is the default). The <value> specifier is also optional (although the "=" symbol is not). If absent, you will be prompted to specify a value, at run-time. Special case: if <type> is specified as "guid" or "uuid", a new 128-bit unique identifier is generated, and the canonical string representation is assigned to the argument (guids with curly braces, uuids without).

XCC returns the following values to the shell, to indicate success or failure:

0 success (or, help requested)
1 unrecognized command line argument
2 source template file not found
3 the X-Code template threw an exception
5 access denied (eg: output file is read-only)
9 unexpected, internal error
10+ JScipt .NET compiler error


XCC thankyounote.html.xc //From=Barney //To=
(will prompt for name of recipient, then emit HTML for a thank-you note to the console)
XCC vector.cs.xc /out=FooVector.cs //T=Foo //InitialSize:int=20
(will create a new C# source file with the specified template parameters)
XCC coclass.h.xc /out=Foo.h //Name=CFoo //ID:guid=
(will generate a new GUID, then use it to create a new C++ header file for a COM class)

Advanced usage:

When specifying a value, either on the command line or when prompted, enter the value exactly as it would appear in JScript .NET code (as the right-hand-side of an assignment expression).  This implies the ability to use real, live expressions on the command line!  However, be sure to consider the standard command line-parsing rules, regarding backslashes and doublequotes.

XCC myXCode.txt.xc //yesterday:System.DateTime="DateTime.Today - new TimeSpan(1,0,0,0)"

Again, always enter values exactly as they would appear on the r.h.s. of an assignment expression in JScript .NET code.  This means enclosing literal String-type values in double or singlequotes.  As a convenience, arguments with the (default) type of "string" will be automatically enclosed in doublequotes, for you.  However, arguments of type "System.String" are not.  For example, the following command will fail (unless qux happens to be a valid variable name).

XCC myXCode.txt.xc //myString1:string=foo //myString2=bar //myString3:String=qux
(will fail)
XCC myXCode.txt.xc //myString1:string=foo //myString2=var //myString3:String="qux"
(will succeed)

Note that you can define types in your X-Code .NET script, and use them from the command line, to enhance type-safety.  For example, consider an X-Code .NET template that contains the following enumeration:

<% enum ReleaseType { Alpha1, Alpha2, Beta1, Beta2, ShipIt } %>

Such a script might be invoked like this:

XCC AssemblyVersion.cs.xc /out=AssemblyVersion.cs  //releaseType:ReleaseType=ReleaseType.Alpha2
(this is much clearer than //releaseType=1, or even //releaseType:short=1)

If any invalid arguments are specified, your X-Code .NET script should throw an exception of type System.ArgumentException (or one of its derived types).  These exceptions will be trapped by XCC, and a friendly error message will be written to the console.

Known issues:

Currently there is no way for an X-Code .NET template to return a specific errorlevel value back to the shell.  Throwing an exception is the only way to signal an error.  XCC catches such exceptions, and returns a non-zero error code to the shell.  The recommended convention is to throw a System.ArgumentException or System.ArgumentOutOfRangeException for any invalid arguments (wrong type, unreasonable value, etc).

The JIT-debugging exerience leaves a little to be desired: in the case of NullReferenceExceptions and the like, you're not always given line-numbers, a useful stack trace, or the opportunity to launch and break into the debugger -- even when specifying the /debug switch.  One possible workaround is to insert the JScript .NET debugger keyword into your source, early on, then step through until you encounter the error.  This issue is currently being researched.