V4 DB Record Instance Syntax

From EPICSWIKI

The syntax used for record instances has to change in EPICS V4, since we now have to support structured data. While it would have been possible to modify the V3 syntax to allow for this, a complete redesign of the syntax has been done to help improve parsing, and to provide commonality between the syntax of a DB file and the string representation of structured data values passed through Channel Access.

Record Instances

I'm changing some of this, and am going to rework the description into a BNF grammar; note that I've already changed some of Marty's original text below, but not all of it.

A record instance loaded from a DB file has the syntax shown below, which was derived from the syntax for C99 initializers. Spaces are significant when used as word separators or within quoted strings, not otherwise.

# comment
recordType recordName = {
    fieldName = fieldValue;
    structFieldName = { fieldValue, fieldValue, .. }
    structFieldName = { fieldName = fieldValue; .. }
    structFieldName = { fieldName = fieldValue, fieldValue, .. }
    structFieldName = { structFieldName = { .. } .. }
    arrayFieldName = { arrayValue, arrayValue, .. }
    arrayFieldName = type { arrayValue, arrayValue, .. }
    arrayFieldName = [size, ..] { { arrayValue, arrayValue, .. }, { .. } .. }
    arrayFieldName = type [size, ..] { arrayValue, arrayValue, .. }
    linkFieldName = linkName { linkValue }
    deviceFieldName = deviceName { deviceValue }
    info infoName = "infoString";
    add varFieldName = {
                 {fieldName,interfaceName,choiceName,{dataStructValue}},
                 ...
    }
    ...
}

where

recordType
The name of the record type
recordName
The name of the record instance
Q: What restrictions will we place on record instance name? Can this contain non-ascii characters? That is will UTF-8 instance names be supported?
Currently record names may contain A-Z a-z _ - ; : < > [ ]. We should probably extend that to include non-ASCII Unicode/UTF-8 characters, but no new ASCII characters
info infoName
Sets additional configuration information stored with the record.
fieldName
The field name.
type
One of the types bool,...,string. This is only specified if the record definition did not specify a type.
size, ..
The size of an array in each of its dimensions. This can only be specified if the record type definition does not specify the number of dimensions or their sizes. It takes the format of a comma-separated list of integers, one for each dimension in turn. The number of dimensions must agree with what the record type defines. For example if the record defines a field as array(type[]) then only one dimension can be specified. If a field is defined as just array(<type>) than the record instance determines both the number of dimensions and their sizes.
choiceName
This is for struct, link, and device fields. choiceName is a choice defined in a struct, link, or device definition.
fieldValue
The syntax depends on the field type. The details are described next..

fieldValue

The format for fieldValue depends of the field type.

Single Item Field types
The following just have a single value: int16, uint16, int32, uint32, uint32, float32, float64, octet, string, enum, menu
For example
        value = {"1.0"} #Field Definition is float64
        scan = {"1 second"} #Field Definition is menu
        description = {"This is a description"} #Field Definition is string
        junk = {"\x01\x02"} #Field Definition is array(octet[])
Structure fields
The syntax follows the C99 syntax for initializing structures. Lets give some examples.
Assume that the following definitions have been made in a dbd file:
        struct(point) {
            field(x,float64)
            field(y,float64)
            field(z,float64)
        }
        ...
        struct (pointdes) {
            field(des,string)
            field(point,struct(point))
        }
        ...
        record(example) extends iocRecord {
        ...
            field(value,struct(pointdes))
        ...
        }
Then the following are some of the valid ways to initialize the val field of an instance of an example record. They all do the same initialization.
        value = {"this is the value for val.des",{0.0,1.0,2.0}}
or
        value = {des = "this is the value for val.des",
                 {x = 0.0, y =1.0, z = 2.0}}
or
        value = {"this is the value for val.des", {y =1.0, z = 2.0}}
Array fields
The syntax for array fields uses the C99 array initialization syntax. Some examples:
        oneD = [3] {1.0,2.0,3.0}
        #The following creates a 3x3 identity matrix
        twoD = [3,3] { {1},{[1] = 1}, {[2] = 1}}
        #The following initializes an arbitrary type, arbitrary dim matrix
        anyDanyT = int16[3,3] { {1},{[1] = 1}, {[2] = 1}}
link or device fields
The syntax is:
        field = choiceName {structValue}
For link choiceName is one of the choices from link definitions that have compatible directions. For device choiceName is one of the choices from link and device definitions that have compatible directions. structValue is like the value for struct fields where the structure is the dataStruct from the link or device definition which choiceName selected.
varFields contains user defined fields, i.e. extra fields for the record that are defined for record instances. Each has associated data and code. When a record is processed the associated code is invoked just before alarm and monitors are processed.
varFieldsis defined in iocRecord as follows:
       struct(varFields) {
           field(fieldName,string)
           field(interfaceName,string) 
       }
       ...
       record(iocRecord) {
           ...
           field(varFields,array(struct(varFields)[]))
           ...
       }
As an example assume that the following has been defined:
       struct (computeAverageData) {
           field(source,string) #name of field that is to be averaged
           ...
       }
       interface(computeAverageIface,computeAverage,computeAverageData)
Then a record instance could contain:
       varFields = [1] {average,computeAverage,value}
This tells computeAverageIface to compute the average of the value field. The result will be stored in user defined field average.