NAME

stubgen - code generator for Database wrapper classes

SYNOPSIS

stubgen [-v] category definition_file [-h header_dir] [-cc body_dir] [-t template_dir] [-r report_file] [-o out_file]

where category is one of

bridge for bridge classes,

bridge-data for bridge data classes

facade for opaque facade classes,

client_prefix for client facade classes

OPTIONS

Options can be placed in any order, anywhere on the command line.

-v

Verbose

-h header_dir

Specifies the directory into which generated header files (.h) will be placed. If this option is omitted, no header files will be generated.

-cc body_dir

Specifies the directory into which generated implementation files (.cc) and an Imakefile fragment will be placed. If this option is omitted, no implementation files will be generated.

-t template_dir

Specifies the directory where the template files are located.

-r report_file

Requests the generation of a report which is placed in report_file.

-o log_file

Requests creation of a list of generated files which is placed in log_file

-p include_prefix

Overrides the standard prefix used in generating values for certain variables (see "Variables" for details.)

DESCRIPTION

stubgen parses the definition_file and generates C++ source code for the specified category of classes. If the -h option was specified, C++ header files are generated for each qualified database entity. If the -cc option was specified, C++ implementation files are generated for each qualified database entity. Thus one can simply parse the definition_file by omitting both options.

Qualified database entities are those which match the category according to the following rules:

Category

Qualified Entities

Generated Classes

bridge

All entities

Bridge (<Entity>Bridge)

facade

All entities

Opaque Facade (<Entity>)

TEST

All entities

Client Facade (TEST<Entity>)

client_prefix

Entities having at least one method whose access list contains the client_prefix or which are available to all clients.

Client Facade (<client_prefix><Entity>)

Code is generated by expanding template files. stubgen uses the following rule to determine the location of the template files:

    1. If a -t option was specified use the directory supplied with that option.
    2. Otherwise, if the environment variable, STUBGEN_TEMPLATES, is defined, use the directory defined by that variable
    3. Otherwise, use the directory in which the stubgen executable is located.

Normally users of stubgen need not tinker with the templates. They are documented here for completeness.

FILES

Entity.cc

Template for Opaque Façade implementation

Entity.h

Template for Opaque Facade header

EntityBridge.cc

Template for Bridge implementation

EntityBridge.h

Template for Bridge header

ClientEntity.cc

Template for Client Facade implementation

ClientEntity.h

Template for Client Facade header

Category.imk

Template for generated Imakefile

 

BACKGROUND

Each persistent class (a "Database Entity") is implemented by a family of related classes as illustrated in Figure 1. The roles of each class are described below.

Figure 1: Implementation of Database Entities

An Objectivity persistent class. Responsible for most of the Database Entity’s functionality, and for storage of its persistent state. The interface to this class is defined entirely in terms of types recognized by Objectivity. In particular no <Entity> or <Entity>Bridge classes cross this interface.

A transient C++ class which functions as a surrogate for the oby<Entity>. Access to the corresponding oby<Entity> is via an Objectivity handle, ooHandle(oby<Entity>) embedded in the <Entity>BridgeData object. Responsible for:

a) Data type conversion of oby<Entity> method parameters and return values.

b) Translation of oby<Entity> error status returns into C++ exceptions. (Objectivity reports errors via status codes rather than by throwing exceptions).

c) Management of Objectivity databases and transactions. This role includes coordinating with other Objectivity clients on the use of a federated database and the state of the current transaction. (Objectivity only allows one open federation and one active transaction per Unix process). This coordination is accomplished via interaction with a collection of Objectivity Management objects.

d) Implementing those aspects of the Database Entity’s functionality that would otherwise require the oby<Entity> class to know about <Entity> or <Entity>Bridge classes. For instance, the visitor pattern is implemented by the Bridge class with the assistance of Objectivity iterators.

A transient C++ class which functions as an abstract class from which client interface classes (<Client><Entity>) are derived. This class implements the common features of all client interfaces:

a) Provide compile-time decoupling of the Client and the Database. The include file for <Entity> does not #include <Entity>Bridge. Thus changes in the implementation of <Entity>Bridge simply require relinking of the client, rather than recompilation and relinking.

b) Automate the memory management of <Entity>Bridge, which is always allocated on the heap. (This functionality is accomplished by reference counting, inherited from Handle/HandleBody).

c) Provide the client with a model of the Database Entity as a concrete class.

A transient C++ class which represents the Database Entity for a particular client. It provides that subset of the Database Entity’s interface which is accessible by the client.

DEFINITION FILE

The definition file provides all of the information needed to generate the C++ code. It is formatted as an ASCII file. The syntax and semantic of the definition language is presented below.

The Definition File consists of a sequence of comments and directives. Comments always occupy a single physical line, which must begin with the character, ‘#’. Directives always occupy at least one physical line (i.e. no more than one directive per physical line). If a directive occupies more than one physical line, then all but the last physical line must end with a continuation character, ‘\’, as the last non white-space character of the line.

Directives consist of fields separated by the field separation character, ‘|’. The first field of a directive is a keyword identifying the directive’s type. The number and contents of the remaining fields depends upon the directive’s type. The directives are summarized in the following table:

Table 1: Definition File Directives

Directive

Role

type

Declares a type (other than a Database Entity) used by some method of an Entity.

entity

Declares the name of a Database Entity.

default-entity

Identifies the Database Entity to which following method directives apply.

method

Declares a method of the current default Database Entity.

(The entries in the table are in order of appearance in a Definition File.)

The syntax of the directives is given using extended BNF using the following conventions:

In the following syntax definitions, the field separation character is represented by the non-terminal, sep.

sep ::= ‘|’

Type Directive

This directive provides information about types (Other than the classes representing Database Entities), which are used in the interface of some Database Entity. (Built in C++ types are not introduced by a Type Directive

Syntax:

TypeDirective ::= type sep TypeName sep TypeKind sep TypeHeader

TypeName ::= The C++ identifier for the type.

TypeKind ::= class | typedef

TypeHeader ::= The filespec of the include file containing the type’s C++ declaration.

Example:

type|RWBoolean|typedef|rw/types.h

type|RWCString|class|rw/cstring.h

stubgen uses the class/typedef distinction given by TypeKind to optimize generated header files. If a type of kind, class, is not passed by value in the interface of the generated class, then the header file for that type is not #included in the generated header file. Instead a C++ forward declaration of the class is generated.

Entity Directive

This directive declares all of the Database Entities for which code can be generated. A Default-Entity Directive which references an undeclared Database Entity will be flagged as an error during the loading of the Definition File.

Syntax:

EntityDirective ::= entity sep EntityName

EntityName ::= C++ identifier for the Database Entity

Example:

entity|Foo

entity|Bar

The C++ names of the various classes representing the Database Entity are derived according to the conventions illustrated in Figure 1 where the value of EntityName is substituted for <Entity>.

File names for the generated classes are then derived from the class names by lowercasing the class name.

Default Entity Directive

This directive establishes the name of the Database Entity to which subsequent Method Directives implicitly refer. The EntityName specified here must have appeared in a prior Entity Directive. If not, an error message is issued.

Syntax:

DefaultEntityDirective ::= default-entity sep [ EntityName ]

EntityName ::= C++ identifier for the Database Entity

Example:

default-entity|Foo

# Methods for Foo declared here

default-entity|

If EntityName is omitted, there is no default entity, and subsequent Method Directives will generate error messages to this effect. The example illustrates the recommended practice of undefining the default entity so that the omission of a subsequent Default Entity directive will cause errors during Definition File loading.

Method Directive

This directive defines a method of the default entity. It provides the information needed to generate C++ source code for that method.

Syntax:

MethodDirective ::= MethodOpcode sep [ MethodQualifiers ] sep MethodName sep [ MethodType ] sep [ ArgumentList ] sep [ AccessList ]

MethodOpcode ::= method [ BodyVersion ]

MethodQualifiers ::= [ static ] [ const ]

MethodName ::= C++ method identifier

MethodType ::= TypeDecl

ArgumentList ::= ArgumentDecl { , ArgumentDecl }

ArgumentDecl ::= TypeDecl ArgumentName

ArgumentName ::= C++ method argument identifier

TypeDecl ::= [ const ] TypeName [ & | * ]

TypeName ::= C++ type identifier

AccessList ::= AccessKey { , AccessKey }

AccessKey ::= ALL | ClientPrefix

ClientPrefix ::= The standard prefix for a given client.

MethodOpcode

The keyword, nocode, indicates that no code will be generated for this method in the <Entity>Bridge class. (However code will be generated in each of the other classes).

BodyVersion

This token is a string which identifies an alternative version of the method’s expansion in the various templates. If the template contains an $alt-method directive which references the BodyVersion, then the corresponding expansion text will be used instead of the default text. (If the template does not contain such an $alt-method directive, the default text is used anyway)

MethodQualifiers

The keyword, const, indicates that the method is a ‘const’ method. The declaration of the method will be postfixed with "const"

The keyword, static, indicates that the method is a class method (C++ static method).

MethodType

This field specifies the return type of the method. The default value is "void"

ArgumentList

This field defines the method’s arguments in format similar to that used by C++ (The only difference is the restrictions imposed by TypeDecl on the format of the argument type declarations.). In other words, the argument list is a comma separated list of argument declarations, each consisting of an argument type declaration and an argument name.

AccessList

This field defines which clients are granted access to this method. It is a comma separated list of AccessKeys. The presence of a ClientPrefix (say SC) in the list indicates that the corresponding client (e.g. the SemanticChecker) has access to this method, and hence it will appear in the public section of the corresponding <Client><Entity> class.

The reserved key, ALL, indicates that the method is accessible to all clients.

If the AccessList is empty, the method is not accessible to any client (except TEST).

NOTE: The client prefix, TEST, is implicitly placed on all methods, allowing a test client to have access to the full Database interface.

TEMPLATES

Templates are schematic representations of C++ header and implementation files, and Imakefiles which are expanded by a specialized macro processor within stubgen.

A Template consists of a sequence of source lines and directives. Directives always begin with a ‘$’ followed by the directive name. All other lines are considered to be source lines.

Source lines may contain variable references which are replaced with the value of the corresponding variable when the source line is expanded for output. The process of outputting expanded source lines is called ‘expanding the template’.

Variables

Variables are symbolic names for text strings which are to be substituted whereever a reference to that variable occurs. The text string associated with a variable is called its value. The value of a variable may not contain variable references. Variable references have the following syntax:

VariableReference ::= $[VariableName]

No whitespace is allowed inside the braces enclosing the VariableName.

There are a large number of predefined variables. Additionally, variables may be defined via the $define directive (see below)

Table 2: Predefined Template Variables

Variable

Value

Directive
(a)

Date

The current date & time when the file is generated

 

File

The name of the file being generated.

 

Entity

Name of the Entity’s Opaque Facade class

 

EntityHeader

Name of the header file for the Opaque Facade class

 

EntityBridge

Name of the Entity’s Bridge class

 

EntityBridgeHeader

Name of the header file for the Bridge class

 

ObyEntity

Name of the Entity’s Objectivity class

 

ObyEntityHeader

Name of the header file for the Objectivity class

 

ClientEntity

Name of the Entity’s Client Facade class

 

ClientEntityHeader

Name of the header file for the Client Facade class

 

ClassHeaderKey

C++ preprocessor symbol to be used in the "smart include" mechanism of the class’s header file

 

ExternalClass

Name of the current external class

$forwards

Header

Name of the current include file

$includes

MethodType

Return type of the current method

$methods

MethodName

Name of the method.

$methods

MethodSignature

Signature of the current method
<Name>(<ArgDeclList>) [const]

$methods

MethodCall

Invocation of the current method
<Name>(<ArgList>)

$methods

Return

if MethodType == "void" then "" else "return "

$methods

SourceFile

Name of a generated implementation file without .cc

$sources

CodeTag (b)

String identifying the category of code being generatd

 

  1. If non-blank, the variable is defined only within the scope of the directive(s) listed.
  2. Defined only in the Imakefile template

The variables representing header files (e.g. EntityHeader) have a value of the form: PathPrefix/ClassName.h where PathPrefix is empty unless specified by the -p option and ClassName is the name of the class defined by the header file.

Directives

Directives tell stubgen to take special actions when expanding a template. Many of them cause stubgen to repeatedly expand a section of the template, supplying different values for directive specific macros on each iteration. Unlike Definition File directives, Template directives must occupy a single physical line.

Table 3: Template Directives

Directive

Use

Scope
(a)

$define

Define new variables

 

$includes

Iterate over all include files required by the entity

C++

$forwards

Iterate over all external classes not passed by value

C++

$methods

Iterate over all object methods of the class

C++

$alt-method (b)

Specify named alternative expansion of a method

C++

$sources

Iterate over all generated implementation files

Imake

    1. If non-blank, the directive is defined only for the indicated category of template (C++ means headers and implementation files, Imake means the Imake file)
    2. Only allowed within the scope of a $methods directive

$define Directive

This directive is used to define new variables within a template.

Syntax

DefineDirective ::= $define VariableName Delim VariableDefinition Delim

VariableName ::= A sequence of alphanumerics and "_"

Delim ::= the first non-whitespace character following VariableName

VariableDefinition ::= All the text between Delim

The VariableDefinition can contain whitespace. It can contain variable references which will be expanded at the time the directive is processed. References to the variable being defined will result in a warning, and will be expanded to the empty string.

The Delim can be abutted to the VariableName

Example

The following directives all define the variable, obyClass, as the expansion of "ooHandle($[ObyEntity])"

$define obyClass%ooHandle($[ObyEntity])%
$define obyClass %ooHandle($[ObyEntity])%
$define obyClass "ooHandle($[ObyEntity])"

$includes Directive

This directive is used to generate C++ #include directives for the header files needed by the template.

For a header file template, this list consists of headers for all types (including DatabaseEntity classes) which are used in the declaration of the generated class’s methods, except for classes which are never passed by value either as a method return or argument. The names of these latter classes can be visited by use of the $forwards directive within the same template.

For an implementation file template, this list consists of headers for all of those types that were omitted in the implementation template, i.e. headers of those classes which are never passed by value either as a method return or argument. This policy assumes that the implementation file template will #include the header of the class.

Syntax

IncludesDirective ::= $includes newline SourceLines newline $end-includes

The $includes and $end-includes directives bracket a sequence of source lines which will be repeatedly expanded, once for each header file. See Table 2 for those template variables which are defined within the SourceLines of this directive.

Do not place any other directives within the SourceLines.

Example

$includes
#include <$[Header]>
$end-includes

The above example will generate #include directives for all of the include files needed by the generated source file (If the template itself contains occurrences of types, then the template must also contain the appropriate '#include' directives. Stubgen does not attempt to parse the template itself.)

$forwards Directive

This directive is used to generate C++ forward declarations for classes needed by the template.

For a header file template, this list consists of those classes which are never passed by value either as return or argument in the generated methods.

For an implementation file, this list is always empty.

Syntax

ForwardsDirective ::= $forwards newline SourceLines newline $end-includes

The $forwards and $end-forwards directives bracket a sequence of source lines which will be repeatedly expanded, once for each class. See Table 2 for those template variables which are defined within the SourceLines of this directive.

Do not place any other directives within the SourceLines.

Example

$forwards
class $[ExternalClass];
$end-forwards

The above example will generate forward declarations for all of the external classes referenced by the generated methods of a header file

$methods Directive

This directive is used to generate C++ declarations and definitions of the qualified, non-static methods extracted from the Definition File.

Syntax

MethodsDirective ::= $methods newline ExpansionText newline $end-methods

ExpansionText ::= { SourceLine | AltMethodDirective }

AltMethodDirective ::= $alt-method AltTag { , AltTag }

The $methods and $end-methods directives bracket a sequence of source lines which will be repeatedly expanded, once for each qualified non-static method extracted from the Definition File. See Table 2 for those template variables which are defined within the SourceLines of this directive.

The ExpansionText defines one or more (possibly empty) sequences of SourceLines, one of which will be expanded for each qualified non-static method extracted from the Definition File. (See Table 2 for those template variables which are defined within the SourceLines of this directive). The first sequence (between the $methods and the first $alt-method or $end-methods directive) is called the default text for the method. The subsequent sequences (between an $alt-method and the next $alt-method or $end-methods directive), are called alternate texts for the method. Each alternate text is identified by one or more AltTags. The same AltTag cannot appear in more than one $alt-method directive within a $methods directive.

For a given method, the alternate text which has a tag matching the BodyVersion of the method is used. If no such text can be found, the default text is used. Consequently, methods having no BodyVersion will always used the default text.

Example: Header File

$methods
$[MethodType] $[MethodSigniture];
$end-methods

The above sequence will generate the declarations of all generated methods within a header file.

Example: Implementation File - Bridge Class:

$methods
// Name: $[MethodName]
$[MethodType]
$[EntityBridge]::$[MethodSignature]
{
  $[Return]obyEntity_->$[MethodCall];
}
$alt-method returns-entity
//Name:$[MethodName]
$[MethodType]
$[EntityBridge]::$[MethodSignature]
{
  ooHandle(oby$[MethodType]) result =
    obyEntity_->$[MethodCall];
  return $[MethodType]Bridge::make(result);
}
$alt-method static
// Name: $[MethodName]
$[MethodType]
$[EntityBridge]::$[MethodSigniture]
{
  $[Return]$[ObyEntity]::$[MethodCall];
}
$alt-method static-returns-entity
//Name:$[MethodName]
$[MethodType]
$[EntityBridge]::$[MethodSignature]
{
  ooHandle(oby$[MethodType]) result
    =$[ObyEntity]::$[MethodCall];
  return $[MethodType]Bridge::make(result);
}
$alt-method nocode
$end-methods

The above sequence will generate the definitions of all generated methods within an implementation file. (The variable, Return expands to an empty string if the MethodType expands to ‘void’, otherwise it expands to ‘return ‘ )

The default, is for non-static methods which do not return an entity.

The alternative, returns-entity, is used for non-static methods known to return a generic facade to some entity. In this case the return value from the Objectivity class is an ooHandle which must be converted to a generic facade.

The alternative, static, is used for methods which are static and do not return an entity.

The alternative, static-returns-entity, is for static methods known to return a generic facade to an entity.

The alternative, no-code, is used for methods which will be implemented manually in a separate file.

$sources Directive

This directive is used to generate dependencies in the Imakefile which is companion to a set of implementation files.

Syntax

SourcesDirective ::= $sources newline SourceLines newline $end-sources

The $sources and $end-sources directives bracket a sequence of source lines which will be repeatedly expanded, once for each implementation file that was generated from the Definition File. See Table 2 for those template variables which are defined within the SourceLines of this directive.

Do not place any other directives within the SourceLines.

Example: Header File

$sources
EZCompile( $[SourceFile],STUBGEN)
$end-sources

The above sequence will generate compilation directives for all of the generated implementation files of a given category.