Author image Marvin Humphrey
and 1 contributors

NAME

boilerplater.pl - Generate boilerplate OO code for KinoSearch

SYNOPSIS

     perl boilerplater.pl INPUT_DIR DEST_DIR

PRIVATE API

boilerplater.pl is an implementation detail. This documentation is partial -- enough for the curious hacker, but not a full API.

DESCRIPTION

The boilerplater.pl utility looks for special keywords in C header files and generates boilerplate OO code when it finds them. The keywords all begin with KINO_, and they must be the first item on a line to be recognized as valid.

As far as the C compiler is concerned, the keywords are simply macros defined to do nothing -- so they only have meaning vis-a-vis boilerplater.

Rationale

Inheritance and polymorphism are messy in C, but basically required for implementing Lucene. Auto-generating code makes saves a lot of error-prone typing.

Object Model

  • Single inheritance.

  • Memory management via reference counting.

  • Method dispatch using virtual tables.

  • All classes descend from KinoSearch::Util::Obj.

Inclusion

The boilerplate code is written to a file with whose name is the same as the header file, but with a ".r" extension (for "representation") rather than ".h". Files should include "KinoSearch/Util/Foo.r" rather than "KinoSearch/Util/Foo.h".

Short names

Short names -- names minus the prefix "kino_", "Kino_", or "KINO_" -- will be auto-generated for all class symbols.

Header File

Class declarations begin with a KINO_CLASS directive and end with KINO_END_CLASS. They must be prepared by including Obj.r and pre-declaring the object and vtable typedefs.

    #ifndef H_KINO_FOO
    #define H_KINO_FOO 1

    #include "KinoSearch/Util/Obj.r"

    typedef struct kino_Foo kino_Foo;
    typedef struct KINO_FOO_VTABLE KINO_FOO_VTABLE;

    KINO_CLASS("KinoSearch::Util::Foo", "Foo", "KinoSearch::Util::Obj")

    struct kino_Foo {
        const KINO_FOO_VTABLE *_;
        kino_u32_t refcount;
        kino_u32_t num_widgets;
    };

    KINO_FUNCTION(
    kino_Foo*
    kino_Foo_new());
    
    KINO_METHOD("Kino_Foo_Do_Stuff",
    int
    kino_Foo_do_stuff(Foo *self));

    KINO_METHOD("Kino_Foo_Destroy",
    void
    kino_Foo_destroy(Foo *self));

    KINO_END_CLASS

    #endif /* H_KINO_FOO */

In between KINO_CLASS and KINO_END_CLASS, all code must adhere strictly to all guidelines. Comments are allowed, but auxiliary macros, functions and such should be defined outside the class declaration, since boilerplater's parser will throw an error if it finds something it doesn't understand.

Pre-declaring object and vtable structs

The name of the object struct must be in UpperCamelCase and be prepended with kino_:

    typedef kino_ClassName kino_ClassName;

The vtable struct's name must be an upper-cased version of the struct name with _VTABLE appended. (The vtable struct definition will be auto-generated.)

    typedef struct KINO_CLASSNAME_VTABLE KINO_CLASSNAME_VTABLE;

Object struct definition

The class's object struct definition must adhere to the following criteria:

  • The first member must be a vtable pointer named _.

  • The second member must be kino_u32_t refcount.

  • If the class inherits anything besides Obj, it must match all members of its parent other than the vtable. To this end, a macro named KINO_CLASSNAME_MEMBER_VARS is auto-generated for each class which contains all members save _ and refcount. This macro should follow refcount in the child class's object struct definition:

        struct kino_FooJr {
            KINO_FOOJR_VTABLE *_;
            kino_u32_t refcount;
            KINO_FOO_MEMBER_VARS
            kino_i32_t another_variable;
        };

Keywords

KINO_CLASS( [class_name], [class_nick], [parent_class] );

Begin a class declaration. Three double-quoted string arguments are required, and the struct definition for the object must follow on immediately afterwards.

  • class_name - The name of this class. The last word should match the struct's short name.

  • class_nick - A recognizable abbreviation of the class name, used as a prefix for every function and method.

  • parent_class - The full name of the parent class.

KINO_END_CLASS

Terminate a class declaration.

KINO_FUNCTION(function_declaration);

All this directive does is generate a short name and perform some validation. The function's name must follow this pattern:

    kino_ . $class_nick . '_' . $micro_name;

$class_nick must be the one specified in KINO_CLASS. $micro_name must consist of only characters matching [a-z0-9_].

KINO_METHOD( "Kino_ClassNick_Method_Name", function_declaration );

This directive does everything KINO_FUNCTION does, but in addition assigns method semantics to the first argument, which must be a double-quoted string.

Method declarations look identical to function declarations, and the function names must match the same pattern. However, as an additional constraint, the first argument must be an object.

KINO_FINAL_METHOD( "Kino_ClassNick_Method_Name", function_decl );

As KINO_METHOD above, but method macro becomes a direct alias to the function name, rather than a vtable invocation.

KINO_FINAL_CLASS( [class_name], [class_nick], [parent_class] );

As KINO_CLASS above, but causes all methods to become final.

Class definition file

There is only one requirement for the C file where the class is fully defined. Before the pound-include directive for the ".r" file, the vtable must be claimed:

    #define KINO_WANT_FOO_VTABLE
    #include "KinoSearch/Util/Foo.r"

COPYRIGHT AND LICENSE

Copyright 2006-2007 Marvin Humphrey

This program is free software; you can redistribute it and/or modify under the same terms as Perl itself.