Next: , Previous: Event Handling, Up: Software Environment


4.6 Template Drivers

A template is a crude implementation of a reusable code block, similar in purpose to C++ templates but much more limited. Were FreeWPC written in C++, regular templates would have been used here.

Templates end in .ct (for C template) and are always kept in the drivers/ directory. A template file is instantiated via commands in the machine description. The script ctemp converts a template to one or more .c or .h files, which are then compiled normally. Thus, templates can contain RTTs or event handlers just like any other file.

4.6.1 Template Syntax

A template contains ordinary C code, plus special template directives. These always begin with two at-signs (@@). The list of valid directives, in the order that they are normally used, is listed below:

@@class
Gives the name of the template; usually this is related to the filename.
@@parameter name
Declares a template parameter. The value is substituted during instantiation.
@@file
Sets the current output filename. A template can generate any number of output files. You can switch between the different output files with this directive.
@@
A template comment. Used to insert a comment line that is not placed into the current output file. Ordinary C-like (or shell) comments will be emitted into the output files like any other non-directive line.

Within the C code, you use single-at (@) references to substitute the values of template variables into the text. For example,

     @@class xyz
     int @class_variable

would be translated into the following plain C code:

     int xyz_variable

Notice that template variable names cannot contain underscores.

You define your own template variables with the @@parameter directive. Some variables are predefined by the code generator:

@class
The name of the template, as given in a @@class directive.
@self
The name of the instance. If a template is instantiated multiple times, each should have a different name. For example, the ‘sling’ class might have instances named ‘left_sling’ and ‘right_sling’.
@instance
Like @self, but a zero-based ID. These are assigned by the code generator during instantiation.

Variable substitutions can occur just about anywhere. For example, you can use a variable as the argument to the @@file directive. In fact, this is generally how you would use it. Consider the following:

     @@class widget
     @@file @class.h
     @@file @self.h
     @@file @class.c
     @@file @self.c

Here, the template named widget is defined. It generates four different source files: two based on the name of the class (widget.c and widget.h), and two based on the name of each instance. If there were 2 widgets instantiated by the machine, say a left widget and a right widget, then we would have left_widget.c, left_widget.h, right_widget.c, and right_widget.h.

4.6.2 Template Usage

The use case for templates is to define reusable device drivers. From game to game, there is commonality on how certain devices should be treated, although the parameters are different.

Typically, a device requires a number of different functions to control it. Most devices need a realtime function if hardware accesses must be frequent. A periodic function can handle less critical actions. APIs are defined for the rest of the logic to access it. All of this can be put into a single template, then instantiated by each machine with values for the machine-specific parameters.

Currently there are device drivers for all of the following: