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_
andrefcount
. This macro should followrefcount
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_METHOD( "Kino_ClassNick_Method_Name", function_declaration );
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.