Difference between revisions of "V4 DBD Statement Syntax"
(→array) |
|||
Line 56: | Line 56: | ||
= Structures, Record types and | = 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 | 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 92: | Line 92: | ||
field(fieldName, fieldType) { | field(fieldName, fieldType) { | ||
fieldAttribute | fieldAttribute | ||
... | |||
} | |||
... | |||
view(viewName) { | |||
property(propName, fieldName) | |||
... | ... | ||
} | } | ||
Line 107: | Line 112: | ||
; <tt>fieldAttribute</tt> | ; <tt>fieldAttribute</tt> | ||
: See [[#fieldAttribute|fieldAttribute]] below. | : See [[#fieldAttribute|fieldAttribute]] below. | ||
; <tt>viewName</tt> and <tt>propName</tt> | |||
: See [[#Views of a record|Views of a record]] below. | |||
== fieldType == | == fieldType == | ||
Line 118: | Line 124: | ||
The syntax for <tt>fieldType</tt> 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. | The syntax for <tt>fieldType</tt> 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. | ||
<blockquote> | <blockquote> | ||
Line 212: | Line 219: | ||
</blockquote> | </blockquote> | ||
== fieldAttribute == | == fieldAttribute == | ||
Line 224: | Line 230: | ||
design(yesNo) | design(yesNo) | ||
special(yesNo) | special(yesNo) | ||
dynamic(yesNo) | |||
asl(securityLevel) | asl(securityLevel) | ||
Line 237: | Line 244: | ||
; <tt>group("promptGroup")</tt> | ; <tt>group("promptGroup")</tt> | ||
: 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. | : 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. | ||
; <tt>readonly(yesNo)</tt> | |||
: Can this field be modified via channel access or database links? Takes the value No if not specified. | |||
: '''Q: Is this really an attribute of the view?''' No, this controls all access to the field, but a view may declare some fields/properties to be readonly that are modifyable through other views. | |||
; <tt>design(yesNo)</tt> | ; <tt>design(yesNo)</tt> | ||
Line 244: | Line 255: | ||
: 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. | : 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. | ||
; <tt> | ; <tt>dynamic(yesNo)</tt> | ||
: Can | : 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. | ||
; <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. | ||
: '''Q: Is this really an attribute of the view?''' | : '''Q: Is this really an attribute of the view?''' Not sure, it might be an attribute of both - this entry provides the ASL for the standard field view, other views may need to change it. | ||
== Views of a record == | |||
There needs to be more than one way to look at a record remotely (via Channel Access). Often we just want to get its value field and some metadata associated with that value, but there may be more than one value field which shares metadata with others. Therefore we can't do metadata using structures. | |||
A view of a record provides a mapping between some of the record's fields and a Data Access property catalog that can be reached using Channel Access. All records have a view named "field" that provides direct access to the individual public fields of the record, with no metadata. Record types can declare additional views and define which fields appear under which property names. | |||
A view looks like this: | |||
view(viewName) { | |||
property(propName, fieldName) | |||
... | |||
} | |||
; <tt>viewName</tt> | |||
: The view name must be a valid C identifier, which must be unique in the context of the particular record type. | |||
; <tt>propName</tt> | |||
: A Data Access property name, which must be a valid C identifier. | |||
; <tt>fieldName</tt> | |||
: The name of a field in this record type. To use a field inside a structure field, give the full path to that field: <tt>controlLimit.upper</tt> for example. If the field named is a structure, a property catalog containing the whole structure will be sent, with property names matching the structure field names. | |||
Example: | |||
record(ao) extends iocRecord { | |||
field(value, float64) { ... } | |||
field(units, string) { ... } | |||
field(displayLimit, struct(displayLimit)) { ... } | |||
view(value) { | |||
property(value, value) | |||
property(timeStamp, time) | |||
property(alarmSeverity, alarmSeverity) | |||
property(alarmStatus, alarmStatus) | |||
property(displayLimit, displayLimit) | |||
property(units, units) | |||
} | |||
view(outValue) { | |||
property(outValue, outValue) | |||
property(timeStamp, time) | |||
property(alarmSeverity, alarmSeverity) | |||
property(alarmStatus, alarmStatus) | |||
property(displayLimit, displayLimit) | |||
property(units, units) | |||
} | |||
} |
Revision as of 22:29, 12 May 2005
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 external to the DBD file itself.
Question: Where is this allowed?
# 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.
- choiceValue
- Can be any UTF-8 compatible string
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 ... } ... }
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
- See fieldAttribute below.
record
A record type is defined as follows:
include "dbCommon.dbd" record(name) extends iocRecord { field(fieldName, fieldType) { fieldAttribute ... } ... view(viewName) { property(propName, fieldName) ... } ... }
- 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. Only single inheritance is supported.
- 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
- See fieldAttribute below.
- viewName and propName
- See Views of a record below.
fieldType
Both struct and record define a field as:
field(fieldName, fieldType) { fieldAttribute ... }
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.
Numeric types, octet, and string
The following field types have no arguments: bool, int16, uint16, int32, uint32, int64, uint54, float32, float64, octet, and string.
Examples: field(description,string) field(value,float64)
enum
An enum field needs no arguments after the type name, but internally it does have an implicit definition: struct() { field(index,int16) field(choice,array(string[]) }
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 has the definition: struct(structName)
where structName is the name of a struct which must have been previously defined.
Example: struct(point) { field(x, float64) field(y, float64) field(z, float64) } ... record(haspoint) extends iocRecord { ... field(point, struct(point)) }
array
An array has one of the following definitions:
- array(arrayType>[capacity])
- 1-dimensional array/vector
- array(arrayType[capacityX, capacityY, ...])
- multi-dimensional array
- array(arrayType)
- arbitrary dimensional 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. Q: If the record instance defines the type, is it limited further in what types it can pick?
- capacity is the array's size in each 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 capacities.
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
private
This is to allow "private" fields, i.e. fields not meant for use by database or channel access. The syntax is: private("typename") where typename is a valid C typename.
Example: field(asp, private("void *"))
The typename must not include a field name; the member name in the generated include file is taken from the field definition, and will be appended to the typename provided. This may require that a typedef be added if a suitable one does not already exist. WHERE DO WE FIND THE TYPE DEFINITION?
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 obtains it's choices from link definitions. A device field obtains it's choices from device definitions. The main difference between link and device is that record support communicates with link support via a standard interface, but with device support via an interface that can be different for different record types.
The syntax is: link(linkDirection) device(linkDirection,deviceInterface) where linkDirection is null, in, out, fwd, or inout. If null or inout the direction is determined by the link or device a record instance selects.
Examples: field(disableLink,link(in)) field(flnk,link(fwd)) field(inp,device(in,digitalIO))
fieldAttribute
Each field definition has various associated attributes, which look like this:
default("fieldValue") prompt("promptString") group("promptGroup") readonly(yesNo) design(yesNo) special(yesNo) dynamic(yesNo) asl(securityLevel)
The attribute arguments 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.
- 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.
- readonly(yesNo)
- Can this field be modified via channel access or database links? Takes the value No if not specified.
- Q: Is this really an attribute of the view? No, this controls all access to the field, but a view may declare some fields/properties to be readonly that are modifyable through other views.
- 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.
- Q: Is this really an attribute of the view? Not sure, it might be an attribute of both - this entry provides the ASL for the standard field view, other views may need to change it.
Views of a record
There needs to be more than one way to look at a record remotely (via Channel Access). Often we just want to get its value field and some metadata associated with that value, but there may be more than one value field which shares metadata with others. Therefore we can't do metadata using structures.
A view of a record provides a mapping between some of the record's fields and a Data Access property catalog that can be reached using Channel Access. All records have a view named "field" that provides direct access to the individual public fields of the record, with no metadata. Record types can declare additional views and define which fields appear under which property names.
A view looks like this:
view(viewName) { property(propName, fieldName) ... }
- 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.
- fieldName
- The name of 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 the field named is a structure, a property catalog containing the whole structure will be sent, with property names matching the structure field names.
Example:
record(ao) extends iocRecord { field(value, float64) { ... } field(units, string) { ... } field(displayLimit, struct(displayLimit)) { ... } view(value) { property(value, value) property(timeStamp, time) property(alarmSeverity, alarmSeverity) property(alarmStatus, alarmStatus) property(displayLimit, displayLimit) property(units, units) } view(outValue) { property(outValue, outValue) property(timeStamp, time) property(alarmSeverity, alarmSeverity) property(alarmStatus, alarmStatus) property(displayLimit, displayLimit) property(units, units) } }