Difference between revisions of "V4 DB Record Instance Syntax"

From EPICSWIKI
(Start of rework using grammar)
Line 1: Line 1:
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.
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.
: '''This page still being written...'''
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.
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:
; symbolBeingDefined:
: otherSymbol
: alternateSymbol 'literal'
= General Symbols =
These symbols are used but not defined in the grammar:
;integerConstant
;floatingConstant
;identifier
: A legal C99 identifier. Note that C99 ''permits'' implementations to allow extended characters to be used in identifiers, but does not ''require'' it, so the use of extended characters may reduce portability and is not recommended.
;stringConstant
: A sequence of characters within double-quotes, using the C99 escape sequence syntax defined below
;escapeSequence
: simpleEscapeSequence
: octalEscapeSequence
: hexadecimalEscapeSequence
: universalCharacterName
;simpleEscapeSequence
: ''one of:'' \' \" \? \\ \a \b \f \n \r \t \v
;octalEscapeSequence
: \''d''
: \''dd''
: \''ddd''
where ''d'' is an octal digit.
;hexadecimalEscapeSequence
: \x''hex-digits''
;universalCharacterName
: \u''hhhh''
: \U''hhhhhhhh''
where ''h'' is a hex digit
The following symbols are like identifier, but may have a different set of legal characters TBD (but which cannot include space).
;recordName
: ''Currently record names may contain <tt>A-Z a-z _ - ; : < > [ ]</tt>. We should probably extend that to include non-ASCII Unicode/UTF-8 characters, but no new ASCII characters''
;linkType
;deviceType
: ''I'd like these two to have to be valid C99 identifiers, but we could probably expand that to add some other ASCII characters if desired. No spaces, brackets or braces though, for syntax reasons.''
We can be generous in what we accept as a boolean value:
;booleanConstant
: booleanTrue
: '"' booleanTrue '"'
: booleanFalse
: '"' booleanFalse '"'
;booleanTrue
: ''any of'' 1 T TRUE True t true Y YES Yes y yes
: booleanFalse
: ''any of'' 0 F FALSE False f false N NO No n no
= Database File =
I need to define these, which are really preprocessor objects:
* comments
* substitution macros
* templates and ports


= Record Instances =
= 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.'''
;recordDefinition
: recordType recordName '=' '{' recordBody '}'


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.
;recordType
: identifier


# comment
;recordBody
  recordType recordName = {
: recordBodyItem
     fieldName = fieldValue;
: recordBody recordBodyItem
    structFieldName = { fieldValue, fieldValue, .. }
 
    structFieldName = { fieldName = fieldValue; .. }
Record definitions will look very similar to a C99 structure definition with initialization in EPICS V4. For example:
    structFieldName = { fieldName = fieldValue, fieldValue, .. }
 
    structFieldName = { structFieldName = { .. } .. }
  ai foo:bar:temperature = {
    arrayFieldName = { arrayValue, arrayValue, .. }
     ...
    arrayFieldName = type { arrayValue, arrayValue, .. }
}
    arrayFieldName = [size, ..] { { arrayValue, arrayValue, .. }, { .. } .. }
 
    arrayFieldName = type [size, ..] { arrayValue, arrayValue, .. }
Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement. Note these statements must all be terminated with a semi-colon (which is different from inside a struct).
    linkFieldName = linkName { linkValue }
 
    deviceFieldName = deviceName { deviceValue }
;recordBodyItem
    info infoName = "infoString";
: 'info' infoName '=' stringConstant ';'
    add varFieldName = {
: fieldName '=' initializer ';'
                  {fieldName,interfaceName,choiceName,{dataStructValue}},
: extraField '=' extraInitializer ';'
                  ...
 
     }
;infoName
: identifier
: stringConstant
 
Info items provide additional configuration data about this record that can be accessed by other software running on the IOC.
 
info savePeriod = "30.0";
info restorePhase = "1";
info "my favourite things" = "raindrops on roses";
 
;fieldName
: identifier
 
;initializer
: constant
: '{' structAssignmentList '}'
: '{' arrayAssignmentList '}'
: arrayType '{' arrayAssignmentList '}'
: '[' arrayCapacity ']' '{' arrayAssignmentList '}'
: arrayType '[' arrayCapacity ']' '{' arrayAssignmentList '}'
: linkType '{' structAssignmentList '}'
: deviceType '{' structAssignmentList '}'
 
;constant
: booleanConstant
: integerConstant
: floatingConstant
: stringConstant
 
The syntax for setting field values depends on the data type represented by fieldName.  Basic types (numeric or string) should need no comment other than to note that numeric values should not be given inside quotes:
 
ai foo:bar:temperature = {
    inputSmoothing = 0.98;
    invalidValue = 1000;
     units = "Celcius";
     ...
     ...
  }
  }


where
;structAssignmentList
: initializerList
: fieldName '=' initializerList
: structAssignmentList ';' fieldName '=' initializerList
 
;initializerList
: initializer
: initializerList ',' initializer
 
Initializers for a structure field look similar to a nested record body, but the rules are slightly different:
* You can give a series of values for adjacent items using a simple comma-separated list (for a record body, you ''must'' name each field)
* Semi-colons are required between a value and a following named item.
 
For example:
 
ai foo:bar:temperature = {
    linearConvert = {
        mode = "Linear";
        low = -12.5, 133.5
    };
    displayLimit = { 0, 100 };
    ...
}


; <tt>recordType</tt>
: The name of the record type
; <tt>recordName</tt>
: 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 <tt>A-Z a-z _ - ; : < > [ ]</tt>. We should probably extend that to include non-ASCII Unicode/UTF-8 characters, but no new ASCII characters''
; <tt>info infoName</tt>
: Sets additional configuration information stored with the record.
; <tt>fieldName</tt>
: The field name.
; <tt>type</tt>
: One of the types <tt>bool</tt>,...,<tt>string</tt>. This is only specified if the record definition did not specify a type.
; <tt>size, ..</tt>
: 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.
; <tt>choiceName</tt>
: This is  for <tt>struct</tt>, <tt>link</tt>, and <tt>device</tt> fields. <tt>choiceName</tt> is a choice defined in a <tt>struct</tt>, <tt>link</tt>, or <tt>device</tt> definition.
; <tt>fieldValue</tt>
: The syntax depends on the field type. The details are described next..


== fieldValue ==
;arrayAssignmentList
: initializerList
: '[' integerConstant ']' '=' initializerList
: arrayAssignmentList ';' '[' integerConstant ']' '=' initializerList


The format for <tt>fieldValue</tt> depends of the field type.
;arrayType
: 'bool'
: 'int16'
: 'uint16'
: 'int32'
: 'uint32'
: 'float32'
: 'float64'
: 'octet'
: 'string'


; Single Item Field types
;arrayCapacity
: The following just have a single value: <tt>int16, uint16, int32, uint32, uint32, float32, float64, octet, string, enum, menu</tt>
: integerConstant
: For example
: integerConstant ',' arrayCapacity
        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.
:<tt>varFields</tt> 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.
: <tt>varFields</tt>is defined in <tt>iocRecord</tt> 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.

Revision as of 23:17, 19 May 2005

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.

This page still being written...

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.

This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:

symbolBeingDefined
otherSymbol
alternateSymbol 'literal'

General Symbols

These symbols are used but not defined in the grammar:

integerConstant
floatingConstant
identifier
A legal C99 identifier. Note that C99 permits implementations to allow extended characters to be used in identifiers, but does not require it, so the use of extended characters may reduce portability and is not recommended.
stringConstant
A sequence of characters within double-quotes, using the C99 escape sequence syntax defined below
escapeSequence
simpleEscapeSequence
octalEscapeSequence
hexadecimalEscapeSequence
universalCharacterName
simpleEscapeSequence
one of: \' \" \? \\ \a \b \f \n \r \t \v
octalEscapeSequence
\d
\dd
\ddd

where d is an octal digit.

hexadecimalEscapeSequence
\xhex-digits
universalCharacterName
\uhhhh
\Uhhhhhhhh

where h is a hex digit

The following symbols are like identifier, but may have a different set of legal characters TBD (but which cannot include space).

recordName
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
linkType
deviceType
I'd like these two to have to be valid C99 identifiers, but we could probably expand that to add some other ASCII characters if desired. No spaces, brackets or braces though, for syntax reasons.

We can be generous in what we accept as a boolean value:

booleanConstant
booleanTrue
'"' booleanTrue '"'
booleanFalse
'"' booleanFalse '"'
booleanTrue
any of 1 T TRUE True t true Y YES Yes y yes
booleanFalse
any of 0 F FALSE False f false N NO No n no


Database File

I need to define these, which are really preprocessor objects:

  • comments
  • substitution macros
  • templates and ports


Record Instances

recordDefinition
recordType recordName '=' '{' recordBody '}'
recordType
identifier
recordBody
recordBodyItem
recordBody recordBodyItem

Record definitions will look very similar to a C99 structure definition with initialization in EPICS V4. For example:

ai foo:bar:temperature = {
    ...
}

Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement. Note these statements must all be terminated with a semi-colon (which is different from inside a struct).

recordBodyItem
'info' infoName '=' stringConstant ';'
fieldName '=' initializer ';'
extraField '=' extraInitializer ';'
infoName
identifier
stringConstant

Info items provide additional configuration data about this record that can be accessed by other software running on the IOC.

info savePeriod = "30.0";
info restorePhase = "1";
info "my favourite things" = "raindrops on roses";
fieldName
identifier
initializer
constant
'{' structAssignmentList '}'
'{' arrayAssignmentList '}'
arrayType '{' arrayAssignmentList '}'
'[' arrayCapacity ']' '{' arrayAssignmentList '}'
arrayType '[' arrayCapacity ']' '{' arrayAssignmentList '}'
linkType '{' structAssignmentList '}'
deviceType '{' structAssignmentList '}'
constant
booleanConstant
integerConstant
floatingConstant
stringConstant

The syntax for setting field values depends on the data type represented by fieldName. Basic types (numeric or string) should need no comment other than to note that numeric values should not be given inside quotes:

ai foo:bar:temperature = {
    inputSmoothing = 0.98;
    invalidValue = 1000;
    units = "Celcius";
    ...
}
structAssignmentList
initializerList
fieldName '=' initializerList
structAssignmentList ';' fieldName '=' initializerList
initializerList
initializer
initializerList ',' initializer

Initializers for a structure field look similar to a nested record body, but the rules are slightly different:

  • You can give a series of values for adjacent items using a simple comma-separated list (for a record body, you must name each field)
  • Semi-colons are required between a value and a following named item.

For example:

ai foo:bar:temperature = {
    linearConvert = {
        mode = "Linear";
        low = -12.5, 133.5
    };
    displayLimit = { 0, 100 };
    ...
}


arrayAssignmentList
initializerList
'[' integerConstant ']' '=' initializerList
arrayAssignmentList ';' '[' integerConstant ']' '=' initializerList
arrayType
'bool'
'int16'
'uint16'
'int32'
'uint32'
'float32'
'float64'
'octet'
'string'
arrayCapacity
integerConstant
integerConstant ',' arrayCapacity