Definition Table
The interface to the definition table module has two parts, one fixed and
the other dependent on a specification supplied by the user.
The fixed part of the interface exports the value NoKey and the
operation NewKey
(see How to create and use definition table keys).
The variable part of the interface exports the query and update operations
for the properties specified by the user.
A library of predefined query and update operations is provided to
implement common tasks; users can also provide their own operations.
The set of operations and properties for a specific processor is defined by
a specification written in a special-purpose language.
PDL generates definitions for each of the operations specified in files
of type `.pdl'. These definitions are made available in the
generated file `pdl_gen.h'. Although this file is automatically
included for use in your attribute grammar specifications, any C files
which use definition table operations must include this file.
The basic query and update operations for the Name property
are GetName
(see Behavior of the basic query operations),
SetName , and ResetName
(see Behavior of the basic update operations).
These operations are sufficient in most cases, and are provided
automatically for every property.
Other operations, such as IsName and UniqueName are available,
but must be explicitly requested as
discussed in the next section.
void IsName(DefTableKey key, Type which, Type error)
If IsName is applied to a definition table key that has no
associated Name property,
then a Name property with the value of parameter which
becomes associated with that definition table key as a result of the
operation.
If it is applied to a definition table key that does have an associated
Name property, and the current value of that property is not equal to
the value of the parameter which , then the value of that property is
changed to the value of the parameter error .
Otherwise the operation has no effect.
Since NoKey represents an invalid entity that has no properties,
applying IsName to NoKey has no effect.
void UniqueName(DefTableKey key, Type next())
If UniqueName is applied to a definition table key that has no
associated Name property,
then a Name property with the value returned by the invocation of
parameter next becomes associated with that definition table key as a
result of the operation.
Otherwise the operation has no effect.
Since NoKey represents an invalid entity that has no properties,
applying UniqueName to NoKey has no effect.
Parameter next is invoked if and only if UniqueName is
applied to a definition table key that differs from NoKey and has
no associated Name property.
int HasName(DefTableKey key)
If Has is applied to a definition table key that has an
associated Name property, then it yields 1; otherwise it yields 0.
Since NoKey represents an invalid entity that has no properties,
applying Has to NoKey yields 0.
The property definition language allows a user to specify an arbitrary set
of properties of arbitrary types, to assert that certain operations from
the library should be available to query or update these properties, and to
define new operations.
It also allows a user to establish the initial state of the definition table.
Specifications in the property definition language are distinguished by
being provided in files of type pdl .
An arbitrary number of such files may be provided; they will be
concatenated to form the complete specification of the variable part of the
definition table module's interface.
Each file consists of a set of property and operation declarations
as are described in the following sections.
Because the files are concatenated, specifications in one need not be
repeated in another.
Nevertheless, we strongly suggest that each file contain a
complete specification for one or more tasks.
This allows maximum reuse of existing text.
C pre-processor directives and C comments can be used in type-pdl
files.
Properties are declared by specifying the property name and type,
optionally with a set of operations that should apply to properties of the
type specified.
If the type is defined by a typedef, and is not equal to
DefTableKey ,
the file containing the typedef must be specified.
The general form of a property declaration is given by:
PropertySpec: FileName / PropertyDecl .
FileName: String .
PropertyDecl: PropertyNameList ':' Type ';' .
PropertyNameList: Identifier / PropertyNameList ',' Identifier .
Type: Identifier / Identifier '[' OperationList ']' .
OperationList: Identifier / OperationList ',' Identifier .
Both String and Identifier are constructed according to the
rules of C.
The FileName string must be a valid file name.
Each Identifier appearing in a PropertyNameList is a defining
occurrence; all other occurrences of Identifier are applied.
Multiple defining occurrences for property names are allowed, provided that
they all define the property to hold values of the same type.
Operation names are formed by concatenating an Identifier appearing
in an OperationList with an Identifier appearing in a
PropertyNameList .
Reset , Get and Set are automatically defined
for every property, and need not appear in any OperationList .
Here are some valid property definitions:
Def, Kind: int;
Type: DefTableKey [Is];
Storage: StorageRequired; "Storage.h"
Def and Kind are integer-valued properties.
The variable part of the definition table interface will export operations
GetDef , SetDef , ResetDef ,
GetKind , SetKind , and ResetKind .
It will also export GetType , SetType , ResetType ,
and IsType
because the library operation Is appears in the OperationList
on the second line.
Note that this specification will produce GetStorage ,
SetStorage , and ResetStorage , but will not produce
IsStorage , because Is does not appear in any
OperationList for the property Storage .
If Is did appear in an OperationList for the property
Storage anywhere in the specification, even in another
type-pdl file, then the generated module would export
IsStorage .
Type int is a primitive type of C, and DefTableKey is defined
by the definition table module itself.
Thus neither of these types needs to be defined specially.
StorageRequired must be defined, however, and therefore file
`storage.h' is named explicitly
(see Storage Allocation Module of Library Reference Manual).
This file name could be placed anywhere in the specification, even in
another type-pdl file. The order in which such header files are
named within any given pdl file is maintained in the generated
modules.
Operations can be declared by specifying a name, a prototype and a body.
The operations are generic, with the operand and result types depending on
the type of the property for which the generic operation is associated
(see How to declare properties).
If an operation is declared to have the same name as one present in the
library, the user-defined operation will take precedence.
The general form of an operation declaration is given by:
OperationDecl: Gtype Identifier '(' Parameters ')' Text .
Gtype: 'TYPE' / Ctype .
Parameters: Parameter / Parameters ',' Parameter .
Parameter: Gtype Identifier .
TYPE is used to represent the type of the property with which the
operation is associated, while Ctype stands for any valid C type
declarator.
One of the parameters (by convention the first) must be of type
DefTableKey , and must have the name key ; the other parameters
are arbitrary.
Text is any C compound statement, enclosed in {} .
Within this compound statement, certain macros may be used:
PRESENT
- Returns true if the property has an associated value and false if it
does not.
ACCESS
- The return value is the same as that of PRESENT, but ACCESS guarantees
that space has been allocated for the property after invocation.
VALUE
- Current value of the property.
The VALUE macro can be used either as the source of an existing
value or the destination for a new value.
It is defined after an invocation of the ACCESS macro, or whenever
the PRESENT macro returns true.
Here is the declaration of the basic query operation from the library:
TYPE Get(DefTableKey key, TYPE deflt)
{ if (key == NoKey) return deflt;
if (PRESENT) return VALUE;
else return deflt;
}
The type of the value returned by a Get operation is the type of the
associated property (TYPE ), which is also the type of the
deflt parameter.
PRESENT is used to check whether a value is associated with the
property, and if so that value (VALUE ) is returned.
Here is the declaration of the Set operation from the library:
void Set(DefTableKey key, TYPE add, TYPE replace)
{ if (key == NoKey) return;
if (ACCESS) VALUE = replace;
else VALUE = add;
}
No value is returned by a Set operation.
ACCESS is used to check whether a value is associated with the
property, and also to guarantee that space for a value is available.
The available space is then filled appropriately.
Here is the declaration of the Reset operation from the library:
void Reset(DefTableKey key, TYPE val)
{ if (key == NoKey) return;
ACCESS; VALUE = val;
}
No value is returned by a Reset operation.
ACCESS is used to ensure that space is made available to hold
the value of the property. The value is then set to val .
Here is the declaration of the conditional update operation from the library:
void Is(DefTableKey key, TYPE which, TYPE error)
{ if (key == NoKey) return;
if (!ACCESS) VALUE = which;
else if (VALUE != which) VALUE = error;
}
Here is the library operation that guarantees a unique value for a
property:
void Unique(DefTableKey key, TYPE next())
{ if (key == NoKey) return;
if (!ACCESS) VALUE = next();
}
The next parameter is a function that delivers a new value of the
type of the associated property each time it is called.
It will be invoked only when there is currently no value associated with
the property.
The initial state of the definition table consists of a set of
known keys,
some of which may have associated property values.
Each known key is represented by an identifier, which can be used anywhere
that a value of type DefTableKey is required.
The general form of a known key specification is given by:
KnownKey: Identifier PropertyValueList ';' .
PropertyValueList: / '->' PropertyValues .
PropertyValues: PropertyValue // ',' .
PropertyValue: Identifier '=' Text .
Text is any C initializer valid for the type of the property, enclosed
in {} .
It may contain constant identifiers, including identifiers that represent
known keys, regardless of where they are declared.
Each Identifier appearing in a PropertyValue must be declared
elsewhere in the PDL specification (i.e. in some type-pdl file,
see The property definition language).
Here are some valid specifications of known keys:
ErrorType;
IntegerKey -> Def={1}, Type={IntegerType};
IntegerType -> Storage = {4,4,0};
The known key ErrorType has no properties initially, while the known
key IntegerKey has two and the known key IntegerType has one.
All of these properties were declared above
(see The property definition language).
IntegerType is a value of type DefTableKey , and is therefore
a valid initializer for the Type property of IntegerKey .
To see that the initializer given for the Storage property of
IntegerType is valid, one would need to consult the file
`storage.h'.
That file is the interface specification for the data mapping module, and
its name appeared in the declaration of the Storage property.
|