Difference between revisions of "V4 DB Record Instance Syntax"
(Headings, more examples) |
|||
Line 2: | Line 2: | ||
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. | ||
= Document Conventions = | |||
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows: | This syntax is presented below in the form of a grammar. The conventions I'm using are as follows: | ||
Line 7: | Line 9: | ||
;''symbolBeingDefined:'' | ;''symbolBeingDefined:'' | ||
: ''otherSymbol'' | : ''otherSymbol'' | ||
: '' | : ''alternateSymbolFollowedBy'' <tt>literal</tt> | ||
: ''one of:'' <tt>list of posible literal values</tt> | |||
= General Symbols = | = General Symbols = | ||
Line 33: | Line 36: | ||
;''simpleEscapeSequence:'' | ;''simpleEscapeSequence:'' | ||
: ''one of:'' <tt>\ \" \? \\ \a \b \f \n \r \t \v</tt> | : ''one of:'' <tt>\' \" \? \\ \a \b \f \n \r \t \v</tt> | ||
;''octalEscapeSequence:'' | ;''octalEscapeSequence:'' | ||
Line 41: | Line 44: | ||
;''octalDigit:'' | ;''octalDigit:'' | ||
: ''one of:'' <tt>0 | : ''one of:'' <tt>0-7</tt> | ||
;''hexadecimalEscapeSequence:'' | ;''hexadecimalEscapeSequence:'' | ||
Line 48: | Line 51: | ||
;''hexDigit:'' | ;''hexDigit:'' | ||
: ''one of:'' <tt>0 | : ''one of:'' <tt>0-9 a-f A-F</tt> | ||
Note: C99 does not limit the number of hex digits that can appear in a ''hexadecimalEscapeSequence'', but it does state that the behaviour is undefined if the resulting character value exceeds that of the largest character. | |||
;''universalCharacterName:'' | ;''universalCharacterName:'' | ||
Line 56: | Line 61: | ||
;''hexQuad:'' | ;''hexQuad:'' | ||
: ''hexDigit'' ''hexDigit'' ''hexDigit'' ''hexDigit'' | : ''hexDigit'' ''hexDigit'' ''hexDigit'' ''hexDigit'' | ||
We could afford to be generous in what we accept as a boolean value: | We could afford to be generous in what we accept as a boolean value: | ||
Line 75: | Line 71: | ||
;''booleanTrue:'' | ;''booleanTrue:'' | ||
: ''one of:'' <tt>1 T TRUE | : ''one of:'' <tt>1 T TRUE t true True Y YES Yes y yes</tt> | ||
;''booleanFalse:'' | ;''booleanFalse:'' | ||
: ''one of:'' <tt>0 F FALSE | : ''one of:'' <tt>0 F FALSE f false False N NO No n no</tt> | ||
'''I'm proposing all these possibilities for true/false as they are all obvious in meaning, and will allow a CA Put of a string to a boolean field to understand them all. I will listen to objections though, and we might want to allow registration of strings in other languages...''' | |||
Line 90: | Line 88: | ||
= Record | = Record Definitions = | ||
;''recordDefinition:'' | ;''recordDefinition:'' | ||
Line 97: | Line 95: | ||
;''recordType:'' | ;''recordType:'' | ||
: ''identifier'' | : ''identifier'' | ||
;''recordName:'' | |||
: ''recordNameChar'' | |||
: ''recordName'' ''recordNameChar'' | |||
;''recordNameChar:'' | |||
: ''one of:'' <tt>0-9 A-Z a-z _ - : ; < > [ ]</tt> | |||
: Any Unicode/UTF-8 character outside of the Basic Latin set | |||
This extends the character set available to a V3 record name, adding all possible multi-byte characters. However, EPICS sites are strongly advised to confirm that such record names can be processed using all of their database and CA client tools before actually making use of this particular extension. | |||
;''recordBody:'' | ;''recordBody:'' | ||
Line 102: | Line 110: | ||
: ''recordBody'' ''recordBodyItem'' | : ''recordBody'' ''recordBodyItem'' | ||
Record definitions | Record instance definitions in EPICS V4 look very similar to a C99 structure definition with initialization. For example: | ||
ai foo:bar:temperature = { | ai foo:bar:temperature = { | ||
Line 108: | Line 116: | ||
} | } | ||
Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement. Note these statements must | Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement. Note these statements must be terminated with a semi-colon (which is different from inside a struct). The reason for this difference is to prevent database instance files from becoming dependent on the order of fields in a record; if we permit record instances to be created from a single comma-separated list of field values without the field names, it could lead to significant confusion if the field order ever changes. | ||
;''recordBodyItem:'' | ;''recordBodyItem:'' | ||
Line 114: | Line 122: | ||
: ''fieldAssignment'' | : ''fieldAssignment'' | ||
: ''extraFieldAssigment'' | : ''extraFieldAssigment'' | ||
== Information Fields == | |||
;''infoAssignment:'' | ;''infoAssignment:'' | ||
Line 127: | Line 137: | ||
info restorePhase = "1"; | info restorePhase = "1"; | ||
info "my favourite things" = "raindrops on roses"; | info "my favourite things" = "raindrops on roses"; | ||
== Field Assignment == | |||
;''fieldAssignment:'' | ;''fieldAssignment:'' | ||
Line 135: | Line 147: | ||
;''initializer:'' | ;''initializer:'' | ||
: '' | : ''basicInitializer'' | ||
: | : ''structInitializer'' | ||
: | : ''arrayInitializer'' | ||
: '' | : ''devlinkInitializer'' | ||
: | |||
: '' | ;''initializerList:'' | ||
: ''initializer'' | |||
: ''initializerList'' <tt>,</tt> ''initializer'' | |||
The ''initializer'' in a field assignment is also the exact same syntax that will be used when converting a string value from a CA client for example into a field value that is being put into a field. | |||
=== Basic and Enumerated Initializers === | |||
;'' | ;''basicInitializer:'' | ||
: ''booleanConstant'' | : ''booleanConstant'' | ||
: ''integerConstant'' | : ''integerConstant'' | ||
Line 150: | Line 166: | ||
: ''stringConstant'' | : ''stringConstant'' | ||
The syntax for | The syntax for the field initializer depends on the data type represented by fieldName. Basic types (numeric or string) should need no comment other than to note that values for numeric fields must not be given inside quotes (unlike EPICS V3). Menu field values may be given as either a string or an integer. For enum fields, if the related field that contains the strings is defined first, the enum field may be specified using a string; otherwise it can only be set using an integer value. | ||
Examples: | |||
ai foo:bar:temperature = { | ai foo:bar:temperature = { | ||
inputSmoothing = 0.98; | inputSmoothing = 0.98; | ||
invalidValue = 1000; | invalidValue = 1000; | ||
units = "Celcius"; | units = "Celcius"; | ||
scan = "Interrupt"; | |||
... | ... | ||
} | } | ||
=== Structure Initializers === | |||
;''structInitializer:'' | |||
: <tt>{</tt> ''structAssignmentList'' <tt>}</tt> | |||
;''structAssignmentList:'' | ;''structAssignmentList:'' | ||
Line 163: | Line 186: | ||
: ''fieldName'' <tt>=</tt> ''initializerList'' | : ''fieldName'' <tt>=</tt> ''initializerList'' | ||
: ''structAssignmentList'' <tt>;</tt> ''fieldName'' <tt>=</tt> ''initializerList'' | : ''structAssignmentList'' <tt>;</tt> ''fieldName'' <tt>=</tt> ''initializerList'' | ||
Initializers for a structure field look similar to a nested record body, but the rules are slightly different: | Initializers for a structure field look similar to a nested record body, but the rules are slightly different: | ||
Line 174: | Line 193: | ||
For example: | For example: | ||
ai foo: | ai foo:temperature:sensor = { | ||
linearConvert = { | linearConvert = { | ||
mode = "Linear"; | mode = "Linear"; | ||
Line 183: | Line 202: | ||
} | } | ||
=== Link and Device Initializers === | |||
;''devlinkInitializer:'' | |||
: ''linkType'' <tt>(</tt> ''structAssignmentList'' <tt>)</tt> | |||
: ''deviceType'' <tt>(</tt> ''structAssignmentList'' <tt>)</tt> | |||
;''linkType:'' | |||
: ''identifier'' | |||
;''deviceType:'' | |||
: ''identifier'' | |||
These select a particular link or device support for the field, and set its address according to the structure type defined for that link or device type. | |||
calcout foo:temperature:controller = { | |||
output = ca("fum:baz:heater"; pp=y); | |||
inputs = { | |||
{ "setpoint", pv("foo:temperature:setpoint") } | |||
{ "current", db("foo:temperature:sensor"; ms=y) } | |||
}; | |||
expression = "(setpoint - current) > 0"; | |||
} | |||
mbbi foo:bar:door = { | |||
input = acro9440 { 0, 5 }; | |||
} | |||
=== Array Initializers === | |||
;''arrayInitializer:'' | |||
: <tt>{</tt> ''arrayAssignmentList'' <tt>}</tt> | |||
: ''arrayType'' <tt>{</tt> ''arrayAssignmentList'' <tt>}</tt> | |||
: <tt>[</tt> ''arrayCapacity'' <tt>] {</tt> ''arrayAssignmentList'' <tt>}</tt> | |||
: ''arrayType'' <tt>[</tt> ''arrayCapacity'' <tt>] {</tt> ''arrayAssignmentList'' <tt>}</tt> | |||
;''arrayAssignmentList:'' | ;''arrayAssignmentList:'' | ||
Line 202: | Line 255: | ||
;''arrayCapacity:'' | ;''arrayCapacity:'' | ||
: ''integerConstant'' | : ''integerConstant'' | ||
: '' | : ''arrayCapacity'' <tt>,</tt> ''integerConstant'' | ||
If the definition of the array field being set did not do so, an array field initialization must include the size of the array and/or the type of the data stored in it. Inside the braces data values are given in a comma-separated list; the index can also be set to initialize individual values, and any mixture of the two can be used as desired: | |||
mbbi foo:bar:door = { | |||
stateNames = [4] {"Broken", "Closed", "Open", "Moving"}; | |||
stateSeverity = [4] {"Major"; [3] = "Minor"}; | |||
} | |||
For multi-dimensional arrays, data values can only appear inside the inner-most sets of braces, although index settings are permitted outside of these. These two definitions give the same result: | |||
matrix identity1 = { | |||
value = [3,3] { {1, 0, 0}, {0, 1, 0}, {1, 0, 0}}; | |||
} | |||
matrix identity2 = { | |||
value = [3,3] { {1}, {[1] = 1}, {[2] = 1}}; | |||
} | |||
== Extra Fields == | |||
;''extraFieldAssigment:'' | ;''extraFieldAssigment:'' |
Revision as of 22:44, 23 May 2005
- This page still being worked on...
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.
Document Conventions
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:
- symbolBeingDefined:
- otherSymbol
- alternateSymbolFollowedBy literal
- one of: list of posible literal values
General Symbols
These symbols are used but not defined in the grammar:
- integerConstant:
- floatingConstant:
- Standard format numbers
- 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:
- " escapedCharacterList "
- escapedCharacterList:
- A series of characters, using the C99 escapeSequence syntax defined below:
- escapeSequence:
- simpleEscapeSequence
- octalEscapeSequence
- hexadecimalEscapeSequence
- universalCharacterName
- simpleEscapeSequence:
- one of: \' \" \? \\ \a \b \f \n \r \t \v
- octalEscapeSequence:
- \ octalDigit
- \ octalDigit octalDigit
- \ octalDigit octalDigit octalDigit
- octalDigit:
- one of: 0-7
- hexadecimalEscapeSequence:
- \x hexDigit
- hexadecimalEscapeSequence hexDigit
- hexDigit:
- one of: 0-9 a-f A-F
Note: C99 does not limit the number of hex digits that can appear in a hexadecimalEscapeSequence, but it does state that the behaviour is undefined if the resulting character value exceeds that of the largest character.
- universalCharacterName:
- \u hexQuad
- \U hexQuad hexQuad
- hexQuad:
- hexDigit hexDigit hexDigit hexDigit
We could afford to be generous in what we accept as a boolean value:
- booleanConstant:
- booleanTrue
- " booleanTrue "
- booleanFalse
- " booleanFalse "
- booleanTrue:
- one of: 1 T TRUE t true True Y YES Yes y yes
- booleanFalse:
- one of: 0 F FALSE f false False N NO No n no
I'm proposing all these possibilities for true/false as they are all obvious in meaning, and will allow a CA Put of a string to a boolean field to understand them all. I will listen to objections though, and we might want to allow registration of strings in other languages...
Database File
I need to define these, which are really preprocessor objects:
- comments
- substitution macros
- templates and ports
Record Definitions
- recordDefinition:
- recordType recordName = { recordBody }
- recordType:
- identifier
- recordName:
- recordNameChar
- recordName recordNameChar
- recordNameChar:
- one of: 0-9 A-Z a-z _ - : ; < > [ ]
- Any Unicode/UTF-8 character outside of the Basic Latin set
This extends the character set available to a V3 record name, adding all possible multi-byte characters. However, EPICS sites are strongly advised to confirm that such record names can be processed using all of their database and CA client tools before actually making use of this particular extension.
- recordBody:
- recordBodyItem
- recordBody recordBodyItem
Record instance definitions in EPICS V4 look very similar to a C99 structure definition with initialization. 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 be terminated with a semi-colon (which is different from inside a struct). The reason for this difference is to prevent database instance files from becoming dependent on the order of fields in a record; if we permit record instances to be created from a single comma-separated list of field values without the field names, it could lead to significant confusion if the field order ever changes.
- recordBodyItem:
- infoAssignment
- fieldAssignment
- extraFieldAssigment
Information Fields
- infoAssignment:
- info infoName = stringConstant ;
- 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";
Field Assignment
- fieldAssignment:
- fieldName = initializer ;
- fieldName:
- identifier
- initializer:
- basicInitializer
- structInitializer
- arrayInitializer
- devlinkInitializer
- initializerList:
- initializer
- initializerList , initializer
The initializer in a field assignment is also the exact same syntax that will be used when converting a string value from a CA client for example into a field value that is being put into a field.
Basic and Enumerated Initializers
- basicInitializer:
- booleanConstant
- integerConstant
- floatingConstant
- stringConstant
The syntax for the field initializer depends on the data type represented by fieldName. Basic types (numeric or string) should need no comment other than to note that values for numeric fields must not be given inside quotes (unlike EPICS V3). Menu field values may be given as either a string or an integer. For enum fields, if the related field that contains the strings is defined first, the enum field may be specified using a string; otherwise it can only be set using an integer value.
Examples:
ai foo:bar:temperature = { inputSmoothing = 0.98; invalidValue = 1000; units = "Celcius"; scan = "Interrupt"; ... }
Structure Initializers
- structInitializer:
- { structAssignmentList }
- structAssignmentList:
- initializerList
- fieldName = initializerList
- structAssignmentList ; fieldName = initializerList
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:temperature:sensor = { linearConvert = { mode = "Linear"; low = -12.5, 133.5 }; displayLimit = { 0, 100 }; ... }
Link and Device Initializers
- devlinkInitializer:
- linkType ( structAssignmentList )
- deviceType ( structAssignmentList )
- linkType:
- identifier
- deviceType:
- identifier
These select a particular link or device support for the field, and set its address according to the structure type defined for that link or device type.
calcout foo:temperature:controller = { output = ca("fum:baz:heater"; pp=y); inputs = { { "setpoint", pv("foo:temperature:setpoint") } { "current", db("foo:temperature:sensor"; ms=y) } }; expression = "(setpoint - current) > 0"; }
mbbi foo:bar:door = { input = acro9440 { 0, 5 }; }
Array Initializers
- arrayInitializer:
- { arrayAssignmentList }
- arrayType { arrayAssignmentList }
- [ arrayCapacity ] { arrayAssignmentList }
- arrayType [ arrayCapacity ] { arrayAssignmentList }
- arrayAssignmentList:
- initializerList
- [ integerConstant ] = initializerList
- arrayAssignmentList ; [ integerConstant ] = initializerList
- arrayType:
- bool
- int16
- uint16
- int32
- uint32
- float32
- float64
- octet
- string
- arrayCapacity:
- integerConstant
- arrayCapacity , integerConstant
If the definition of the array field being set did not do so, an array field initialization must include the size of the array and/or the type of the data stored in it. Inside the braces data values are given in a comma-separated list; the index can also be set to initialize individual values, and any mixture of the two can be used as desired:
mbbi foo:bar:door = { stateNames = [4] {"Broken", "Closed", "Open", "Moving"}; stateSeverity = [4] {"Major"; [3] = "Minor"}; }
For multi-dimensional arrays, data values can only appear inside the inner-most sets of braces, although index settings are permitted outside of these. These two definitions give the same result:
matrix identity1 = { value = [3,3] { {1, 0, 0}, {0, 1, 0}, {1, 0, 0}}; } matrix identity2 = { value = [3,3] { {1}, {[1] = 1}, {[2] = 1}}; }
Extra Fields
- extraFieldAssigment:
- extraField = extraInitializer ;
This section not yet completed.