Difference between revisions of "V4 DBD Statement Syntax"
(Added template structs and methods) |
MartyKraimer (talk | contribs) |
||
Line 1: | Line 1: | ||
DBD Statement Syntax Sept 16 2005 | |||
= Overview = | |||
This document presents the syntax for V4 database definition files. | |||
<center> | |||
= General Statements = | = General Statements = | ||
</center> | |||
== include == | == include == | ||
Line 56: | Line 61: | ||
} | } | ||
<center> | |||
= Structures, Record types, Fields and Views = | = Structures, Record types, Fields and Views = | ||
</center> | |||
Structures and record types have significant commonality in that they both define a data structure type containing fields. The main difference is that you can't create or populate an instance of a structure outside of a record; only records can appear at the very top level. Record types also define views of the record, which is not possible for a structure | Structures and record types have significant commonality in that they both define a data structure type containing fields. The main difference is that you can't create or populate an instance of a structure outside of a record; only records can appear at the very top level. Record types also define views of the record, which is not possible for a structure. | ||
== struct == | == struct == | ||
Line 69: | Line 76: | ||
... | ... | ||
} | } | ||
... | ... | ||
} | } | ||
Line 84: | Line 89: | ||
; <tt>fieldAttribute</tt> and <tt>attributeValue</tt> | ; <tt>fieldAttribute</tt> and <tt>attributeValue</tt> | ||
: See [[#fieldAttribute|fieldAttribute]] below. | : See [[#fieldAttribute|fieldAttribute]] below. | ||
== record == | == record == | ||
Line 161: | Line 135: | ||
=== Basic types: Boolean, numerics, octet, and string === | === Basic types: Boolean, numerics, octet, and string === | ||
The following field types have no arguments: <tt>bool</tt>, <tt>int16 | The following field types have no arguments: <tt>bool</tt>, <tt>int16</tt>, <tt>int32</tt>, <tt>int64</tt>, <tt>float32</tt>, <tt>float64</tt>, <tt>octet</tt>, and <tt>string</tt>. | ||
Examples: | Examples: | ||
Line 173: | Line 147: | ||
enum(fieldName) | enum(fieldName) | ||
where fieldName is the name of another field in the same record that must be of type <tt>array(string[] | where fieldName is the name of another field in the same record that must be of type <tt>array(string[])</tt>. The values in this other field at runtime define the available choice strings for the enum field. | ||
Examples: | Examples: | ||
Line 179: | Line 153: | ||
field(choices, array(string[]) | field(choices, array(string[]) | ||
field(value, enum(choices)) | field(value, enum(choices)) | ||
=== menu === | === menu === | ||
Line 202: | Line 171: | ||
where <tt>structName</tt> is the name of a struct which must have been previously defined. | where <tt>structName</tt> is the name of a struct which must have been previously defined. | ||
Example: | Example: | ||
Line 245: | Line 212: | ||
: <tt>array([,])</tt> | : <tt>array([,])</tt> | ||
* <tt>arrayType</tt> may be any fieldType except | * <tt>arrayType</tt> may be any fieldType except <tt>device</tt> or <tt>array</tt>, or may be omitted completely in which case the data type stored is determined by record instance. If the record instance defines the type, it can only be one of the types listed above under [[#Basic types: Boolean, numerics, octet, and string|Basic types]] | ||
* <tt>capacity</tt> is the array's size in the relevent dimension, and must be specified for all dimensions or for none. If not specified by the record type, the record instance determines an array's dimensionality and size. | * <tt>capacity</tt> is the array's size in the relevent dimension, and must be specified for all dimensions or for none. If not specified by the record type, the record instance determines an array's dimensionality and size. | ||
Line 252: | Line 219: | ||
field(VAL2D,array(float64[,])) #2d array with arbitrary capacities | field(VAL2D,array(float64[,])) #2d array with arbitrary capacities | ||
field(anyTypeAnyD,array()) #arbitrary type,number of dimensions, and capacities | field(anyTypeAnyD,array()) #arbitrary type,number of dimensions, and capacities | ||
=== link and device === | === link and device === | ||
Line 292: | Line 231: | ||
link(linkDirection) | link(linkDirection) | ||
device(linkDirection, | device(linkDirection, deviceInterfaceName) | ||
where <tt>linkDirection</tt> is <tt>none</tt>, <tt>in</tt>, <tt>out</tt>, <tt> | where <tt>linkDirection</tt> is <tt>none</tt>, <tt>in</tt>, <tt>out</tt>, <tt>process</tt>, or <tt>inout</tt>. The direction <tt>none</tt> means there is no direction associated with this interface. For <tt>inout</tt> the direction is determined by the particular <tt>link</tt> or <tt>device</tt> that the record instance selects. | ||
<tt>deviceInterfaceName</tt> selects compatible device support fom the DBD | |||
<tt>device</tt> definitions. | |||
Examples: | Examples: | ||
field(disableLink, link(in)) | field(disableLink, link(in)) | ||
field( | field(process, link(process)) | ||
field(inp, device(in, digitalIO)) | field(inp, device(in, digitalIO)) | ||
Line 313: | Line 254: | ||
dynamic(yesNo) | dynamic(yesNo) | ||
asl(securityLevel) | asl(securityLevel) | ||
link(yesNo) | |||
'''Marty thinks we should get rid of these two:''' | '''Marty thinks we should get rid of these two:''' | ||
Line 340: | Line 282: | ||
; <tt>asl(securityLevel)</tt> | ; <tt>asl(securityLevel)</tt> | ||
: Channel Access security level for this field, 0 or 1. Takes the value 1 if not specified. | : Channel Access security level for this field, 0 or 1. Takes the value 1 if not specified. | ||
; <tt>link</tt> | |||
: This is only valid for string fields. It signifies the the field is the name of an external link. This is for use by Database Configuration Tools. | |||
''These attributes may disappear, see comment above:'' | ''These attributes may disappear, see comment above:'' | ||
Line 409: | Line 354: | ||
} | } | ||
<center> | |||
= link and device = | = link and device = | ||
</center> | |||
: '''Can we do something to define the interfaces here by using struct methods and member function pointers, rather than making up our own separate interface code?''' | : '''Can we do something to define the interfaces here by using struct methods and member function pointers, rather than making up our own separate interface code?''' | ||
Line 419: | Line 366: | ||
The syntax for these is: | The syntax for these is: | ||
link(dir, choiceName, | link(dir, choiceName, dataStructName) | ||
device(dir, choiceName, | device(dir, choiceName, deviceInterfaceName, dataStructName) | ||
where | where | ||
; <tt> | ; <tt>deviceInterfaceName</tt> | ||
: The name of an interface via which record support communicates with device support. | : The name of an interface via which record support communicates with device support. | ||
Line 431: | Line 378: | ||
; <tt>dir</tt> | ; <tt>dir</tt> | ||
: Must be one of <tt>none</tt>,<tt>in</tt>,<tt>out</tt>,<tt> | : Must be one of <tt>none</tt>,<tt>in</tt>,<tt>out</tt>,<tt>process</tt>, or <tt>inout</tt>. Compatible checks are made to match the interface with a field. | ||
: '''Q: What are the rules?''' | : '''Q: What are the rules?''' | ||
:: ''It certainly doesn't seem to make sense to have a none or inout link for instance.'' | :: ''It certainly doesn't seem to make sense to have a none or inout link for instance.'' |
Revision as of 15:37, 16 September 2005
DBD Statement Syntax Sept 16 2005
Overview
This document presents the syntax for V4 database definition files.
General Statements
include
include "filename"
where
- filename
- must be a valid filename
The file system search path that will be used to look for the file is determined by the build system, and cannot be modified by the DBD file itself.
Include statements can be used at the top level, or inside the braces of a menu, struct or record definition.
# comment
# anything
Anything on a line after a # character is a comment, and will be ignored. Comments may appear on a line by themselves, or at the end of another statement. They may not appear inside the parentheses belonging to another statement, but they are permitted inside braces. Inside a single- or double- quoted string the # character has no special meaning.
A menu is an enumerated type where the choice strings are defined once for each IOC. Menus are defined like this:
menu(menuName) { choice(choiceName, "choiceValue") ... }
where
- menuName
- Must be a valid, unique C identifier.
- choiceName
- Must be a valid, unique C identifier. By convention, every choiceName should start with the menuName it belongs to. These names are only available to C/C++ source code using the header file generated from the menu definition; they are not stored in the IOC itself.
- choiceValue
- Can be any UTF-8 compatible string, which should be unique within the context of this menu.
In general menus should only be definable once, in the DBD file (first definition seen wins in the event of duplicates, give a warning for duplicates and error if subsequent definition is different). However we may want to include a syntax that allows specific menu definitions to be extended at database load time.
Example:
menu(menuScan) { choice(menuScanPassive, "Passive") choice(menuScanEvent, "Event") choice(menuScanInterrupt, "Interrupt") choice(menuScan10second, "10 second") choice(menuScan5second, "5 second") choice(menuScan2second, "2 second") choice(menuScan1second, "1 second") choice(menuScan_5second, ".5 second") choice(menuScan_2second, ".2 second") choice(menuScan_1second, ".1 second") }
Structures, Record types, Fields and Views
Structures and record types have significant commonality in that they both define a data structure type containing fields. The main difference is that you can't create or populate an instance of a structure outside of a record; only records can appear at the very top level. Record types also define views of the record, which is not possible for a structure.
struct
A structure is defined as follows:
struct(name) { field(fieldName, fieldType) { fieldAttribute(attributeValue) ... } ... }
where
- name
- The structure name must be a valid, unique C identifier.
- fieldName
- Must be a valid C identifier, unique within the context of this particular structure.
- fieldType
- See fieldType below.
- fieldAttribute and attributeValue
- See fieldAttribute below.
record
A record type is defined as follows:
include "dbCommon.dbd" record(name) extends iocRecord { field(fieldName, fieldType) { fieldAttribute(attributeValue) ... } ... view(viewName) { property(propName, fieldPath) ... } ... }
- name
- The record type name. It must be a valid, unique C identifier.
- extends iocRecord
- This states that the record type extends the set of fields defined in iocRecord. It should be permissable to name other record types instead of iocRecord here, as long as the inheritance tree starts at iocRecord. Inheritance from multiple record types is not supported; you can only have one extends phrase.
- fieldName
- Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).
- fieldType
- See fieldType below.
- fieldAttribute and attributeValue
- See fieldAttribute below.
- viewName, propName and fieldPath
- See Views of a record below.
fieldType
Both struct and record define a field as:
field(fieldName, fieldType) { fieldAttribute(attributeValue) ... }
The syntax for fieldType depends of the field type. For the more complex types the field definition needs additional information to be provided, which is given inside parentheses following the type name.
Basic types: Boolean, numerics, octet, and string
The following field types have no arguments: bool, int16, int32, int64, float32, float64, octet, and string.
Examples: field(description,string) field(value,float64)
enum
An enum field takes one argument after the type name:
enum(fieldName)
where fieldName is the name of another field in the same record that must be of type array(string[]). The values in this other field at runtime define the available choice strings for the enum field.
Examples:
field(choices, array(string[]) field(value, enum(choices))
A menu field is defined like this: menu(menuName)
where menuName is the name of the menu.
Example: field(scan, menu(menuScan))
struct
A struct field is declared using the type name struct(structName)
where structName is the name of a struct which must have been previously defined.
Example: struct(point, Coordinate) { field(x, Coordinate) field(y, Coordinate) field(z, Coordinate) } ... record(haspoint) extends iocRecord { ... field(point, struct(point, float64)) }array
An array field uses definitions like these:
- 1-dimensional array
- array(arrayType[capacity])
- multi-dimensional array
- array(arrayType[capacityX, capacityY, ...])
- arbitrarily dimensioned array
- array(arrayType)
- 1-dimensional array of unknown size
- array(arrayType[])
- 3-dimensional array of unknown size
- array(arrayType[,,])
- 1-dimensional array of unknown type
- array([capacity])
- multi-dimensional array of unknown type
- array([capacityX, capacityY, ...])
- arbitrarily dimensioned array of unknown type
- array()
- 1-dimensional array of unknown type or size
- array([])
- 2-dimensional array of unknown type or size
- array([,])
- arrayType may be any fieldType except device or array, or may be omitted completely in which case the data type stored is determined by record instance. If the record instance defines the type, it can only be one of the types listed above under Basic types
- capacity is the array's size in the relevent dimension, and must be specified for all dimensions or for none. If not specified by the record type, the record instance determines an array's dimensionality and size.
Examples: field(VAL1D,array(float64[])) #1d array with arbitrary capacity field(VAL2D,array(float64[,])) #2d array with arbitrary capacities field(anyTypeAnyD,array()) #arbitrary type,number of dimensions, and capacities
link and device
These field types that can get or put data from/to some source outside of the record. Link fields replace the DBF_INLINK and DBF_OUTLINK fields from EPICS V3, other than INP or OUT which were special. A device field replaces the INP or OUT and DTYP fields from EPICS V3.
A link field's choices come from link definitions, and a device field from device definitions - see the link and device section below for more details. The main difference between links and devices is that iocCore and the record support communicate with all the link implementations via a standard link support interface, but communication with device support uses an explicitly named interface.
Q: Does the device also have to implement some standard device interface, and if yes how do we find that? If not, only the record type can talk to the device, so it has to get called to change a device address.
The syntax is:
link(linkDirection) device(linkDirection, deviceInterfaceName)
where linkDirection is none, in, out, process, or inout. The direction none means there is no direction associated with this interface. For inout the direction is determined by the particular link or device that the record instance selects. deviceInterfaceName selects compatible device support fom the DBD device definitions.
Examples: field(disableLink, link(in)) field(process, link(process)) field(inp, device(in, digitalIO))
fieldAttribute
Each field definition has several associated attributes, the values of which are set like this:
default("fieldValue") readonly(yesNo) design(yesNo) special(yesNo) dynamic(yesNo) asl(securityLevel) link(yesNo)
Marty thinks we should get rid of these two:
prompt("promptString") group("promptGroup")
I am thinking about combining readonly and design into a single attribute called access, which takes one of four choices: design (the default), runtime, readonly, or none.
The attribute parameter values have the following meanings:
- default("fieldValue")
- Default value for an instance of this field, using the record instance value syntax. If a default is not specified, the field will initialize to all zero bits.
- If the field is itself a structure, the default value for the instance of the whole structure can override default values declared for individual fields inside that structure. This can occur at multiple levels.
- readonly(yesNo)
- Can this field be modified via channel access or database links? Takes the value No if not specified.
- design(yesNo)
- Should a Database Configuration Tool allow the field to be configured at design time? If No, values for the field cannot be set when loading record instance data at startup. Takes the value Yes if not specified.
- special(yesNo)
- Does the record have to take special action if the field is modified? If this is Yes, the record types special processing will be invoked to actually change the field value, which will allow it to perform value checks or additional processing. Takes the value No if not specified.
- dynamic(yesNo)
- Can the field change as a result of record processing? If Yes, then changes will be posted to channel access automatically. If No, only DB or CA puts can change the field, and these post monitors automatically.
- asl(securityLevel)
- Channel Access security level for this field, 0 or 1. Takes the value 1 if not specified.
- link
- This is only valid for string fields. It signifies the the field is the name of an external link. This is for use by Database Configuration Tools.
These attributes may disappear, see comment above:
- prompt("promptString")
- A description of this field for the database designer, this string will be displayed by a Database Configuration Tool. Empty if not specified. Not used within the IOC.
- group("promptGroup")
- A name that can be used by a Database Configuration Tool to group similar or related fields together. Empty if not specified. Not used within the IOC.
view
There needs to be more than one way to look at a record remotely (via Channel Access or some other similar network protocol). Often we just want to get the contents of the value field and some metadata associated with that value, but there are often several fields which can share metadata - engineering units for example. We can't do metadata using structures because that would mean replicating this metadata, so we add a level of indirection to allow us to group fields together.
A view of a record provides a hierarchical mapping of some of the record's fields from a named Data Access property catalog that can be reached using Channel Access. Records automatically get a view named "field" that provides direct access to the individual public fields of the record, with no metadata. Beyond that, record types can declare additional hierarchical views and define the fields that appear in them inside the DBD file. The first view defined for a record type is used as its default view (if no views are defined, the field view will become the default view; view parameters may not be permitted).
A simple view looks like this:
view(viewName) { property(propName) { property(propName, fieldPath) ... } property(propName, fieldPath) ... }
- viewName
- The view name must be a valid C identifier, which must be unique in the context of the particular record type.
- propName
- A Data Access property name, which must be a valid C identifier.
- fieldPath
- The path to a field in this record type. To use a field inside a structure field, give the full path to that field: controlLimit.upper for example.
- If fieldPath resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.
- The fieldPath may be omitted as long as there is a subordinate property catalog below this property.
Example:
record(ao) extends iocRecord { field(value, float64) { ... } field(outValue, float64) { ... } field(rawValue, int32) { ... } field(units, string) { ... } field(displayLimit, struct(displayLimit)) { ... } ... view(value) property(value, value) { property(units, units) property(timeStamp, time) property(alarmSeverity, alarmSeverity) property(alarmStatus, alarmStatus) property(displayLimit, displayLimit) } } view(outValue) property(value, outValue) { property(units, units) property(timeStamp, time) property(alarmSeverity, alarmSeverity) property(alarmStatus, alarmStatus) } } view(rawValue) property(value, rawValue) { property(timeStamp, time) } } ... }
link and device
- Can we do something to define the interfaces here by using struct methods and member function pointers, rather than making up our own separate interface code?
A link statement describes an implementation of the generic link interface, which will be available for use in matching link field instances.
A device statement describes an implementation of a device choice for device fields.
The syntax for these is:
link(dir, choiceName, dataStructName) device(dir, choiceName, deviceInterfaceName, dataStructName)
where
- deviceInterfaceName
- The name of an interface via which record support communicates with device support.
- choiceName
- UTF-8 string that describes the choice
- dir
- Must be one of none,in,out,process, or inout. Compatible checks are made to match the interface with a field.
- Q: What are the rules?
- It certainly doesn't seem to make sense to have a none or inout link for instance.
- dataStructName
- The name of a struct that the interface understands. This interface can contain data and configuration information. The struct must be defined before record instances can be created that assign values to it.
- Need to rewrite this paragraph to clarify.