tools

July 15, 2001 tools

Basic Monikers

Wish there was a moniker that did CoCreateInstance just like the Class Moniker calls CoGetClassObject? Wish you were able to compose the Class Moniker with a host name? Then you’ll want the BasicMonikers project, which bundles together the New moniker and the Host moniker. Sample syntax follows:

dm.newmk.1:Excel.Application
dm.newmk.1:00024500-0000-0000-C000-000000000046:
dm.hostmk.1:frodo:!dm.newmk.1:00024500-0000-0000-C000-000000000046:
dm.hostmk.1:frodo:!clsid:00024500-0000-0000-C000-000000000046:
July 14, 2001 tools

regsvr.reg

July 14, 2001

regsvr.reg is a regedit script file that adds Register COM Server and Unregister COM Server to the context menu for DLLs, OCXs and EXEs under Win95+ and NT4+. In addition, it’s also been updated to add Register TypeLib and Unregister TypeLib commands to .tlb, .odl, .dll, .ocx and .exe files, using VC6′s new regtlib tool.

July 13, 2001 tools

ATL Composition

July 13, 2001

I’ve developed a set of macros to support implementing interfaces using nested composition in ATL (the one common way of implementing interfaces they neglected). The benefit of composition is that it is easy to implement multiple interfaces with methods with the same name but that require different behavior, e.g.

interface IArtist : IUnknown {
     HRESULT Draw();
}

interface ICowboy : IUnknown {
     HRESULT Draw();
}

The benefit of this particular implementation is that it has no object size overhead. Interfaces implemented using nested composition have no greater overhead than using multiple-inheritance. Feel free to download atlcompose.h for your own use.

July 12, 2001 tools

STL Enumerator Iterator

Have you ever been jealous of the VB programmer who could write this:

sub EnumVariants(col as Collection)
    dim v as variant for each v in col
        ' Do something with v
    next v
end sub

when we poor C++ programmers have to write this:

void EnumVariants(IEnumVARIANT* pevar)
{
    HRESULT hr;
    enum { CHUNKSIZE = 100 };
    VARIANT rgvar[CHUNKSIZE] = { 0 };
    do {
        ULONG cFetched;

        hr = pevar->Next(CHUNKSIZE, rgvar, &cFetched)
        if( SUCCEEDED(hr) ) {
            if( hr == S_OK ) cFetched = CHUNKSIZE;
            for( ULONG i = 0; i < cFetched; i++ )
            {
                // Do something with rgvar[i]
                VariantClear(&rgvar[i]);
            }
        }
    }
    while (hr == S_OK);
}

Well no more! I’ve built an enumeration iterator class that holds IEnumXxx and exposes an STL-compatible iterator:

template <typename EnumItf, const IID* pIIDEnumItf,
          typename EnumType, typename CopyClass = _Copy<EnumType> >
class enum_iterator;

It uses the same copy policy classes as ATL for convenience. Now you can write:

void EnumVariants(IEnumVARIANT* pevar)
{
    typedef enum_iterator<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT> EVI;
    for( EVI i = EVI(pevar); i != EVI(); ++i )
    {
        VARIANT&    v = *i;
        // Do something with v
    }
}

or you can use the typedefs for the standard enumerators:

void EnumVariants(IEnumVARIANT* pevar)
{
    for( variant_iterator i = variant_iterator(pevar);
         i != variant_iterator();
         ++i )
    {
        VARIANT&    v = *i;
        // Do something with v
    }
}

or you can use STL algorithms (this is my personal favorite):

struct DoSomethingWithVariant
{
    void operator()(const VARIANT& v)
    {
        // Do something with v
    }
};

void EnumVariants(IEnumVARIANT* pevar)
{
    for_each(enum_variant(pevar),
             enum_variant(),
             DoSomethingWithVariant());    
}

Feel free to download the enum_iterator class for your own use. You’ll also need a supporting file, atlcopies.h.

July 12, 2001 tools

Client-Side Enumeration Iterator

July 12, 2001

Have you ever been jealous of the VB programmer who could write this:

sub EnumVariants(col as Collection)
    dim v as variant for each v in col
        ' Do something with v
    next v
end sub

If so, you may be interested in the STL-style IEnumXxx iterator I’ve built. You’ll also need a supporting file, atlcopies.h.

July 11, 2001 tools

GitHelp

July 11, 2001

githelp.hdefines a set of wrappers for implementing inter-thread marshaling using the GIT instead of streams. githelp.cpp provides the non-inline implementation. For another spin on GIT usage, check out Don Box’s GitLip.

June 30, 2001 tools

Codename TextBox

The Need for Code Generation

Have you ever wanted to generate code like the wizards do, i.e. start with a template, mix in some symbols and boom, out comes the code? If you’re building a custom AppWizard, you define code like so:

    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShow) {
    $$IF(coinit)
        // Initialize COM
        CoInitialize(0);

    $$ENDIF
        // Initialize the ATL module
        _Module.Init(0, hinst);
    $$IF(axhost)

        // Initialize support for control containment
        AtlAxWinInit();
    $$ENDIF

        // Create and show the main window
        HMENU   hMenu = LoadMenu(_Module.GetResourceInstance(),
                       MAKEINTRESOURCE(IDR_$$ROOT$$));
    ...
    

This is fine if you’ve got the MFC-based interpreter building your code and you’re willing to live within the boundaries of a very small set of features. The ATL Object Wizard-style of generation is similar, i.e.

    class [!ClassName] : 
     public CAxDialogImpl<[!ClassName]>
    {
    public:
     [!ClassName]()
     {
     }
    [!crlf]
    ...
    

Again, only good if you’re running under the ObjectWizard and again, somewhat limited. What you really want is to be able to do things ASP-style, e.g.

    <%@ language=vbscript %>
    <% ' test.cpp.asp %>
    <%
        greeting = Request.QueryString("greeting")
        if len(greeting) = 0 then greeting = "Hello, World."
    %>
    // test.cpp

    <% if Request.QueryString("iostream") <> "" then %>
    #include <iostream>
    using namespace std;
    <% else %>
    #include <stdio.h>
    <% end if %>

    int main()
    {
    <% if Request.QueryString("iostream") <> "" then %>
        cout << "<%= greeting %>" << endl;
    <% else %>
        printf("<%= greeting %>\n");
    <% end if %>
        return 0;
    }

In this case, you get the same effect as the other two, but you’ve got the full power of a scripting language. However, for this to work, you had to run under ASP… until now…

TextBox

TextBox is a ASP-like script host that will process any file you give it looking for:

  • text blocks
  • script blocks (<% script %>)
  • output blocks (<%= output %>)
  • An optional language block as the first line in the file only (<%@ language= language %>)
    (TextBox defaults to vbscript and currently only works with vbscript and jscript).

TextBox pre-processes the text to turn the whole thing into into script and hands it to the scripting engine for execution, outputting the result to standard out. Whatever features of the scripting language you want to use, feel free.

Usage

To provide for I/O, TextBox emulates ASP somewhat. It provides two intrinsics, the request object and the response object. The Request object has a single property, QueryString, that works just like ASP. The Response object has a single property, Write, just like ASP. In fact, if you only use Request.QueryString and Response.Write, you should be able to test your script files using ASP.

To set name/value pairs for use by the script via the Request object, the usage of TextBox is like so:

    usage: textbox <file> [name=value]

For example, to interpret the file above, any of the following command lines would work:

    textbox test.cpp.asp
    textbox test.cpp.asp greeting="Double Wahoo!"
    textbox test.cpp.asp iostream=true greeting="Double Wahoo!"
    

The first would yield the following output:

    // test.cpp

    #include <stdio.h>

    int main()
    {
        printf("Hello, World.\n");
        return 0;
    }
    

while the last would yield the following:

    // test.cpp

    #include <iostream>
    using namespace std;

    int main()
    {
        cout << "Double Wahoo!" << endl;
        return 0;
    }
    

Errors and Debugging

If the scripting engine finds an error, it will notify TextBox, who will notify you. However, if you’ve got script debugging enabled on your machine, the scripting engine will ask you if you’d like to fire up the debugger, showing you exactly the offending code.

Not Just Code

Of course, TextBox is good for the generation of any text, not just code.

Download

TextBox is available for download. It’s just a prototype, so please adjust your expectations accordingly. If you have any comments, please send them to csells@sellsbrothers.com.

Copyright

Copyright (c) 1998-2001, Chris Sells All rights reserved. NO WARRANTIES EXTENDED. Use at your own risk.

February 22, 2001 tools

TZ Data to XML Project

These are the outputs of my attempts to translate the native tz data into XML for easier parsing for applications other than implementations of the standard C routines related to time.

This is the first step in a project to merge time zone and map data by the Time Zone Map Group, lead by Chuck Ellis.

Done

  • tz2xml.zip: A VC++ program to translate native tz data files into XML. Warning: This requires a certain directory structure and a few modified files from the tz code to export shared functions. I’m working to fix that.
  • /tools/tz/tzxml.zip: Native tz data files translated to XML, including comments. Suitable for replacement as the native format. Generated by running tz2xml on the tz data files.

Yet To Do

  • Namespace support.
  • XSD support.
  • An XSLT to translate back to native tz data format.
  • An XSLT to output popular data needs, e.g. all the zones, all the rules, etc.
  • An updated zic to use the new XML format instead of the existing format.
  • Unix port of tz2data (I’ll need help on that one).

Help!

Unfortunately, I’m but one man. If you’d like to help on any of these projects, let me know.

License

Copyright © 2001 by Chris Sells. All rights reserved. No warrantees extended. Use at your own risk. You may not distribute any portion of the tz2xml source code without express written consent. You may, however, use the source with no fee or redistribute the sample XML data at will.