Compare commits
97 Commits
Release-2-
...
stream_2_7
Author | SHA1 | Date | |
---|---|---|---|
56b6c9a627 | |||
2830f07324 | |||
abd8daafc3 | |||
489e783872 | |||
10d1fa8b02 | |||
c8bffebfc6 | |||
0a90eb3d9c | |||
0936ac7840 | |||
704ece6231 | |||
5c6e98127e | |||
8805437c68 | |||
3acf791409 | |||
0ba674a341 | |||
40c33abac7 | |||
bc67317b0b | |||
06e212c66e | |||
7b314ccffd | |||
1d84986ee8 | |||
2ca8a129f7 | |||
126da8c499 | |||
ea110d5047 | |||
b37fad41c6 | |||
74775996db | |||
74426aab66 | |||
690bbb13d4 | |||
871fbed2b0 | |||
85c68d2ae6 | |||
8870611d4d | |||
67af7fc1bf | |||
93bea174e4 | |||
84fc6aabc8 | |||
38c4f5bcb6 | |||
e2af7e3149 | |||
950d75ba43 | |||
e651c99697 | |||
9694628d3f | |||
046582d1a0 | |||
f6f0ea9ae5 | |||
018547cdf3 | |||
d763a64f03 | |||
cefa460a0d | |||
cc5948ad0b | |||
be1943a66d | |||
d9acb47afe | |||
b721d26fb8 | |||
7530c7c67d | |||
824cd4d283 | |||
2e30e7aee6 | |||
3a5a3e22b9 | |||
51bd766ba6 | |||
0ab0d6db07 | |||
a12de614d6 | |||
240abd2788 | |||
e131fcb32f | |||
f88f594e87 | |||
56ef0651f2 | |||
9b9726b800 | |||
b139221f0b | |||
b0ab8a7a8b | |||
ddac589676 | |||
5b380cdaad | |||
cc9adc77fa | |||
2b38f7bcfa | |||
0ceada70b5 | |||
7bf91b403d | |||
bf5c359649 | |||
c41ac44bd1 | |||
e36013d64e | |||
9e48ad3e61 | |||
054e74d04a | |||
5f6319ed3d | |||
2f39622a57 | |||
7801119215 | |||
a6696cae49 | |||
40b52167aa | |||
814e3d53a3 | |||
6bd46e0470 | |||
d5cda13f6f | |||
bfc8e6a9cd | |||
73cba130c3 | |||
c09bc44aa4 | |||
b907e3f469 | |||
8c3bed09e4 | |||
4c99b82bb7 | |||
a6d72761b9 | |||
6c504d30cf | |||
1c814a451b | |||
daafc125c3 | |||
63f680bdc1 | |||
e88a327957 | |||
223c71bc68 | |||
14a04fd200 | |||
dc85511fe9 | |||
d0b8d3f585 | |||
97652917c9 | |||
c171a62f93 | |||
c7c28e7fa2 |
@ -1,12 +1,11 @@
|
|||||||
|
# Remove this file if not using the PSI build system
|
||||||
include /ioc/tools/driver.makefile
|
include /ioc/tools/driver.makefile
|
||||||
EXCLUDE_VERSIONS = 3.13.2
|
EXCLUDE_VERSIONS = 3.13.2
|
||||||
PROJECT=stream2
|
PROJECT=stream
|
||||||
BUILDCLASSES += Linux
|
BUILDCLASSES += Linux
|
||||||
|
|
||||||
#DOCUDIR = doc
|
#DOCUDIR = doc
|
||||||
|
|
||||||
DBDS = stream.dbd
|
|
||||||
|
|
||||||
BUSSES += AsynDriver
|
BUSSES += AsynDriver
|
||||||
BUSSES += Dummy
|
BUSSES += Dummy
|
||||||
|
|
||||||
@ -41,18 +40,17 @@ HEADERS += StreamFormatConverter.h
|
|||||||
HEADERS += StreamBuffer.h
|
HEADERS += StreamBuffer.h
|
||||||
HEADERS += StreamError.h
|
HEADERS += StreamError.h
|
||||||
|
|
||||||
ifeq (${EPICS_BASETYPE},3.13)
|
ifneq (${EPICS_BASETYPE},3.13)
|
||||||
USR_INCLUDES += -include $(INSTALL_INCLUDE)/compat3_13.h
|
|
||||||
endif
|
|
||||||
ifeq (${EPICS_BASETYPE},3.14)
|
|
||||||
RECORDTYPES += calcout
|
RECORDTYPES += calcout
|
||||||
endif
|
endif
|
||||||
|
|
||||||
StreamCore.o: streamReferences
|
StreamCore.o StreamCore.d: streamReferences
|
||||||
|
|
||||||
streamReferences:
|
streamReferences:
|
||||||
perl ../src/makeref.pl Interface $(BUSSES) > $@
|
perl ../src/makeref.pl Interface $(BUSSES) > $@
|
||||||
perl ../src/makeref.pl Converter $(FORMATS) >> $@
|
perl ../src/makeref.pl Converter $(FORMATS) >> $@
|
||||||
|
|
||||||
stream.dbd:
|
export DBDFILES = streamSup.dbd
|
||||||
|
streamSup.dbd:
|
||||||
|
@echo Creating $@
|
||||||
perl ../src/makedbd.pl $(RECORDTYPES) > $@
|
perl ../src/makedbd.pl $(RECORDTYPES) > $@
|
5
MODULE
5
MODULE
@ -1,5 +0,0 @@
|
|||||||
# Please change the following email with yours.
|
|
||||||
Email: dirk.zimoch@psi.ch
|
|
||||||
Module-Name: StreamDevice2
|
|
||||||
Description: StreamDevice2
|
|
||||||
Project-Name:
|
|
BIN
doc/PSI.gif
BIN
doc/PSI.gif
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
BIN
doc/PSI.png
Normal file
BIN
doc/PSI.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: aai Records</h1>
|
<h1>aai Records</h1>
|
||||||
<p>
|
<p>
|
||||||
<b>Note:</b> aai record support is disabled per default.
|
<b>Note:</b> aai record support is disabled per default.
|
||||||
Enable it in <code>src/CONFIG_STREAM</code>.
|
Enable it in <code>src/CONFIG_STREAM</code>.
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: aao Records</h1>
|
<h1>aao Records</h1>
|
||||||
<p>
|
<p>
|
||||||
<b>Note:</b> aao record support is disabled per default.
|
<b>Note:</b> aao record support is disabled per default.
|
||||||
Enable it in <code>src/CONFIG_STREAM</code>.
|
Enable it in <code>src/CONFIG_STREAM</code>.
|
||||||
|
10
doc/ai.html
10
doc/ai.html
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: ai Records</h1>
|
<h1>ai Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
@ -41,6 +41,12 @@ written or read value.
|
|||||||
(=20.0/0xFFFF) maps 0x0000 to -10.0, 0x7FFF to 0.0 and 0xFFFF to 10.0.
|
(=20.0/0xFFFF) maps 0x0000 to -10.0, 0x7FFF to 0.0 and 0xFFFF to 10.0.
|
||||||
Using unsigned formats with values ≥ 0x800000 gives different results
|
Using unsigned formats with values ≥ 0x800000 gives different results
|
||||||
on 64 bit machines.
|
on 64 bit machines.
|
||||||
|
<p>
|
||||||
|
If <code>LINR=="NO CONVERSION"</code> (the default), <code>VAL</code>
|
||||||
|
is directly converted from and to <code>long</code> without going through
|
||||||
|
<code>RVAL</code>. This allows for more bits on 64 bit machines.
|
||||||
|
To get the old behavior, use <code>LINR=="LINEAR"</code>.
|
||||||
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
||||||
<dd>
|
<dd>
|
||||||
@ -78,6 +84,6 @@ written or read value.
|
|||||||
<a href="calcout.html">calcout</a>
|
<a href="calcout.html">calcout</a>
|
||||||
<a href="scalcout.html">scalcout</a>
|
<a href="scalcout.html">scalcout</a>
|
||||||
</p>
|
</p>
|
||||||
<p><small>Dirk Zimoch, 2005</small></p>
|
<p><small>Dirk Zimoch, 2015</small></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
10
doc/ao.html
10
doc/ao.html
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: ao Records</h1>
|
<h1>ao Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
@ -40,6 +40,12 @@ written or read value.
|
|||||||
(=20.0/0xFFFF) maps -10.0 to 0x0000, 0.0 to 0x7FFF and 10.0 to 0xFFFF.
|
(=20.0/0xFFFF) maps -10.0 to 0x0000, 0.0 to 0x7FFF and 10.0 to 0xFFFF.
|
||||||
Using unsigned formats with values ≥ 0x800000 gives different results
|
Using unsigned formats with values ≥ 0x800000 gives different results
|
||||||
on 64 bit machines.
|
on 64 bit machines.
|
||||||
|
<p>
|
||||||
|
If <code>LINR=="NO CONVERSION"</code> (the default), <code>OVAL</code>
|
||||||
|
is directly converted to <code>long</code> without going through
|
||||||
|
<code>RVAL</code>. This allows for more bits on 64 bit machines.
|
||||||
|
To get the old behavior, use <code>LINR=="LINEAR"</code>.
|
||||||
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
||||||
<dd>
|
<dd>
|
||||||
@ -79,6 +85,6 @@ written or read value.
|
|||||||
<a href="calcout.html">calcout</a>
|
<a href="calcout.html">calcout</a>
|
||||||
<a href="scalcout.html">scalcout</a>
|
<a href="scalcout.html">scalcout</a>
|
||||||
</p>
|
</p>
|
||||||
<p><small>Dirk Zimoch, 2005</small></p>
|
<p><small>Dirk Zimoch, 2015</small></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: bi Records</h1>
|
<h1>bi Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: bo Records</h1>
|
<h1>bo Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: calcout Records</h1>
|
<h1>calcout Records</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>Note:</b> Device support for calcout records is only available for
|
<b>Note:</b> Device support for calcout records is only available for
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Using EPICS 3.13</h1>
|
<h1>Using EPICS 3.13</h1>
|
||||||
|
|
||||||
<a name="pre"></a>
|
<a name="pre"></a>
|
||||||
<h2>1. Prerequisites</h2>
|
<h2>1. Prerequisites</h2>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Format Converter API</h1>
|
<h1>Format Converter API</h1>
|
||||||
|
|
||||||
<a name="class"></a>
|
<a name="class"></a>
|
||||||
<h2>Converter Class</h2>
|
<h2>Converter Class</h2>
|
||||||
|
197
doc/formats.html
197
doc/formats.html
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Format Converters</h1>
|
<h1>Format Converters</h1>
|
||||||
|
|
||||||
<a name="syntax"></a>
|
<a name="syntax"></a>
|
||||||
<h2>1. Format Syntax</h2>
|
<h2>1. Format Syntax</h2>
|
||||||
@ -28,8 +28,8 @@ A format converter consists of
|
|||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>The <code>%</code> character</li>
|
<li>The <code>%</code> character</li>
|
||||||
<li>Optionally a field <span class="new">or record</span> name in <code>()</code></li>
|
<li>Optionally a field or record name in <code>()</code></li>
|
||||||
<li>Optionally flags out of the characters <code>*# +0-<span class="new">?=</span></code></li>
|
<li>Optionally flags out of the characters <code>*# +0-?=!</code></li>
|
||||||
<li>Optionally an integer <em>width</em> field</li>
|
<li>Optionally an integer <em>width</em> field</li>
|
||||||
<li>Optionally a period character (<code>.</code>) followed
|
<li>Optionally a period character (<code>.</code>) followed
|
||||||
by an integer <em>precision</em> field (input ony for most formats)</li>
|
by an integer <em>precision</em> field (input ony for most formats)</li>
|
||||||
@ -40,7 +40,7 @@ A format converter consists of
|
|||||||
<p>
|
<p>
|
||||||
The flags <code>*# +0-</code> work like in the C functions
|
The flags <code>*# +0-</code> work like in the C functions
|
||||||
<em>printf()</em> and <em>scanf()</em>.
|
<em>printf()</em> and <em>scanf()</em>.
|
||||||
The flags <code>?</code> and <code>=</code> are extensions.
|
The flags <code>?</code>, <code>=</code> and <code>!</code> are extensions.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The <code>*</code> flag skips data in input formats.
|
The <code>*</code> flag skips data in input formats.
|
||||||
@ -67,16 +67,24 @@ The <code>0</code> flag says that numbers should be left padded with
|
|||||||
The <code>-</code> flag specifies that output is left justified if
|
The <code>-</code> flag specifies that output is left justified if
|
||||||
<em>width</em> is larger than required.
|
<em>width</em> is larger than required.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
The <code>?</code> flag makes failing input conversions succeed with
|
The <code>?</code> flag makes failing input conversions succeed with
|
||||||
a default zero value (0, 0.0, or "", depending on the format type).
|
a default zero value (0, 0.0, or "", depending on the format type).
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
The <code>=</code> flag allows to compare input with current values.
|
The <code>=</code> flag allows to compare input with current values.
|
||||||
It is only allowed in input formats.
|
It is only allowed in input formats.
|
||||||
Instead of reading a new value from input, the current value is
|
Instead of reading a new value from input, the current value is
|
||||||
formatted (like for output) and then compared to the input.
|
formatted (like for output) and then compared to the input.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
The <code>!</code> flag demands that input is exactly <em>width</em>
|
||||||
|
bytes long (normally <em>width</em> defines the maximum number of
|
||||||
|
bytes read in many formats).
|
||||||
|
For example <code>in "%!5d";</code> expects exactly 5 digits.
|
||||||
|
Fewer digits are considered loss of data and make the format fail.
|
||||||
|
This feature has been added by Klemen Vodopivec, SNS.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3>Examples:</h3>
|
<h3>Examples:</h3>
|
||||||
<table>
|
<table>
|
||||||
@ -143,11 +151,8 @@ field formatted as a string.
|
|||||||
Use <code>in "%(<i>otherrecord</i>.RVAL)f";</code> to write the floating
|
Use <code>in "%(<i>otherrecord</i>.RVAL)f";</code> to write the floating
|
||||||
point input value into the <code>RVAL</code> field of
|
point input value into the <code>RVAL</code> field of
|
||||||
<code><i>otherrecord</i></code>.
|
<code><i>otherrecord</i></code>.
|
||||||
<span class="new">
|
|
||||||
If no field is given for an other record .VAL is assumed.
|
If no field is given for an other record .VAL is assumed.
|
||||||
When a record name conflicts with a field name use .VAL explicitly.
|
When a record name conflicts with a field name use .VAL explicitly.
|
||||||
</span>
|
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This feature is very useful when one line of input contains many values that should
|
This feature is very useful when one line of input contains many values that should
|
||||||
@ -158,6 +163,9 @@ attribute (see
|
|||||||
target="ex">Record Reference Manual</a>), the record will be processed.
|
target="ex">Record Reference Manual</a>), the record will be processed.
|
||||||
It is your responsibility that the data type of the record field is
|
It is your responsibility that the data type of the record field is
|
||||||
compatible to the the data type of the converter.
|
compatible to the the data type of the converter.
|
||||||
|
STRING formats are compatible with arrays of CHAR or UCHAR.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
Note that using this syntax is by far not as efficient as using the
|
Note that using this syntax is by far not as efficient as using the
|
||||||
default field.
|
default field.
|
||||||
At the moment it is not possible to set <code>otherrecord</code> to an alarm
|
At the moment it is not possible to set <code>otherrecord</code> to an alarm
|
||||||
@ -189,13 +197,13 @@ With the <code>#</code> flag, output always contains a period character.
|
|||||||
<p>
|
<p>
|
||||||
<b>Input:</b> All these formats are equivalent. Leading whitespaces are skipped.
|
<b>Input:</b> All these formats are equivalent. Leading whitespaces are skipped.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
With the <code>#</code> flag additional whitespace between sign and number
|
With the <code>#</code> flag additional whitespace between sign and number
|
||||||
is accepted.
|
is accepted.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
When a maximum field width is given, leading whitespace only counts to the
|
When a maximum field width is given, leading whitespace only counts to the
|
||||||
field witdth when the space flag is given.
|
field witdth when the space flag is used.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a name="stdl"></a>
|
<a name="stdl"></a>
|
||||||
@ -210,6 +218,10 @@ field witdth when the space flag is given.
|
|||||||
<p>
|
<p>
|
||||||
With the <code>#</code> flag, octal values are prefixed with <code>0</code>
|
With the <code>#</code> flag, octal values are prefixed with <code>0</code>
|
||||||
and hexadecimal values with <code>0x</code> or <code>0X</code>.
|
and hexadecimal values with <code>0x</code> or <code>0X</code>.
|
||||||
|
<p>
|
||||||
|
Unlike printf, <code>%x</code> and <code>%X</code> truncate the
|
||||||
|
output to the the given width (number of least significant half bytes).
|
||||||
|
</p>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<b>Input:</b> <code>%d</code> matches signed decimal, <code>%u</code> matches
|
<b>Input:</b> <code>%d</code> matches signed decimal, <code>%u</code> matches
|
||||||
@ -221,16 +233,16 @@ Octal and hexadecimal values can optionally be prefixed.
|
|||||||
hexadecimal notation.
|
hexadecimal notation.
|
||||||
Leading whitespaces are skipped.
|
Leading whitespaces are skipped.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
With the <code>-</code> negative octal and hexadecimal values are accepted.
|
With the <code>-</code> negative octal and hexadecimal values are accepted.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
With the <code>#</code> flag additional whitespace between sign and number
|
With the <code>#</code> flag additional whitespace between sign and number
|
||||||
is accepted.
|
is accepted.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
When a maximum field width is given, leading whitespace only counts to the
|
When a maximum field width is given, leading whitespace only counts to the
|
||||||
field witdth when the space flag is given.
|
field witdth when the space flag is used.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a name="stds"></a>
|
<a name="stds"></a>
|
||||||
@ -246,13 +258,11 @@ and <code>%c</code> matches a sequence of not-null characters.
|
|||||||
The maximum string length is given by <em>width</em>.
|
The maximum string length is given by <em>width</em>.
|
||||||
The default <em>width</em> is infinite for <code>%s</code> and
|
The default <em>width</em> is infinite for <code>%s</code> and
|
||||||
1 for <code>%c</code>.
|
1 for <code>%c</code>.
|
||||||
Leading whitespaces are skipped with <code>%s</code>
|
Leading whitespaces are skipped with <code>%s</code> except when
|
||||||
<span class="new">
|
the space flag is used but not with <code>%c</code>.
|
||||||
except when the space flag is given</span>
|
|
||||||
but not with <code>%c</code>.
|
|
||||||
The empty string matches.
|
The empty string matches.
|
||||||
</p>
|
</p>
|
||||||
<p class="new">
|
<p>
|
||||||
With the <code>#</code> flag <code>%s</code> matches a sequence of not-null
|
With the <code>#</code> flag <code>%s</code> matches a sequence of not-null
|
||||||
characters instead of non-whitespace characters.
|
characters instead of non-whitespace characters.
|
||||||
</p>
|
</p>
|
||||||
@ -286,9 +296,20 @@ to the value 0, <code>STANDBY</code> to 1 and <code>ON</code> to 2.
|
|||||||
<p>
|
<p>
|
||||||
When using the <code>#</code> flag it is allowed to assign integer values
|
When using the <code>#</code> flag it is allowed to assign integer values
|
||||||
to the strings using <code>=</code>.
|
to the strings using <code>=</code>.
|
||||||
|
Unassigned strings increment their values by 1 as usual.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Example: <code>%#{neg=-1|stop=0|pos=1|fast=10}</code>.
|
If one string is the initial substing of another, the substing must come
|
||||||
|
later to ensure correct matching.
|
||||||
|
In particular if one string is the emptry string, it must be the last one.
|
||||||
|
Use <code>#</code> and <code>=</code> to renumber if necessary.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Use the assignment <code>=?</code> for the last string to make it the
|
||||||
|
default value for output formats.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Example: <code>%#{neg=-1|stop|pos|fast=10|rewind=-10}</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If one of the strings contains <code>|</code> or <code>}</code>
|
If one of the strings contains <code>|</code> or <code>}</code>
|
||||||
@ -296,10 +317,11 @@ If one of the strings contains <code>|</code> or <code>}</code>
|
|||||||
a <code>\</code> must be used to escape the character.
|
a <code>\</code> must be used to escape the character.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In output, depending on the value, one of the strings is printed.
|
<b>Output:</b> Depending on the value, one of the strings is printed,
|
||||||
|
or the default if no value matches.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In input, if any of the strings matches the value is set accordingly.
|
<b>Input:</b> If any of the strings matches, the value is set accordingly.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a name="bin"></a>
|
<a name="bin"></a>
|
||||||
@ -345,9 +367,12 @@ endian</em>, i.e. least significant byte first.
|
|||||||
With the <code>0</code> flag, the value is unsigned, otherwise signed.
|
With the <code>0</code> flag, the value is unsigned, otherwise signed.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In output, the <em>prec</em> (or sizeof(long) whatever is less) least
|
In output, the <em>precision</em> (or sizeof(long) whatever is less) least
|
||||||
significant bytes of the value are sign extended or zero extended
|
significant bytes of the value are sign extended or zero extended
|
||||||
(depending on the <code>0</code> flag) to <em>width</em> bytes.
|
(depending on the <code>0</code> flag) to <em>width</em> bytes.
|
||||||
|
The default for <em>precision</em> is 1. Thus if you do not specify
|
||||||
|
the <em>precision</em>, only the least significant byte is written!
|
||||||
|
It is common error to write <code>out "%2r";</code> instead of <code>out "%.2r";</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In input, <em>width</em> bytes are read and put into the value.
|
In input, <em>width</em> bytes are read and put into the value.
|
||||||
@ -358,7 +383,7 @@ the value is sign extended or zero extended, depending on the
|
|||||||
<code>0</code> flag.
|
<code>0</code> flag.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Example: <code>out "%.2r"</code>
|
Examples: <code>out "%.2r"; in "%02r";</code>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a name="rawdouble"></a>
|
<a name="rawdouble"></a>
|
||||||
@ -412,7 +437,7 @@ The <em>width</em> field is the byte number from which to start
|
|||||||
calculating the checksum.
|
calculating the checksum.
|
||||||
Default is 0, i.e. the first byte of the input or output of the current
|
Default is 0, i.e. the first byte of the input or output of the current
|
||||||
command.
|
command.
|
||||||
The last byte is <em>prec</em> bytes before the checksum (default 0).
|
The last byte is <em>precision</em> bytes before the checksum (default 0).
|
||||||
For example in <code>"abcdefg%<xor>"</code> the checksum is calculated
|
For example in <code>"abcdefg%<xor>"</code> the checksum is calculated
|
||||||
from <code>abcdefg</code>,
|
from <code>abcdefg</code>,
|
||||||
but in <code>"abcdefg%2.1<xor>"</code> only from <code>cdef</code>.
|
but in <code>"abcdefg%2.1<xor>"</code> only from <code>cdef</code>.
|
||||||
@ -466,21 +491,24 @@ In input, the next byte or bytes must match the checksum.
|
|||||||
(poly=0x07, init=0x00, xorout=0x00).</dd>
|
(poly=0x07, init=0x00, xorout=0x00).</dd>
|
||||||
<dt><code>%<ccitt8></code></dt>
|
<dt><code>%<ccitt8></code></dt>
|
||||||
<dd>One byte. The CCITT standard 8 bit crc checksum
|
<dd>One byte. The CCITT standard 8 bit crc checksum
|
||||||
(poly=0x31, init=0x00, xorout=0x00).</dd>
|
(poly=0x31, init=0x00, xorout=0x00, reflected).</dd>
|
||||||
<dt><code>%<crc16></code></dt>
|
<dt><code>%<crc16></code></dt>
|
||||||
<dd>Two bytes. An often used 16 bit crc checksum
|
<dd>Two bytes. An often used 16 bit crc checksum
|
||||||
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
|
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
|
||||||
<dt><code>%<crc16r></code></dt>
|
<dt><code>%<crc16r></code></dt>
|
||||||
<dd>Two bytes. An often used reflected 16 bit crc checksum
|
<dd>Two bytes. An often used reflected 16 bit crc checksum
|
||||||
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
|
(poly=0x8005, init=0x0000, xorout=0x0000, reflected).</dd>
|
||||||
|
<dt><code>%<modbus></code></dt>
|
||||||
|
<dd>Two bytes. The modbus 16 bit crc checksum
|
||||||
|
(poly=0x8005, init=0xffff, xorout=0x0000, reflected)</dd>
|
||||||
<dt><code>%<ccitt16></code></dt>
|
<dt><code>%<ccitt16></code></dt>
|
||||||
<dd>Two bytes. The usual (but <a target="ex"
|
<dd>Two bytes. The usual (but <a target="ex"
|
||||||
href="http://www.joegeluso.com/software/articles/ccitt.htm">wrong?</a>)
|
href="http://srecord.sourceforge.net/crc16-ccitt.html">wrong?</a>)
|
||||||
implementation of the CCITT standard 16 bit crc checksum
|
implementation of the CCITT standard 16 bit crc checksum
|
||||||
(poly=0x1021, init=0xFFFF, xorout=0x0000).</dd>
|
(poly=0x1021, init=0xFFFF, xorout=0x0000).</dd>
|
||||||
<dt><code>%<ccitt16a></code></dt>
|
<dt><code>%<ccitt16a></code></dt>
|
||||||
<dd>Two bytes. The unusual (but <a target="ex"
|
<dd>Two bytes. The unusual (but <a target="ex"
|
||||||
href="http://www.joegeluso.com/software/articles/ccitt.htm">correct?</a>)
|
href="http://srecord.sourceforge.net/crc16-ccitt.html">correct?</a>)
|
||||||
implementation of the CCITT standard 16 bit crc checksum with augment.
|
implementation of the CCITT standard 16 bit crc checksum with augment.
|
||||||
(poly=0x1021, init=0x1D0F, xorout=0x0000).</dd>
|
(poly=0x1021, init=0x1D0F, xorout=0x0000).</dd>
|
||||||
<dt><code>%<ccitt16x></code> or <code>%<crc16c></code> or <code>%<xmodem></code></dt>
|
<dt><code>%<ccitt16x></code> or <code>%<crc16c></code> or <code>%<xmodem></code></dt>
|
||||||
@ -491,10 +519,10 @@ In input, the next byte or bytes must match the checksum.
|
|||||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
|
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
|
||||||
<dt><code>%<crc32r></code></dt>
|
<dt><code>%<crc32r></code></dt>
|
||||||
<dd>Four bytes. The standard reflected 32 bit crc checksum.
|
<dd>Four bytes. The standard reflected 32 bit crc checksum.
|
||||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
|
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF, reflected).</dd>
|
||||||
<dt><code>%<jamcrc></code></dt>
|
<dt><code>%<jamcrc></code></dt>
|
||||||
<dd>Four bytes. Another reflected 32 bit crc checksum.
|
<dd>Four bytes. Another reflected 32 bit crc checksum.
|
||||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0x00000000).</dd>
|
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0x00000000, reflected).</dd>
|
||||||
<dt><code>%<adler32></code></dt>
|
<dt><code>%<adler32></code></dt>
|
||||||
<dd>Four bytes. The Adler32 checksum according to <a target="ex"
|
<dd>Four bytes. The Adler32 checksum according to <a target="ex"
|
||||||
href="http://www.ietf.org/rfc/rfc1950.txt">RFC 1950</a>.</dd>
|
href="http://www.ietf.org/rfc/rfc1950.txt">RFC 1950</a>.</dd>
|
||||||
@ -503,41 +531,44 @@ In input, the next byte or bytes must match the checksum.
|
|||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<a name="regex"></a>
|
<a name="regex"></a>
|
||||||
<h2>12. Regular Expresion STRING Converter (<code>%/<em>regex</em>/</code>)</h2>
|
<h2>13. Regular Expresion STRING Converter (<code>%/<em>regex</em>/</code>)</h2>
|
||||||
<p>
|
<p>
|
||||||
This input-only format matches <a target="ex"
|
This input-only format matches <a target="ex"
|
||||||
href="http://www.pcre.org/" >Perl compatible regular expressions (PCRE)</a>.
|
href="http://www.pcre.org/" >Perl compatible regular expressions (PCRE)</a>.
|
||||||
It is only available if a PCRE library is installed.
|
It is only available if a PCRE library is installed.
|
||||||
</p>
|
</p>
|
||||||
|
<div class="box">
|
||||||
<p>
|
<p>
|
||||||
If PCRE is not available for your host or cross architecture, download
|
If PCRE is not available for your host or cross architecture, download
|
||||||
the sourcecode from <a target="ex" href="http://www.pcre.org/">www.pcre.org</a>
|
the sourcecode from <a target="ex" href="http://www.pcre.org/">www.pcre.org</a>
|
||||||
and try my EPICS compatible <a target="ex"
|
and try my EPICS compatible <a target="ex"
|
||||||
href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile">Makefile</a>
|
href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile">Makefile</a>
|
||||||
to compile it like a normal EPICS application.
|
to compile it like a normal EPICS support module.
|
||||||
The Makefile is known to work with EPICS 3.14.8 and PCRE 7.2.
|
The Makefile is known to work with EPICS 3.14.8 and PCRE 7.2.
|
||||||
In your RELEASE file define the variable <code>PCRE</code> so that
|
In your RELEASE file define the variable <code>PCRE</code> so that
|
||||||
it points to the install location of PCRE.
|
it points to the install location of PCRE.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If PCRE is already installed on your system, use the variables
|
If PCRE is already installed on (some of) your systems, you may add
|
||||||
<code>PCRE_INCLUDE</code> and <code>PCRE_LIB</code> instead to provide
|
architectures where PCRE can be found in standard include and library
|
||||||
the install directories of <code>pcre.h</code> and the library.
|
locations to the variable <code>WITH_SYSTEM_PCRE</code>.
|
||||||
</p>
|
If either the header file or the library are in a non-standard place,
|
||||||
<p>
|
set in your RELEASE file the variables <code>PCRE_INCLUDE_<em>arch</em></code>
|
||||||
If you have PCRE installed in different locations for different (cross)
|
and/or <code>PCRE_LIB_<em>arch</em></code> for the respective architectures
|
||||||
architectures, define the variables in RELEASE.Common.<architecture>
|
to the correct directories or set
|
||||||
instead of the global RELEASE file.
|
<code>PCRE_INCLUDE</code> and/or <code>PCRE_LIB</code>
|
||||||
|
in architecture specific RELEASE.Common.<em>arch</em> files.
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
<p>
|
<p>
|
||||||
If the regular expression is not anchored, i.e. does not start with
|
If the regular expression is not anchored, i.e. does not start with
|
||||||
<code>^</code>, leading non-matching input is skipped.
|
<code>^</code>, leading non-matching input is skipped.
|
||||||
A maximum of <em>width</em> bytes is matched, if specified.
|
A maximum of <em>width</em> bytes is matched, if specified.
|
||||||
If <em>prec</em> is given, it specifies the sub-expression whose match
|
If <em>precision</em> is given, it specifies the sub-expression whose match
|
||||||
is retuned.
|
is retuned.
|
||||||
Otherwise the complete match is returned.
|
Otherwise the complete match is returned.
|
||||||
In any case, the complete match is consumed from the input buffer.
|
In any case, the complete match is consumed from the input buffer.
|
||||||
If the expression contains a <code>/</code> it must be escaped.
|
If the expression contains a <code>/</code> it must be escaped like <code>\/</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Example: <code>%.1/<title>(.*)<\/title>/</code> returns
|
Example: <code>%.1/<title>(.*)<\/title>/</code> returns
|
||||||
@ -545,8 +576,74 @@ the title of an HTML page, skipps anything before the
|
|||||||
<code><title></code> tag and leaves anything after the
|
<code><title></code> tag and leaves anything after the
|
||||||
<code></title></code> tag in the input buffer.
|
<code></title></code> tag in the input buffer.
|
||||||
</p>
|
</p>
|
||||||
|
<a name="regsub"></a>
|
||||||
|
<h2>14. Regular Expresion Substitution Pseudo-Converter (<code>%#/<em>regex</em>/<em>subst</em>/</code>)</h2>
|
||||||
|
<p>
|
||||||
|
This is a variant of the previous converter (note the <code>#</code>)
|
||||||
|
but instead of returning the matching string,
|
||||||
|
it can be used as a pre-processor for input or
|
||||||
|
as a post-processor for output.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Matches of the <em>regex</em> are replaced by the string <em>subst</em> with all
|
||||||
|
<code>&</code> or <code>\0</code> in <em>subst</em> replaced with the match itself and all
|
||||||
|
<code>\1</code> through <code>\9</code> replaced with the match of the corresponding sub-expression.
|
||||||
|
To get a literal <code>&</code> or <code>\</code> or <code>/</code> in the substitution write
|
||||||
|
<code>\&</code> or <code>\\</code> or <code>\/</code>.
|
||||||
|
There is no way to specify literal bytes with values less or equal to 9 in the
|
||||||
|
substitution!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If <em>width</em> is specified, it limits the number of characters processed.
|
||||||
|
If the <code>-</code> flag is used (i.e. <em>width</em> looks like a negative number)
|
||||||
|
only the last <em>width</em> characters are processed, else the first.
|
||||||
|
Without <em>width</em> (or 0) all available characters are processed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If <em>precision</em> is specified, it indicates which matches to replace.
|
||||||
|
With the <code>+</code> flag given, <em>precision</em> is the maximum
|
||||||
|
number of matches to replace.
|
||||||
|
Otherwise <em>precision</em> is the index (counting from 1) of the match to replace.
|
||||||
|
Without <em>precision</em> (or 0), all matches are replaced.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In input this converter pre-processes data received from the device before
|
||||||
|
following converters read it.
|
||||||
|
Converters preceding this one will read unmodified input.
|
||||||
|
Thus place this converter before those whose input should be pre-processed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In output it post-processes data already formatted by preceding converters
|
||||||
|
before sending it to the device.
|
||||||
|
Converters following this one will send their output unmodified.
|
||||||
|
Thus place this converter after those whose output should be post-processed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Examples:
|
||||||
|
<div class="indent">
|
||||||
|
<code>%#+-10.2/ab/X/</code> replaces the string <code>ab</code> with <code>X</code>
|
||||||
|
maximal 2 times in the last 10 characters.
|
||||||
|
(<code>abcabcabcabc</code> becomes <code>abcXcXcabc</code>)
|
||||||
|
</div>
|
||||||
|
<div class="indent">
|
||||||
|
<code>%#/\\/\//</code> replaces all <code>\</code> with <code>/</code>
|
||||||
|
(<code>\dir\file</code> becomes <code>/dir/file</code>)
|
||||||
|
</div>
|
||||||
|
<div class="indent">
|
||||||
|
<code>%#/..\B/&:/</code> inserts <code>:</code> after every second character
|
||||||
|
which is not at the end of a word.
|
||||||
|
(<code>0b19353134</code> becomes <code>0b:19:35:31:34</code>)
|
||||||
|
</div>
|
||||||
|
<div class="indent">
|
||||||
|
<code>%#/://</code> removes all <code>:</code> characters.
|
||||||
|
(<code>0b:19:35:31:34</code> becomes <code>0b19353134</code>)
|
||||||
|
</div>
|
||||||
|
<div class="indent">
|
||||||
|
<code>%#/([^+-])*([+-])/\2\1/</code> moves a postfix sign to the front.
|
||||||
|
(<code>1.23-</code> becomes <code>-1.23</code>)<br>
|
||||||
|
</div>
|
||||||
<a name="mantexp"></a>
|
<a name="mantexp"></a>
|
||||||
<h2>13. MantissaExponent DOUBLE converter (<code>%m</code>)</h2>
|
<h2>15. MantissaExponent DOUBLE converter (<code>%m</code>)</h2>
|
||||||
<p>
|
<p>
|
||||||
This exotic and experimental format matches numbers in the format
|
This exotic and experimental format matches numbers in the format
|
||||||
<i>[sign] mantissa sign exponent</i>, e.g <code>+123-4</code> meaning
|
<i>[sign] mantissa sign exponent</i>, e.g <code>+123-4</code> meaning
|
||||||
@ -565,9 +662,8 @@ Format flags <code>+</code>, <code>-</code>, and space are supported in
|
|||||||
the usual way (always sign, left justified, space instead of + sign).
|
the usual way (always sign, left justified, space instead of + sign).
|
||||||
Flags <code>#</code> and <code>0</code> are unsupported.
|
Flags <code>#</code> and <code>0</code> are unsupported.
|
||||||
</p>
|
</p>
|
||||||
<div class="new">
|
|
||||||
<a name="timestamp"></a>
|
<a name="timestamp"></a>
|
||||||
<h2>14. Timestamp DOUBLE converter (<code>%T(<em>timeformat</em>)</code>)</h2>
|
<h2>16. Timestamp DOUBLE converter (<code>%T(<em>timeformat</em>)</code>)</h2>
|
||||||
<p>
|
<p>
|
||||||
This format reads or writes timestamps and converts them to a double number.
|
This format reads or writes timestamps and converts them to a double number.
|
||||||
The value represents the number of seconds since 1970 (the UNIX epoch).
|
The value represents the number of seconds since 1970 (the UNIX epoch).
|
||||||
@ -604,7 +700,7 @@ In output, the system function <em>strftime()</em> is used to format the time.
|
|||||||
There may be differences in the implementation between operating systems.
|
There may be differences in the implementation between operating systems.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In input, <em>StreamDevice</em> used its own implementation because many
|
In input, <em>StreamDevice</em> uses its own implementation because many
|
||||||
systems are missing the <em>strptime()</em> function and additional formats
|
systems are missing the <em>strptime()</em> function and additional formats
|
||||||
are supported.
|
are supported.
|
||||||
</p>
|
</p>
|
||||||
@ -618,9 +714,8 @@ Because of the complexity of the problem, locales are not supported.
|
|||||||
Thus, only the English month names can be used (week day names are
|
Thus, only the English month names can be used (week day names are
|
||||||
ignored anyway).
|
ignored anyway).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
<hr>
|
<hr>
|
||||||
<p align="right"><a href="processing.html">Next: Record Processing</a></p>
|
<p align="right"><a href="processing.html">Next: Record Processing</a></p>
|
||||||
<p><small>Dirk Zimoch, 2011</small></p>
|
<p><small>Dirk Zimoch, 2015</small></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -104,13 +104,8 @@ This marks text you typically type in configuration files etc.
|
|||||||
<pre>
|
<pre>
|
||||||
Longer code segments are often set in a box.
|
Longer code segments are often set in a box.
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
|
||||||
Important modifications and new features are
|
|
||||||
<span class="new">highlighted with a yellow background</span>.
|
|
||||||
Obsolete features are <strike class="new">highlighted and crossed out</strike>.
|
|
||||||
</p>
|
|
||||||
<hr>
|
<hr>
|
||||||
<p align="right"><a href="setup.html">Next: Setup</a></p>
|
<p align="right"><a href="setup.html">Next: Setup</a></p>
|
||||||
<p><small>Dirk Zimoch, 2011</small></p>
|
<p><small>Dirk Zimoch, 2015</small></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: longin Records</h1>
|
<h1>longin Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: longout Records</h1>
|
<h1>longout Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
35
doc/makepdf
Executable file
35
doc/makepdf
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
PAGES="
|
||||||
|
index.html
|
||||||
|
setup.html
|
||||||
|
epics3_13.html
|
||||||
|
protocol.html
|
||||||
|
formats.html
|
||||||
|
processing.html
|
||||||
|
recordtypes.html
|
||||||
|
aai.html
|
||||||
|
aao.html
|
||||||
|
ai.html
|
||||||
|
ao.html
|
||||||
|
bi.html
|
||||||
|
bo.html
|
||||||
|
mbbi.html
|
||||||
|
mbbo.html
|
||||||
|
mbbiDirect.html
|
||||||
|
mbboDirect.html
|
||||||
|
stringin.html
|
||||||
|
stringout.html
|
||||||
|
longin.html
|
||||||
|
longout.html
|
||||||
|
waveform.html
|
||||||
|
calcout.html
|
||||||
|
scalcout.html
|
||||||
|
tipsandtricks.html
|
||||||
|
recordinterface.html
|
||||||
|
businterface.html
|
||||||
|
formatconverter.html
|
||||||
|
osinterface.html
|
||||||
|
"
|
||||||
|
|
||||||
|
rm -f stream.pdf
|
||||||
|
wkhtmltopdf --print-media-type --dpi 1200 --zoom 0.85 --page-size Letter \
|
||||||
|
$PAGES stream.pdf
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: mbbi Records</h1>
|
<h1>mbbi Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: mbbiDirect Records</h1>
|
<h1>mbbiDirect Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: mbbo Records</h1>
|
<h1>mbbo Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: mbboDirect Records</h1>
|
<h1>mbboDirect Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -132,6 +132,7 @@ div div div a {list-style-type:circle;}
|
|||||||
<a target="_parent" href="formats.html#bcd" title="Binary coded decimal LONG converter">%D</a>
|
<a target="_parent" href="formats.html#bcd" title="Binary coded decimal LONG converter">%D</a>
|
||||||
<a target="_parent" href="formats.html#chksum" title="Checksum pseudo converter">%<<em>checksum</em>></a>
|
<a target="_parent" href="formats.html#chksum" title="Checksum pseudo converter">%<<em>checksum</em>></a>
|
||||||
<a target="_parent" href="formats.html#regex" title="Perl regular expression STRING converter">%/<em>regex</em>/</a>
|
<a target="_parent" href="formats.html#regex" title="Perl regular expression STRING converter">%/<em>regex</em>/</a>
|
||||||
|
<a target="_parent" href="formats.html#regsub" title="Perl regular expression substitution pseudo converter">%#/<em>regex</em>/<em>subst</em>/</a>
|
||||||
<a target="_parent" href="formats.html#mantexp" title="MantissaExponent DOUBLE converter">%m</a>
|
<a target="_parent" href="formats.html#mantexp" title="MantissaExponent DOUBLE converter">%m</a>
|
||||||
<a target="_parent" href="formats.html#timestamp" title="Timestamp DOUBLE converter">%T</a>
|
<a target="_parent" href="formats.html#timestamp" title="Timestamp DOUBLE converter">%T</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Operating System API</h1>
|
<h1>Operating System API</h1>
|
||||||
|
|
||||||
<h2>Sorry, this documentation is still missing.</h2>
|
<h2>Sorry, this documentation is still missing.</h2>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Record Processing</h1>
|
<h1>Record Processing</h1>
|
||||||
|
|
||||||
<a name="proc"></a>
|
<a name="proc"></a>
|
||||||
<h2>1. Normal Processing</h2>
|
<h2>1. Normal Processing</h2>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Protocol Files</h1>
|
<h1>Protocol Files</h1>
|
||||||
<a name="gen"></a>
|
<a name="gen"></a>
|
||||||
<h2>1. General Information</h2>
|
<h2>1. General Information</h2>
|
||||||
<p>
|
<p>
|
||||||
@ -261,7 +261,7 @@ number in the range of <code>-128</code> to <code>255</code>,
|
|||||||
or <code>-0200</code> to <code>0377</code>, respectively.
|
or <code>-0200</code> to <code>0377</code>, respectively.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<em>StreamDevice</em> also recordgnizes the ASCII symbolic names
|
<em>StreamDevice</em> also recognizes the ASCII symbolic names
|
||||||
(not case sensitive) for several byte codes:<br>
|
(not case sensitive) for several byte codes:<br>
|
||||||
<code>NUL </code>(= <code>0x00</code>) <em>null</em><br>
|
<code>NUL </code>(= <code>0x00</code>) <em>null</em><br>
|
||||||
<code>SOH </code>(= <code>0x01</code>) <em>start of heading</em><br>
|
<code>SOH </code>(= <code>0x01</code>) <em>start of heading</em><br>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Record API</h1>
|
<h1>Record API</h1>
|
||||||
|
|
||||||
<h2>Sorry, this documentation is still missing.</h2>
|
<h2>Sorry, this documentation is still missing.</h2>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Record Types</h1>
|
<h1>Record Types</h1>
|
||||||
|
|
||||||
<h2>Supported Record Types</h2>
|
<h2>Supported Record Types</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: scalcout Records</h1>
|
<h1>scalcout Records</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>Note:</b> The scalcout record is part of the <i>calc</i> module of
|
<b>Note:</b> The scalcout record is part of the <i>calc</i> module of
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Setup</h1>
|
<h1>Setup</h1>
|
||||||
|
|
||||||
<a name="pre"></a>
|
<a name="pre"></a>
|
||||||
<h2>1. Prerequisites</h2>
|
<h2>1. Prerequisites</h2>
|
||||||
|
@ -5,8 +5,9 @@ a:hover {color: #FF0000;}
|
|||||||
body {
|
body {
|
||||||
margin-right:1em;
|
margin-right:1em;
|
||||||
margin-left:15em;
|
margin-left:15em;
|
||||||
margin-top:11ex;
|
margin-top:70px;
|
||||||
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
padding-top:1px;
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
font-size:14px;
|
font-size:14px;
|
||||||
background-color:#ffffff;
|
background-color:#ffffff;
|
||||||
}
|
}
|
||||||
@ -30,26 +31,26 @@ dt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size:225%;
|
font-size:250%;
|
||||||
margin-top:0;
|
margin-top:0;
|
||||||
font-style:italic;
|
font-style:italic;
|
||||||
font-family:serif;
|
font-weight:bold;
|
||||||
|
font-family:"Times New Roman", serif;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
position:fixed;
|
position:fixed;
|
||||||
top:0;
|
top:0;
|
||||||
left:0;
|
left:0;
|
||||||
width:100%;
|
width:100%;
|
||||||
min-height:60px;
|
|
||||||
height: 4ex;
|
|
||||||
line-height:190%;
|
line-height:190%;
|
||||||
background-color:white;
|
background-color:white;
|
||||||
border-top:6px solid #1b4486;
|
border-width:0;
|
||||||
border-bottom:4px solid #1b4486;
|
border-bottom:3px solid #1b4486;
|
||||||
white-space:nowrap;
|
white-space:nowrap;
|
||||||
background-image:url(PSI.gif);
|
background-image:url(PSI.png);
|
||||||
background-repeat:no-repeat;
|
background-repeat:no-repeat;
|
||||||
background-position:10px 2px;
|
background-position:10px 5px;
|
||||||
text-shadow: .1em .1em .1em lightgray;
|
text-shadow:.1em .1em .1em darkgray;
|
||||||
|
box-shadow:0 .3em .1em -.2em darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
@ -87,11 +88,21 @@ code {
|
|||||||
text-align:left;
|
text-align:left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
margin-left:1ex;
|
||||||
|
margin-right:1ex;
|
||||||
|
margin-top:0.5ex;
|
||||||
|
padding: 0 1ex;
|
||||||
|
border: 1px solid black;
|
||||||
|
text-align:left;
|
||||||
|
background-color:#f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
#navleft {
|
#navleft {
|
||||||
position:fixed;
|
position:fixed;
|
||||||
left:0;
|
left:0;
|
||||||
top:0;
|
top:0;
|
||||||
padding-top:9ex;
|
padding-top:70px;
|
||||||
width:14em;
|
width:14em;
|
||||||
height:100%;
|
height:100%;
|
||||||
border-style:solid;
|
border-style:solid;
|
||||||
@ -115,13 +126,9 @@ a[target=ex]:hover:after {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
a:link {color: black; text-decoration:none;}
|
a:link {text-decoration:none;}
|
||||||
a:visited {color: black; text-decoration:none;}
|
|
||||||
a:hover {color: black; text-decoration:none;}
|
|
||||||
a[target=ex] {text-decoration:underline;}
|
|
||||||
a[target=ex]:after {content:" [" attr(href) "]";}
|
a[target=ex]:after {content:" [" attr(href) "]";}
|
||||||
code {color: black; }
|
body {margin:0 4em;}
|
||||||
body {margin-left:10px;}
|
h1 {position:relative; background-position:0 0;}
|
||||||
h1 {position:absolute;}
|
|
||||||
#navleft {display:none;}
|
#navleft {display:none;}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: stringin Records</h1>
|
<h1>stringin Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: stringout Records</h1>
|
<h1>stringout Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: Tips and Tricks</h1>
|
<h1>Tips and Tricks</h1>
|
||||||
|
|
||||||
<a name="argvar"></a>
|
<a name="argvar"></a>
|
||||||
<h2>I have many almost identical protocols</h2>
|
<h2>I have many almost identical protocols</h2>
|
||||||
@ -281,7 +281,7 @@ With some more records, you can clean the message record if SEVR is not INVALID.
|
|||||||
<code>
|
<code>
|
||||||
record (calcout, "$(DEVICE):clean_1") {<br>
|
record (calcout, "$(DEVICE):clean_1") {<br>
|
||||||
field (INPA, "$(DEVICE):readcurrent.SEVR CP")<br>
|
field (INPA, "$(DEVICE):readcurrent.SEVR CP")<br>
|
||||||
field (CALC, "A!=2")<br>
|
field (CALC, "A#3")<br>
|
||||||
field (OOPT, "When Non-zero")<br>
|
field (OOPT, "When Non-zero")<br>
|
||||||
field (OUT, "$(DEVICE):clean_2.PROC")<br>
|
field (OUT, "$(DEVICE):clean_2.PROC")<br>
|
||||||
}<br>
|
}<br>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="nav.html" id="navleft"></iframe>
|
<iframe src="nav.html" id="navleft"></iframe>
|
||||||
<h1>StreamDevice: waveform Records</h1>
|
<h1>waveform Records</h1>
|
||||||
|
|
||||||
<h2>Normal Operation</h2>
|
<h2>Normal Operation</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -22,11 +22,6 @@
|
|||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
#include "StreamBuffer.h"
|
#include "StreamBuffer.h"
|
||||||
|
|
||||||
#include <epicsVersion.h>
|
|
||||||
#ifdef BASE_VERSION
|
|
||||||
#define EPICS_3_13
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EPICS_3_13
|
#ifdef EPICS_3_13
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <wdLib.h>
|
#include <wdLib.h>
|
||||||
@ -203,7 +198,7 @@ class AsynDriverInterface : StreamBusInterface
|
|||||||
|
|
||||||
// local methods
|
// local methods
|
||||||
void timerExpired();
|
void timerExpired();
|
||||||
bool connectToBus(const char* busname, int addr);
|
bool connectToBus(const char* portname, int addr);
|
||||||
void lockHandler();
|
void lockHandler();
|
||||||
void writeHandler();
|
void writeHandler();
|
||||||
void readHandler();
|
void readHandler();
|
||||||
@ -247,7 +242,7 @@ class AsynDriverInterface : StreamBusInterface
|
|||||||
public:
|
public:
|
||||||
// static creator method
|
// static creator method
|
||||||
static StreamBusInterface* getBusInterface(Client* client,
|
static StreamBusInterface* getBusInterface(Client* client,
|
||||||
const char* busname, int addr, const char* param);
|
const char* portname, int addr, const char* param);
|
||||||
};
|
};
|
||||||
|
|
||||||
RegisterStreamBusInterface(AsynDriverInterface);
|
RegisterStreamBusInterface(AsynDriverInterface);
|
||||||
@ -255,6 +250,7 @@ RegisterStreamBusInterface(AsynDriverInterface);
|
|||||||
AsynDriverInterface::
|
AsynDriverInterface::
|
||||||
AsynDriverInterface(Client* client) : StreamBusInterface(client)
|
AsynDriverInterface(Client* client) : StreamBusInterface(client)
|
||||||
{
|
{
|
||||||
|
debug ("AsynDriverInterface(%s)\n", client->name());
|
||||||
pasynCommon = NULL;
|
pasynCommon = NULL;
|
||||||
pasynOctet = NULL;
|
pasynOctet = NULL;
|
||||||
intrPvtOctet = NULL;
|
intrPvtOctet = NULL;
|
||||||
@ -266,20 +262,25 @@ AsynDriverInterface(Client* client) : StreamBusInterface(client)
|
|||||||
eventMask = 0;
|
eventMask = 0;
|
||||||
receivedEvent = 0;
|
receivedEvent = 0;
|
||||||
peeksize = 1;
|
peeksize = 1;
|
||||||
|
debug ("AsynDriverInterface(%s) createAsynUser\n", client->name());
|
||||||
pasynUser = pasynManager->createAsynUser(handleRequest,
|
pasynUser = pasynManager->createAsynUser(handleRequest,
|
||||||
handleTimeout);
|
handleTimeout);
|
||||||
assert(pasynUser);
|
assert(pasynUser);
|
||||||
pasynUser->userPvt = this;
|
pasynUser->userPvt = this;
|
||||||
#ifdef EPICS_3_13
|
#ifdef EPICS_3_13
|
||||||
|
debug ("AsynDriverInterface(%s) wdCreate()\n", client->name());
|
||||||
timer = wdCreate();
|
timer = wdCreate();
|
||||||
callbackSetCallback(expire, &timeoutCallback);
|
callbackSetCallback(expire, &timeoutCallback);
|
||||||
callbackSetUser(this, &timeoutCallback);
|
callbackSetUser(this, &timeoutCallback);
|
||||||
#else
|
#else
|
||||||
|
debug ("AsynDriverInterface(%s) epicsTimerQueueActive::allocate(true)\n", client->name());
|
||||||
timerQueue = &epicsTimerQueueActive::allocate(true);
|
timerQueue = &epicsTimerQueueActive::allocate(true);
|
||||||
assert(timerQueue);
|
assert(timerQueue);
|
||||||
|
debug ("AsynDriverInterface(%s) timerQueue->createTimer()\n", client->name());
|
||||||
timer = &timerQueue->createTimer();
|
timer = &timerQueue->createTimer();
|
||||||
assert(timer);
|
assert(timer);
|
||||||
#endif
|
#endif
|
||||||
|
debug ("AsynDriverInterface(%s) done\n", client->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
AsynDriverInterface::
|
AsynDriverInterface::
|
||||||
@ -325,17 +326,19 @@ AsynDriverInterface::
|
|||||||
}
|
}
|
||||||
|
|
||||||
// interface function getBusInterface():
|
// interface function getBusInterface():
|
||||||
// do we have this bus/addr ?
|
// do we have this port/addr ?
|
||||||
StreamBusInterface* AsynDriverInterface::
|
StreamBusInterface* AsynDriverInterface::
|
||||||
getBusInterface(Client* client,
|
getBusInterface(Client* client,
|
||||||
const char* busname, int addr, const char*)
|
const char* portname, int addr, const char*)
|
||||||
{
|
{
|
||||||
|
debug ("AsynDriverInterface::getBusInterface(%s, %s, %d)\n",
|
||||||
|
client->name(), portname, addr);
|
||||||
AsynDriverInterface* interface = new AsynDriverInterface(client);
|
AsynDriverInterface* interface = new AsynDriverInterface(client);
|
||||||
if (interface->connectToBus(busname, addr))
|
if (interface->connectToBus(portname, addr))
|
||||||
{
|
{
|
||||||
debug ("AsynDriverInterface::getBusInterface(%s, %d): "
|
debug ("AsynDriverInterface::getBusInterface(%s, %d): "
|
||||||
"new Interface allocated\n",
|
"new interface allocated\n",
|
||||||
busname, addr);
|
portname, addr);
|
||||||
return interface;
|
return interface;
|
||||||
}
|
}
|
||||||
delete interface;
|
delete interface;
|
||||||
@ -347,7 +350,66 @@ getBusInterface(Client* client,
|
|||||||
bool AsynDriverInterface::
|
bool AsynDriverInterface::
|
||||||
supportsEvent()
|
supportsEvent()
|
||||||
{
|
{
|
||||||
return (pasynInt32 != NULL) || (pasynUInt32 != NULL);
|
if (intrPvtInt32 || intrPvtUInt32) return true;
|
||||||
|
|
||||||
|
// look for interfaces for events
|
||||||
|
asynInterface* pasynInterface;
|
||||||
|
|
||||||
|
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||||
|
asynInt32Type, true);
|
||||||
|
if (pasynInterface)
|
||||||
|
{
|
||||||
|
pasynInt32 = static_cast<asynInt32*>(pasynInterface->pinterface);
|
||||||
|
pvtInt32 = pasynInterface->drvPvt;
|
||||||
|
pasynUser->reason = ASYN_REASON_SIGNAL; // required for GPIB
|
||||||
|
if (pasynInt32->registerInterruptUser(pvtInt32, pasynUser,
|
||||||
|
intrCallbackInt32, this, &intrPvtInt32) == asynSuccess)
|
||||||
|
{
|
||||||
|
printf ("%s: AsynDriverInterface::supportsEvent: "
|
||||||
|
"pasynInt32->registerInterruptUser(%p, %p, %p, %p, %p)\n",
|
||||||
|
clientName(), pvtInt32, pasynUser,
|
||||||
|
intrCallbackInt32, this, &intrPvtInt32);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const char *portname;
|
||||||
|
pasynManager->getPortName(pasynUser, &portname);
|
||||||
|
error("%s: port %s does not allow to register for "
|
||||||
|
"Int32 interrupts: %s\n",
|
||||||
|
clientName(), portname, pasynUser->errorMessage);
|
||||||
|
pasynInt32 = NULL;
|
||||||
|
intrPvtInt32 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no asynInt32 available, thus try asynUInt32
|
||||||
|
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||||
|
asynUInt32DigitalType, true);
|
||||||
|
if (pasynInterface)
|
||||||
|
{
|
||||||
|
pasynUInt32 =
|
||||||
|
static_cast<asynUInt32Digital*>(pasynInterface->pinterface);
|
||||||
|
pvtUInt32 = pasynInterface->drvPvt;
|
||||||
|
pasynUser->reason = ASYN_REASON_SIGNAL;
|
||||||
|
if (pasynUInt32->registerInterruptUser(pvtUInt32,
|
||||||
|
pasynUser, intrCallbackUInt32, this, 0xFFFFFFFF,
|
||||||
|
&intrPvtUInt32) == asynSuccess)
|
||||||
|
{
|
||||||
|
printf ("%s: AsynDriverInterface::supportsEvent: "
|
||||||
|
"pasynUInt32->registerInterruptUser(%p, %p, %p, %p, %#X, %p)\n",
|
||||||
|
clientName(), pvtUInt32, pasynUser,
|
||||||
|
intrCallbackUInt32, this, 0xFFFFFFFF, &intrPvtInt32);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const char *portname;
|
||||||
|
pasynManager->getPortName(pasynUser, &portname);
|
||||||
|
error("%s: port %s does not allow to register for "
|
||||||
|
"UInt32 interrupts: %s\n",
|
||||||
|
clientName(), portname, pasynUser->errorMessage);
|
||||||
|
pasynUInt32 = NULL;
|
||||||
|
intrPvtUInt32 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no event interface available
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsynDriverInterface::
|
bool AsynDriverInterface::
|
||||||
@ -359,20 +421,32 @@ supportsAsyncRead()
|
|||||||
if (pasynOctet->registerInterruptUser(pvtOctet, pasynUser,
|
if (pasynOctet->registerInterruptUser(pvtOctet, pasynUser,
|
||||||
intrCallbackOctet, this, &intrPvtOctet) != asynSuccess)
|
intrCallbackOctet, this, &intrPvtOctet) != asynSuccess)
|
||||||
{
|
{
|
||||||
error("%s: bus does not support asynchronous input: %s\n",
|
const char *portname;
|
||||||
clientName(), pasynUser->errorMessage);
|
int addr;
|
||||||
|
pasynManager->getPortName(pasynUser, &portname);
|
||||||
|
pasynManager->getAddr(pasynUser, &addr);
|
||||||
|
if (addr >= 0)
|
||||||
|
error("%s: asyn port %s addr %d does not support asynchronous input: %s\n",
|
||||||
|
clientName(), portname, addr, pasynUser->errorMessage);
|
||||||
|
else
|
||||||
|
error("%s: asyn port %s does not support asynchronous input: %s\n",
|
||||||
|
clientName(), portname, pasynUser->errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsynDriverInterface::
|
bool AsynDriverInterface::
|
||||||
connectToBus(const char* busname, int addr)
|
connectToBus(const char* portname, int addr)
|
||||||
{
|
{
|
||||||
if (pasynManager->connectDevice(pasynUser, busname, addr) !=
|
asynStatus status = pasynManager->connectDevice(pasynUser, portname, addr);
|
||||||
asynSuccess)
|
debug("%s: AsynDriverInterface::connectToBus(%s, %d): "
|
||||||
|
"pasynManager->connectDevice(%p, %s, %d) = %s\n",
|
||||||
|
clientName(), portname, addr, pasynUser,portname, addr,
|
||||||
|
asynStatusStr[status]);
|
||||||
|
if (status != asynSuccess)
|
||||||
{
|
{
|
||||||
// asynDriver does not know this busname/address
|
// asynDriver does not know this portname/address
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,10 +455,10 @@ connectToBus(const char* busname, int addr)
|
|||||||
// find the asynCommon interface
|
// find the asynCommon interface
|
||||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||||
asynCommonType, true);
|
asynCommonType, true);
|
||||||
if(!pasynInterface)
|
if (!pasynInterface)
|
||||||
{
|
{
|
||||||
error("%s: bus %s does not support asynCommon interface\n",
|
error("%s: asyn port %s does not support asynCommon interface\n",
|
||||||
clientName(), busname);
|
clientName(), portname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pasynCommon = static_cast<asynCommon*>(pasynInterface->pinterface);
|
pasynCommon = static_cast<asynCommon*>(pasynInterface->pinterface);
|
||||||
@ -393,10 +467,10 @@ connectToBus(const char* busname, int addr)
|
|||||||
// find the asynOctet interface
|
// find the asynOctet interface
|
||||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||||
asynOctetType, true);
|
asynOctetType, true);
|
||||||
if(!pasynInterface)
|
if (!pasynInterface)
|
||||||
{
|
{
|
||||||
error("%s: bus %s does not support asynOctet interface\n",
|
error("%s: asyn port %s does not support asynOctet interface\n",
|
||||||
clientName(), busname);
|
clientName(), portname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pasynOctet = static_cast<asynOctet*>(pasynInterface->pinterface);
|
pasynOctet = static_cast<asynOctet*>(pasynInterface->pinterface);
|
||||||
@ -405,7 +479,7 @@ connectToBus(const char* busname, int addr)
|
|||||||
// is it a GPIB interface ?
|
// is it a GPIB interface ?
|
||||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||||
asynGpibType, true);
|
asynGpibType, true);
|
||||||
if(pasynInterface)
|
if (pasynInterface)
|
||||||
{
|
{
|
||||||
pasynGpib = static_cast<asynGpib*>(pasynInterface->pinterface);
|
pasynGpib = static_cast<asynGpib*>(pasynInterface->pinterface);
|
||||||
pvtGpib = pasynInterface->drvPvt;
|
pvtGpib = pasynInterface->drvPvt;
|
||||||
@ -413,50 +487,6 @@ connectToBus(const char* busname, int addr)
|
|||||||
// (read only one byte first).
|
// (read only one byte first).
|
||||||
peeksize = inputBuffer.capacity();
|
peeksize = inputBuffer.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for interfaces for events
|
|
||||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
|
||||||
asynInt32Type, true);
|
|
||||||
if(pasynInterface)
|
|
||||||
{
|
|
||||||
pasynInt32 = static_cast<asynInt32*>(pasynInterface->pinterface);
|
|
||||||
pvtInt32 = pasynInterface->drvPvt;
|
|
||||||
pasynUser->reason = ASYN_REASON_SIGNAL; // required for GPIB
|
|
||||||
if (pasynInt32->registerInterruptUser(pvtInt32, pasynUser,
|
|
||||||
intrCallbackInt32, this, &intrPvtInt32) == asynSuccess)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
error("%s: bus %s does not allow to register for "
|
|
||||||
"Int32 interrupts: %s\n",
|
|
||||||
clientName(), busname, pasynUser->errorMessage);
|
|
||||||
pasynInt32 = NULL;
|
|
||||||
intrPvtInt32 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no asynInt32 available, thus try asynUInt32
|
|
||||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
|
||||||
asynUInt32DigitalType, true);
|
|
||||||
if(pasynInterface)
|
|
||||||
{
|
|
||||||
pasynUInt32 =
|
|
||||||
static_cast<asynUInt32Digital*>(pasynInterface->pinterface);
|
|
||||||
pvtUInt32 = pasynInterface->drvPvt;
|
|
||||||
pasynUser->reason = ASYN_REASON_SIGNAL;
|
|
||||||
if (pasynUInt32->registerInterruptUser(pvtUInt32,
|
|
||||||
pasynUser, intrCallbackUInt32, this, 0xFFFFFFFF,
|
|
||||||
&intrPvtUInt32) == asynSuccess)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
error("%s: bus %s does not allow to register for "
|
|
||||||
"UInt32 interrupts: %s\n",
|
|
||||||
clientName(), busname, pasynUser->errorMessage);
|
|
||||||
pasynUInt32 = NULL;
|
|
||||||
intrPvtUInt32 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no event interface available, never mind
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,23 +495,14 @@ connectToBus(const char* busname, int addr)
|
|||||||
bool AsynDriverInterface::
|
bool AsynDriverInterface::
|
||||||
lockRequest(unsigned long lockTimeout_ms)
|
lockRequest(unsigned long lockTimeout_ms)
|
||||||
{
|
{
|
||||||
int connected;
|
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
|
|
||||||
debug("AsynDriverInterface::lockRequest(%s, %ld msec)\n",
|
debug("AsynDriverInterface::lockRequest(%s, %ld msec)\n",
|
||||||
clientName(), lockTimeout_ms);
|
clientName(), lockTimeout_ms);
|
||||||
lockTimeout = lockTimeout_ms ? lockTimeout_ms*0.001 : -1.0;
|
lockTimeout = lockTimeout_ms ? lockTimeout_ms*0.001 : -1.0;
|
||||||
ioAction = Lock;
|
ioAction = Lock;
|
||||||
status = pasynManager->isConnected(pasynUser, &connected);
|
|
||||||
if (status != asynSuccess)
|
|
||||||
{
|
|
||||||
error("%s: pasynManager->isConnected() failed: %s\n",
|
|
||||||
clientName(), pasynUser->errorMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
status = pasynManager->queueRequest(pasynUser,
|
status = pasynManager->queueRequest(pasynUser,
|
||||||
connected ? priority() : asynQueuePriorityConnect,
|
priority(), lockTimeout);
|
||||||
lockTimeout);
|
|
||||||
if (status != asynSuccess)
|
if (status != asynSuccess)
|
||||||
{
|
{
|
||||||
error("%s lockRequest: pasynManager->queueRequest() failed: %s\n",
|
error("%s lockRequest: pasynManager->queueRequest() failed: %s\n",
|
||||||
@ -503,9 +524,13 @@ connectToAsynPort()
|
|||||||
debug("AsynDriverInterface::connectToAsynPort(%s)\n",
|
debug("AsynDriverInterface::connectToAsynPort(%s)\n",
|
||||||
clientName());
|
clientName());
|
||||||
status = pasynManager->isConnected(pasynUser, &connected);
|
status = pasynManager->isConnected(pasynUser, &connected);
|
||||||
|
debug("%s: AsynDriverInterface::connectToAsynPort: "
|
||||||
|
"pasynManager->isConnected(%p, %p) = %s => %s\n",
|
||||||
|
clientName(), pasynUser, &connected, asynStatusStr[status],
|
||||||
|
connected ? "yes" : "no");
|
||||||
if (status != asynSuccess)
|
if (status != asynSuccess)
|
||||||
{
|
{
|
||||||
error("%s: pasynManager->isConnected() failed: %s\n",
|
error("%s connectToAsynPort: pasynManager->isConnected() failed: %s\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -537,13 +562,19 @@ connectToAsynPort()
|
|||||||
clientName(), connected ? "already" : "not yet");
|
clientName(), connected ? "already" : "not yet");
|
||||||
if (!connected)
|
if (!connected)
|
||||||
{
|
{
|
||||||
|
printf ("%s: AsynDriverInterface::connectToAsynPort: "
|
||||||
|
"pasynCommon->connect(%p, %p)\n",
|
||||||
|
clientName(), pvtCommon, pasynUser);
|
||||||
status = pasynCommon->connect(pvtCommon, pasynUser);
|
status = pasynCommon->connect(pvtCommon, pasynUser);
|
||||||
|
printf ("%s: AsynDriverInterface::connectToAsynPort: "
|
||||||
|
"pasynCommon->connect(%p, %p) = %s\n",
|
||||||
|
clientName(), pvtCommon, pasynUser, asynStatusStr[status]);
|
||||||
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
||||||
"status=%s\n",
|
"status=%s\n",
|
||||||
clientName(), asynStatusStr[status]);
|
clientName(), asynStatusStr[status]);
|
||||||
if (status != asynSuccess)
|
if (status != asynSuccess)
|
||||||
{
|
{
|
||||||
error("%s: pasynCommon->connect() failed: %s\n",
|
error("%s connectToAsynPort: pasynCommon->connect() failed: %s\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -561,21 +592,37 @@ connectToAsynPort()
|
|||||||
void AsynDriverInterface::
|
void AsynDriverInterface::
|
||||||
lockHandler()
|
lockHandler()
|
||||||
{
|
{
|
||||||
int connected;
|
asynStatus status;
|
||||||
|
|
||||||
debug("AsynDriverInterface::lockHandler(%s)\n",
|
debug("AsynDriverInterface::lockHandler(%s)\n",
|
||||||
clientName());
|
clientName());
|
||||||
pasynManager->blockProcessCallback(pasynUser, false);
|
|
||||||
connected = connectToAsynPort();
|
status = pasynManager->blockProcessCallback(pasynUser, false);
|
||||||
lockCallback(connected ? StreamIoSuccess : StreamIoFault);
|
if (status != asynSuccess)
|
||||||
|
{
|
||||||
|
error("%s lockHandler: pasynManager->blockProcessCallback() failed: %s\n",
|
||||||
|
clientName(), pasynUser->errorMessage);
|
||||||
|
lockCallback(StreamIoFault);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lockCallback(StreamIoSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interface function: we don't need exclusive access any more
|
// interface function: we don't need exclusive access any more
|
||||||
bool AsynDriverInterface::
|
bool AsynDriverInterface::
|
||||||
unlock()
|
unlock()
|
||||||
{
|
{
|
||||||
|
asynStatus status;
|
||||||
|
|
||||||
debug("AsynDriverInterface::unlock(%s)\n",
|
debug("AsynDriverInterface::unlock(%s)\n",
|
||||||
clientName());
|
clientName());
|
||||||
pasynManager->unblockProcessCallback(pasynUser, false);
|
status = pasynManager->unblockProcessCallback(pasynUser, false);
|
||||||
|
if (status != asynSuccess)
|
||||||
|
{
|
||||||
|
error("%s unlock: pasynManager->unblockProcessCallback() failed: %s\n",
|
||||||
|
clientName(), pasynUser->errorMessage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,20 +665,33 @@ writeHandler()
|
|||||||
asynStatus status;
|
asynStatus status;
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
|
||||||
|
pasynUser->timeout = 0;
|
||||||
|
if (!pasynGpib)
|
||||||
// discard any early input, but forward it to potential async records
|
// discard any early input, but forward it to potential async records
|
||||||
// thus do not use pasynOctet->flush()
|
// thus do not use pasynOctet->flush()
|
||||||
pasynUser->timeout = 0;
|
// unfortunately we cannot do this with GPIB because addressing a device as talker
|
||||||
|
// when it has nothing to say is an error. Also timeout=0 does not help here (would need
|
||||||
|
// a change in asynGPIB), thus use flush() for GPIB.
|
||||||
do {
|
do {
|
||||||
char buffer [256];
|
char buffer [256];
|
||||||
size_t received = sizeof(buffer);
|
size_t received = 0;
|
||||||
int eomReason = 0;
|
int eomReason = 0;
|
||||||
|
debug("AsynDriverInterface::writeHandler(%s): reading old input\n",
|
||||||
|
clientName());
|
||||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||||
buffer, received, &received, &eomReason);
|
buffer, sizeof(buffer), &received, &eomReason);
|
||||||
|
if (status == asynError || received == 0) break;
|
||||||
#ifndef NO_TEMPORARY
|
#ifndef NO_TEMPORARY
|
||||||
if (received) debug("AsynDriverInterface::writeHandler(%s): flushing %ld bytes: \"%s\"\n",
|
if (received) debug("AsynDriverInterface::writeHandler(%s): flushing %ld bytes: \"%s\"\n",
|
||||||
clientName(), (long)received, StreamBuffer(buffer, received).expand()());
|
clientName(), (long)received, StreamBuffer(buffer, received).expand()());
|
||||||
#endif
|
#endif
|
||||||
} while (status != asynTimeout);
|
} while (status == asynSuccess);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("AsynDriverInterface::writeHandler(%s): flushing old input\n",
|
||||||
|
clientName());
|
||||||
|
pasynOctet->flush(pvtOctet, pasynUser);
|
||||||
|
}
|
||||||
|
|
||||||
// discard any early events
|
// discard any early events
|
||||||
receivedEvent = 0;
|
receivedEvent = 0;
|
||||||
@ -658,14 +718,26 @@ writeHandler()
|
|||||||
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
}
|
}
|
||||||
|
pasynUser->errorMessage[0] = 0;
|
||||||
status = pasynOctet->write(pvtOctet, pasynUser,
|
status = pasynOctet->write(pvtOctet, pasynUser,
|
||||||
outputBuffer, outputSize, &written);
|
outputBuffer, outputSize, &written);
|
||||||
|
#ifndef NO_TEMPORARY
|
||||||
debug("AsynDriverInterface::writeHandler(%s): "
|
debug("AsynDriverInterface::writeHandler(%s): "
|
||||||
"write(..., outputSize=%ld, written=%ld) "
|
"write(..., \"%s\", outputSize=%ld, written=%ld) "
|
||||||
"[timeout=%g sec] = %s\n",
|
"[timeout=%g sec] = %s (%s)\n",
|
||||||
clientName(), (long)outputSize, (long)written,
|
clientName(),
|
||||||
pasynUser->timeout, asynStatusStr[status]);
|
StreamBuffer(outputBuffer, outputSize).expand()(),
|
||||||
|
(long)outputSize, (long)written,
|
||||||
|
pasynUser->timeout, asynStatusStr[status],
|
||||||
|
pasynUser->errorMessage);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (oldeoslen >= 0) // restore asyn terminator
|
||||||
|
{
|
||||||
|
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
||||||
|
oldeos, oldeoslen);
|
||||||
|
}
|
||||||
|
|
||||||
// Up to asyn 4.17 I can't see when the server has disconnected. Why?
|
// Up to asyn 4.17 I can't see when the server has disconnected. Why?
|
||||||
int connected;
|
int connected;
|
||||||
pasynManager->isConnected(pasynUser, &connected);
|
pasynManager->isConnected(pasynUser, &connected);
|
||||||
@ -673,17 +745,12 @@ writeHandler()
|
|||||||
"device is %sconnected\n",
|
"device is %sconnected\n",
|
||||||
clientName(),connected?"":"dis");
|
clientName(),connected?"":"dis");
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
error("%s: connection closed in write\n",
|
error("%s: write failed because connection was closed by device\n",
|
||||||
clientName());
|
clientName());
|
||||||
writeCallback(StreamIoFault);
|
writeCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldeoslen >= 0) // restore asyn terminator
|
|
||||||
{
|
|
||||||
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
|
||||||
oldeos, oldeoslen);
|
|
||||||
}
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case asynSuccess:
|
case asynSuccess:
|
||||||
@ -708,32 +775,34 @@ writeHandler()
|
|||||||
writeCallback(StreamIoSuccess);
|
writeCallback(StreamIoSuccess);
|
||||||
return;
|
return;
|
||||||
case asynTimeout:
|
case asynTimeout:
|
||||||
|
error("%s: asynTimeout (%g sec) in write. Asyn driver says: \"%s\"\n",
|
||||||
|
clientName(), pasynUser->timeout, pasynUser->errorMessage);
|
||||||
writeCallback(StreamIoTimeout);
|
writeCallback(StreamIoTimeout);
|
||||||
return;
|
return;
|
||||||
case asynOverflow:
|
case asynOverflow:
|
||||||
error("%s: asynOverflow in write: %s\n",
|
error("%s: asynOverflow in write. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
writeCallback(StreamIoFault);
|
writeCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
case asynError:
|
case asynError:
|
||||||
error("%s: asynError in write: %s\n",
|
error("%s: asynError in write. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
writeCallback(StreamIoFault);
|
writeCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
#ifdef ASYN_VERSION // asyn >= 4.14
|
#ifdef ASYN_VERSION // asyn >= 4.14
|
||||||
case asynDisconnected:
|
case asynDisconnected:
|
||||||
error("%s: asynDisconnected in write: %s\n",
|
error("%s: asynDisconnected in write. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
writeCallback(StreamIoFault);
|
writeCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
case asynDisabled:
|
case asynDisabled:
|
||||||
error("%s: asynDisconnected in write: %s\n",
|
error("%s: asynDisconnected in write. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
writeCallback(StreamIoFault);
|
writeCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
error("%s: unknown asyn error in write: %s\n",
|
error("%s: unknown asyn error in write. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
writeCallback(StreamIoFault);
|
writeCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
@ -824,6 +893,11 @@ readHandler()
|
|||||||
oldeoslen = -1;
|
oldeoslen = -1;
|
||||||
} else do {
|
} else do {
|
||||||
// device (e.g. GPIB) might not accept full eos length
|
// device (e.g. GPIB) might not accept full eos length
|
||||||
|
if ((int)deveoslen == oldeoslen && strcmp(deveos, oldeos) == 0)
|
||||||
|
{
|
||||||
|
// nothing to do: old and new eos are the same
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (pasynOctet->setInputEos(pvtOctet, pasynUser,
|
if (pasynOctet->setInputEos(pvtOctet, pasynUser,
|
||||||
deveos, deveoslen) == asynSuccess)
|
deveos, deveoslen) == asynSuccess)
|
||||||
{
|
{
|
||||||
@ -831,8 +905,9 @@ readHandler()
|
|||||||
if (ioAction != AsyncRead)
|
if (ioAction != AsyncRead)
|
||||||
{
|
{
|
||||||
debug("AsynDriverInterface::readHandler(%s) "
|
debug("AsynDriverInterface::readHandler(%s) "
|
||||||
"input EOS set to %s\n",
|
"input EOS changed from \"%s\" to \"%s\"\n",
|
||||||
clientName(),
|
clientName(),
|
||||||
|
StreamBuffer(oldeos, oldeoslen).expand()(),
|
||||||
StreamBuffer(deveos, deveoslen).expand()());
|
StreamBuffer(deveos, deveoslen).expand()());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -888,6 +963,7 @@ readHandler()
|
|||||||
readMore = 0;
|
readMore = 0;
|
||||||
received = 0;
|
received = 0;
|
||||||
eomReason = 0;
|
eomReason = 0;
|
||||||
|
pasynUser->errorMessage[0] = 0;
|
||||||
|
|
||||||
debug("AsynDriverInterface::readHandler(%s): ioAction=%s "
|
debug("AsynDriverInterface::readHandler(%s): ioAction=%s "
|
||||||
"read(..., bytesToRead=%ld, ...) "
|
"read(..., bytesToRead=%ld, ...) "
|
||||||
@ -896,12 +972,13 @@ readHandler()
|
|||||||
bytesToRead, pasynUser->timeout);
|
bytesToRead, pasynUser->timeout);
|
||||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||||
buffer, bytesToRead, &received, &eomReason);
|
buffer, bytesToRead, &received, &eomReason);
|
||||||
|
#ifndef NO_TEMPORARY
|
||||||
debug("AsynDriverInterface::readHandler(%s): "
|
debug("AsynDriverInterface::readHandler(%s): "
|
||||||
"read returned %s: ioAction=%s received=%ld, eomReason=%s, buffer=\"%s\"\n",
|
"read returned %s: ioAction=%s received=%ld, eomReason=%s, buffer=\"%s\"\n",
|
||||||
clientName(), asynStatusStr[status], ioActionStr[ioAction],
|
clientName(), asynStatusStr[status], ioActionStr[ioAction],
|
||||||
(long)received,eomReasonStr[eomReason&0x7],
|
(long)received,eomReasonStr[eomReason&0x7],
|
||||||
StreamBuffer(buffer, received).expand()());
|
StreamBuffer(buffer, received).expand()());
|
||||||
|
#endif
|
||||||
pasynManager->isConnected(pasynUser, &connected);
|
pasynManager->isConnected(pasynUser, &connected);
|
||||||
debug("AsynDriverInterface::readHandler(%s): "
|
debug("AsynDriverInterface::readHandler(%s): "
|
||||||
"device is now %sconnected\n",
|
"device is now %sconnected\n",
|
||||||
@ -1031,29 +1108,29 @@ readHandler()
|
|||||||
}
|
}
|
||||||
peeksize = inputBuffer.capacity();
|
peeksize = inputBuffer.capacity();
|
||||||
// deliver whatever we could save
|
// deliver whatever we could save
|
||||||
error("%s: asynOverflow in read: %s\n",
|
error("%s: asynOverflow in read. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
readCallback(StreamIoFault, buffer, received);
|
readCallback(StreamIoFault, buffer, received);
|
||||||
break;
|
break;
|
||||||
case asynError:
|
case asynError:
|
||||||
error("%s: asynError in read: %s\n",
|
error("%s: asynError in read. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
readCallback(StreamIoFault, buffer, received);
|
readCallback(StreamIoFault, buffer, received);
|
||||||
break;
|
break;
|
||||||
#ifdef ASYN_VERSION // asyn >= 4.14
|
#ifdef ASYN_VERSION // asyn >= 4.14
|
||||||
case asynDisconnected:
|
case asynDisconnected:
|
||||||
error("%s: asynDisconnected in read: %s\n",
|
error("%s: asynDisconnected in read. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
readCallback(StreamIoFault);
|
readCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
case asynDisabled:
|
case asynDisabled:
|
||||||
error("%s: asynDisconnected in read: %s\n",
|
error("%s: asynDisconnected in read. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
readCallback(StreamIoFault);
|
readCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
error("%s: unknown asyn error in read: %s\n",
|
error("%s: unknown asyn error in read. Asyn driver says: \"%s\"\n",
|
||||||
clientName(), pasynUser->errorMessage);
|
clientName(), pasynUser->errorMessage);
|
||||||
readCallback(StreamIoFault);
|
readCallback(StreamIoFault);
|
||||||
return;
|
return;
|
||||||
@ -1075,10 +1152,16 @@ readHandler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore original EOS
|
// restore original EOS
|
||||||
if (oldeoslen >= 0)
|
if (oldeoslen >= 0 && oldeoslen != (int)deveoslen && strcmp(deveos, oldeos) != 0)
|
||||||
{
|
{
|
||||||
pasynOctet->setInputEos(pvtOctet, pasynUser,
|
pasynOctet->setInputEos(pvtOctet, pasynUser,
|
||||||
oldeos, oldeoslen);
|
oldeos, oldeoslen);
|
||||||
|
#ifndef NO_TEMPORARY
|
||||||
|
debug("AsynDriverInterface::readHandler(%s) "
|
||||||
|
"input EOS restored to \"%s\"\n",
|
||||||
|
clientName(),
|
||||||
|
StreamBuffer(oldeos, oldeoslen).expand()());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1216,7 +1299,7 @@ acceptEvent(unsigned long mask, unsigned long replytimeout_ms)
|
|||||||
}
|
}
|
||||||
eventMask = mask;
|
eventMask = mask;
|
||||||
ioAction = ReceiveEvent;
|
ioAction = ReceiveEvent;
|
||||||
startTimer(replytimeout_ms*0.001);
|
if (replytimeout_ms) startTimer(replytimeout_ms*0.001);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ class BCDConverter : public StreamFormatConverter
|
|||||||
};
|
};
|
||||||
|
|
||||||
int BCDConverter::
|
int BCDConverter::
|
||||||
parse(const StreamFormat&, StreamBuffer&, const char*&, bool)
|
parse(const StreamFormat& fmt, StreamBuffer&, const char*&, bool)
|
||||||
{
|
{
|
||||||
return long_format;
|
return (fmt.flags & sign_flag) ? signed_format : unsigned_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BCDConverter::
|
bool BCDConverter::
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
#include "StreamFormatConverter.h"
|
#include "StreamFormatConverter.h"
|
||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
|
|
||||||
@ -32,51 +33,59 @@ class BinaryConverter : public StreamFormatConverter
|
|||||||
};
|
};
|
||||||
|
|
||||||
int BinaryConverter::
|
int BinaryConverter::
|
||||||
parse(const StreamFormat& format, StreamBuffer& info,
|
parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||||
const char*& source, bool)
|
const char*& source, bool)
|
||||||
{
|
{
|
||||||
if (format.conv == 'B')
|
if (fmt.conv == 'b')
|
||||||
{
|
{
|
||||||
// user defined characters for %B (next 2 in source)
|
// default characters 0 and 1 for %b
|
||||||
|
info.append("01");
|
||||||
|
return unsigned_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
// user defined characters for %B (next 2 in source)
|
||||||
|
if (*source)
|
||||||
|
{
|
||||||
|
if (*source == esc) source++;
|
||||||
|
info.append(*source++);
|
||||||
if (*source)
|
if (*source)
|
||||||
{
|
{
|
||||||
if (*source == esc) source++;
|
if (*source == esc) source++;
|
||||||
info.append(*source++);
|
info.append(*source++);
|
||||||
if (*source)
|
return unsigned_format;
|
||||||
{
|
|
||||||
if (*source == esc) source++;
|
|
||||||
info.append(*source++);
|
|
||||||
return long_format;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
error("Missing characters after %%B format conversion\n");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
// default characters for %b
|
error("Missing characters after %%B format conversion\n");
|
||||||
info.append("01");
|
return false;
|
||||||
return long_format;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BinaryConverter::
|
bool BinaryConverter::
|
||||||
printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||||
{
|
{
|
||||||
int prec = format.prec;
|
int prec = fmt.prec;
|
||||||
if (prec == -1)
|
if (prec == -1)
|
||||||
{
|
{
|
||||||
// find number of significant bits
|
// Find number of significant bits is nothing is specified.
|
||||||
prec = sizeof (value) * 8;
|
unsigned long x = (unsigned long) value;
|
||||||
while (prec && (value & (1L << (prec - 1))) == 0) prec--;
|
prec = 32;
|
||||||
|
#if (LONG_BIT > 32)
|
||||||
|
if (x > 0xFFFFFFFF) { prec = 64; x >>=32; }
|
||||||
|
#endif
|
||||||
|
if (x <= 0x0000FFFF) { prec -= 16; x <<=16; }
|
||||||
|
if (x <= 0x00FFFFFF) { prec -= 8; x <<=8; }
|
||||||
|
if (x <= 0x0FFFFFFF) { prec -= 4; x <<=4; }
|
||||||
|
if (x <= 0x3FFFFFFF) { prec -= 2; x <<=2; }
|
||||||
|
if (x <= 0x7FFFFFFF) { prec -= 1; }
|
||||||
}
|
}
|
||||||
if (prec == 0) prec++; // print at least one bit
|
|
||||||
int width = prec;
|
int width = prec;
|
||||||
if (format.width > width) width = format.width;
|
if (fmt.width > width) width = fmt.width;
|
||||||
char zero = format.info[0];
|
char zero = fmt.info[0];
|
||||||
char one = format.info[1];
|
char one = fmt.info[1];
|
||||||
char fill = (format.flags & zero_flag) ? zero : ' ';
|
char fill = (fmt.flags & zero_flag) ? zero : ' ';
|
||||||
if (format.flags & alt_flag)
|
if (fmt.flags & alt_flag)
|
||||||
{
|
{
|
||||||
// little endian (least significant bit first)
|
// little endian (least significant bit first)
|
||||||
if (!(format.flags & left_flag))
|
if (!(fmt.flags & left_flag))
|
||||||
{
|
{
|
||||||
// pad left
|
// pad left
|
||||||
while (width > prec)
|
while (width > prec)
|
||||||
@ -100,7 +109,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// big endian (most significant bit first)
|
// big endian (most significant bit first)
|
||||||
if (!(format.flags & left_flag))
|
if (!(fmt.flags & left_flag))
|
||||||
{
|
{
|
||||||
// pad left
|
// pad left
|
||||||
while (width > prec)
|
while (width > prec)
|
||||||
@ -124,18 +133,18 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int BinaryConverter::
|
int BinaryConverter::
|
||||||
scanLong(const StreamFormat& format, const char* input, long& value)
|
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||||
{
|
{
|
||||||
long val = 0;
|
long val = 0;
|
||||||
int width = format.width;
|
int width = fmt.width;
|
||||||
if (width == 0) width = -1;
|
if (width == 0) width = -1;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
char zero = format.info[0];
|
char zero = fmt.info[0];
|
||||||
char one = format.info[1];
|
char one = fmt.info[1];
|
||||||
if (!isspace(zero) && !isspace(one))
|
if (!isspace(zero) && !isspace(one))
|
||||||
while (isspace(input[length])) length++; // skip whitespaces
|
while (isspace(input[length])) length++; // skip whitespaces
|
||||||
if (input[length] != zero && input[length] != one) return -1;
|
if (input[length] != zero && input[length] != one) return -1;
|
||||||
if (format.flags & alt_flag)
|
if (fmt.flags & alt_flag)
|
||||||
{
|
{
|
||||||
// little endian (least significan bit first)
|
// little endian (least significan bit first)
|
||||||
long mask = 1;
|
long mask = 1;
|
||||||
|
@ -22,17 +22,26 @@
|
|||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
#if defined(__vxworks) || defined(vxWorks) || defined(_WIN32) || defined(__rtems__)
|
#if defined(__vxworks) || defined(vxWorks) || defined(_WIN32) || defined(__rtems__)
|
||||||
// These systems have no strncasecmp
|
// These systems have no strncasecmp
|
||||||
|
#include <epicsVersion.h>
|
||||||
|
#ifdef BASE_VERSION
|
||||||
|
// 3.13
|
||||||
|
#include <ctype.h>
|
||||||
|
static int strncasecmp(const char *s1, const char *s2, size_t n)
|
||||||
|
{
|
||||||
|
int r=0;
|
||||||
|
while (n && (r = toupper(*s1)-toupper(*s2)) == 0) { n--; s1++; s2++; };
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#else
|
||||||
#include <epicsString.h>
|
#include <epicsString.h>
|
||||||
#define strncasecmp epicsStrnCaseCmp
|
#define strncasecmp epicsStrnCaseCmp
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
typedef unsigned long ulong;
|
typedef unsigned int (*checksumFunc)(const unsigned char* data, unsigned int len, unsigned int init);
|
||||||
typedef unsigned char uchar;
|
|
||||||
|
|
||||||
typedef ulong (*checksumFunc)(const uchar* data, ulong len, ulong init);
|
static unsigned int sum(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||||
|
|
||||||
static ulong sum(const uchar* data, ulong len, ulong sum)
|
|
||||||
{
|
{
|
||||||
while (len--)
|
while (len--)
|
||||||
{
|
{
|
||||||
@ -41,7 +50,7 @@ static ulong sum(const uchar* data, ulong len, ulong sum)
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong xor8(const uchar* data, ulong len, ulong sum)
|
static unsigned int xor8(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||||
{
|
{
|
||||||
while (len--)
|
while (len--)
|
||||||
{
|
{
|
||||||
@ -50,15 +59,15 @@ static ulong xor8(const uchar* data, ulong len, ulong sum)
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong xor7(const uchar* data, ulong len, ulong sum)
|
static unsigned int xor7(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||||
{
|
{
|
||||||
return xor8(data, len, sum) & 0x7F;
|
return xor8(data, len, sum) & 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x07(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x07(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^8 + x^2 + x^1 + x^0 (0x07)
|
// x^8 + x^2 + x^1 + x^0 (0x07)
|
||||||
const static uchar table[256] = {
|
const static unsigned char table[256] = {
|
||||||
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
||||||
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||||
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
||||||
@ -96,10 +105,10 @@ static ulong crc_0x07(const uchar* data, ulong len, ulong crc)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x31(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x31(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^8 + x^5 + x^4 + x^0 (0x31)
|
// x^8 + x^5 + x^4 + x^0 (0x31)
|
||||||
const static uchar table[256] = {
|
const static unsigned char table[256] = {
|
||||||
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
|
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
|
||||||
0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
|
0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
|
||||||
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
|
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
|
||||||
@ -137,90 +146,90 @@ static ulong crc_0x31(const uchar* data, ulong len, ulong crc)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x8005(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x8005(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
||||||
const static unsigned short table[256] = {
|
const static unsigned short table[256] = {
|
||||||
0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011,
|
0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
|
||||||
0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022,
|
0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
|
||||||
0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072,
|
0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
|
||||||
0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041,
|
0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
|
||||||
0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2,
|
0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
|
||||||
0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1,
|
0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
|
||||||
0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1,
|
0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
|
||||||
0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082,
|
0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
|
||||||
0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192,
|
0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
|
||||||
0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1,
|
0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
|
||||||
0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1,
|
0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
|
||||||
0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2,
|
0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
|
||||||
0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151,
|
0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
|
||||||
0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162,
|
0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
|
||||||
0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132,
|
0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
|
||||||
0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101,
|
0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
|
||||||
0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312,
|
0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
|
||||||
0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321,
|
0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
|
||||||
0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371,
|
0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
|
||||||
0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342,
|
0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
|
||||||
0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1,
|
0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
|
||||||
0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2,
|
0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
|
||||||
0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2,
|
0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
|
||||||
0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381,
|
0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
|
||||||
0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291,
|
0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
|
||||||
0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2,
|
0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
|
||||||
0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2,
|
0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
|
||||||
0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1,
|
0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
|
||||||
0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252,
|
0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
|
||||||
0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261,
|
0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
|
||||||
0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231,
|
0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
|
||||||
0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202 };
|
0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 };
|
||||||
|
|
||||||
while (len--) crc = table[((crc>>8) ^ *data++) & 0xFF] ^ (crc << 8);
|
while (len--) crc = table[((crc>>8) ^ *data++) & 0xFF] ^ (crc << 8);
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x8005_r(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x8005_r(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
||||||
// reflected
|
// reflected
|
||||||
const static unsigned short table[256] = {
|
const static unsigned short table[256] = {
|
||||||
0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
|
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||||
0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
|
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||||||
0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
|
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||||||
0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
|
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||||||
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
|
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||||||
0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
|
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||||||
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
|
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||||||
0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
|
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||||||
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
|
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||||||
0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
|
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||||||
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
|
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||||||
0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
|
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||||||
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
|
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||||||
0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
|
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||||||
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
|
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||||||
0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
|
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||||||
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
|
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||||||
0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
|
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||||||
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
|
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||||||
0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
|
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||||||
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
|
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||||||
0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
|
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||||||
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
|
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||||||
0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
|
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||||||
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
|
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||||||
0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
|
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||||||
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
|
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||||||
0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
|
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||||||
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
|
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||||||
0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
|
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||||||
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
|
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||||||
0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040 };
|
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };
|
||||||
|
|
||||||
while (len--) crc = table[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
|
while (len--) crc = table[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x1021(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x1021(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^16 + x^12 + x^5 + x^0 (0x1021)
|
// x^16 + x^12 + x^5 + x^0 (0x1021)
|
||||||
const static unsigned short table[256] = {
|
const static unsigned short table[256] = {
|
||||||
@ -261,7 +270,7 @@ static ulong crc_0x1021(const uchar* data, ulong len, ulong crc)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x04C11DB7(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x04C11DB7(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
||||||
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
||||||
@ -335,7 +344,7 @@ static ulong crc_0x04C11DB7(const uchar* data, ulong len, ulong crc)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong crc_0x04C11DB7_r(const uchar* data, ulong len, ulong crc)
|
static unsigned int crc_0x04C11DB7_r(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||||
{
|
{
|
||||||
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
||||||
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
||||||
@ -410,13 +419,13 @@ static ulong crc_0x04C11DB7_r(const uchar* data, ulong len, ulong crc)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong adler32(const uchar* data, ulong len, ulong init)
|
static unsigned int adler32(const unsigned char* data, unsigned int len, unsigned int init)
|
||||||
{
|
{
|
||||||
ulong a = init & 0xFFFF;
|
unsigned int a = init & 0xFFFF;
|
||||||
ulong b = (init >> 16) & 0xFFFF;
|
unsigned int b = (init >> 16) & 0xFFFF;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
ulong tlen = len > 5550 ? 5550 : len;
|
unsigned int tlen = len > 5550 ? 5550 : len;
|
||||||
len -= tlen;
|
len -= tlen;
|
||||||
do {
|
do {
|
||||||
a += *data++;
|
a += *data++;
|
||||||
@ -431,10 +440,10 @@ static ulong adler32(const uchar* data, ulong len, ulong init)
|
|||||||
return b << 16 | a;
|
return b << 16 | a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong hexsum(const uchar* data, ulong len, ulong sum)
|
static unsigned int hexsum(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||||
{
|
{
|
||||||
// Add all hex digits, ignore all other bytes.
|
// Add all hex digits, ignore all other bytes.
|
||||||
ulong d;
|
unsigned int d;
|
||||||
while (len--)
|
while (len--)
|
||||||
{
|
{
|
||||||
d = toupper(*data++);
|
d = toupper(*data++);
|
||||||
@ -452,8 +461,8 @@ struct checksum
|
|||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
checksumFunc func;
|
checksumFunc func;
|
||||||
ulong init;
|
unsigned int init;
|
||||||
ulong xorout;
|
unsigned int xorout;
|
||||||
signed char bytes;
|
signed char bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -465,20 +474,6 @@ static checksum checksumMap[] =
|
|||||||
{"sum8", sum, 0x00, 0x00, 1}, // 0xDD
|
{"sum8", sum, 0x00, 0x00, 1}, // 0xDD
|
||||||
{"sum16", sum, 0x0000, 0x0000, 2}, // 0x01DD
|
{"sum16", sum, 0x0000, 0x0000, 2}, // 0x01DD
|
||||||
{"sum32", sum, 0x00000000, 0x00000000, 4}, // 0x000001DD
|
{"sum32", sum, 0x00000000, 0x00000000, 4}, // 0x000001DD
|
||||||
{"nsum", sum, 0xFF, 0xFF, 1}, // 0x23
|
|
||||||
{"negsum", sum, 0xFF, 0xFF, 1}, // 0x23
|
|
||||||
{"-sum", sum, 0xFF, 0xFF, 1}, // 0x23
|
|
||||||
{"nsum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
|
||||||
{"negsum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
|
||||||
{"-sum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
|
||||||
{"nsum16", sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
|
||||||
{"negsum16",sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
|
||||||
{"-sum16", sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
|
||||||
{"nsum32", sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
|
||||||
{"negsum32",sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
|
||||||
{"-sum32", sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
|
||||||
{"notsum", sum, 0x00, 0xFF, 1}, // 0x22
|
|
||||||
{"~sum", sum, 0x00, 0xFF, 1}, // 0x22
|
|
||||||
{"xor", xor8, 0x00, 0x00, 1}, // 0x31
|
{"xor", xor8, 0x00, 0x00, 1}, // 0x31
|
||||||
{"xor8", xor8, 0x00, 0x00, 1}, // 0x31
|
{"xor8", xor8, 0x00, 0x00, 1}, // 0x31
|
||||||
{"xor7", xor7, 0x00, 0x00, 1}, // 0x31
|
{"xor7", xor7, 0x00, 0x00, 1}, // 0x31
|
||||||
@ -486,6 +481,7 @@ static checksum checksumMap[] =
|
|||||||
{"ccitt8", crc_0x31, 0x00, 0x00, 1}, // 0xA1
|
{"ccitt8", crc_0x31, 0x00, 0x00, 1}, // 0xA1
|
||||||
{"crc16", crc_0x8005, 0x0000, 0x0000, 2}, // 0xFEE8
|
{"crc16", crc_0x8005, 0x0000, 0x0000, 2}, // 0xFEE8
|
||||||
{"crc16r", crc_0x8005_r, 0x0000, 0x0000, 2}, // 0xBB3D
|
{"crc16r", crc_0x8005_r, 0x0000, 0x0000, 2}, // 0xBB3D
|
||||||
|
{"modbus", crc_0x8005_r, 0xFFFF, 0x0000, 2}, // 0x4B37
|
||||||
{"ccitt16", crc_0x1021, 0xFFFF, 0x0000, 2}, // 0x29B1
|
{"ccitt16", crc_0x1021, 0xFFFF, 0x0000, 2}, // 0x29B1
|
||||||
{"ccitt16a",crc_0x1021, 0x1D0F, 0x0000, 2}, // 0xE5CC
|
{"ccitt16a",crc_0x1021, 0x1D0F, 0x0000, 2}, // 0xE5CC
|
||||||
{"ccitt16x",crc_0x1021, 0x0000, 0x0000, 2}, // 0x31C3
|
{"ccitt16x",crc_0x1021, 0x0000, 0x0000, 2}, // 0x31C3
|
||||||
@ -498,7 +494,7 @@ static checksum checksumMap[] =
|
|||||||
{"hexsum8", hexsum, 0x00, 0x00, 1} // 0x2D
|
{"hexsum8", hexsum, 0x00, 0x00, 1} // 0x2D
|
||||||
};
|
};
|
||||||
|
|
||||||
static ulong mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
static unsigned int mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||||
|
|
||||||
class ChecksumConverter : public StreamFormatConverter
|
class ChecksumConverter : public StreamFormatConverter
|
||||||
{
|
{
|
||||||
@ -517,39 +513,80 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fnum;
|
bool negflag=false;
|
||||||
|
bool notflag=false;
|
||||||
|
if (*source == '-')
|
||||||
|
{
|
||||||
|
source++;
|
||||||
|
negflag = true;
|
||||||
|
}
|
||||||
|
if (strncasecmp(source, "neg", 3) == 0)
|
||||||
|
{
|
||||||
|
source+=3;
|
||||||
|
negflag = true;
|
||||||
|
}
|
||||||
|
if (*source == '~')
|
||||||
|
{
|
||||||
|
source++;
|
||||||
|
notflag = true;
|
||||||
|
}
|
||||||
|
if (strncasecmp(source, "not", 3) == 0)
|
||||||
|
{
|
||||||
|
source+=3;
|
||||||
|
notflag = true;
|
||||||
|
}
|
||||||
|
unsigned fnum;
|
||||||
|
int len = p-source;
|
||||||
|
unsigned int init, xorout;
|
||||||
for (fnum = 0; fnum < sizeof(checksumMap)/sizeof(checksum); fnum++)
|
for (fnum = 0; fnum < sizeof(checksumMap)/sizeof(checksum); fnum++)
|
||||||
{
|
{
|
||||||
if (strncasecmp(source, checksumMap[fnum].name, p-source) == 0)
|
if ((strncasecmp(source, checksumMap[fnum].name, len) == 0) ||
|
||||||
|
(*source == 'n' && len > 1 && strncasecmp(source+1, checksumMap[fnum].name, len-1) == 0 && (negflag = true)))
|
||||||
{
|
{
|
||||||
|
init = checksumMap[fnum].init;
|
||||||
|
xorout = checksumMap[fnum].xorout;
|
||||||
|
if (negflag)
|
||||||
|
{
|
||||||
|
init = ~init;
|
||||||
|
xorout = ~xorout;
|
||||||
|
}
|
||||||
|
if (notflag)
|
||||||
|
{
|
||||||
|
xorout = ~xorout;
|
||||||
|
}
|
||||||
|
info.append(&init, sizeof(init));
|
||||||
|
info.append(&xorout, sizeof(xorout));
|
||||||
info.append(fnum);
|
info.append(fnum);
|
||||||
source = p+1;
|
source = p+1;
|
||||||
return pseudo_format;
|
return pseudo_format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error ("Unknown checksum algorithm \"%.*s\"\n",
|
error ("Unknown checksum algorithm \"%.*s\"\n", len, source);
|
||||||
static_cast<int>(p-source), source);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChecksumConverter::
|
bool ChecksumConverter::
|
||||||
printPseudo(const StreamFormat& format, StreamBuffer& output)
|
printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||||
{
|
{
|
||||||
ulong sum;
|
unsigned int sum;
|
||||||
int fnum = format.info[0];
|
const char* info = format.info;
|
||||||
|
unsigned int init = extract<unsigned int>(info);
|
||||||
|
unsigned int xorout = extract<unsigned int>(info);
|
||||||
|
int fnum = extract<char>(info);
|
||||||
|
|
||||||
int start = format.width;
|
int start = format.width;
|
||||||
int length = output.length()-format.width;
|
int length = output.length()-format.width;
|
||||||
if (format.prec > 0) length -= format.prec;
|
if (format.prec > 0) length -= format.prec;
|
||||||
|
|
||||||
debug("ChecksumConverter %s: output to check: \"%s\"\n",
|
debug("ChecksumConverter %s: output to check: \"%s\"\n",
|
||||||
checksumMap[fnum].name, output.expand(start,length)());
|
checksumMap[fnum].name, output.expand(start,length)());
|
||||||
|
|
||||||
|
sum = (xorout ^ checksumMap[fnum].func(
|
||||||
|
reinterpret_cast<unsigned char*>(output(start)), length, init))
|
||||||
|
& mask[checksumMap[fnum].bytes];
|
||||||
|
|
||||||
sum = (checksumMap[fnum].xorout ^ checksumMap[fnum].func(
|
debug("ChecksumConverter %s: output checksum is 0x%X\n",
|
||||||
reinterpret_cast<uchar*>(output(start)), length,
|
|
||||||
checksumMap[fnum].init)) & mask[checksumMap[fnum].bytes];
|
|
||||||
|
|
||||||
debug("ChecksumConverter %s: output checksum is 0x%lX\n",
|
|
||||||
checksumMap[fnum].name, sum);
|
checksumMap[fnum].name, sum);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -559,13 +596,11 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
|||||||
{
|
{
|
||||||
// get number of decimal digits from number of bytes: ceil(xbytes*2.5)
|
// get number of decimal digits from number of bytes: ceil(xbytes*2.5)
|
||||||
i = (checksumMap[fnum].bytes+1)*25/10-2;
|
i = (checksumMap[fnum].bytes+1)*25/10-2;
|
||||||
output.print("%0*ld", i, sum);
|
output.print("%0*d", i, sum);
|
||||||
debug("ChecksumConverter %s: decimal appending %0*ld\n",
|
debug("ChecksumConverter %s: decimal appending %0*d\n",
|
||||||
checksumMap[fnum].name, i, sum);
|
checksumMap[fnum].name, i, sum);
|
||||||
return true;
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
|
|
||||||
if (format.flags & alt_flag) // lsb first (little endian)
|
if (format.flags & alt_flag) // lsb first (little endian)
|
||||||
{
|
{
|
||||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||||
@ -575,6 +610,10 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
|||||||
checksumMap[fnum].name, outchar);
|
checksumMap[fnum].name, outchar);
|
||||||
if (format.flags & zero_flag) // ASCII
|
if (format.flags & zero_flag) // ASCII
|
||||||
output.print("%02X", outchar);
|
output.print("%02X", outchar);
|
||||||
|
else
|
||||||
|
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||||
|
output.print("%c%c",
|
||||||
|
((outchar>>4)&0x0f)|0x30, (outchar&0x0f)|0x30);
|
||||||
else // binary
|
else // binary
|
||||||
output.append(outchar);
|
output.append(outchar);
|
||||||
sum >>= 8;
|
sum >>= 8;
|
||||||
@ -590,6 +629,10 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
|||||||
checksumMap[fnum].name, outchar);
|
checksumMap[fnum].name, outchar);
|
||||||
if (format.flags & zero_flag) // ASCII
|
if (format.flags & zero_flag) // ASCII
|
||||||
output.print("%02X", outchar);
|
output.print("%02X", outchar);
|
||||||
|
else
|
||||||
|
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||||
|
output.print("%c%c",
|
||||||
|
((outchar>>4)&0x0f)|0x30, (outchar&0x0f)|0x30);
|
||||||
else // binary
|
else // binary
|
||||||
output.append(outchar);
|
output.append(outchar);
|
||||||
sum <<= 8;
|
sum <<= 8;
|
||||||
@ -601,57 +644,88 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
|||||||
int ChecksumConverter::
|
int ChecksumConverter::
|
||||||
scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||||
{
|
{
|
||||||
int fnum = format.info[0];
|
unsigned int sum;
|
||||||
ulong sum;
|
const char* info = format.info;
|
||||||
|
unsigned int init = extract<unsigned int>(info);
|
||||||
|
unsigned int xorout = extract<unsigned int>(info);
|
||||||
int start = format.width;
|
int start = format.width;
|
||||||
|
int fnum = extract<char>(info);
|
||||||
int length = cursor-format.width;
|
int length = cursor-format.width;
|
||||||
|
|
||||||
if (format.prec > 0) length -= format.prec;
|
if (format.prec > 0) length -= format.prec;
|
||||||
|
|
||||||
debug("ChecksumConverter %s: input to check: \"%s\n",
|
debug("ChecksumConverter %s: input to check: \"%s\n",
|
||||||
checksumMap[fnum].name, input.expand(start,length)());
|
checksumMap[fnum].name, input.expand(start,length)());
|
||||||
|
|
||||||
if (input.length() - cursor <
|
int expectedLength =
|
||||||
(format.flags & zero_flag ? 2 : 1) * checksumMap[fnum].bytes)
|
// get number of decimal digits from number of bytes: ceil(bytes*2.5)
|
||||||
|
format.flags & sign_flag ? (checksumMap[fnum].bytes + 1) * 25 / 10 - 2 :
|
||||||
|
format.flags & (zero_flag|left_flag) ? 2 * checksumMap[fnum].bytes :
|
||||||
|
checksumMap[fnum].bytes;
|
||||||
|
|
||||||
|
if (input.length() - cursor < expectedLength)
|
||||||
{
|
{
|
||||||
error("Input too short for checksum\n");
|
debug("ChecksumConverter %s: Input '%s' too short for checksum\n",
|
||||||
|
checksumMap[fnum].name, input.expand(cursor)());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum = (checksumMap[fnum].xorout ^ checksumMap[fnum].func(
|
sum = (xorout ^ checksumMap[fnum].func(
|
||||||
reinterpret_cast<uchar*>(input(start)), length,
|
reinterpret_cast<unsigned char*>(input(start)), length, init))
|
||||||
checksumMap[fnum].init)) & mask[checksumMap[fnum].bytes];
|
& mask[checksumMap[fnum].bytes];
|
||||||
|
|
||||||
debug("ChecksumConverter %s: input checksum is 0x%0*lX\n",
|
debug("ChecksumConverter %s: input checksum is 0x%0*X\n",
|
||||||
checksumMap[fnum].name, 2*checksumMap[fnum].bytes, sum);
|
checksumMap[fnum].name, 2*checksumMap[fnum].bytes, sum);
|
||||||
|
|
||||||
int i,j;
|
int i, j;
|
||||||
unsigned inchar;
|
unsigned inchar;
|
||||||
|
|
||||||
if (format.flags & sign_flag) // decimal
|
if (format.flags & sign_flag) // decimal
|
||||||
{
|
{
|
||||||
ulong sumin = 0;
|
unsigned int sumin = 0;
|
||||||
// get number of decimal digits from number of bytes: ceil(xbytes*2.5)
|
for (i = 0; i < expectedLength; i++)
|
||||||
j = (checksumMap[fnum].bytes+1)*25/10-2;
|
|
||||||
for (i = 0; i < j; i++)
|
|
||||||
{
|
{
|
||||||
inchar = input[cursor+i];
|
inchar = input[cursor+i];
|
||||||
if (isdigit(inchar)) sumin = sumin*10+inchar-'0';
|
if (isdigit(inchar)) sumin = sumin*10+inchar-'0';
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
if (sumin==sum) return i;
|
if (sumin != sum)
|
||||||
error("Input %0*lu does not match checksum %0*lu\n",
|
{
|
||||||
i, sumin, j, sum);
|
debug("ChecksumConverter %s: Input %0*u does not match checksum %0*u\n",
|
||||||
return -1;
|
checksumMap[fnum].name, i, sumin, expectedLength, sum);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
|
||||||
if (format.flags & alt_flag) // lsb first (little endian)
|
if (format.flags & alt_flag) // lsb first (little endian)
|
||||||
{
|
{
|
||||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||||
{
|
{
|
||||||
if (format.flags & zero_flag) // ASCII
|
if (format.flags & zero_flag) // ASCII
|
||||||
{
|
{
|
||||||
sscanf(input(cursor+2*i), "%2X", &inchar);
|
if (sscanf(input(cursor+2*i), "%2X", &inchar) != 1)
|
||||||
|
{
|
||||||
|
debug("ChecksumConverter %s: Input byte '%s' is not a hex byte\n",
|
||||||
|
checksumMap[fnum].name, input.expand(cursor+2*i,2)());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||||
|
{
|
||||||
|
if ((input[cursor+2*i] & 0xf0) != 0x30)
|
||||||
|
{
|
||||||
|
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||||
|
checksumMap[fnum].name, input[cursor+2*i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((input[cursor+2*i+1] & 0xf0) != 0x30)
|
||||||
|
{
|
||||||
|
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||||
|
checksumMap[fnum].name, input[cursor+2*i+1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
inchar = ((input[cursor+2*i] & 0x0f) << 4) | (input[cursor+2*i+1] & 0x0f);
|
||||||
}
|
}
|
||||||
else // binary
|
else // binary
|
||||||
{
|
{
|
||||||
@ -659,8 +733,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
|||||||
}
|
}
|
||||||
if (inchar != ((sum >> 8*i) & 0xff))
|
if (inchar != ((sum >> 8*i) & 0xff))
|
||||||
{
|
{
|
||||||
error("Input byte 0x%02X does not match checksum 0x%0*lX\n",
|
debug("ChecksumConverter %s: Input byte 0x%02X does not match checksum 0x%0*X\n",
|
||||||
inchar, 2*checksumMap[fnum].bytes, sum);
|
checksumMap[fnum].name, inchar, 2*checksumMap[fnum].bytes, sum);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -673,21 +747,36 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
|||||||
{
|
{
|
||||||
sscanf(input(cursor+2*i), "%2x", &inchar);
|
sscanf(input(cursor+2*i), "%2x", &inchar);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||||
|
{
|
||||||
|
if ((input[cursor+2*i] & 0xf0) != 0x30)
|
||||||
|
{
|
||||||
|
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||||
|
checksumMap[fnum].name, input[cursor+2*i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((input[cursor+2*i+1] & 0xf0) != 0x30)
|
||||||
|
{
|
||||||
|
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||||
|
checksumMap[fnum].name, input[cursor+2*i+1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
inchar = ((input[cursor+2*i] & 0x0f) << 4) | (input[cursor+2*i+1] & 0x0f);
|
||||||
|
}
|
||||||
else // binary
|
else // binary
|
||||||
{
|
{
|
||||||
inchar = input[cursor+i] & 0xff;
|
inchar = input[cursor+i] & 0xff;
|
||||||
}
|
}
|
||||||
if (inchar != ((sum >> 8*j) & 0xff))
|
if (inchar != ((sum >> 8*j) & 0xff))
|
||||||
{
|
{
|
||||||
error("Input byte 0x%02X does not match checksum 0x%0*lX\n",
|
debug("ChecksumConverter %s: Input byte 0x%02X does not match checksum 0x%0*X\n",
|
||||||
inchar, 2*checksumMap[fnum].bytes, sum);
|
checksumMap[fnum].name, inchar, 2*checksumMap[fnum].bytes, sum);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (format.flags & zero_flag) // ASCII
|
return expectedLength;
|
||||||
return 2*checksumMap[fnum].bytes;
|
|
||||||
return checksumMap[fnum].bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterConverter (ChecksumConverter, "<");
|
RegisterConverter (ChecksumConverter, "<");
|
||||||
|
@ -36,7 +36,7 @@ class EnumConverter : public StreamFormatConverter
|
|||||||
|
|
||||||
int EnumConverter::
|
int EnumConverter::
|
||||||
parse(const StreamFormat& fmt, StreamBuffer& info,
|
parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||||
const char*& source, bool)
|
const char*& source, bool scanFormat)
|
||||||
{
|
{
|
||||||
if (fmt.flags & (left_flag|sign_flag|space_flag|zero_flag))
|
if (fmt.flags & (left_flag|sign_flag|space_flag|zero_flag))
|
||||||
{
|
{
|
||||||
@ -56,7 +56,30 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
|||||||
if (*source == '=' && (fmt.flags & alt_flag))
|
if (*source == '=' && (fmt.flags & alt_flag))
|
||||||
{
|
{
|
||||||
char* p;
|
char* p;
|
||||||
index = strtol(++source, &p, 0);
|
|
||||||
|
if (*++source == '?')
|
||||||
|
{
|
||||||
|
// default choice
|
||||||
|
if (scanFormat)
|
||||||
|
{
|
||||||
|
error("Default value only allowed in output formats\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*++source != '}')
|
||||||
|
{
|
||||||
|
error("Default value must be last\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
source++;
|
||||||
|
numEnums = -(numEnums+1);
|
||||||
|
info.append('\0');
|
||||||
|
memcpy(info(n), &numEnums, sizeof(numEnums));
|
||||||
|
debug("EnumConverter::parse %ld choices with default: %s\n",
|
||||||
|
-numEnums, info.expand()());
|
||||||
|
return enum_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = strtol(source, &p, 0);
|
||||||
if (p == source || (*p != '|' && *p != '}'))
|
if (p == source || (*p != '|' && *p != '}'))
|
||||||
{
|
{
|
||||||
error("Integer expected after '=' "
|
error("Integer expected after '=' "
|
||||||
@ -99,6 +122,9 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
|||||||
const char* s = fmt.info;
|
const char* s = fmt.info;
|
||||||
long numEnums = extract<long>(s);
|
long numEnums = extract<long>(s);
|
||||||
long index = extract<long>(s);
|
long index = extract<long>(s);
|
||||||
|
bool noDefault = numEnums >= 0;
|
||||||
|
|
||||||
|
if (numEnums < 0) numEnums=-numEnums-1;
|
||||||
while (numEnums-- && (value != index))
|
while (numEnums-- && (value != index))
|
||||||
{
|
{
|
||||||
while(*s)
|
while(*s)
|
||||||
@ -109,7 +135,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
|||||||
s++;
|
s++;
|
||||||
index = extract<long>(s);
|
index = extract<long>(s);
|
||||||
}
|
}
|
||||||
if (numEnums == -1)
|
if (numEnums == -1 && noDefault)
|
||||||
{
|
{
|
||||||
error("Value %li not found in enum set\n", value);
|
error("Value %li not found in enum set\n", value);
|
||||||
return false;
|
return false;
|
||||||
|
@ -31,23 +31,23 @@ class RawConverter : public StreamFormatConverter
|
|||||||
};
|
};
|
||||||
|
|
||||||
int RawConverter::
|
int RawConverter::
|
||||||
parse(const StreamFormat&, StreamBuffer&,
|
parse(const StreamFormat& fmt, StreamBuffer&,
|
||||||
const char*&, bool)
|
const char*&, bool)
|
||||||
{
|
{
|
||||||
return long_format;
|
return (fmt.flags & (sign_flag|zero_flag)) ? signed_format : unsigned_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawConverter::
|
bool RawConverter::
|
||||||
printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||||
{
|
{
|
||||||
int prec = format.prec; // number of bytes from value
|
int prec = fmt.prec; // number of bytes from value
|
||||||
if (prec == -1) prec = 1; // default: 1 byte
|
if (prec == -1) prec = 1; // default: 1 byte
|
||||||
int width = prec; // number of bytes in output
|
int width = prec; // number of bytes in output
|
||||||
if (prec > (int)sizeof(long)) prec=sizeof(long);
|
if (prec > (int)sizeof(long)) prec=sizeof(long);
|
||||||
if (format.width > width) width = format.width;
|
if (fmt.width > width) width = fmt.width;
|
||||||
|
|
||||||
char byte = 0;
|
char byte = 0;
|
||||||
if (format.flags & alt_flag) // little endian (lsb first)
|
if (fmt.flags & alt_flag) // little endian (lsb first)
|
||||||
{
|
{
|
||||||
while (prec--)
|
while (prec--)
|
||||||
{
|
{
|
||||||
@ -56,7 +56,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
|||||||
value >>= 8;
|
value >>= 8;
|
||||||
width--;
|
width--;
|
||||||
}
|
}
|
||||||
if (format.flags & zero_flag)
|
if (fmt.flags & zero_flag)
|
||||||
{
|
{
|
||||||
// fill with zero
|
// fill with zero
|
||||||
byte = 0;
|
byte = 0;
|
||||||
@ -73,7 +73,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
|||||||
}
|
}
|
||||||
else // big endian (msb first)
|
else // big endian (msb first)
|
||||||
{
|
{
|
||||||
if (format.flags & zero_flag)
|
if (fmt.flags & zero_flag)
|
||||||
{
|
{
|
||||||
// fill with zero
|
// fill with zero
|
||||||
byte = 0;
|
byte = 0;
|
||||||
@ -97,17 +97,17 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int RawConverter::
|
int RawConverter::
|
||||||
scanLong(const StreamFormat& format, const char* input, long& value)
|
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||||
{
|
{
|
||||||
long length = 0;
|
long length = 0;
|
||||||
long val = 0;
|
long val = 0;
|
||||||
int width = format.width;
|
int width = fmt.width;
|
||||||
if (width == 0) width = 1; // default: 1 byte
|
if (width == 0) width = 1; // default: 1 byte
|
||||||
if (format.flags & skip_flag)
|
if (fmt.flags & skip_flag)
|
||||||
{
|
{
|
||||||
return width; // just skip input
|
return width; // just skip input
|
||||||
}
|
}
|
||||||
if (format.flags & alt_flag)
|
if (fmt.flags & alt_flag)
|
||||||
{
|
{
|
||||||
// little endian (lsb first)
|
// little endian (lsb first)
|
||||||
unsigned int shift = 0;
|
unsigned int shift = 0;
|
||||||
@ -118,7 +118,7 @@ scanLong(const StreamFormat& format, const char* input, long& value)
|
|||||||
}
|
}
|
||||||
if (width == 0)
|
if (width == 0)
|
||||||
{
|
{
|
||||||
if (format.flags & zero_flag)
|
if (fmt.flags & zero_flag)
|
||||||
{
|
{
|
||||||
// fill with zero
|
// fill with zero
|
||||||
val |= ((unsigned char) input[length++]) << shift;
|
val |= ((unsigned char) input[length++]) << shift;
|
||||||
@ -134,7 +134,7 @@ scanLong(const StreamFormat& format, const char* input, long& value)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// big endian (msb first)
|
// big endian (msb first)
|
||||||
if (format.flags & zero_flag)
|
if (fmt.flags & zero_flag)
|
||||||
{
|
{
|
||||||
// fill with zero
|
// fill with zero
|
||||||
val = (unsigned char) input[length++];
|
val = (unsigned char) input[length++];
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "pcre.h"
|
#include "pcre.h"
|
||||||
|
|
||||||
// Perl regular expressions (PCRE) %/regexp/
|
// Perl regular expressions (PCRE) %/regexp/ and %#/regexp/subst/
|
||||||
|
|
||||||
/* Notes:
|
/* Notes:
|
||||||
- Memory for compiled regexp is allocated in parse but never freed.
|
- Memory for compiled regexp is allocated in parse but never freed.
|
||||||
@ -37,15 +37,17 @@
|
|||||||
|
|
||||||
class RegexpConverter : public StreamFormatConverter
|
class RegexpConverter : public StreamFormatConverter
|
||||||
{
|
{
|
||||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
|
int parse (const StreamFormat& fmt, StreamBuffer&, const char*&, bool);
|
||||||
int scanString(const StreamFormat&, const char*, char*, size_t);
|
int scanString(const StreamFormat& fmt, const char*, char*, size_t);
|
||||||
|
int scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor);
|
||||||
|
bool printPseudo(const StreamFormat& fmt, StreamBuffer& output);
|
||||||
};
|
};
|
||||||
|
|
||||||
int RegexpConverter::
|
int RegexpConverter::
|
||||||
parse(const StreamFormat& fmt, StreamBuffer& info,
|
parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||||
const char*& source, bool scanFormat)
|
const char*& source, bool scanFormat)
|
||||||
{
|
{
|
||||||
if (!scanFormat)
|
if (!scanFormat && !(fmt.flags & alt_flag))
|
||||||
{
|
{
|
||||||
error("Format conversion %%/regexp/ is only allowed in input formats\n");
|
error("Format conversion %%/regexp/ is only allowed in input formats\n");
|
||||||
return false;
|
return false;
|
||||||
@ -55,28 +57,31 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
|||||||
error("Subexpression index %d too big (>9)\n", fmt.prec);
|
error("Subexpression index %d too big (>9)\n", fmt.prec);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (fmt.flags & (left_flag|space_flag|zero_flag|alt_flag))
|
|
||||||
{
|
|
||||||
error("Use of modifiers '-', ' ', '0', '#'"
|
|
||||||
"not allowed with %%/regexp/ conversion\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
StreamBuffer pattern;
|
StreamBuffer pattern;
|
||||||
while (*source != '/')
|
while (*source != '/')
|
||||||
{
|
{
|
||||||
if (!*source) {
|
if (!*source) {
|
||||||
error("Missing closing '/' after %%/ format conversion\n");
|
error("Missing closing '/' after %%/%s format conversion\n", pattern());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (*source == esc) {
|
if (*source == esc) { // handle escaped chars
|
||||||
source++;
|
if (*++source != '/') // just un-escape /
|
||||||
pattern.print("\\x%02x", *source++ & 0xFF);
|
{
|
||||||
continue;
|
pattern.append('\\');
|
||||||
|
if ((*source & 0x7f) < 0x30) // handle control chars
|
||||||
|
{
|
||||||
|
pattern.print("x%02x", *source++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// fall through for PCRE codes like \B
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pattern.append(*source++);
|
pattern.append(*source++);
|
||||||
}
|
}
|
||||||
source++;
|
source++;
|
||||||
debug("regexp = \"%s\"\n", pattern());
|
debug("regexp = \"%s\"\n", pattern.expand()());
|
||||||
|
|
||||||
const char* errormsg;
|
const char* errormsg;
|
||||||
int eoffset;
|
int eoffset;
|
||||||
pcre* code = pcre_compile(pattern(), 0,
|
pcre* code = pcre_compile(pattern(), 0,
|
||||||
@ -87,6 +92,26 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
info.append(&code, sizeof(code));
|
info.append(&code, sizeof(code));
|
||||||
|
|
||||||
|
if (fmt.flags & alt_flag)
|
||||||
|
{
|
||||||
|
StreamBuffer subst;
|
||||||
|
debug("check for subst in \"%s\"\n", StreamBuffer(source).expand()());
|
||||||
|
while (*source != '/')
|
||||||
|
{
|
||||||
|
if (!*source) {
|
||||||
|
error("Missing closing '/' after %%#/%s/%s format conversion\n", pattern(), subst());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*source == esc)
|
||||||
|
subst.append(*source++);
|
||||||
|
subst.append(*source++);
|
||||||
|
}
|
||||||
|
source++;
|
||||||
|
debug("subst = \"%s\"\n", subst.expand()());
|
||||||
|
info.append(subst).append('\0');
|
||||||
|
return pseudo_format;
|
||||||
|
}
|
||||||
return string_format;
|
return string_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,32 +119,130 @@ int RegexpConverter::
|
|||||||
scanString(const StreamFormat& fmt, const char* input,
|
scanString(const StreamFormat& fmt, const char* input,
|
||||||
char* value, size_t maxlen)
|
char* value, size_t maxlen)
|
||||||
{
|
{
|
||||||
pcre* code;
|
|
||||||
size_t len;
|
|
||||||
int ovector[30];
|
int ovector[30];
|
||||||
int rc;
|
int rc;
|
||||||
int subexpr = 0;
|
unsigned int l;
|
||||||
|
|
||||||
memcpy (&code, fmt.info, sizeof(code));
|
const char* info = fmt.info;
|
||||||
|
pcre* code = extract<pcre*>(info);
|
||||||
|
int length = fmt.width > 0 ? fmt.width : strlen(input);
|
||||||
|
int subexpr = fmt.prec > 0 ? fmt.prec : 0;
|
||||||
|
|
||||||
len = fmt.width > 0 ? fmt.width : strlen(input);
|
debug("input = \"%s\"\n", input);
|
||||||
subexpr = fmt.prec > 0 ? fmt.prec : 0;
|
debug("length=%d\n", length);
|
||||||
rc = pcre_exec(code, NULL, input, len, 0, 0, ovector, 30);
|
|
||||||
if (rc < 1) return -1;
|
rc = pcre_exec(code, NULL, input, length, 0, 0, ovector, 30);
|
||||||
if (fmt.flags & skip_flag) return ovector[1];
|
debug("pcre_exec match \"%.*s\" result = %d\n", length, input, rc);
|
||||||
len = ovector[subexpr*2+1] - ovector[subexpr*2];
|
if ((subexpr && rc <= subexpr) || rc < 0)
|
||||||
if (len >= maxlen) {
|
{
|
||||||
|
// error or no match or not enough sub-expressions
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fmt.flags & skip_flag) return ovector[subexpr*2+1];
|
||||||
|
|
||||||
|
l = ovector[subexpr*2+1] - ovector[subexpr*2];
|
||||||
|
if (l >= maxlen) {
|
||||||
if (!(fmt.flags & sign_flag)) {
|
if (!(fmt.flags & sign_flag)) {
|
||||||
error("Regexp: Matching string \"%s\" too long (%d>%d bytes). You may want to try the + flag: \"%%+/.../\"\n",
|
error("Regexp: Matching string \"%s\" too long (%d>%ld bytes). You may want to try the + flag: \"%%+/.../\"\n",
|
||||||
StreamBuffer(input+ovector[subexpr*2], len).expand()(),
|
StreamBuffer(input + ovector[subexpr*2],l).expand()(),
|
||||||
(int)len, (int)maxlen-1);
|
l, (long)maxlen-1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
len = maxlen-1;
|
l = maxlen-1;
|
||||||
}
|
}
|
||||||
memcpy(value, input+ovector[subexpr*2], len);
|
memcpy(value, input + ovector[subexpr*2], l);
|
||||||
value[len]=0;
|
value[l] = '\0';
|
||||||
return ovector[1];
|
return ovector[1]; // consume input until end of match
|
||||||
|
}
|
||||||
|
|
||||||
|
static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||||
|
{
|
||||||
|
const char* subst = fmt.info;
|
||||||
|
pcre* code = extract<pcre*>(subst);
|
||||||
|
long length;
|
||||||
|
int rc, l, c, r, rl, n;
|
||||||
|
int ovector[30];
|
||||||
|
StreamBuffer s;
|
||||||
|
|
||||||
|
length = buffer.length() - start;
|
||||||
|
if (fmt.width && fmt.width < length)
|
||||||
|
length = fmt.width;
|
||||||
|
if (fmt.flags & sign_flag)
|
||||||
|
start = buffer.length() - length;
|
||||||
|
|
||||||
|
debug("regsubst buffer=\"%s\", start=%ld, length=%ld, subst = \"%s\"\n",
|
||||||
|
buffer.expand()(), start, length, subst);
|
||||||
|
|
||||||
|
for (c = 0, n = 1; c < length; n++)
|
||||||
|
{
|
||||||
|
rc = pcre_exec(code, NULL, buffer(start+c), length-c, 0, 0, ovector, 30);
|
||||||
|
debug("pcre_exec match \"%.*s\" result = %d\n", (int)length-c, buffer(start+c), rc);
|
||||||
|
if (rc < 0) // no match
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(fmt.flags & sign_flag) && n < fmt.prec) // without + flag
|
||||||
|
{
|
||||||
|
// do not yet replace this match
|
||||||
|
c += ovector[1];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// replace & by match in subst
|
||||||
|
l = ovector[1] - ovector[0];
|
||||||
|
debug("start = \"%s\"\n", buffer(start+c));
|
||||||
|
debug("match = \"%.*s\"\n", l, buffer(start+c+ovector[0]));
|
||||||
|
for (r = 1; r < rc; r++)
|
||||||
|
debug("sub%d = \"%.*s\"\n", r, ovector[r*2+1]-ovector[r*2], buffer(start+c+ovector[r*2]));
|
||||||
|
debug("rest = \"%s\"\n", buffer(start+c+ovector[1]));
|
||||||
|
s = subst;
|
||||||
|
debug("subs = \"%s\"\n", s.expand()());
|
||||||
|
for (r = 0; r < s.length(); r++)
|
||||||
|
{
|
||||||
|
debug("check \"%s\"\n", s.expand(r)());
|
||||||
|
if (s[r] == esc)
|
||||||
|
{
|
||||||
|
unsigned char ch = s[r+1];
|
||||||
|
if (ch < 9) // escaped 0 - 9 : replace with subexpr
|
||||||
|
{
|
||||||
|
ch *= 2;
|
||||||
|
rl = ovector[ch+1] - ovector[ch];
|
||||||
|
debug("replace \\%d: \"%.*s\"\n", ch/2, rl, buffer(start+c+ovector[ch]));
|
||||||
|
s.replace(r, 2, buffer(start+c+ovector[ch]), rl);
|
||||||
|
r += rl - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s.remove(r, 1); // just remove escape
|
||||||
|
}
|
||||||
|
else if (s[r] == '&') // unescaped & : replace with match
|
||||||
|
{
|
||||||
|
debug("replace &: \"%.*s\"\n", l, buffer(start+c+ovector[0]));
|
||||||
|
s.replace(r, 1, buffer(start+c+ovector[0]), l);
|
||||||
|
r += l - 1;
|
||||||
|
}
|
||||||
|
else continue;
|
||||||
|
debug("subs = \"%s\"\n", s());
|
||||||
|
}
|
||||||
|
buffer.replace(start+c+ovector[0], l, s);
|
||||||
|
length += s.length() - l;
|
||||||
|
c += s.length();
|
||||||
|
if (n == fmt.prec) // max match reached
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegexpConverter::
|
||||||
|
scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor)
|
||||||
|
{
|
||||||
|
/* re-write input buffer */
|
||||||
|
regsubst(fmt, input, cursor);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegexpConverter::
|
||||||
|
printPseudo(const StreamFormat& fmt, StreamBuffer& output)
|
||||||
|
{
|
||||||
|
/* re-write output buffer */
|
||||||
|
regsubst(fmt, output, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterConverter (RegexpConverter, "/");
|
RegisterConverter (RegexpConverter, "/");
|
||||||
|
@ -30,15 +30,17 @@
|
|||||||
#define vsnprintf epicsVsnprintf
|
#define vsnprintf epicsVsnprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define P PRINTF_SIZE_T_PREFIX
|
||||||
|
|
||||||
void StreamBuffer::
|
void StreamBuffer::
|
||||||
init(const void* s, long minsize)
|
init(const void* s, ssize_t minsize)
|
||||||
{
|
{
|
||||||
len = 0;
|
len = 0;
|
||||||
offs = 0;
|
offs = 0;
|
||||||
buffer = local;
|
buffer = local;
|
||||||
cap = sizeof(local);
|
cap = sizeof(local);
|
||||||
if (minsize < 0) minsize = 0;
|
if (minsize < 0) minsize = 0;
|
||||||
if (minsize >= cap)
|
if ((size_t)minsize >= cap)
|
||||||
{
|
{
|
||||||
// use allocated buffer
|
// use allocated buffer
|
||||||
grow(minsize);
|
grow(minsize);
|
||||||
@ -55,18 +57,18 @@ init(const void* s, long minsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// How the buffer looks like:
|
// How the buffer looks like:
|
||||||
// |----free-----|####used####|-------free-------|
|
// |----free-----|####used####|--------00--------|
|
||||||
///|<--- offs -->|<-- len --->|<- cap-offs-len ->|
|
///|<--- offs -->|<-- len --->|<- cap-offs-len ->|
|
||||||
// 0 offs offs+len cap
|
// 0 offs offs+len cap
|
||||||
// |<-------------- minsize --------------->
|
// |<-------------- minsize --------------->
|
||||||
|
|
||||||
|
|
||||||
void StreamBuffer::
|
void StreamBuffer::
|
||||||
grow(long minsize)
|
grow(size_t minsize)
|
||||||
{
|
{
|
||||||
// make space for minsize + 1 (for termination) bytes
|
// make space for minsize + 1 (for termination) bytes
|
||||||
char* newbuffer;
|
char* newbuffer;
|
||||||
long newcap;
|
size_t newcap;
|
||||||
#ifdef EXPLODE
|
#ifdef EXPLODE
|
||||||
if (minsize > 1000000)
|
if (minsize > 1000000)
|
||||||
{
|
{
|
||||||
@ -117,12 +119,12 @@ grow(long minsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
StreamBuffer& StreamBuffer::
|
StreamBuffer& StreamBuffer::
|
||||||
append(const void* s, long size)
|
append(const void* s, ssize_t size)
|
||||||
{
|
{
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
{
|
{
|
||||||
// append negative number of bytes? let's delete some
|
// append negative number of bytes? let's delete some
|
||||||
if (size < -len) size = -len;
|
if (size < -(ssize_t)len) size = -(ssize_t)len;
|
||||||
memset (buffer+offs+len+size, 0, -size);
|
memset (buffer+offs+len+size, 0, -size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -134,8 +136,8 @@ append(const void* s, long size)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int StreamBuffer::
|
ssize_t StreamBuffer::
|
||||||
find(const void* m, long size, long start) const
|
find(const void* m, size_t size, ssize_t start) const
|
||||||
{
|
{
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
{
|
{
|
||||||
@ -147,7 +149,7 @@ find(const void* m, long size, long start) const
|
|||||||
const char* s = static_cast<const char*>(m);
|
const char* s = static_cast<const char*>(m);
|
||||||
char* b = buffer+offs;
|
char* b = buffer+offs;
|
||||||
char* p = b+start;
|
char* p = b+start;
|
||||||
long i;
|
size_t i;
|
||||||
while ((p = static_cast<char*>(memchr(p, s[0], b-p+len-size+1))))
|
while ((p = static_cast<char*>(memchr(p, s[0], b-p+len-size+1))))
|
||||||
{
|
{
|
||||||
for (i = 1; i < size; i++)
|
for (i = 1; i < size; i++)
|
||||||
@ -161,7 +163,7 @@ next: p++;
|
|||||||
}
|
}
|
||||||
|
|
||||||
StreamBuffer& StreamBuffer::
|
StreamBuffer& StreamBuffer::
|
||||||
replace(long remstart, long remlen, const void* ins, long inslen)
|
replace(ssize_t remstart, ssize_t remlen, const void* ins, ssize_t inslen)
|
||||||
{
|
{
|
||||||
if (remstart < 0)
|
if (remstart < 0)
|
||||||
{
|
{
|
||||||
@ -187,12 +189,12 @@ replace(long remstart, long remlen, const void* ins, long inslen)
|
|||||||
remlen += remstart;
|
remlen += remstart;
|
||||||
remstart = 0;
|
remstart = 0;
|
||||||
}
|
}
|
||||||
if (remstart > len)
|
if ((size_t)remstart > len)
|
||||||
{
|
{
|
||||||
// remove begins after bufferend
|
// remove begins after bufferend
|
||||||
remstart = len;
|
remstart = len;
|
||||||
}
|
}
|
||||||
if (remlen >= len-remstart)
|
if ((size_t)remlen >= len-remstart)
|
||||||
{
|
{
|
||||||
// truncate remove after bufferend
|
// truncate remove after bufferend
|
||||||
remlen = len-remstart;
|
remlen = len-remstart;
|
||||||
@ -205,12 +207,12 @@ replace(long remstart, long remlen, const void* ins, long inslen)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
if (inslen < 0) inslen = 0;
|
if (inslen < 0) inslen = 0;
|
||||||
long remend = remstart+remlen;
|
size_t remend = remstart+remlen;
|
||||||
long newlen = len+inslen-remlen;
|
size_t newlen = len+inslen-remlen;
|
||||||
if (cap <= newlen)
|
if (cap <= newlen)
|
||||||
{
|
{
|
||||||
// buffer too short
|
// buffer too short
|
||||||
long newcap;
|
size_t newcap;
|
||||||
for (newcap = sizeof(local)*2; newcap <= newlen; newcap *= 2);
|
for (newcap = sizeof(local)*2; newcap <= newlen; newcap *= 2);
|
||||||
char* newbuffer = new char[newcap];
|
char* newbuffer = new char[newcap];
|
||||||
memcpy(newbuffer, buffer+offs, remstart);
|
memcpy(newbuffer, buffer+offs, remstart);
|
||||||
@ -251,13 +253,13 @@ StreamBuffer& StreamBuffer::
|
|||||||
print(const char* fmt, ...)
|
print(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
int printed;
|
ssize_t printed;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
printed = vsnprintf(buffer+offs+len, cap-offs-len, fmt, va);
|
printed = vsnprintf(buffer+offs+len, cap-offs-len, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
if (printed > -1 && printed < (int)(cap-offs-len))
|
if (printed > -1 && printed < (ssize_t)(cap-offs-len))
|
||||||
{
|
{
|
||||||
len += printed;
|
len += printed;
|
||||||
return *this;
|
return *this;
|
||||||
@ -267,9 +269,9 @@ print(const char* fmt, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamBuffer StreamBuffer::expand(long start, long length) const
|
StreamBuffer StreamBuffer::expand(ssize_t start, ssize_t length) const
|
||||||
{
|
{
|
||||||
long end;
|
size_t end;
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
{
|
{
|
||||||
start += len;
|
start += len;
|
||||||
@ -289,12 +291,12 @@ StreamBuffer StreamBuffer::expand(long start, long length) const
|
|||||||
StreamBuffer result((end-start)*2);
|
StreamBuffer result((end-start)*2);
|
||||||
start += offs;
|
start += offs;
|
||||||
end += offs;
|
end += offs;
|
||||||
long i;
|
size_t i;
|
||||||
char c;
|
char c;
|
||||||
for (i = start; i < end; i++)
|
for (i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
c = buffer[i];
|
c = buffer[i];
|
||||||
if ((c & 0x7f) < 0x20 || (c & 0x7f) == 0x7f)
|
if (c < 0x20 || c >= 0x7f)
|
||||||
{
|
{
|
||||||
result.print("<%02x>", c & 0xff);
|
result.print("<%02x>", c & 0xff);
|
||||||
}
|
}
|
||||||
@ -311,8 +313,8 @@ dump() const
|
|||||||
{
|
{
|
||||||
StreamBuffer result(256+cap*5);
|
StreamBuffer result(256+cap*5);
|
||||||
result.append("\033[0m");
|
result.append("\033[0m");
|
||||||
long i;
|
size_t i;
|
||||||
result.print("%ld,%ld,%ld:\033[37m", offs, len, cap);
|
result.print("%"P"d,%"P"d,%"P"d:\033[37m", offs, len, cap);
|
||||||
for (i = 0; i < cap; i++)
|
for (i = 0; i < cap; i++)
|
||||||
{
|
{
|
||||||
if (i == offs) result.append("\033[34m[\033[0m");
|
if (i == offs) result.append("\033[34m[\033[0m");
|
||||||
|
@ -21,29 +21,34 @@
|
|||||||
#define StreamBuffer_h
|
#define StreamBuffer_h
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#define __attribute__(x)
|
#define __attribute__(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define ssize_t ptrdiff_t
|
||||||
|
#endif
|
||||||
|
|
||||||
class StreamBuffer
|
class StreamBuffer
|
||||||
{
|
{
|
||||||
char local[64];
|
char local[64];
|
||||||
long len;
|
size_t len;
|
||||||
long cap;
|
size_t cap;
|
||||||
long offs;
|
size_t offs;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
|
|
||||||
void init(const void* s, long minsize);
|
void init(const void* s, ssize_t minsize);
|
||||||
|
|
||||||
void check(long size)
|
void check(size_t size)
|
||||||
{if (len+offs+size >= cap) grow(len+size);}
|
{if (len+offs+size >= cap) grow(len+size);}
|
||||||
|
|
||||||
void grow(long minsize);
|
void grow(size_t minsize);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Hints:
|
// Hints:
|
||||||
// * Any index parameter (long) can be negative
|
// * Any index parameter (ssize_t) can be negative
|
||||||
// meaning "count from end" (-1 is the last byte)
|
// meaning "count from end" (-1 is the last byte)
|
||||||
// * Appending negative count deletes from end
|
// * Appending negative count deletes from end
|
||||||
// * Any returned char* pointer becomes invalid when
|
// * Any returned char* pointer becomes invalid when
|
||||||
@ -54,7 +59,7 @@ public:
|
|||||||
StreamBuffer()
|
StreamBuffer()
|
||||||
{init(NULL, 0);}
|
{init(NULL, 0);}
|
||||||
|
|
||||||
StreamBuffer(const void* s, long size)
|
StreamBuffer(const void* s, ssize_t size)
|
||||||
{init(s, size);}
|
{init(s, size);}
|
||||||
|
|
||||||
StreamBuffer(const char* s)
|
StreamBuffer(const char* s)
|
||||||
@ -63,24 +68,24 @@ public:
|
|||||||
StreamBuffer(const StreamBuffer& s)
|
StreamBuffer(const StreamBuffer& s)
|
||||||
{init(s.buffer+s.offs, s.len);}
|
{init(s.buffer+s.offs, s.len);}
|
||||||
|
|
||||||
StreamBuffer(long size)
|
StreamBuffer(ssize_t size)
|
||||||
{init(NULL, size);}
|
{init(NULL, size);}
|
||||||
|
|
||||||
~StreamBuffer()
|
~StreamBuffer()
|
||||||
{if (buffer != local) delete buffer;}
|
{if (buffer != local) delete buffer;}
|
||||||
|
|
||||||
// operator (): get char* pointing to index
|
// operator (): get char* pointing to index
|
||||||
const char* operator()(long index=0) const
|
const char* operator()(ssize_t index=0) const
|
||||||
{return buffer+offs+(index<0?index+len:index);}
|
{return buffer+offs+(index<0?index+len:index);}
|
||||||
|
|
||||||
char* operator()(long index=0)
|
char* operator()(ssize_t index=0)
|
||||||
{return buffer+offs+(index<0?index+len:index);}
|
{return buffer+offs+(index<0?index+len:index);}
|
||||||
|
|
||||||
// operator []: get byte at index
|
// operator []: get byte at index
|
||||||
char operator[](long index) const
|
char operator[](ssize_t index) const
|
||||||
{return buffer[offs+(index<0?index+len:index)];}
|
{return buffer[offs+(index<0?index+len:index)];}
|
||||||
|
|
||||||
char& operator[](long index)
|
char& operator[](ssize_t index)
|
||||||
{return buffer[offs+(index<0?index+len:index)];}
|
{return buffer[offs+(index<0?index+len:index)];}
|
||||||
|
|
||||||
// cast to bool: not empty?
|
// cast to bool: not empty?
|
||||||
@ -88,11 +93,11 @@ public:
|
|||||||
{return len>0;}
|
{return len>0;}
|
||||||
|
|
||||||
// length: get current data length
|
// length: get current data length
|
||||||
long length() const
|
ssize_t length() const
|
||||||
{return len;}
|
{return len;}
|
||||||
|
|
||||||
// capacity: get current max data length (spare one byte for end)
|
// capacity: get current max data length (spare one byte for end)
|
||||||
long capacity() const
|
ssize_t capacity() const
|
||||||
{return cap-1;}
|
{return cap-1;}
|
||||||
|
|
||||||
// end: get pointer to byte after last data byte
|
// end: get pointer to byte after last data byte
|
||||||
@ -105,19 +110,19 @@ public:
|
|||||||
|
|
||||||
// reserve: reserve size bytes of memory and return
|
// reserve: reserve size bytes of memory and return
|
||||||
// pointer to that memory (for copying something to it)
|
// pointer to that memory (for copying something to it)
|
||||||
char* reserve(long size)
|
char* reserve(size_t size)
|
||||||
{check(size); char* p=buffer+offs+len; len+=size; return p;}
|
{check(size); char* p=buffer+offs+len; len+=size; return p;}
|
||||||
|
|
||||||
// append: append data at the end of the buffer
|
// append: append data at the end of the buffer
|
||||||
StreamBuffer& append(char c)
|
StreamBuffer& append(char c)
|
||||||
{check(1); buffer[offs+len++]=c; return *this;}
|
{check(1); buffer[offs+len++]=c; return *this;}
|
||||||
|
|
||||||
StreamBuffer& append(char c, long count)
|
StreamBuffer& append(char c, ssize_t count)
|
||||||
{if (count < 0) truncate(count);
|
{if (count < 0) truncate(count);
|
||||||
else {check(count); memset(buffer+offs+len, c, count); len+=count;}
|
else {check(count); memset(buffer+offs+len, c, count); len+=count;}
|
||||||
return *this;}
|
return *this;}
|
||||||
|
|
||||||
StreamBuffer& append(const void* s, long size);
|
StreamBuffer& append(const void* s, ssize_t size);
|
||||||
|
|
||||||
StreamBuffer& append(const char* s)
|
StreamBuffer& append(const char* s)
|
||||||
{return append(s, s?strlen(s):0);}
|
{return append(s, s?strlen(s):0);}
|
||||||
@ -125,7 +130,7 @@ public:
|
|||||||
StreamBuffer& append(const StreamBuffer& s)
|
StreamBuffer& append(const StreamBuffer& s)
|
||||||
{return append(s.buffer+s.offs, s.len);}
|
{return append(s.buffer+s.offs, s.len);}
|
||||||
|
|
||||||
// operator += alias for set
|
// operator += alias for append
|
||||||
StreamBuffer& operator+=(char c)
|
StreamBuffer& operator+=(char c)
|
||||||
{return append(c);}
|
{return append(c);}
|
||||||
|
|
||||||
@ -136,7 +141,7 @@ public:
|
|||||||
{return append(s);}
|
{return append(s);}
|
||||||
|
|
||||||
// set: clear buffer and fill with new data
|
// set: clear buffer and fill with new data
|
||||||
StreamBuffer& set(const void* s, long size)
|
StreamBuffer& set(const void* s, size_t size)
|
||||||
{clear(); return append(s, size);}
|
{clear(); return append(s, size);}
|
||||||
|
|
||||||
StreamBuffer& set(const char* s)
|
StreamBuffer& set(const char* s)
|
||||||
@ -154,61 +159,61 @@ public:
|
|||||||
|
|
||||||
// replace: delete part of buffer (pos/length) and insert new data
|
// replace: delete part of buffer (pos/length) and insert new data
|
||||||
StreamBuffer& replace(
|
StreamBuffer& replace(
|
||||||
long pos, long length, const void* s, long size);
|
ssize_t pos, ssize_t length, const void* s, ssize_t size);
|
||||||
|
|
||||||
StreamBuffer& replace(long pos, long length, const char* s)
|
StreamBuffer& replace(ssize_t pos, ssize_t length, const char* s)
|
||||||
{return replace(pos, length, s, s?strlen(s):0);}
|
{return replace(pos, length, s, s?strlen(s):0);}
|
||||||
|
|
||||||
StreamBuffer& replace(long pos, long length, const StreamBuffer& s)
|
StreamBuffer& replace(ssize_t pos, ssize_t length, const StreamBuffer& s)
|
||||||
{return replace(pos, length, s.buffer+s.offs, s.len);}
|
{return replace(pos, length, s.buffer+s.offs, s.len);}
|
||||||
|
|
||||||
// remove: delete from start/pos
|
// remove: delete from start/pos
|
||||||
StreamBuffer& remove(long pos, long length)
|
StreamBuffer& remove(ssize_t pos, ssize_t length)
|
||||||
{return replace(pos, length, NULL, 0);}
|
{return replace(pos, length, NULL, 0);}
|
||||||
|
|
||||||
// remove from start: no memset, no function call, fast!
|
// remove from start: no memset, no function call, fast!
|
||||||
StreamBuffer& remove(long length)
|
StreamBuffer& remove(size_t length)
|
||||||
{if (length>len) length=len;
|
{if (length>len) length=len;
|
||||||
offs+=length; len-=length; return *this;}
|
offs+=length; len-=length; return *this;}
|
||||||
|
|
||||||
// truncate: delete end of buffer
|
// truncate: delete end of buffer
|
||||||
StreamBuffer& truncate(long pos)
|
StreamBuffer& truncate(ssize_t pos)
|
||||||
{return replace(pos, len, NULL, 0);}
|
{return replace(pos, len, NULL, 0);}
|
||||||
|
|
||||||
// insert: insert new data into buffer
|
// insert: insert new data into buffer
|
||||||
StreamBuffer& insert(long pos, const void* s, long size)
|
StreamBuffer& insert(ssize_t pos, const void* s, ssize_t size)
|
||||||
{return replace(pos, 0, s, size);}
|
{return replace(pos, 0, s, size);}
|
||||||
|
|
||||||
StreamBuffer& insert(long pos, const char* s)
|
StreamBuffer& insert(ssize_t pos, const char* s)
|
||||||
{return replace(pos, 0, s, s?strlen(s):0);}
|
{return replace(pos, 0, s, s?strlen(s):0);}
|
||||||
|
|
||||||
StreamBuffer& insert(long pos, const StreamBuffer& s)
|
StreamBuffer& insert(ssize_t pos, const StreamBuffer& s)
|
||||||
{return replace(pos, 0, s.buffer+s.offs, s.len);}
|
{return replace(pos, 0, s.buffer+s.offs, s.len);}
|
||||||
|
|
||||||
StreamBuffer& insert(long pos, char c)
|
StreamBuffer& insert(ssize_t pos, char c)
|
||||||
{return replace(pos, 0, &c, 1);}
|
{return replace(pos, 0, &c, 1);}
|
||||||
|
|
||||||
StreamBuffer& print(const char* fmt, ...)
|
StreamBuffer& print(const char* fmt, ...)
|
||||||
__attribute__ ((format(printf,2,3)));
|
__attribute__ ((format(printf,2,3)));
|
||||||
|
|
||||||
// find: get index of data in buffer or -1
|
// find: get index of data in buffer or -1
|
||||||
long find(char c, long start=0) const
|
ssize_t find(char c, ssize_t start=0) const
|
||||||
{char* p;
|
{char* p;
|
||||||
return (p = static_cast<char*>(
|
return (p = static_cast<char*>(
|
||||||
memchr(buffer+offs+(start<0?start+len:start),
|
memchr(buffer+offs+(start<0?start+len:start),
|
||||||
c, start<0?-start:len-start)))?
|
c, start<0?-start:len-start)))?
|
||||||
p-(buffer+offs) : -1;}
|
p-(buffer+offs) : -1;}
|
||||||
|
|
||||||
long find(const void* s, long size, long start=0) const;
|
ssize_t find(const void* s, size_t size, ssize_t start=0) const;
|
||||||
|
|
||||||
long find(const char* s, long start=0) const
|
ssize_t find(const char* s, ssize_t start=0) const
|
||||||
{return find(s, s?strlen(s):0, start);}
|
{return find(s, s?strlen(s):0, start);}
|
||||||
|
|
||||||
long int find(const StreamBuffer& s, long start=0) const
|
ssize_t find(const StreamBuffer& s, ssize_t start=0) const
|
||||||
{return find(s.buffer+s.offs, s.len, start);}
|
{return find(s.buffer+s.offs, s.len, start);}
|
||||||
|
|
||||||
// startswith: returns true if first size bytes are equal
|
// startswith: returns true if first size bytes are equal
|
||||||
bool startswith(const void* s, long size) const
|
bool startswith(const void* s, size_t size) const
|
||||||
{return len>=size ? memcmp(buffer+offs, s, size) == 0 : false;}
|
{return len>=size ? memcmp(buffer+offs, s, size) == 0 : false;}
|
||||||
|
|
||||||
// startswith: returns true if first string is equal (empty string matches)
|
// startswith: returns true if first string is equal (empty string matches)
|
||||||
@ -217,9 +222,9 @@ public:
|
|||||||
|
|
||||||
// expand: create copy of StreamBuffer where all nonprintable characters
|
// expand: create copy of StreamBuffer where all nonprintable characters
|
||||||
// are replaced by <xx> with xx being the hex code of the characters
|
// are replaced by <xx> with xx being the hex code of the characters
|
||||||
StreamBuffer expand(long start, long length) const;
|
StreamBuffer expand(ssize_t start, ssize_t length) const;
|
||||||
|
|
||||||
StreamBuffer expand(long start=0) const
|
StreamBuffer expand(ssize_t start=0) const
|
||||||
{return expand(start, len);}
|
{return expand(start, len);}
|
||||||
|
|
||||||
// dump: debug function, like expand but also show the 'hidden' memory
|
// dump: debug function, like expand but also show the 'hidden' memory
|
||||||
@ -227,4 +232,13 @@ public:
|
|||||||
StreamBuffer dump() const;
|
StreamBuffer dump() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// printf size prefix for size_t and ssize_t
|
||||||
|
#if defined (__GNUC__) && __GNUC__ >= 3
|
||||||
|
#define PRINTF_SIZE_T_PREFIX "z"
|
||||||
|
#elif defined (_WIN32)
|
||||||
|
#define PRINTF_SIZE_T_PREFIX "I"
|
||||||
|
#else
|
||||||
|
#define PRINTF_SIZE_T_PREFIX ""
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,14 +18,9 @@
|
|||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "StreamBusInterface.h"
|
#include "StreamBusInterface.h"
|
||||||
|
#include "StreamError.h"
|
||||||
|
|
||||||
const char* StreamIoStatusStr[] = {
|
StreamIoStatusStrClass StreamIoStatusStr;
|
||||||
"StreamIoSuccess",
|
|
||||||
"StreamIoTimeout",
|
|
||||||
"StreamIoNoReply",
|
|
||||||
"StreamIoEnd",
|
|
||||||
"StreamIoFault"
|
|
||||||
};
|
|
||||||
|
|
||||||
StreamBusInterfaceRegistrarBase* StreamBusInterfaceRegistrarBase::first;
|
StreamBusInterfaceRegistrarBase* StreamBusInterfaceRegistrarBase::first;
|
||||||
|
|
||||||
@ -64,11 +59,17 @@ supportsAsyncRead()
|
|||||||
StreamBusInterface* StreamBusInterface::
|
StreamBusInterface* StreamBusInterface::
|
||||||
find(Client* client, const char* busname, int addr, const char* param)
|
find(Client* client, const char* busname, int addr, const char* param)
|
||||||
{
|
{
|
||||||
|
debug("StreamBusInterface::find(%s, %s, %d, \"%s\")\n",
|
||||||
|
client->name(), busname, addr, param);
|
||||||
StreamBusInterfaceRegistrarBase* r;
|
StreamBusInterfaceRegistrarBase* r;
|
||||||
StreamBusInterface* bus;
|
StreamBusInterface* bus;
|
||||||
for (r = r->first; r; r = r->next)
|
for (r = StreamBusInterfaceRegistrarBase::first; r; r = r->next)
|
||||||
{
|
{
|
||||||
|
debug("StreamBusInterface::find %s check %s\n",
|
||||||
|
client->name(), r->name);
|
||||||
bus = r->find(client, busname, addr, param);
|
bus = r->find(client, busname, addr, param);
|
||||||
|
debug("StreamBusInterface::find %s %s\n",
|
||||||
|
r->name, bus ? "matches" : "does not match");
|
||||||
if (bus) return bus;
|
if (bus) return bus;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -21,13 +21,26 @@
|
|||||||
#define StreamBusInterface_h
|
#define StreamBusInterface_h
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <StreamBuffer.h>
|
||||||
|
|
||||||
enum StreamIoStatus {
|
enum StreamIoStatus {
|
||||||
StreamIoSuccess, StreamIoTimeout, StreamIoNoReply,
|
StreamIoSuccess, StreamIoTimeout, StreamIoNoReply,
|
||||||
StreamIoEnd, StreamIoFault
|
StreamIoEnd, StreamIoFault
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char* StreamIoStatusStr[];
|
class StreamIoStatusStrClass {
|
||||||
|
public:
|
||||||
|
const char* operator [] (int index) {
|
||||||
|
switch (index) {
|
||||||
|
case StreamIoSuccess: return "StreamIoSuccess";
|
||||||
|
case StreamIoTimeout: return "StreamIoTimeout";
|
||||||
|
case StreamIoNoReply: return "StreamIoNoReply";
|
||||||
|
case StreamIoEnd: return "StreamIoEnd";
|
||||||
|
case StreamIoFault: return "StreamIoFault";
|
||||||
|
default: return "illegal status";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} extern StreamIoStatusStr;
|
||||||
|
|
||||||
class StreamBusInterface
|
class StreamBusInterface
|
||||||
{
|
{
|
||||||
@ -44,70 +57,53 @@ public:
|
|||||||
virtual void connectCallback(StreamIoStatus status);
|
virtual void connectCallback(StreamIoStatus status);
|
||||||
virtual void disconnectCallback(StreamIoStatus status);
|
virtual void disconnectCallback(StreamIoStatus status);
|
||||||
virtual long priority();
|
virtual long priority();
|
||||||
virtual const char* name() = 0;
|
|
||||||
virtual const char* getInTerminator(size_t& length) = 0;
|
virtual const char* getInTerminator(size_t& length) = 0;
|
||||||
virtual const char* getOutTerminator(size_t& length) = 0;
|
virtual const char* getOutTerminator(size_t& length) = 0;
|
||||||
public:
|
public:
|
||||||
|
virtual const char* name() = 0;
|
||||||
virtual ~Client();
|
virtual ~Client();
|
||||||
protected:
|
protected:
|
||||||
StreamBusInterface* businterface;
|
StreamBusInterface* businterface;
|
||||||
bool busSupportsEvent() {
|
bool busSupportsEvent() {
|
||||||
if (businterface)
|
return businterface && businterface->supportsEvent();
|
||||||
return businterface->supportsEvent();
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
bool busSupportsAsyncRead() {
|
bool busSupportsAsyncRead() {
|
||||||
if (businterface)
|
return businterface && businterface->supportsAsyncRead();
|
||||||
return businterface->supportsAsyncRead();
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
bool busAcceptEvent(unsigned long mask,
|
bool busAcceptEvent(unsigned long mask,
|
||||||
unsigned long replytimeout_ms) {
|
unsigned long replytimeout_ms) {
|
||||||
if (businterface)
|
return businterface && businterface->acceptEvent(mask, replytimeout_ms);
|
||||||
return businterface->acceptEvent(mask, replytimeout_ms);
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
void busRelease() {
|
void busRelease() {
|
||||||
if (businterface)
|
if (businterface) businterface->release();
|
||||||
businterface->release();
|
|
||||||
}
|
}
|
||||||
bool busLockRequest(unsigned long timeout_ms) {
|
bool busLockRequest(unsigned long timeout_ms) {
|
||||||
if (businterface)
|
return businterface && businterface->lockRequest(timeout_ms);
|
||||||
return businterface->lockRequest(timeout_ms);
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
bool busUnlock() {
|
bool busUnlock() {
|
||||||
if (businterface)
|
return businterface && businterface->unlock();
|
||||||
return businterface->unlock();
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
bool busWriteRequest(const void* output, size_t size,
|
bool busWriteRequest(const void* output, size_t size,
|
||||||
unsigned long timeout_ms) {
|
unsigned long timeout_ms) {
|
||||||
if (businterface)
|
return businterface && businterface->writeRequest(output, size, timeout_ms);
|
||||||
return businterface->writeRequest(output, size, timeout_ms);
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
bool busReadRequest(unsigned long replytimeout_ms,
|
bool busReadRequest(unsigned long replytimeout_ms,
|
||||||
unsigned long readtimeout_ms, long expectedLength,
|
unsigned long readtimeout_ms, long expectedLength,
|
||||||
bool async) {
|
bool async) {
|
||||||
if (businterface)
|
return businterface && businterface->readRequest(replytimeout_ms,
|
||||||
return businterface->readRequest(replytimeout_ms,
|
|
||||||
readtimeout_ms, expectedLength, async);
|
readtimeout_ms, expectedLength, async);
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
void busFinish() {
|
void busFinish() {
|
||||||
if (businterface)
|
if (businterface) businterface->finish();
|
||||||
businterface->finish();
|
|
||||||
}
|
}
|
||||||
bool busConnectRequest(unsigned long timeout_ms) {
|
bool busConnectRequest(unsigned long timeout_ms) {
|
||||||
if (businterface)
|
return businterface && businterface->connectRequest(timeout_ms);
|
||||||
return businterface->connectRequest(timeout_ms);
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
bool busDisconnect() {
|
bool busDisconnect() {
|
||||||
if (businterface)
|
return businterface && businterface->disconnectRequest();
|
||||||
return businterface->disconnectRequest();
|
}
|
||||||
else return false;
|
void busPrintStatus(StreamBuffer& buffer) {
|
||||||
|
if (businterface) businterface->printStatus(buffer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -157,6 +153,7 @@ protected:
|
|||||||
virtual bool connectRequest(unsigned long connecttimeout_ms);
|
virtual bool connectRequest(unsigned long connecttimeout_ms);
|
||||||
virtual bool disconnectRequest();
|
virtual bool disconnectRequest();
|
||||||
virtual void finish();
|
virtual void finish();
|
||||||
|
virtual void printStatus(StreamBuffer& buffer) {};
|
||||||
|
|
||||||
// pure virtual
|
// pure virtual
|
||||||
virtual bool lockRequest(unsigned long timeout_ms) = 0;
|
virtual bool lockRequest(unsigned long timeout_ms) = 0;
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define P PRINTF_SIZE_T_PREFIX
|
||||||
|
|
||||||
enum Commands { end_cmd, in_cmd, out_cmd, wait_cmd, event_cmd, exec_cmd,
|
enum Commands { end_cmd, in_cmd, out_cmd, wait_cmd, event_cmd, exec_cmd,
|
||||||
connect_cmd, disconnect_cmd };
|
connect_cmd, disconnect_cmd };
|
||||||
const char* commandStr[] = { "end", "in", "out", "wait", "event", "exec",
|
const char* commandStr[] = { "end", "in", "out", "wait", "event", "exec",
|
||||||
@ -57,7 +59,7 @@ static char* printCommands(StreamBuffer& buffer, const char* c)
|
|||||||
break;
|
break;
|
||||||
case wait_cmd:
|
case wait_cmd:
|
||||||
timeout = extract<unsigned long>(c);
|
timeout = extract<unsigned long>(c);
|
||||||
buffer.print(" wait %ld;\n # ms", timeout);
|
buffer.print(" wait %ld; # ms\n", timeout);
|
||||||
break;
|
break;
|
||||||
case event_cmd:
|
case event_cmd:
|
||||||
eventnumber = extract<unsigned long>(c);
|
eventnumber = extract<unsigned long>(c);
|
||||||
@ -163,7 +165,7 @@ attachBus(const char* busname, int addr, const char* param)
|
|||||||
businterface = StreamBusInterface::find(this, busname, addr, param);
|
businterface = StreamBusInterface::find(this, busname, addr, param);
|
||||||
if (!businterface)
|
if (!businterface)
|
||||||
{
|
{
|
||||||
error("Businterface '%s' not found for '%s'\n",
|
error("Cannot find a bus named '%s' for '%s'\n",
|
||||||
busname, name());
|
busname, name());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -341,6 +343,7 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
args++;
|
args++;
|
||||||
|
while (isspace(*args)) args++;
|
||||||
}
|
}
|
||||||
buffer.append(&eventmask, sizeof(eventmask));
|
buffer.append(&eventmask, sizeof(eventmask));
|
||||||
if (*args)
|
if (*args)
|
||||||
@ -457,7 +460,7 @@ finishProtocol(ProtocolResult status)
|
|||||||
status = Fault;
|
status = Fault;
|
||||||
}
|
}
|
||||||
//// flags &= ~(AcceptInput|AcceptEvent);
|
//// flags &= ~(AcceptInput|AcceptEvent);
|
||||||
if (runningHandler)
|
if (runningHandler || flags & InitRun)
|
||||||
{
|
{
|
||||||
// get original error status
|
// get original error status
|
||||||
if (status == Success) status = runningHandler;
|
if (status == Success) status = runningHandler;
|
||||||
@ -746,7 +749,7 @@ printSeparator()
|
|||||||
bool StreamCore::
|
bool StreamCore::
|
||||||
printValue(const StreamFormat& fmt, long value)
|
printValue(const StreamFormat& fmt, long value)
|
||||||
{
|
{
|
||||||
if (fmt.type != long_format && fmt.type != enum_format)
|
if (fmt.type != unsigned_format && fmt.type != signed_format && fmt.type != enum_format)
|
||||||
{
|
{
|
||||||
error("%s: printValue(long) called with %%%c format\n",
|
error("%s: printValue(long) called with %%%c format\n",
|
||||||
name(), fmt.conv);
|
name(), fmt.conv);
|
||||||
@ -760,8 +763,8 @@ printValue(const StreamFormat& fmt, long value)
|
|||||||
name(), value);
|
name(), value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
debug("StreamCore::printValue(%s, long): \"%s\"\n",
|
debug("StreamCore::printValue %s %%%c long %ld (%lx): \"%s\"\n",
|
||||||
name(), outputLine.expand()());
|
name(), fmt.conv, value, value, outputLine.expand()());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,8 +785,8 @@ printValue(const StreamFormat& fmt, double value)
|
|||||||
name(), value);
|
name(), value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
debug("StreamCore::printValue(%s, double): \"%s\"\n",
|
debug("StreamCore::printValue %s %%%c double %#g: \"%s\"\n",
|
||||||
name(), outputLine.expand()());
|
name(), fmt.conv, value, outputLine.expand()());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,8 +808,8 @@ printValue(const StreamFormat& fmt, char* value)
|
|||||||
name(), buffer.expand()());
|
name(), buffer.expand()());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
debug("StreamCore::printValue(%s, char*): \"%s\"\n",
|
debug("StreamCore::printValue %s %%%c char* \"%s\"): \"%s\"\n",
|
||||||
name(), outputLine.expand()());
|
name(), fmt.conv, value, outputLine.expand()());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,7 +818,7 @@ lockCallback(StreamIoStatus status)
|
|||||||
{
|
{
|
||||||
MutexLock lock(this);
|
MutexLock lock(this);
|
||||||
debug("StreamCore::lockCallback(%s, status=%s)\n",
|
debug("StreamCore::lockCallback(%s, status=%s)\n",
|
||||||
name(), status ? "Timeout" : "Success");
|
name(), StreamIoStatusStr[status]);
|
||||||
if (!(flags & LockPending))
|
if (!(flags & LockPending))
|
||||||
{
|
{
|
||||||
error("StreamCore::lockCallback(%s) called unexpectedly\n",
|
error("StreamCore::lockCallback(%s) called unexpectedly\n",
|
||||||
@ -829,9 +832,21 @@ lockCallback(StreamIoStatus status)
|
|||||||
case StreamIoSuccess:
|
case StreamIoSuccess:
|
||||||
break;
|
break;
|
||||||
case StreamIoTimeout:
|
case StreamIoTimeout:
|
||||||
|
debug("%s: Cannot lock device within %ld ms, device seems to be busy\n",
|
||||||
|
name(), lockTimeout);
|
||||||
|
flags &= ~BusOwner;
|
||||||
|
finishProtocol(LockTimeout);
|
||||||
|
return;
|
||||||
|
case StreamIoFault:
|
||||||
|
error("%s: Locking failed because of a device fault\n",
|
||||||
|
name());
|
||||||
|
flags &= ~BusOwner;
|
||||||
finishProtocol(LockTimeout);
|
finishProtocol(LockTimeout);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
error("StreamCore::lockCallback(%s) unexpected status %s\n",
|
||||||
|
name(), StreamIoStatusStr[status]);
|
||||||
|
flags &= ~BusOwner;
|
||||||
finishProtocol(Fault);
|
finishProtocol(Fault);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -976,13 +991,13 @@ readCallback(StreamIoStatus status,
|
|||||||
evalIn();
|
evalIn();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
error("%s: No reply from device within %ld ms\n",
|
debug("StreamCore::readCallback(%s): No reply from device within %ld ms\n",
|
||||||
name(), replyTimeout);
|
name(), replyTimeout);
|
||||||
inputBuffer.clear();
|
inputBuffer.clear();
|
||||||
finishProtocol(ReplyTimeout);
|
finishProtocol(ReplyTimeout);
|
||||||
return 0;
|
return 0;
|
||||||
case StreamIoFault:
|
case StreamIoFault:
|
||||||
error("%s: I/O error after reading %ld byte%s: \"%s%s\"\n",
|
error("%s: I/O error after reading %"P"d byte%s: \"%s%s\"\n",
|
||||||
name(),
|
name(),
|
||||||
inputBuffer.length(), inputBuffer.length()==1 ? "" : "s",
|
inputBuffer.length(), inputBuffer.length()==1 ? "" : "s",
|
||||||
inputBuffer.length() > 20 ? "..." : "",
|
inputBuffer.length() > 20 ? "..." : "",
|
||||||
@ -991,7 +1006,7 @@ readCallback(StreamIoStatus status,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
inputBuffer.append(input, size);
|
inputBuffer.append(input, size);
|
||||||
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %ld\n",
|
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %"P"d\n",
|
||||||
name(), inputBuffer.expand()(), inputBuffer.length());
|
name(), inputBuffer.expand()(), inputBuffer.length());
|
||||||
if (*activeCommand != in_cmd)
|
if (*activeCommand != in_cmd)
|
||||||
{
|
{
|
||||||
@ -1184,6 +1199,7 @@ normal_format:
|
|||||||
int consumed;
|
int consumed;
|
||||||
// code layout:
|
// code layout:
|
||||||
// formatstring <eos> StreamFormat [info]
|
// formatstring <eos> StreamFormat [info]
|
||||||
|
formatstring.clear();
|
||||||
commandIndex = StreamProtocolParser::printString(formatstring, commandIndex);
|
commandIndex = StreamProtocolParser::printString(formatstring, commandIndex);
|
||||||
|
|
||||||
StreamFormat fmt = extract<StreamFormat>(commandIndex);
|
StreamFormat fmt = extract<StreamFormat>(commandIndex);
|
||||||
@ -1200,7 +1216,8 @@ normal_format:
|
|||||||
double ddummy;
|
double ddummy;
|
||||||
switch (fmt.type)
|
switch (fmt.type)
|
||||||
{
|
{
|
||||||
case long_format:
|
case unsigned_format:
|
||||||
|
case signed_format:
|
||||||
case enum_format:
|
case enum_format:
|
||||||
consumed = StreamFormatConverter::find(fmt.conv)->
|
consumed = StreamFormatConverter::find(fmt.conv)->
|
||||||
scanLong(fmt, inputLine(consumedInput), ldummy);
|
scanLong(fmt, inputLine(consumedInput), ldummy);
|
||||||
@ -1303,8 +1320,8 @@ normal_format:
|
|||||||
inputLine.length()-consumedInput > 20 ? "..." : "",
|
inputLine.length()-consumedInput > 20 ? "..." : "",
|
||||||
formatstring());
|
formatstring());
|
||||||
else
|
else
|
||||||
error("%s: Format \"%%%s\" has data type %s which does not match variable \"%s\".\n",
|
error("%s: Format \"%%%s\" has data type %s which does not match the type of \"%s\".\n",
|
||||||
name(), formatstring(), StreamFormatTypeStr[fmt.type], fieldName);
|
name(), formatstring(), StreamFormatTypeStr[fmt.type], fieldAddress ? fieldName : name());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1441,7 +1458,7 @@ matchSeparator()
|
|||||||
long StreamCore::
|
long StreamCore::
|
||||||
scanValue(const StreamFormat& fmt, long& value)
|
scanValue(const StreamFormat& fmt, long& value)
|
||||||
{
|
{
|
||||||
if (fmt.type != long_format && fmt.type != enum_format)
|
if (fmt.type != unsigned_format && fmt.type != signed_format && fmt.type != enum_format)
|
||||||
{
|
{
|
||||||
error("%s: scanValue(long&) called with %%%c format\n",
|
error("%s: scanValue(long&) called with %%%c format\n",
|
||||||
name(), fmt.conv);
|
name(), fmt.conv);
|
||||||
@ -1462,6 +1479,7 @@ scanValue(const StreamFormat& fmt, long& value)
|
|||||||
}
|
}
|
||||||
else return -1;
|
else return -1;
|
||||||
}
|
}
|
||||||
|
if (fmt.flags & fix_width_flag && consumed != fmt.width) return -1;
|
||||||
if (consumed > inputLine.length()-consumedInput) return -1;
|
if (consumed > inputLine.length()-consumedInput) return -1;
|
||||||
debug("StreamCore::scanValue(%s) scanned %li\n",
|
debug("StreamCore::scanValue(%s) scanned %li\n",
|
||||||
name(), value);
|
name(), value);
|
||||||
@ -1493,6 +1511,7 @@ scanValue(const StreamFormat& fmt, double& value)
|
|||||||
}
|
}
|
||||||
else return -1;
|
else return -1;
|
||||||
}
|
}
|
||||||
|
if (fmt.flags & fix_width_flag && (consumed != (fmt.width + fmt.prec + 1))) return -1;
|
||||||
if (consumed > inputLine.length()-consumedInput) return -1;
|
if (consumed > inputLine.length()-consumedInput) return -1;
|
||||||
debug("StreamCore::scanValue(%s) scanned %#g\n",
|
debug("StreamCore::scanValue(%s) scanned %#g\n",
|
||||||
name(), value);
|
name(), value);
|
||||||
@ -1525,6 +1544,7 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen)
|
|||||||
}
|
}
|
||||||
else return -1;
|
else return -1;
|
||||||
}
|
}
|
||||||
|
if (fmt.flags & fix_width_flag && consumed != fmt.width) return -1;
|
||||||
if (consumed > inputLine.length()-consumedInput) return -1;
|
if (consumed > inputLine.length()-consumedInput) return -1;
|
||||||
#ifndef NO_TEMPORARY
|
#ifndef NO_TEMPORARY
|
||||||
debug("StreamCore::scanValue(%s) scanned \"%s\"\n",
|
debug("StreamCore::scanValue(%s) scanned \"%s\"\n",
|
||||||
@ -1734,4 +1754,25 @@ disconnectCallback(StreamIoStatus status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StreamCore::
|
||||||
|
printStatus(StreamBuffer& buffer)
|
||||||
|
{
|
||||||
|
buffer.print("active command=%s ",
|
||||||
|
activeCommand ? commandName(*activeCommand) : "NULL");
|
||||||
|
buffer.print("flags=0x%04lx ", flags);
|
||||||
|
if (flags & IgnoreExtraInput) buffer.append("IgnoreExtraInput ");
|
||||||
|
if (flags & InitRun) buffer.append("InitRun ");
|
||||||
|
if (flags & AsyncMode) buffer.append("AsyncMode ");
|
||||||
|
if (flags & GotValue) buffer.append("GotValue ");
|
||||||
|
if (flags & BusOwner) buffer.append("BusOwner ");
|
||||||
|
if (flags & Separator) buffer.append("Separator ");
|
||||||
|
if (flags & ScanTried) buffer.append("ScanTried ");
|
||||||
|
if (flags & AcceptInput) buffer.append("AcceptInput ");
|
||||||
|
if (flags & AcceptEvent) buffer.append("AcceptEvent ");
|
||||||
|
if (flags & LockPending) buffer.append("LockPending ");
|
||||||
|
if (flags & WritePending) buffer.append("WritePending ");
|
||||||
|
if (flags & WaitPending) buffer.append("WaitPending ");
|
||||||
|
busPrintStatus(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
#include "streamReferences"
|
#include "streamReferences"
|
||||||
|
@ -219,6 +219,7 @@ public:
|
|||||||
bool parse(const char* filename, const char* protocolname);
|
bool parse(const char* filename, const char* protocolname);
|
||||||
void printProtocol();
|
void printProtocol();
|
||||||
const char* name() { return streamname; }
|
const char* name() { return streamname; }
|
||||||
|
void printStatus(StreamBuffer& buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
#include "devStream.h"
|
#include "devStream.h"
|
||||||
|
#undef epicsExportSharedSymbols
|
||||||
#include "StreamCore.h"
|
#include "StreamCore.h"
|
||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
|
|
||||||
@ -31,6 +33,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define epicsAlarmGLOBAL
|
||||||
|
#include <alarm.h>
|
||||||
|
#undef epicsAlarmGLOBAL
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -39,8 +44,6 @@ extern "C" {
|
|||||||
#include <recSup.h>
|
#include <recSup.h>
|
||||||
#include <recGbl.h>
|
#include <recGbl.h>
|
||||||
#include <devLib.h>
|
#include <devLib.h>
|
||||||
#define epicsAlarmGLOBAL
|
|
||||||
#include <alarm.h>
|
|
||||||
#include <callback.h>
|
#include <callback.h>
|
||||||
|
|
||||||
#ifdef EPICS_3_13
|
#ifdef EPICS_3_13
|
||||||
@ -112,7 +115,6 @@ class Stream : protected StreamCore
|
|||||||
epicsMutex mutex;
|
epicsMutex mutex;
|
||||||
epicsEvent initDone;
|
epicsEvent initDone;
|
||||||
#endif
|
#endif
|
||||||
StreamBuffer fieldBuffer;
|
|
||||||
int status;
|
int status;
|
||||||
int convert;
|
int convert;
|
||||||
long currentValueLength;
|
long currentValueLength;
|
||||||
@ -178,6 +180,7 @@ public:
|
|||||||
#ifndef EPICS_3_13
|
#ifndef EPICS_3_13
|
||||||
extern "C" {
|
extern "C" {
|
||||||
epicsExportAddress(int, streamDebug);
|
epicsExportAddress(int, streamDebug);
|
||||||
|
epicsExportAddress(int, streamError);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -267,7 +270,7 @@ epicsExportRegistrar(streamRegistrar);
|
|||||||
struct stream_drvsup {
|
struct stream_drvsup {
|
||||||
long number;
|
long number;
|
||||||
long (*report)(int);
|
long (*report)(int);
|
||||||
DRVSUPFUN init;
|
long (*init)();
|
||||||
} stream = {
|
} stream = {
|
||||||
2,
|
2,
|
||||||
Stream::report,
|
Stream::report,
|
||||||
@ -347,6 +350,12 @@ report(int interest)
|
|||||||
{
|
{
|
||||||
printf(" %s: %s\n", pstream->name(),
|
printf(" %s: %s\n", pstream->name(),
|
||||||
pstream->ioLink->value.instio.string);
|
pstream->ioLink->value.instio.string);
|
||||||
|
if (interest == 3)
|
||||||
|
{
|
||||||
|
StreamBuffer buffer;
|
||||||
|
pstream->printStatus(buffer);
|
||||||
|
printf(" %s\n", buffer());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@ -407,6 +416,7 @@ long streamInit(int after)
|
|||||||
long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
||||||
streamIoFunction readData, streamIoFunction writeData)
|
streamIoFunction readData, streamIoFunction writeData)
|
||||||
{
|
{
|
||||||
|
long status;
|
||||||
char filename[80];
|
char filename[80];
|
||||||
char protocol[80];
|
char protocol[80];
|
||||||
char busname[80];
|
char busname[80];
|
||||||
@ -419,26 +429,36 @@ long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
|||||||
if (!pstream)
|
if (!pstream)
|
||||||
{
|
{
|
||||||
// initialize the first time
|
// initialize the first time
|
||||||
|
debug("streamInitRecord(%s): create new Stream object\n",
|
||||||
|
record->name);
|
||||||
pstream = new Stream(record, ioLink, readData, writeData);
|
pstream = new Stream(record, ioLink, readData, writeData);
|
||||||
record->dpvt = pstream;
|
record->dpvt = pstream;
|
||||||
} else {
|
} else {
|
||||||
// stop any running protocol
|
// stop any running protocol
|
||||||
|
debug("streamInitRecord(%s): stop running protocol\n",
|
||||||
|
record->name);
|
||||||
pstream->finishProtocol(Stream::Abort);
|
pstream->finishProtocol(Stream::Abort);
|
||||||
}
|
}
|
||||||
// scan the i/o link
|
// scan the i/o link
|
||||||
pstream->parseLink(ioLink, filename, protocol,
|
debug("streamInitRecord(%s): parse link \"%s\"\n",
|
||||||
|
record->name, ioLink->value.instio.string);
|
||||||
|
status = pstream->parseLink(ioLink, filename, protocol,
|
||||||
busname, &addr, busparam);
|
busname, &addr, busparam);
|
||||||
// (re)initialize bus and protocol
|
// (re)initialize bus and protocol
|
||||||
long status = pstream->initRecord(filename, protocol,
|
debug("streamInitRecord(%s): calling initRecord\n",
|
||||||
busname, addr, busparam);
|
record->name);
|
||||||
|
if (status == 0)
|
||||||
|
status = pstream->initRecord(filename, protocol,
|
||||||
|
busname, addr, busparam);
|
||||||
if (status != OK && status != DO_NOT_CONVERT)
|
if (status != OK && status != DO_NOT_CONVERT)
|
||||||
{
|
{
|
||||||
error("%s: Record initialization failed\n", record->name);
|
error("%s: Record initialization failed\n", record->name);
|
||||||
}
|
}
|
||||||
if (!pstream->ioscanpvt)
|
else if (!pstream->ioscanpvt)
|
||||||
{
|
{
|
||||||
scanIoInit(&pstream->ioscanpvt);
|
scanIoInit(&pstream->ioscanpvt);
|
||||||
}
|
}
|
||||||
|
debug("streamInitRecord(%s) done status=%#lx\n", record->name, status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +604,7 @@ parseLink(const struct link *ioLink, char* filename,
|
|||||||
if (items <= 0)
|
if (items <= 0)
|
||||||
{
|
{
|
||||||
error("%s: Empty I/O link. "
|
error("%s: Empty I/O link. "
|
||||||
"Forgot the leading '@' or confused INP with OUT ?\n",
|
"Forgot the leading '@' or confused INP with OUT or link is too long ?\n",
|
||||||
name());
|
name());
|
||||||
return S_dev_badInitRet;
|
return S_dev_badInitRet;
|
||||||
}
|
}
|
||||||
@ -608,6 +628,8 @@ initRecord(const char* filename, const char* protocol,
|
|||||||
// It is safe to call this function again with different arguments
|
// It is safe to call this function again with different arguments
|
||||||
|
|
||||||
// attach to bus interface
|
// attach to bus interface
|
||||||
|
debug("Stream::initRecord %s: attachBus(%s, %d, \"%s\")\n",
|
||||||
|
name(), busname, addr, busparam);
|
||||||
if (!attachBus(busname, addr, busparam))
|
if (!attachBus(busname, addr, busparam))
|
||||||
{
|
{
|
||||||
error("%s: Can't attach to bus %s %d\n",
|
error("%s: Can't attach to bus %s %d\n",
|
||||||
@ -616,6 +638,8 @@ initRecord(const char* filename, const char* protocol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse protocol file
|
// parse protocol file
|
||||||
|
debug("Stream::initRecord %s: parse(%s, %s)\n",
|
||||||
|
name(), filename, protocol);
|
||||||
if (!parse(filename, protocol))
|
if (!parse(filename, protocol))
|
||||||
{
|
{
|
||||||
error("%s: Protocol parse error\n",
|
error("%s: Protocol parse error\n",
|
||||||
@ -727,21 +751,16 @@ process()
|
|||||||
bool Stream::
|
bool Stream::
|
||||||
print(format_t *format, va_list ap)
|
print(format_t *format, va_list ap)
|
||||||
{
|
{
|
||||||
long lval;
|
|
||||||
double dval;
|
|
||||||
char* sval;
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
case DBF_ENUM:
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
lval = va_arg(ap, long);
|
case DBF_ENUM:
|
||||||
return printValue(*format->priv, lval);
|
return printValue(*format->priv, va_arg(ap, long));
|
||||||
case DBF_DOUBLE:
|
case DBF_DOUBLE:
|
||||||
dval = va_arg(ap, double);
|
return printValue(*format->priv, va_arg(ap, double));
|
||||||
return printValue(*format->priv, dval);
|
|
||||||
case DBF_STRING:
|
case DBF_STRING:
|
||||||
sval = va_arg(ap, char*);
|
return printValue(*format->priv, va_arg(ap, char*));
|
||||||
return printValue(*format->priv, sval);
|
|
||||||
}
|
}
|
||||||
error("INTERNAL ERROR (%s): Illegal format type\n", name());
|
error("INTERNAL ERROR (%s): Illegal format type\n", name());
|
||||||
return false;
|
return false;
|
||||||
@ -751,27 +770,22 @@ bool Stream::
|
|||||||
scan(format_t *format, void* value, size_t maxStringSize)
|
scan(format_t *format, void* value, size_t maxStringSize)
|
||||||
{
|
{
|
||||||
// called by streamScanfN
|
// called by streamScanfN
|
||||||
long* lptr;
|
|
||||||
double* dptr;
|
|
||||||
char* sptr;
|
|
||||||
|
|
||||||
// first remove old value from inputLine (if we are scanning arrays)
|
// first remove old value from inputLine (if we are scanning arrays)
|
||||||
consumedInput += currentValueLength;
|
consumedInput += currentValueLength;
|
||||||
currentValueLength = 0;
|
currentValueLength = 0;
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
lptr = (long*)value;
|
currentValueLength = scanValue(*format->priv, *(long*)value);
|
||||||
currentValueLength = scanValue(*format->priv, *lptr);
|
|
||||||
break;
|
break;
|
||||||
case DBF_DOUBLE:
|
case DBF_DOUBLE:
|
||||||
dptr = (double*)value;
|
currentValueLength = scanValue(*format->priv, *(double*)value);
|
||||||
currentValueLength = scanValue(*format->priv, *dptr);
|
|
||||||
break;
|
break;
|
||||||
case DBF_STRING:
|
case DBF_STRING:
|
||||||
sptr = (char*)value;
|
currentValueLength = scanValue(*format->priv, (char*)value,
|
||||||
currentValueLength = scanValue(*format->priv, sptr,
|
|
||||||
maxStringSize);
|
maxStringSize);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -941,13 +955,13 @@ getFieldAddress(const char* fieldname, StreamBuffer& address)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIELD in this record or VAL in other record
|
// FIELD in this record or VAL in other record
|
||||||
char fullname[PVNAME_SZ + 1];
|
StreamBuffer fullname;
|
||||||
sprintf(fullname, "%s.%s", name(), fieldname);
|
fullname.print("%s.%s", name(), fieldname);
|
||||||
if (dbNameToAddr(fullname, &dbaddr) != OK)
|
if (dbNameToAddr(fullname(), &dbaddr) != OK)
|
||||||
{
|
{
|
||||||
// VAL in other record
|
// VAL in other record
|
||||||
sprintf(fullname, "%s.VAL", fieldname);
|
fullname.clear().print("%s.VAL", fieldname);
|
||||||
if (dbNameToAddr(fullname, &dbaddr) != OK) return false;
|
if (dbNameToAddr(fullname(), &dbaddr) != OK) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
address.append(&dbaddr, sizeof(dbaddr));
|
address.append(&dbaddr, sizeof(dbaddr));
|
||||||
@ -955,9 +969,9 @@ getFieldAddress(const char* fieldname, StreamBuffer& address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char dbfMapping[] =
|
static const unsigned char dbfMapping[] =
|
||||||
{0, DBF_LONG, DBF_ENUM, DBF_DOUBLE, DBF_STRING};
|
{0, DBF_ULONG, DBF_LONG, DBF_ENUM, DBF_DOUBLE, DBF_STRING};
|
||||||
static const short typeSize[] =
|
static const short typeSize[] =
|
||||||
{0, sizeof(epicsInt32), sizeof(epicsUInt16),
|
{0, sizeof(epicsUInt32), sizeof(epicsInt32), sizeof(epicsUInt16),
|
||||||
sizeof(epicsFloat64), MAX_STRING_SIZE};
|
sizeof(epicsFloat64), MAX_STRING_SIZE};
|
||||||
|
|
||||||
bool Stream::
|
bool Stream::
|
||||||
@ -969,16 +983,17 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
// -- TO DO: If SCAN is "I/O Intr" and record has not been processed, --
|
// -- TO DO: If SCAN is "I/O Intr" and record has not been processed, --
|
||||||
// -- do it now to get the latest value (only for output records?) --
|
// -- do it now to get the latest value (only for output records?) --
|
||||||
|
|
||||||
|
format_s fmt;
|
||||||
|
fmt.type = dbfMapping[format.type];
|
||||||
|
fmt.priv = &format;
|
||||||
if (fieldaddress)
|
if (fieldaddress)
|
||||||
{
|
{
|
||||||
// Format like "%([record.]field)..." has requested to get value
|
// Format like "%([record.]field)..." has requested to get value
|
||||||
// from field of this or other record.
|
// from field of this or other record.
|
||||||
|
StreamBuffer fieldBuffer;
|
||||||
DBADDR* pdbaddr = (DBADDR*)fieldaddress;
|
DBADDR* pdbaddr = (DBADDR*)fieldaddress;
|
||||||
long i;
|
|
||||||
long nelem = pdbaddr->no_elements;
|
|
||||||
size_t size = nelem * typeSize[format.type];
|
|
||||||
char* buffer = fieldBuffer.clear().reserve(size);
|
|
||||||
|
|
||||||
|
/* Handle time stamps special. %T converter takes double. */
|
||||||
if (strcmp(((dbFldDes*)pdbaddr->pfldDes)->name, "TIME") == 0)
|
if (strcmp(((dbFldDes*)pdbaddr->pfldDes)->name, "TIME") == 0)
|
||||||
{
|
{
|
||||||
double time;
|
double time;
|
||||||
@ -994,6 +1009,8 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
/* if getting time from own record, update timestamp first */
|
/* if getting time from own record, update timestamp first */
|
||||||
recGblGetTimeStamp(record);
|
recGblGetTimeStamp(record);
|
||||||
}
|
}
|
||||||
|
/* convert EPICS epoch (1990) to unix epoch (1970) */
|
||||||
|
/* we are losing about 3 digits precision here */
|
||||||
time = pdbaddr->precord->time.secPastEpoch +
|
time = pdbaddr->precord->time.secPastEpoch +
|
||||||
631152000u + pdbaddr->precord->time.nsec * 1e-9;
|
631152000u + pdbaddr->precord->time.nsec * 1e-9;
|
||||||
debug("Stream::formatValue(%s): read %f from TIME field\n",
|
debug("Stream::formatValue(%s): read %f from TIME field\n",
|
||||||
@ -1001,7 +1018,28 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
return printValue(format, time);
|
return printValue(format, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbGet(pdbaddr, dbfMapping[format.type], buffer,
|
/* convert type to LONG, ENUM, DOUBLE, or STRING */
|
||||||
|
long nelem = pdbaddr->no_elements;
|
||||||
|
size_t size = nelem * typeSize[format.type];
|
||||||
|
|
||||||
|
/* print (U)CHAR arrays as string */
|
||||||
|
if (format.type == string_format &&
|
||||||
|
(pdbaddr->field_type == DBF_CHAR || pdbaddr->field_type == DBF_UCHAR))
|
||||||
|
{
|
||||||
|
debug("Stream::formatValue(%s): format %s.%s array[%ld] size %d of %s as string\n",
|
||||||
|
name(),
|
||||||
|
pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
nelem,
|
||||||
|
pdbaddr->field_size,
|
||||||
|
pamapdbfType[pdbaddr->field_type].strvalue);
|
||||||
|
fmt.type = DBF_CHAR;
|
||||||
|
size = nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* buffer = fieldBuffer.clear().reserve(size);
|
||||||
|
|
||||||
|
if (dbGet(pdbaddr, fmt.type, buffer,
|
||||||
NULL, &nelem, NULL) != 0)
|
NULL, &nelem, NULL) != 0)
|
||||||
{
|
{
|
||||||
error("%s: dbGet(%s.%s, %s) failed\n",
|
error("%s: dbGet(%s.%s, %s) failed\n",
|
||||||
@ -1011,6 +1049,18 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
pamapdbfType[dbfMapping[format.type]].strvalue);
|
pamapdbfType[dbfMapping[format.type]].strvalue);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
debug("Stream::formatValue(%s): got %ld elements\n",
|
||||||
|
name(),nelem);
|
||||||
|
|
||||||
|
/* terminate CHAR array as string */
|
||||||
|
if (fmt.type == DBF_CHAR)
|
||||||
|
{
|
||||||
|
if (nelem >= pdbaddr->no_elements) nelem = pdbaddr->no_elements-1;
|
||||||
|
buffer[nelem] = 0;
|
||||||
|
nelem = 1; /* array is only 1 string */
|
||||||
|
}
|
||||||
|
|
||||||
|
long i;
|
||||||
for (i = 0; i < nelem; i++)
|
for (i = 0; i < nelem; i++)
|
||||||
{
|
{
|
||||||
switch (format.type)
|
switch (format.type)
|
||||||
@ -1020,7 +1070,12 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
(long)((epicsUInt16*)buffer)[i]))
|
(long)((epicsUInt16*)buffer)[i]))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case long_format:
|
case unsigned_format:
|
||||||
|
if (!printValue(format,
|
||||||
|
(long)((epicsUInt32*)buffer)[i]))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case signed_format:
|
||||||
if (!printValue(format,
|
if (!printValue(format,
|
||||||
(long)((epicsInt32*)buffer)[i]))
|
(long)((epicsInt32*)buffer)[i]))
|
||||||
return false;
|
return false;
|
||||||
@ -1038,6 +1093,7 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
error("%s: %%(FIELD) syntax not allowed "
|
error("%s: %%(FIELD) syntax not allowed "
|
||||||
"with pseudo formats\n",
|
"with pseudo formats\n",
|
||||||
name());
|
name());
|
||||||
|
return false;
|
||||||
default:
|
default:
|
||||||
error("INTERNAL ERROR %s: Illegal format.type=%d\n",
|
error("INTERNAL ERROR %s: Illegal format.type=%d\n",
|
||||||
name(), format.type);
|
name(), format.type);
|
||||||
@ -1046,9 +1102,6 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
format_s fmt;
|
|
||||||
fmt.type = dbfMapping[format.type];
|
|
||||||
fmt.priv = &format;
|
|
||||||
debug("Stream::formatValue(%s) format=%%%c type=%s\n",
|
debug("Stream::formatValue(%s) format=%%%c type=%s\n",
|
||||||
name(), format.conv, pamapdbfType[fmt.type].strvalue);
|
name(), format.conv, pamapdbfType[fmt.type].strvalue);
|
||||||
if (!writeData)
|
if (!writeData)
|
||||||
@ -1074,11 +1127,15 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
char* buffer;
|
char* buffer;
|
||||||
int status;
|
int status;
|
||||||
const char* putfunc;
|
const char* putfunc;
|
||||||
|
format_s fmt;
|
||||||
|
|
||||||
|
fmt.type = dbfMapping[format.type];
|
||||||
|
fmt.priv = &format;
|
||||||
if (fieldaddress)
|
if (fieldaddress)
|
||||||
{
|
{
|
||||||
// Format like "%([record.]field)..." has requested to put value
|
// Format like "%([record.]field)..." has requested to put value
|
||||||
// to field of this or other record.
|
// to field of this or other record.
|
||||||
|
StreamBuffer fieldBuffer;
|
||||||
DBADDR* pdbaddr = (DBADDR*)fieldaddress;
|
DBADDR* pdbaddr = (DBADDR*)fieldaddress;
|
||||||
long nord;
|
long nord;
|
||||||
long nelem = pdbaddr->no_elements;
|
long nelem = pdbaddr->no_elements;
|
||||||
@ -1090,12 +1147,24 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
name(), fieldBuffer.expand()());
|
name(), fieldBuffer.expand()());
|
||||||
switch (format.type)
|
switch (format.type)
|
||||||
{
|
{
|
||||||
case long_format:
|
case unsigned_format:
|
||||||
|
{
|
||||||
|
consumed = scanValue(format, lval);
|
||||||
|
if (consumed >= 0) ((epicsUInt32*)buffer)[nord] = lval;
|
||||||
|
debug("Stream::matchValue(%s): %s.%s[%li] = %lu\n",
|
||||||
|
name(), pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
nord, lval);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case signed_format:
|
||||||
{
|
{
|
||||||
consumed = scanValue(format, lval);
|
consumed = scanValue(format, lval);
|
||||||
if (consumed >= 0) ((epicsInt32*)buffer)[nord] = lval;
|
if (consumed >= 0) ((epicsInt32*)buffer)[nord] = lval;
|
||||||
debug("Stream::matchValue(%s): %s[%li] = %li\n",
|
debug("Stream::matchValue(%s): %s.%s[%li] = %li\n",
|
||||||
name(), pdbaddr->precord->name, nord, lval);
|
name(), pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
nord, lval);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case enum_format:
|
case enum_format:
|
||||||
@ -1103,8 +1172,10 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
consumed = scanValue(format, lval);
|
consumed = scanValue(format, lval);
|
||||||
if (consumed >= 0)
|
if (consumed >= 0)
|
||||||
((epicsUInt16*)buffer)[nord] = (epicsUInt16)lval;
|
((epicsUInt16*)buffer)[nord] = (epicsUInt16)lval;
|
||||||
debug("Stream::matchValue(%s): %s[%li] = %li\n",
|
debug("Stream::matchValue(%s): %s.%s[%li] = %li\n",
|
||||||
name(), pdbaddr->precord->name, nord, lval);
|
name(), pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
nord, lval);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case double_format:
|
case double_format:
|
||||||
@ -1117,18 +1188,34 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
if (consumed >= 0)
|
if (consumed >= 0)
|
||||||
memcpy(((epicsFloat64*)buffer)+nord,
|
memcpy(((epicsFloat64*)buffer)+nord,
|
||||||
&f64, sizeof(f64));
|
&f64, sizeof(f64));
|
||||||
debug("Stream::matchValue(%s): %s[%li] = %#g %#g\n",
|
debug("Stream::matchValue(%s): %s.%s[%li] = %#g %#g\n",
|
||||||
name(), pdbaddr->precord->name, nord, dval,
|
name(), pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
nord, dval,
|
||||||
((epicsFloat64*)buffer)[nord]);
|
((epicsFloat64*)buffer)[nord]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case string_format:
|
case string_format:
|
||||||
{
|
{
|
||||||
consumed = scanValue(format,
|
if (pdbaddr->field_type == DBF_CHAR)
|
||||||
buffer+MAX_STRING_SIZE*nord, MAX_STRING_SIZE);
|
{
|
||||||
debug("Stream::matchValue(%s): %s[%li] = \"%.*s\"\n",
|
// string to char array
|
||||||
name(), pdbaddr->precord->name, nord,
|
consumed = scanValue(format, buffer, nelem);
|
||||||
MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord);
|
debug("Stream::matchValue(%s): %s.%s = \"%.*s\"\n",
|
||||||
|
name(), pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
(int)consumed, buffer);
|
||||||
|
nord = nelem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
consumed = scanValue(format,
|
||||||
|
buffer+MAX_STRING_SIZE*nord, MAX_STRING_SIZE);
|
||||||
|
debug("Stream::matchValue(%s): %s.%s[%li] = \"%.*s\"\n",
|
||||||
|
name(), pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
nord, MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1165,15 +1252,17 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
name());
|
name());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/* convert from Unix epoch (1 Jan 1970) to EPICS epoch (1 Jan 1990) */
|
||||||
dval = dval-631152000u;
|
dval = dval-631152000u;
|
||||||
pdbaddr->precord->time.secPastEpoch = (long)dval;
|
pdbaddr->precord->time.secPastEpoch = (long)dval;
|
||||||
// rouding: we don't have 9 digits precision
|
// rouding: we don't have 9 digits precision
|
||||||
// in a double of today's number of seconds
|
// in a double of today's number of seconds
|
||||||
pdbaddr->precord->time.nsec = (long)((dval-(long)dval)*1e6)*1000;
|
pdbaddr->precord->time.nsec = (long)((dval-(long)dval)*1e6)*1000;
|
||||||
debug("Stream::matchValue(%s): writing %i.%i to TIME field\n",
|
debug("Stream::matchValue(%s): writing %i.%i to %s.TIME field\n",
|
||||||
name(),
|
name(),
|
||||||
pdbaddr->precord->time.secPastEpoch,
|
pdbaddr->precord->time.secPastEpoch,
|
||||||
pdbaddr->precord->time.nsec);
|
pdbaddr->precord->time.nsec,
|
||||||
|
pdbaddr->precord->name);
|
||||||
pdbaddr->precord->tse = epicsTimeEventDeviceTime;
|
pdbaddr->precord->tse = epicsTimeEventDeviceTime;
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
@ -1182,18 +1271,19 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (format.type == string_format &&
|
||||||
|
(pdbaddr->field_type == DBF_CHAR || pdbaddr->field_type == DBF_UCHAR))
|
||||||
|
{
|
||||||
|
/* write strings to [U]CHAR arrays */
|
||||||
|
nord = consumed;
|
||||||
|
fmt.type = DBF_CHAR;
|
||||||
|
}
|
||||||
if (pdbaddr->precord == record || INIT_RUN)
|
if (pdbaddr->precord == record || INIT_RUN)
|
||||||
{
|
{
|
||||||
// write into own record, thus don't process it
|
// write into own record, thus don't process it
|
||||||
// in @init we must not process other record
|
// in @init we must not process other record
|
||||||
debug("Stream::matchValue(%s): dbPut(%s.%s,%s)\n",
|
|
||||||
name(),
|
|
||||||
pdbaddr->precord->name,
|
|
||||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
|
||||||
fieldBuffer.expand()());
|
|
||||||
putfunc = "dbPut";
|
putfunc = "dbPut";
|
||||||
status = dbPut(pdbaddr, dbfMapping[format.type], buffer, nord);
|
status = dbPut(pdbaddr, fmt.type, buffer, nord);
|
||||||
if (INIT_RUN && pdbaddr->precord != record)
|
if (INIT_RUN && pdbaddr->precord != record)
|
||||||
{
|
{
|
||||||
// clean error status of other record in @init
|
// clean error status of other record in @init
|
||||||
@ -1205,41 +1295,44 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// write into other record, thus process it
|
// write into other record, thus process it
|
||||||
debug("Stream::matchValue(%s): dbPutField(%s.%s,%s)\n",
|
|
||||||
name(),
|
|
||||||
pdbaddr->precord->name,
|
|
||||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
|
||||||
fieldBuffer.expand()());
|
|
||||||
putfunc = "dbPutField";
|
putfunc = "dbPutField";
|
||||||
status = dbPutField(pdbaddr, dbfMapping[format.type],
|
status = dbPutField(pdbaddr, fmt.type,
|
||||||
buffer, nord);
|
buffer, nord);
|
||||||
}
|
}
|
||||||
|
debug("Stream::matchValue(%s): %s(%s.%s, %s, %s) status=0x%x\n",
|
||||||
|
name(), putfunc,
|
||||||
|
pdbaddr->precord->name,
|
||||||
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
|
pamapdbfType[fmt.type].strvalue,
|
||||||
|
fieldBuffer.expand()(),
|
||||||
|
status);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
flags &= ~ScanTried;
|
flags &= ~ScanTried;
|
||||||
switch (format.type)
|
switch (fmt.type)
|
||||||
{
|
{
|
||||||
case long_format:
|
case DBF_ULONG:
|
||||||
case enum_format:
|
case DBF_LONG:
|
||||||
|
case DBF_ENUM:
|
||||||
error("%s: %s(%s.%s, %s, %li) failed\n",
|
error("%s: %s(%s.%s, %s, %li) failed\n",
|
||||||
putfunc, name(), pdbaddr->precord->name,
|
name(), putfunc, pdbaddr->precord->name,
|
||||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
pamapdbfType[dbfMapping[format.type]].strvalue,
|
pamapdbfType[fmt.type].strvalue,
|
||||||
lval);
|
lval);
|
||||||
return false;
|
return false;
|
||||||
case double_format:
|
case DBF_DOUBLE:
|
||||||
error("%s: %s(%s.%s, %s, %#g) failed\n",
|
error("%s: %s(%s.%s, %s, %#g) failed\n",
|
||||||
putfunc, name(), pdbaddr->precord->name,
|
name(), putfunc, pdbaddr->precord->name,
|
||||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
pamapdbfType[dbfMapping[format.type]].strvalue,
|
pamapdbfType[fmt.type].strvalue,
|
||||||
dval);
|
dval);
|
||||||
return false;
|
return false;
|
||||||
case string_format:
|
case DBF_STRING:
|
||||||
error("%s: %s(%s.%s, %s, \"%s\") failed\n",
|
error("%s: %s(%s.%s, %s, \"%.*s\") failed\n",
|
||||||
putfunc, name(), pdbaddr->precord->name,
|
name(), putfunc, pdbaddr->precord->name,
|
||||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||||
pamapdbfType[dbfMapping[format.type]].strvalue,
|
pamapdbfType[fmt.type].strvalue,
|
||||||
buffer);
|
(int)consumed, buffer);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -1248,9 +1341,6 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// no fieldaddress (the "normal" case)
|
// no fieldaddress (the "normal" case)
|
||||||
format_s fmt;
|
|
||||||
fmt.type = dbfMapping[format.type];
|
|
||||||
fmt.priv = &format;
|
|
||||||
if (!readData)
|
if (!readData)
|
||||||
{
|
{
|
||||||
error("%s: No readData() function provided\n", name());
|
error("%s: No readData() function provided\n", name());
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int streamDebug = 0;
|
int streamDebug = 0;
|
||||||
|
int streamError = 0;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
__declspec(dllexport)
|
__declspec(dllexport)
|
||||||
@ -74,6 +75,7 @@ void StreamError(int line, const char* file, const char* fmt, ...)
|
|||||||
void StreamVError(int line, const char* file, const char* fmt, va_list args)
|
void StreamVError(int line, const char* file, const char* fmt, va_list args)
|
||||||
{
|
{
|
||||||
char timestamp[40];
|
char timestamp[40];
|
||||||
|
if (!streamError) return; // Error logging disabled
|
||||||
StreamPrintTimestampFunction(timestamp, 40);
|
StreamPrintTimestampFunction(timestamp, 40);
|
||||||
#ifdef va_copy
|
#ifdef va_copy
|
||||||
if (StreamDebugFile)
|
if (StreamDebugFile)
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int streamDebug;
|
extern int streamDebug;
|
||||||
|
extern int streamError;
|
||||||
extern void (*StreamPrintTimestampFunction)(char* buffer, int size);
|
extern void (*StreamPrintTimestampFunction)(char* buffer, int size);
|
||||||
|
|
||||||
void StreamError(int line, const char* file, const char* fmt, ...)
|
void StreamError(int line, const char* file, const char* fmt, ...)
|
||||||
|
@ -30,15 +30,17 @@ typedef enum {
|
|||||||
zero_flag = 0x10,
|
zero_flag = 0x10,
|
||||||
skip_flag = 0x20,
|
skip_flag = 0x20,
|
||||||
default_flag = 0x40,
|
default_flag = 0x40,
|
||||||
compare_flag = 0x80
|
compare_flag = 0x80,
|
||||||
|
fix_width_flag = 0x100,
|
||||||
} StreamFormatFlag;
|
} StreamFormatFlag;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
long_format = 1,
|
unsigned_format = 1,
|
||||||
enum_format = 2,
|
signed_format,
|
||||||
double_format = 3,
|
enum_format,
|
||||||
string_format = 4,
|
double_format,
|
||||||
pseudo_format = 5
|
string_format,
|
||||||
|
pseudo_format
|
||||||
} StreamFormatType;
|
} StreamFormatType;
|
||||||
|
|
||||||
extern const char* StreamFormatTypeStr[];
|
extern const char* StreamFormatTypeStr[];
|
||||||
@ -47,7 +49,7 @@ typedef struct StreamFormat
|
|||||||
{
|
{
|
||||||
char conv;
|
char conv;
|
||||||
StreamFormatType type;
|
StreamFormatType type;
|
||||||
unsigned char flags;
|
unsigned short flags;
|
||||||
short prec;
|
short prec;
|
||||||
unsigned short width;
|
unsigned short width;
|
||||||
unsigned short infolen;
|
unsigned short infolen;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
#include "StreamFormatConverter.h"
|
#include "StreamFormatConverter.h"
|
||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ parseFormat(const char*& source, FormatType formatType, StreamFormat& streamForm
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
source := [flags] [width] ['.' prec] conv [extra]
|
source := [flags] [width] ['.' prec] conv [extra]
|
||||||
flags := '-' | '+' | ' ' | '#' | '0' | '*' | '?' | '='
|
flags := '-' | '+' | ' ' | '#' | '0' | '*' | '?' | '=' | '!'
|
||||||
width := integer
|
width := integer
|
||||||
prec := integer
|
prec := integer
|
||||||
conv := character
|
conv := character
|
||||||
@ -84,6 +85,15 @@ parseFormat(const char*& source, FormatType formatType, StreamFormat& streamForm
|
|||||||
}
|
}
|
||||||
streamFormat.flags |= default_flag;
|
streamFormat.flags |= default_flag;
|
||||||
break;
|
break;
|
||||||
|
case '!':
|
||||||
|
if (formatType != ScanFormat)
|
||||||
|
{
|
||||||
|
error("Use of fixed width modifier '!' "
|
||||||
|
"only allowed in input formats\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
streamFormat.flags |= fix_width_flag;
|
||||||
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
if (formatType != ScanFormat)
|
if (formatType != ScanFormat)
|
||||||
{
|
{
|
||||||
@ -310,12 +320,16 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
|||||||
info.append('l');
|
info.append('l');
|
||||||
info.append(fmt.conv);
|
info.append(fmt.conv);
|
||||||
}
|
}
|
||||||
return long_format;
|
if (fmt.conv == 'd' || fmt.conv == 'i') return signed_format;
|
||||||
|
return unsigned_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StdLongConverter::
|
bool StdLongConverter::
|
||||||
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||||
{
|
{
|
||||||
|
// limits %x/%X formats to number of half bytes in width.
|
||||||
|
if (fmt.width && (fmt.conv == 'x' || fmt.conv == 'X') && fmt.width < 2*sizeof(long))
|
||||||
|
value &= ~(-1L << (fmt.width*4));
|
||||||
output.print(fmt.info, value);
|
output.print(fmt.info, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -327,6 +341,7 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
|||||||
int length;
|
int length;
|
||||||
bool neg;
|
bool neg;
|
||||||
int base;
|
int base;
|
||||||
|
long v;
|
||||||
|
|
||||||
length = prepareval(fmt, input, neg);
|
length = prepareval(fmt, input, neg);
|
||||||
if (length < 0) return -1;
|
if (length < 0) return -1;
|
||||||
@ -336,14 +351,11 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
|||||||
base = 10;
|
base = 10;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
base = 8;
|
|
||||||
goto signcheck;
|
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
base = 16;
|
// allow negative hex and oct numbers with - flag
|
||||||
signcheck:
|
|
||||||
// allow negative hex and oct numbers with - flag
|
|
||||||
if (neg && !(fmt.flags & left_flag)) return -1;
|
if (neg && !(fmt.flags & left_flag)) return -1;
|
||||||
|
base = (fmt.conv == 'o') ? 8 : 16;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
if (neg) return -1;
|
if (neg) return -1;
|
||||||
@ -352,10 +364,10 @@ signcheck:
|
|||||||
default:
|
default:
|
||||||
base = 0;
|
base = 0;
|
||||||
}
|
}
|
||||||
value = strtoul(input, &end, base);
|
v = strtoul(input, &end, base);
|
||||||
if (neg) value = -value;
|
|
||||||
if (end == input) return -1;
|
if (end == input) return -1;
|
||||||
length += end-input;
|
length += end-input;
|
||||||
|
value = neg ? -v : v;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +555,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
|||||||
info.append("%n");
|
info.append("%n");
|
||||||
return string_format;
|
return string_format;
|
||||||
}
|
}
|
||||||
return long_format;
|
return unsigned_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StdCharsConverter::
|
bool StdCharsConverter::
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
|
|
||||||
const char* StreamFormatTypeStr[] = {
|
const char* StreamFormatTypeStr[] = {
|
||||||
"none", "long", "enum", "double", "string", "pseudo"
|
// must match the order in StreamFormat.h
|
||||||
|
"none", "unsigned", "signed", "enum", "double", "string", "pseudo"
|
||||||
};
|
};
|
||||||
|
|
||||||
class StreamProtocolParser::Protocol::Variable
|
class StreamProtocolParser::Protocol::Variable
|
||||||
@ -1037,7 +1038,7 @@ compileNumber(unsigned long& number, const char*& source, unsigned long max)
|
|||||||
"Garbage after numeric value: %s\n", buffer());
|
"Garbage after numeric value: %s\n", buffer());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (n < 0 || n > max)
|
if (n > max)
|
||||||
{
|
{
|
||||||
debug("StreamProtocolParser::Protocol::compileNumber: %s\n",
|
debug("StreamProtocolParser::Protocol::compileNumber: %s\n",
|
||||||
buffer.expand()());
|
buffer.expand()());
|
||||||
@ -1438,7 +1439,7 @@ compileFormat(StreamBuffer& buffer, const char*& formatstr,
|
|||||||
// parsing failed
|
// parsing failed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type < long_format && type > pseudo_format)
|
if (type < 1 && type > pseudo_format)
|
||||||
{
|
{
|
||||||
error(line, filename(),
|
error(line, filename(),
|
||||||
"Illegal format type %d returned from '%%%c' converter\n",
|
"Illegal format type %d returned from '%%%c' converter\n",
|
||||||
|
@ -26,6 +26,24 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* timezone in UNIX contains the seconds between UTC and local time,
|
||||||
|
but not in Free-BSD! Here timezone() is a function delivering
|
||||||
|
the time zone abbreviation (e.g. CET). Alternatively, the timezone
|
||||||
|
value can also be gained from tm_gmtoff of the tm-structure.
|
||||||
|
HJK, 4.4.14 */
|
||||||
|
/* The same seems to be true for other BSDs. DZ. */
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || \
|
||||||
|
defined(__NetBSD__) || \
|
||||||
|
defined(__OpenBSD__) || \
|
||||||
|
defined(__bsdi__ ) || \
|
||||||
|
defined(__DragonFly__)
|
||||||
|
static int timezone_bsd=0;
|
||||||
|
#define timezone timezone_bsd
|
||||||
|
#define tzset() { struct tm tm; time_t timet; tzset(); time(&timet); \
|
||||||
|
localtime_r(&timet, &tm); timezone=tm.tm_gmtoff; }
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define tzset() _tzset()
|
#define tzset() _tzset()
|
||||||
#define timezone _timezone
|
#define timezone _timezone
|
||||||
@ -46,6 +64,13 @@ int timezone = 0;
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
/* MinGW has no re-entrant localtime. How about other environments? */
|
||||||
|
/* Just let's hope for the best */
|
||||||
|
#undef localtime_r
|
||||||
|
#define localtime_r(timet,tm) (*(tm)=*localtime(timet))
|
||||||
|
#endif
|
||||||
|
|
||||||
class TimestampConverter : public StreamFormatConverter
|
class TimestampConverter : public StreamFormatConverter
|
||||||
{
|
{
|
||||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||||
@ -366,7 +391,7 @@ startover:
|
|||||||
debug ("TimestampConverter::scantime: %s hour = %d\n", pm?"PM":"AM", tm->tm_hour);
|
debug ("TimestampConverter::scantime: %s hour = %d\n", pm?"PM":"AM", tm->tm_hour);
|
||||||
break;
|
break;
|
||||||
case 'M': /* minute */
|
case 'M': /* minute */
|
||||||
i = nummatch(input, 1, 59);
|
i = nummatch(input, 0, 59);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
{
|
{
|
||||||
error ("error parsing minute: '%.20s'\n", input);
|
error ("error parsing minute: '%.20s'\n", input);
|
||||||
@ -376,7 +401,7 @@ startover:
|
|||||||
debug ("TimestampConverter::scantime: min = %d\n", tm->tm_min);
|
debug ("TimestampConverter::scantime: min = %d\n", tm->tm_min);
|
||||||
break;
|
break;
|
||||||
case 'S': /* second */
|
case 'S': /* second */
|
||||||
i = nummatch(input, 1, 60);
|
i = nummatch(input, 0, 60);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
{
|
{
|
||||||
error ("error parsing week second: '%.20s'\n", input);
|
error ("error parsing week second: '%.20s'\n", input);
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#define devStream_h
|
#define devStream_h
|
||||||
|
|
||||||
#define STREAM_MAJOR 2
|
#define STREAM_MAJOR 2
|
||||||
#define STREAM_MINOR 6
|
#define STREAM_MINOR 7
|
||||||
#define STREAM_PATCHLEVEL 0
|
#define STREAM_PATCHLEVEL 10
|
||||||
|
|
||||||
#if defined(__vxworks) || defined(vxWorks)
|
#if defined(__vxworks) || defined(vxWorks)
|
||||||
#include <vxWorks.h>
|
#include <vxWorks.h>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
#define INIT_RUN (!interruptAccept)
|
#define INIT_RUN (!interruptAccept)
|
||||||
|
|
||||||
#include <epicsVersion.h>
|
#include <epicsVersion.h>
|
||||||
#ifdef BASE_RELEASE
|
#ifdef BASE_VERSION
|
||||||
#define EPICS_3_13
|
#define EPICS_3_13
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -49,13 +49,22 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef epicsExportSharedSymbols
|
||||||
|
# define devStream_epicsExportSharedSymbols
|
||||||
|
# undef epicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <dbCommon.h>
|
#include <dbCommon.h>
|
||||||
#include <dbScan.h>
|
#include <dbScan.h>
|
||||||
#include <devSup.h>
|
#include <devSup.h>
|
||||||
/* #include <dbFldTypes.h> */
|
|
||||||
#include <dbAccess.h>
|
#include <dbAccess.h>
|
||||||
|
|
||||||
|
#ifdef devStream_epicsExportSharedSymbols
|
||||||
|
# define epicsExportSharedSymbols
|
||||||
|
# include "shareLib.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__cplusplus) && defined(EPICS_3_13)
|
#if defined(__cplusplus) && defined(EPICS_3_13)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -76,16 +85,16 @@ extern const char StreamVersion [];
|
|||||||
|
|
||||||
typedef long (*streamIoFunction) (dbCommon*, format_t*);
|
typedef long (*streamIoFunction) (dbCommon*, format_t*);
|
||||||
|
|
||||||
epicsShareExtern long streamInit(int after);
|
epicsShareFunc long streamInit(int after);
|
||||||
epicsShareExtern long streamInitRecord(dbCommon *record,
|
epicsShareFunc long streamInitRecord(dbCommon *record,
|
||||||
const struct link *ioLink,
|
const struct link *ioLink,
|
||||||
streamIoFunction readData, streamIoFunction writeData);
|
streamIoFunction readData, streamIoFunction writeData);
|
||||||
epicsShareExtern long streamReport(int interest);
|
epicsShareFunc long streamReport(int interest);
|
||||||
epicsShareExtern long streamReadWrite(dbCommon *record);
|
epicsShareFunc long streamReadWrite(dbCommon *record);
|
||||||
epicsShareExtern long streamGetIointInfo(int cmd,
|
epicsShareFunc long streamGetIointInfo(int cmd,
|
||||||
dbCommon *record, IOSCANPVT *ppvt);
|
dbCommon *record, IOSCANPVT *ppvt);
|
||||||
epicsShareExtern long streamPrintf(dbCommon *record, format_t *format, ...);
|
epicsShareFunc long streamPrintf(dbCommon *record, format_t *format, ...);
|
||||||
epicsShareExtern long streamScanfN(dbCommon *record, format_t *format,
|
epicsShareFunc long streamScanfN(dbCommon *record, format_t *format,
|
||||||
void*, size_t maxStringSize);
|
void*, size_t maxStringSize);
|
||||||
|
|
||||||
/* backward compatibility stuff */
|
/* backward compatibility stuff */
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "devStream.h"
|
|
||||||
#include <aaiRecord.h>
|
|
||||||
#include <errlog.h>
|
#include <errlog.h>
|
||||||
|
#include <aaiRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -57,6 +57,7 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
@ -191,6 +192,7 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "devStream.h"
|
|
||||||
#include <aaoRecord.h>
|
|
||||||
#include <errlog.h>
|
#include <errlog.h>
|
||||||
|
#include <aaoRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -57,6 +57,7 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
@ -191,6 +192,7 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
|
@ -18,10 +18,18 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
#include <math.h>
|
||||||
|
#include <menuConvert.h>
|
||||||
#include <aiRecord.h>
|
#include <aiRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
|
#ifdef vxWorks
|
||||||
|
#include <private/mathP.h>
|
||||||
|
#define isinf(x) isInf(x)
|
||||||
|
#define isnan(x) isNan(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
aiRecord *ai = (aiRecord *) record;
|
aiRecord *ai = (aiRecord *) record;
|
||||||
@ -32,20 +40,31 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
double val;
|
double val;
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
if (ai->aslo != 0.0) val *= ai->aslo;
|
if (ai->aslo != 0.0 && ai->aslo != 1.0) val *= ai->aslo;
|
||||||
val += ai->aoff;
|
val += ai->aoff;
|
||||||
if (!INIT_RUN && ai->smoo != 0.0)
|
if (!(ai->smoo == 0.0 || ai->init || ai->udf || isinf(ai->val) || isnan(ai->val)))
|
||||||
{
|
|
||||||
val = ai->val * ai->smoo + val * (1.0 - ai->smoo);
|
val = ai->val * ai->smoo + val * (1.0 - ai->smoo);
|
||||||
}
|
|
||||||
ai->val = val;
|
ai->val = val;
|
||||||
return DO_NOT_CONVERT;
|
return DO_NOT_CONVERT;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
long rval;
|
long rval;
|
||||||
if (streamScanf (record, format, &rval)) return ERROR;
|
if (streamScanf (record, format, &rval)) return ERROR;
|
||||||
ai->rval = rval;
|
ai->rval = rval;
|
||||||
|
if (ai->linr == menuConvertNO_CONVERSION)
|
||||||
|
{
|
||||||
|
/* allow integers with more than 32 bits */
|
||||||
|
double val;
|
||||||
|
if (format->type == DBF_ULONG)
|
||||||
|
val = (unsigned long)rval;
|
||||||
|
else
|
||||||
|
val = rval;
|
||||||
|
if (ai->aslo != 0.0 && ai->aslo != 1.0) val *= ai->aslo;
|
||||||
|
ai->val = val + ai->aoff;
|
||||||
|
return DO_NOT_CONVERT;
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,19 +74,32 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
static long writeData (dbCommon *record, format_t *format)
|
static long writeData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
aiRecord *ai = (aiRecord *) record;
|
aiRecord *ai = (aiRecord *) record;
|
||||||
double val;
|
|
||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
case DBF_DOUBLE:
|
case DBF_DOUBLE:
|
||||||
{
|
{
|
||||||
val = ai->val - ai->aoff;
|
double val = ai->val - ai->aoff;
|
||||||
if (ai->aslo != 0) val /= ai->aslo;
|
if (ai->aslo != 0.0 && ai->aslo != 1.0) val /= ai->aslo;
|
||||||
return streamPrintf (record, format, val);
|
return streamPrintf (record, format, val);
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
|
{
|
||||||
|
if (ai->linr == menuConvertNO_CONVERSION)
|
||||||
|
{
|
||||||
|
/* allow more bits than 32 */
|
||||||
|
return streamPrintf (record, format, (unsigned long)ai->val);
|
||||||
|
}
|
||||||
|
return streamPrintf (record, format, (unsigned long)ai->rval);
|
||||||
|
}
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long) ai->rval);
|
if (ai->linr == menuConvertNO_CONVERSION)
|
||||||
|
{
|
||||||
|
/* allow more bits than 32 */
|
||||||
|
return streamPrintf (record, format, (long)ai->val);
|
||||||
|
}
|
||||||
|
return streamPrintf (record, format, (long)ai->rval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ERROR;
|
return ERROR;
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
#include <menuConvert.h>
|
||||||
#include <aoRecord.h>
|
#include <aoRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -32,16 +33,29 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
double val;
|
double val;
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
if (ao->aslo != 0) val *= ao->aslo;
|
if (ao->aslo != 0.0 && ao->aslo != 1.0) val *= ao->aslo;
|
||||||
ao->val = val + ao->aoff;
|
ao->val = val + ao->aoff;
|
||||||
return DO_NOT_CONVERT;
|
return DO_NOT_CONVERT;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
long rval;
|
long rval;
|
||||||
if (streamScanf (record, format, &rval)) return ERROR;
|
if (streamScanf (record, format, &rval)) return ERROR;
|
||||||
ao->rbv = rval;
|
ao->rbv = rval;
|
||||||
if (INIT_RUN) ao->rval = rval;
|
ao->rval = rval;
|
||||||
|
if (ao->linr == menuConvertNO_CONVERSION)
|
||||||
|
{
|
||||||
|
/* allow integers with more than 32 bits */
|
||||||
|
double val;
|
||||||
|
if (format->type == DBF_ULONG)
|
||||||
|
val = (unsigned long)rval;
|
||||||
|
else
|
||||||
|
val = rval;
|
||||||
|
if (ao->aslo != 0.0 && ao->aslo != 1.0) val *= ao->aslo;
|
||||||
|
ao->val = val + ao->aoff;
|
||||||
|
return DO_NOT_CONVERT;
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,20 +66,32 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
aoRecord *ao = (aoRecord *) record;
|
aoRecord *ao = (aoRecord *) record;
|
||||||
|
|
||||||
|
double val = (INIT_RUN ? ao->val : ao->oval) - ao->aoff;
|
||||||
|
if (ao->aslo != 0.0 && ao->aslo != 1.0) val /= ao->aslo;
|
||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
case DBF_DOUBLE:
|
case DBF_DOUBLE:
|
||||||
{
|
{
|
||||||
double val;
|
|
||||||
if (INIT_RUN) val = ao->val;
|
|
||||||
else val = ao->oval;
|
|
||||||
val -= ao->aoff;
|
|
||||||
if (ao->aslo != 0) val /= ao->aslo;
|
|
||||||
return streamPrintf (record, format, val);
|
return streamPrintf (record, format, val);
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
|
{
|
||||||
|
if (ao->linr == menuConvertNO_CONVERSION)
|
||||||
|
{
|
||||||
|
/* allow integers with more than 32 bits */
|
||||||
|
return streamPrintf (record, format, (unsigned long)val);
|
||||||
|
}
|
||||||
|
return streamPrintf (record, format, (unsigned long)ao->rval);
|
||||||
|
}
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long) ao->rval);
|
if (ao->linr == menuConvertNO_CONVERSION)
|
||||||
|
{
|
||||||
|
/* allow integers with more than 32 bits */
|
||||||
|
return streamPrintf (record, format, (long)val);
|
||||||
|
}
|
||||||
|
return streamPrintf (record, format, (long)ao->rval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ERROR;
|
return ERROR;
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <biRecord.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <biRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -30,6 +30,7 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
@ -69,13 +70,14 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, bi->rval);
|
return streamPrintf (record, format, bi->rval);
|
||||||
}
|
}
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long) bi->val);
|
return streamPrintf (record, format, (long)bi->val);
|
||||||
}
|
}
|
||||||
case DBF_STRING:
|
case DBF_STRING:
|
||||||
{
|
{
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <boRecord.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <boRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -30,6 +30,7 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
@ -70,13 +71,14 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, bo->rval);
|
return streamPrintf (record, format, bo->rval);
|
||||||
}
|
}
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long) bo->val);
|
return streamPrintf (record, format, (long)bo->val);
|
||||||
}
|
}
|
||||||
case DBF_STRING:
|
case DBF_STRING:
|
||||||
{
|
{
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <postfix.h>
|
#include <postfix.h>
|
||||||
#include <calcoutRecord.h>
|
#include <calcoutRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -32,13 +32,17 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
return streamScanf (record, format, &co->val);
|
return streamScanf (record, format, &co->val);
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
long lval;
|
long lval;
|
||||||
|
|
||||||
if (streamScanf (record, format, &lval)) return ERROR;
|
if (streamScanf (record, format, &lval)) return ERROR;
|
||||||
co->val = lval;
|
if (format->type == DBF_LONG)
|
||||||
|
co->val = lval;
|
||||||
|
else
|
||||||
|
co->val = (unsigned long)lval;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,8 +59,12 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
return streamPrintf (record, format, co->oval);
|
return streamPrintf (record, format, co->oval);
|
||||||
}
|
}
|
||||||
case DBF_LONG:
|
case DBF_ULONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
|
{
|
||||||
|
return streamPrintf (record, format, (unsigned long)co->oval);
|
||||||
|
}
|
||||||
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long)co->oval);
|
return streamPrintf (record, format, (long)co->oval);
|
||||||
}
|
}
|
||||||
|
@ -18,20 +18,25 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <longinRecord.h>
|
#include <longinRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
longinRecord *li = (longinRecord *) record;
|
longinRecord *li = (longinRecord *) record;
|
||||||
|
|
||||||
if (format->type == DBF_LONG || format->type == DBF_ENUM)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
long val;
|
case DBF_ULONG:
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
case DBF_LONG:
|
||||||
li->val = val;
|
case DBF_ENUM:
|
||||||
return OK;
|
{
|
||||||
|
long val;
|
||||||
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
|
li->val = val;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
@ -40,9 +45,13 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
longinRecord *li = (longinRecord *) record;
|
longinRecord *li = (longinRecord *) record;
|
||||||
|
|
||||||
if (format->type == DBF_LONG || format->type == DBF_ENUM)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long) li->val);
|
case DBF_ULONG:
|
||||||
|
case DBF_ENUM:
|
||||||
|
return streamPrintf (record, format, (unsigned long)li->val);
|
||||||
|
case DBF_LONG:
|
||||||
|
return streamPrintf (record, format, (long)li->val);
|
||||||
}
|
}
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
@ -19,20 +19,25 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <longoutRecord.h>
|
#include <longoutRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
longoutRecord *lo = (longoutRecord *) record;
|
longoutRecord *lo = (longoutRecord *) record;
|
||||||
|
|
||||||
if (format->type == DBF_LONG || format->type == DBF_ENUM)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
long val;
|
case DBF_ULONG:
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
case DBF_LONG:
|
||||||
lo->val = val;
|
case DBF_ENUM:
|
||||||
return OK;
|
{
|
||||||
|
long val;
|
||||||
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
|
lo->val = val;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
@ -41,9 +46,13 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
longoutRecord *lo = (longoutRecord *) record;
|
longoutRecord *lo = (longoutRecord *) record;
|
||||||
|
|
||||||
if (format->type == DBF_LONG || format->type == DBF_ENUM)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
return streamPrintf (record, format, (long) lo->val);
|
case DBF_ULONG:
|
||||||
|
case DBF_ENUM:
|
||||||
|
return streamPrintf (record, format, (unsigned long)lo->val);
|
||||||
|
case DBF_LONG:
|
||||||
|
return streamPrintf (record, format, (long)lo->val);
|
||||||
}
|
}
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
@ -19,16 +19,16 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <mbbiDirectRecord.h>
|
#include <mbbiDirectRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
mbbiDirectRecord *mbbiD = (mbbiDirectRecord *) record;
|
mbbiDirectRecord *mbbiD = (mbbiDirectRecord *) record;
|
||||||
long val;
|
unsigned long val;
|
||||||
|
|
||||||
if (format->type == DBF_LONG)
|
if (format->type == DBF_ULONG || format->type == DBF_LONG)
|
||||||
{
|
{
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
if (mbbiD->mask)
|
if (mbbiD->mask)
|
||||||
@ -40,7 +40,7 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No MASK, (NOBT = 0): use VAL field */
|
/* No MASK, (NOBT = 0): use VAL field */
|
||||||
mbbiD->val = (short)val;
|
mbbiD->val = (unsigned short)val;
|
||||||
return DO_NOT_CONVERT;
|
return DO_NOT_CONVERT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,9 +50,9 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
static long writeData (dbCommon *record, format_t *format)
|
static long writeData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
mbbiDirectRecord *mbbiD = (mbbiDirectRecord *) record;
|
mbbiDirectRecord *mbbiD = (mbbiDirectRecord *) record;
|
||||||
long val;
|
unsigned long val;
|
||||||
|
|
||||||
if (format->type == DBF_LONG)
|
if (format->type == DBF_ULONG || format->type == DBF_LONG)
|
||||||
{
|
{
|
||||||
if (mbbiD->mask) val = mbbiD->rval & mbbiD->mask;
|
if (mbbiD->mask) val = mbbiD->rval & mbbiD->mask;
|
||||||
else val = mbbiD->val;
|
else val = mbbiD->val;
|
||||||
|
@ -19,19 +19,20 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <mbbiRecord.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <mbbiRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
mbbiRecord *mbbi = (mbbiRecord *) record;
|
mbbiRecord *mbbi = (mbbiRecord *) record;
|
||||||
long val;
|
unsigned long val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
|
@ -19,16 +19,17 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <mbboDirectRecord.h>
|
#include <mbboDirectRecord.h>
|
||||||
|
#include "alarm.h"
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
mbboDirectRecord *mbboD = (mbboDirectRecord *) record;
|
mbboDirectRecord *mbboD = (mbboDirectRecord *) record;
|
||||||
long val;
|
unsigned long val;
|
||||||
|
|
||||||
if (format->type == DBF_LONG)
|
if (format->type == DBF_ULONG || format->type == DBF_LONG)
|
||||||
{
|
{
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
if (mbboD->mask)
|
if (mbboD->mask)
|
||||||
@ -53,7 +54,7 @@ static long writeData (dbCommon *record, format_t *format)
|
|||||||
mbboDirectRecord *mbboD = (mbboDirectRecord *) record;
|
mbboDirectRecord *mbboD = (mbboDirectRecord *) record;
|
||||||
long val;
|
long val;
|
||||||
|
|
||||||
if (format->type == DBF_LONG)
|
if (format->type == DBF_ULONG || format->type == DBF_LONG)
|
||||||
{
|
{
|
||||||
if (mbboD->mask) val = mbboD->rval & mbboD->mask;
|
if (mbboD->mask) val = mbboD->rval & mbboD->mask;
|
||||||
else val = mbboD->val;
|
else val = mbboD->val;
|
||||||
@ -67,9 +68,27 @@ static long initRecord (dbCommon *record)
|
|||||||
mbboDirectRecord *mbboD = (mbboDirectRecord *) record;
|
mbboDirectRecord *mbboD = (mbboDirectRecord *) record;
|
||||||
|
|
||||||
mbboD->mask <<= mbboD->shft;
|
mbboD->mask <<= mbboD->shft;
|
||||||
|
|
||||||
|
/* Workaround for bug in mbboDirect record:
|
||||||
|
Put to VAL overwrites value to 0 if SEVR is INVALID_ALARM
|
||||||
|
Thus first write may send a wrong value.
|
||||||
|
*/
|
||||||
|
mbboD->sevr = 0;
|
||||||
return streamInitRecord (record, &mbboD->out, readData, writeData);
|
return streamInitRecord (record, &mbboD->out, readData, writeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unfortunately the bug also corrupts the next write to VAL after an I/O error.
|
||||||
|
Thus make sure the record is never left in INVALID_ALARM status.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static long write(dbCommon *record)
|
||||||
|
{
|
||||||
|
long status = streamWrite(record);
|
||||||
|
if (record->nsev == INVALID_ALARM) record->nsev = MAJOR_ALARM;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
long number;
|
long number;
|
||||||
DEVSUPFUN report;
|
DEVSUPFUN report;
|
||||||
@ -83,7 +102,7 @@ struct {
|
|||||||
streamInit,
|
streamInit,
|
||||||
initRecord,
|
initRecord,
|
||||||
streamGetIointInfo,
|
streamGetIointInfo,
|
||||||
streamWrite
|
write
|
||||||
};
|
};
|
||||||
|
|
||||||
epicsExportAddress(dset,devmbboDirectStream);
|
epicsExportAddress(dset,devmbboDirectStream);
|
||||||
|
@ -19,19 +19,20 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <mbboRecord.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <mbboRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
mbboRecord *mbbo = (mbboRecord *) record;
|
mbboRecord *mbbo = (mbboRecord *) record;
|
||||||
long val;
|
unsigned long val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
if (streamScanf (record, format, &val)) return ERROR;
|
if (streamScanf (record, format, &val)) return ERROR;
|
||||||
@ -76,11 +77,12 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
static long writeData (dbCommon *record, format_t *format)
|
static long writeData (dbCommon *record, format_t *format)
|
||||||
{
|
{
|
||||||
mbboRecord *mbbo = (mbboRecord *) record;
|
mbboRecord *mbbo = (mbboRecord *) record;
|
||||||
long val;
|
unsigned long val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
/* print VAL or RVAL ? */
|
/* print VAL or RVAL ? */
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <stringinRecord.h>
|
#include <stringinRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <stringoutRecord.h>
|
#include <stringoutRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "devStream.h"
|
|
||||||
#include <waveformRecord.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errlog.h>
|
#include <errlog.h>
|
||||||
|
#include <waveformRecord.h>
|
||||||
|
#include "devStream.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
static long readData (dbCommon *record, format_t *format)
|
static long readData (dbCommon *record, format_t *format)
|
||||||
@ -57,6 +57,7 @@ static long readData (dbCommon *record, format_t *format)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
case DBF_ENUM:
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@ if (@ARGV[0] == "-3.13") {
|
|||||||
shift;
|
shift;
|
||||||
} else {
|
} else {
|
||||||
print "variable(streamDebug, int)\n";
|
print "variable(streamDebug, int)\n";
|
||||||
|
print "variable(streamError, int)\n";
|
||||||
print "registrar(streamRegistrar)\n";
|
print "registrar(streamRegistrar)\n";
|
||||||
}
|
}
|
||||||
print "driver(stream)\n";
|
print "driver(stream)\n";
|
||||||
|
@ -31,9 +31,11 @@ PROD_LIBS = stream
|
|||||||
ifdef ASYN
|
ifdef ASYN
|
||||||
# edit asynRegistrars.dbd if necessary
|
# edit asynRegistrars.dbd if necessary
|
||||||
streamApp_DBD += asynRegistrars.dbd
|
streamApp_DBD += asynRegistrars.dbd
|
||||||
# add asyn.dbd if you want to have asyn Record and asyn device supports
|
# add asynRecord.dbd if you like
|
||||||
# streamApp_DBD += asyn.dbd
|
streamApp_DBD += asynRecord.dbd
|
||||||
PROD_LIBS += asyn
|
PROD_LIBS += asyn
|
||||||
|
# cygwin needs separate RPC library for asyn
|
||||||
|
PROD_SYS_LIBS_cygwin32 += $(CYGWIN_RPC_LIB)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||||
@ -49,7 +51,7 @@ endif
|
|||||||
streamApp_DBD += stream.dbd
|
streamApp_DBD += stream.dbd
|
||||||
|
|
||||||
ifdef PCRE
|
ifdef PCRE
|
||||||
LIB_LIBS += pcre
|
PROD_LIBS += pcre
|
||||||
else
|
else
|
||||||
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||||
PROD_SYS_LIBS_DEFAULT += pcre
|
PROD_SYS_LIBS_DEFAULT += pcre
|
||||||
@ -66,7 +68,7 @@ CPPFLAGS += -DDEBUGFILE=StreamDebug.log
|
|||||||
|
|
||||||
include $(TOP)/configure/RULES
|
include $(TOP)/configure/RULES
|
||||||
|
|
||||||
ifeq ($(EPICS_REVISION),14)
|
ifeq ($(BASE_3_14), YES)
|
||||||
clean:: myclean
|
clean:: myclean
|
||||||
else
|
else
|
||||||
clean: myclean
|
clean: myclean
|
||||||
|
@ -40,11 +40,13 @@ proc escape {string} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc sendReply {sock text} {
|
proc sendReply {sock text} {
|
||||||
.$sock.t mark set insert end
|
catch {
|
||||||
.$sock.t insert end $text
|
# ignore that socket may already be closed
|
||||||
.$sock.t see end
|
.$sock.t mark set insert end
|
||||||
puts -nonewline $sock $text
|
.$sock.t insert end $text
|
||||||
# puts "sending \"[escape $text]\"\n"
|
.$sock.t see end
|
||||||
|
puts -nonewline $sock $text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc checkNum {n} {
|
proc checkNum {n} {
|
||||||
@ -89,7 +91,7 @@ proc receiveHandler {sock} {
|
|||||||
"start" {
|
"start" {
|
||||||
set wait [checkNum [lindex $l 1]]
|
set wait [checkNum [lindex $l 1]]
|
||||||
set ::counter 0
|
set ::counter 0
|
||||||
after $wait sendAsync $wait [list [lrange $l 2 end-1]]
|
after $wait [list sendAsync $wait "[string range $a [string wordend $a 7] end]"]
|
||||||
sendReply $sock "Started\n"
|
sendReply $sock "Started\n"
|
||||||
}
|
}
|
||||||
"stop" {
|
"stop" {
|
||||||
@ -131,7 +133,7 @@ proc receiveHandler {sock} {
|
|||||||
proc sendAsync {wait message} {
|
proc sendAsync {wait message} {
|
||||||
if {$::counter < 0} return
|
if {$::counter < 0} return
|
||||||
foreach term [array names ::socket] {
|
foreach term [array names ::socket] {
|
||||||
sendReply $::socket($term) "Message number [incr ::counter] $message\n";
|
sendReply $::socket($term) "Message number [incr ::counter]$message";
|
||||||
}
|
}
|
||||||
after $wait sendAsync $wait [list $message]
|
after $wait sendAsync $wait [list $message]
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ proc receiveHandler {sock} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc startioc {} {
|
proc startioc {} {
|
||||||
global debug records protocol startup port sock ioc testname env streamversion
|
global debug records protocol startup port sock ioc testname env streamversion asynversion
|
||||||
set fd [open test.db w]
|
set fd [open test.db w]
|
||||||
puts $fd $records
|
puts $fd $records
|
||||||
close $fd
|
close $fd
|
||||||
@ -52,7 +52,10 @@ proc startioc {} {
|
|||||||
|
|
||||||
if [info exists streamversion] {
|
if [info exists streamversion] {
|
||||||
puts $fd "#!/usr/local/bin/iocsh"
|
puts $fd "#!/usr/local/bin/iocsh"
|
||||||
puts $fd "require stream2,$streamversion"
|
if [info exists asynversion] {
|
||||||
|
puts $fd "require asyn,$asynversion"
|
||||||
|
}
|
||||||
|
puts $fd "require stream,$streamversion"
|
||||||
} else {
|
} else {
|
||||||
puts $fd "#!../O.$env(EPICS_HOST_ARCH)/streamApp"
|
puts $fd "#!../O.$env(EPICS_HOST_ARCH)/streamApp"
|
||||||
puts $fd "dbLoadDatabase ../O.Common/streamApp.dbd"
|
puts $fd "dbLoadDatabase ../O.Common/streamApp.dbd"
|
||||||
@ -74,7 +77,9 @@ proc startioc {} {
|
|||||||
}
|
}
|
||||||
fconfigure $ioc -blocking yes -buffering none
|
fconfigure $ioc -blocking yes -buffering none
|
||||||
debugmsg "waiting to connect"
|
debugmsg "waiting to connect"
|
||||||
|
set timer [after 1000 {puts stderr "\033\[31;7mCannot start IOC.\033\[0m"; exit 1}]
|
||||||
vwait sock
|
vwait sock
|
||||||
|
after cancel $timer
|
||||||
}
|
}
|
||||||
|
|
||||||
set lastcommand ""
|
set lastcommand ""
|
||||||
@ -202,3 +207,7 @@ if {[lindex $argv 0] == "-sls"} {
|
|||||||
set streamversion [lindex $argv 1]
|
set streamversion [lindex $argv 1]
|
||||||
set argv [lrange $argv 2 end]
|
set argv [lrange $argv 2 end]
|
||||||
}
|
}
|
||||||
|
if {[lindex $argv 0] == "-asyn"} {
|
||||||
|
set asynversion [lindex $argv 1]
|
||||||
|
set argv [lrange $argv 2 end]
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@ source streamtestlib.tcl
|
|||||||
# Send commands to the ioc shell with ioccmd
|
# Send commands to the ioc shell with ioccmd
|
||||||
|
|
||||||
set records {
|
set records {
|
||||||
record (ao, "DZ:test1")
|
record (stringout, "DZ:test1")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
field (OUT, "@test.proto test1 device")
|
field (OUT, "@test.proto test1 device")
|
||||||
@ -15,7 +15,225 @@ set records {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set protocol {
|
set protocol {
|
||||||
test1 {out 0x55 0x40 0x04 0x00 0x00 'z;' "%<sum>";}
|
Terminator="\n";
|
||||||
|
test1 {
|
||||||
|
out "sum %s %9.1<sum>"; in "sum %=s %9.1<sum>";
|
||||||
|
out "sum8 %s %9.1<sum8>"; in "sum8 %=s %9.1<sum8>";
|
||||||
|
out "sum16 %s %9.1<sum16>"; in "sum16 %=s %9.1<sum16>";
|
||||||
|
out "sum32 %s %9.1<sum32>"; in "sum32 %=s %9.1<sum32>";
|
||||||
|
out "nsum %s %9.1<nsum>"; in "nsum %=s %9.1<nsum>";
|
||||||
|
out "negsum %s %9.1<negsum>"; in "negsum %=s %9.1<negsum>";
|
||||||
|
out "-sum %s %9.1<-sum>"; in "-sum %=s %9.1<-sum>";
|
||||||
|
out "nsum8 %s %9.1<nsum8>"; in "nsum8 %=s %9.1<nsum8>";
|
||||||
|
out "negsum8 %s %9.1<negsum8>"; in "negsum8 %=s %9.1<negsum8>";
|
||||||
|
out "-sum8 %s %9.1<-sum8>"; in "-sum8 %=s %9.1<-sum8>";
|
||||||
|
out "nsum16 %s %9.1<nsum16>"; in "nsum16 %=s %9.1<nsum16>";
|
||||||
|
out "negsum16 %s %9.1<negsum1>"; in "negsum16 %=s %9.1<negsum1>";
|
||||||
|
out "-sum16 %s %9.1<-sum16>"; in "-sum16 %=s %9.1<-sum16>";
|
||||||
|
out "nsum32 %s %9.1<nsum32>"; in "nsum32 %=s %9.1<nsum32>";
|
||||||
|
out "negsum32 %s %9.1<negsum3>"; in "negsum32 %=s %9.1<negsum3>";
|
||||||
|
out "-sum32 %s %9.1<-sum32>"; in "-sum32 %=s %9.1<-sum32>";
|
||||||
|
out "notsum %s %9.1<notsum>"; in "notsum %=s %9.1<notsum>";
|
||||||
|
out "~sum %s %9.1<~sum>"; in "~sum %=s %9.1<~sum>";
|
||||||
|
out "xor %s %9.1<xor>"; in "xor %=s %9.1<xor>";
|
||||||
|
out "xor8 %s %9.1<xor8>"; in "xor8 %=s %9.1<xor8>";
|
||||||
|
out "xor7 %s %9.1<xor7>"; in "xor7 %=s %9.1<xor7>";
|
||||||
|
out "crc8 %s %9.1<crc8>"; in "crc8 %=s %9.1<crc8>";
|
||||||
|
out "ccitt8 %s %9.1<ccitt8>"; in "ccitt8 %=s %9.1<ccitt8>";
|
||||||
|
out "crc16 %s %9.1<crc16>"; in "crc16 %=s %9.1<crc16>";
|
||||||
|
out "crc16r %s %9.1<crc16r>"; in "crc16r %=s %9.1<crc16r>";
|
||||||
|
out "ccitt16 %s %9.1<ccitt16>"; in "ccitt16 %=s %9.1<ccitt16>";
|
||||||
|
out "ccitt16a %s %9.1<ccitt16a>"; in "ccitt16a %=s %9.1<ccitt16a>";
|
||||||
|
out "ccitt16x %s %9.1<ccitt16x>"; in "ccitt16x %=s %9.1<ccitt16x>";
|
||||||
|
out "crc16c %s %9.1<crc16c>"; in "crc16c %=s %9.1<crc16c>";
|
||||||
|
out "xmodem %s %9.1<xmodem>"; in "xmodem %=s %9.1<xmodem>";
|
||||||
|
out "crc32 %s %9.1<crc32>"; in "crc32 %=s %9.1<crc32>";
|
||||||
|
out "crc32r %s %9.1<crc32r>"; in "crc32r %=s %9.1<crc32r>";
|
||||||
|
out "jamcrc %s %9.1<jamcrc>"; in "jamcrc %=s %9.1<jamcrc>";
|
||||||
|
out "adler32 %s %9.1<adler32>"; in "adler32 %=s %9.1<adler32>";
|
||||||
|
out "hexsum8 %s %9.1<hexsum8>"; in "hexsum8 %=s %9.1<hexsum8>";
|
||||||
|
|
||||||
|
out "sum %s %09.1<sum>"; in "sum %=s %09.1<sum>";
|
||||||
|
out "sum8 %s %09.1<sum8>"; in "sum8 %=s %09.1<sum8>";
|
||||||
|
out "sum16 %s %09.1<sum16>"; in "sum16 %=s %09.1<sum16>";
|
||||||
|
out "sum32 %s %09.1<sum32>"; in "sum32 %=s %09.1<sum32>";
|
||||||
|
out "nsum %s %09.1<nsum>"; in "nsum %=s %09.1<nsum>";
|
||||||
|
out "negsum %s %09.1<negsum>"; in "negsum %=s %09.1<negsum>";
|
||||||
|
out "-sum %s %09.1<-sum>"; in "-sum %=s %09.1<-sum>";
|
||||||
|
out "nsum8 %s %09.1<nsum8>"; in "nsum8 %=s %09.1<nsum8>";
|
||||||
|
out "negsum8 %s %09.1<negsum8>"; in "negsum8 %=s %09.1<negsum8>";
|
||||||
|
out "-sum8 %s %09.1<-sum8>"; in "-sum8 %=s %09.1<-sum8>";
|
||||||
|
out "nsum16 %s %09.1<nsum16>"; in "nsum16 %=s %09.1<nsum16>";
|
||||||
|
out "negsum16 %s %09.1<negsum1>"; in "negsum16 %=s %09.1<negsum1>";
|
||||||
|
out "-sum16 %s %09.1<-sum16>"; in "-sum16 %=s %09.1<-sum16>";
|
||||||
|
out "nsum32 %s %09.1<nsum32>"; in "nsum32 %=s %09.1<nsum32>";
|
||||||
|
out "negsum32 %s %09.1<negsum3>"; in "negsum32 %=s %09.1<negsum3>";
|
||||||
|
out "-sum32 %s %09.1<-sum32>"; in "-sum32 %=s %09.1<-sum32>";
|
||||||
|
out "notsum %s %09.1<notsum>"; in "notsum %=s %09.1<notsum>";
|
||||||
|
out "~sum %s %09.1<~sum>"; in "~sum %=s %09.1<~sum>";
|
||||||
|
out "xor %s %09.1<xor>"; in "xor %=s %09.1<xor>";
|
||||||
|
out "xor8 %s %09.1<xor8>"; in "xor8 %=s %09.1<xor8>";
|
||||||
|
out "xor7 %s %09.1<xor7>"; in "xor7 %=s %09.1<xor7>";
|
||||||
|
out "crc8 %s %09.1<crc8>"; in "crc8 %=s %09.1<crc8>";
|
||||||
|
out "ccitt8 %s %09.1<ccitt8>"; in "ccitt8 %=s %09.1<ccitt8>";
|
||||||
|
out "crc16 %s %09.1<crc16>"; in "crc16 %=s %09.1<crc16>";
|
||||||
|
out "crc16r %s %09.1<crc16r>"; in "crc16r %=s %09.1<crc16r>";
|
||||||
|
out "ccitt16 %s %09.1<ccitt16>"; in "ccitt16 %=s %09.1<ccitt16>";
|
||||||
|
out "ccitt16a %s %09.1<ccitt16a>"; in "ccitt16a %=s %09.1<ccitt16a>";
|
||||||
|
out "ccitt16x %s %09.1<ccitt16x>"; in "ccitt16x %=s %09.1<ccitt16x>";
|
||||||
|
out "crc16c %s %09.1<crc16c>"; in "crc16c %=s %09.1<crc16c>";
|
||||||
|
out "xmodem %s %09.1<xmodem>"; in "xmodem %=s %09.1<xmodem>";
|
||||||
|
out "crc32 %s %09.1<crc32>"; in "crc32 %=s %09.1<crc32>";
|
||||||
|
out "crc32r %s %09.1<crc32r>"; in "crc32r %=s %09.1<crc32r>";
|
||||||
|
out "jamcrc %s %09.1<jamcrc>"; in "jamcrc %=s %09.1<jamcrc>";
|
||||||
|
out "adler32 %s %09.1<adler32>"; in "adler32 %=s %09.1<adler32>";
|
||||||
|
out "hexsum8 %s %09.1<hexsum8>"; in "hexsum8 %=s %09.1<hexsum8>";
|
||||||
|
|
||||||
|
out "sum %s %-9.1<sum>"; in "sum %=s %-9.1<sum>";
|
||||||
|
out "sum8 %s %-9.1<sum8>"; in "sum8 %=s %-9.1<sum8>";
|
||||||
|
out "sum16 %s %-9.1<sum16>"; in "sum16 %=s %-9.1<sum16>";
|
||||||
|
out "sum32 %s %-9.1<sum32>"; in "sum32 %=s %-9.1<sum32>";
|
||||||
|
out "nsum %s %-9.1<nsum>"; in "nsum %=s %-9.1<nsum>";
|
||||||
|
out "negsum %s %-9.1<negsum>"; in "negsum %=s %-9.1<negsum>";
|
||||||
|
out "-sum %s %-9.1<-sum>"; in "-sum %=s %-9.1<-sum>";
|
||||||
|
out "nsum8 %s %-9.1<nsum8>"; in "nsum8 %=s %-9.1<nsum8>";
|
||||||
|
out "negsum8 %s %-9.1<negsum8>"; in "negsum8 %=s %-9.1<negsum8>";
|
||||||
|
out "-sum8 %s %-9.1<-sum8>"; in "-sum8 %=s %-9.1<-sum8>";
|
||||||
|
out "nsum16 %s %-9.1<nsum16>"; in "nsum16 %=s %-9.1<nsum16>";
|
||||||
|
out "negsum16 %s %-9.1<negsum1>"; in "negsum16 %=s %-9.1<negsum1>";
|
||||||
|
out "-sum16 %s %-9.1<-sum16>"; in "-sum16 %=s %-9.1<-sum16>";
|
||||||
|
out "nsum32 %s %-9.1<nsum32>"; in "nsum32 %=s %-9.1<nsum32>";
|
||||||
|
out "negsum32 %s %-9.1<negsum3>"; in "negsum32 %=s %-9.1<negsum3>";
|
||||||
|
out "-sum32 %s %-9.1<-sum32>"; in "-sum32 %=s %-9.1<-sum32>";
|
||||||
|
out "notsum %s %-9.1<notsum>"; in "notsum %=s %-9.1<notsum>";
|
||||||
|
out "~sum %s %-9.1<~sum>"; in "~sum %=s %-9.1<~sum>";
|
||||||
|
out "xor %s %-9.1<xor>"; in "xor %=s %-9.1<xor>";
|
||||||
|
out "xor8 %s %-9.1<xor8>"; in "xor8 %=s %-9.1<xor8>";
|
||||||
|
out "xor7 %s %-9.1<xor7>"; in "xor7 %=s %-9.1<xor7>";
|
||||||
|
out "crc8 %s %-9.1<crc8>"; in "crc8 %=s %-9.1<crc8>";
|
||||||
|
out "ccitt8 %s %-9.1<ccitt8>"; in "ccitt8 %=s %-9.1<ccitt8>";
|
||||||
|
out "crc16 %s %-9.1<crc16>"; in "crc16 %=s %-9.1<crc16>";
|
||||||
|
out "crc16r %s %-9.1<crc16r>"; in "crc16r %=s %-9.1<crc16r>";
|
||||||
|
out "ccitt16 %s %-9.1<ccitt16>"; in "ccitt16 %=s %-9.1<ccitt16>";
|
||||||
|
out "ccitt16a %s %-9.1<ccitt16a>"; in "ccitt16a %=s %-9.1<ccitt16a>";
|
||||||
|
out "ccitt16x %s %-9.1<ccitt16x>"; in "ccitt16x %=s %-9.1<ccitt16x>";
|
||||||
|
out "crc16c %s %-9.1<crc16c>"; in "crc16c %=s %-9.1<crc16c>";
|
||||||
|
out "xmodem %s %-9.1<xmodem>"; in "xmodem %=s %-9.1<xmodem>";
|
||||||
|
out "crc32 %s %-9.1<crc32>"; in "crc32 %=s %-9.1<crc32>";
|
||||||
|
out "crc32r %s %-9.1<crc32r>"; in "crc32r %=s %-9.1<crc32r>";
|
||||||
|
out "jamcrc %s %-9.1<jamcrc>"; in "jamcrc %=s %-9.1<jamcrc>";
|
||||||
|
out "adler32 %s %-9.1<adler32>"; in "adler32 %=s %-9.1<adler32>";
|
||||||
|
out "hexsum8 %s %-9.1<hexsum8>"; in "hexsum8 %=s %-9.1<hexsum8>";
|
||||||
|
|
||||||
|
out "sum %s %#9.1<sum>"; in "sum %=s %#9.1<sum>";
|
||||||
|
out "sum8 %s %#9.1<sum8>"; in "sum8 %=s %#9.1<sum8>";
|
||||||
|
out "sum16 %s %#9.1<sum16>"; in "sum16 %=s %#9.1<sum16>";
|
||||||
|
out "sum32 %s %#9.1<sum32>"; in "sum32 %=s %#9.1<sum32>";
|
||||||
|
out "nsum %s %#9.1<nsum>"; in "nsum %=s %#9.1<nsum>";
|
||||||
|
out "negsum %s %#9.1<negsum>"; in "negsum %=s %#9.1<negsum>";
|
||||||
|
out "-sum %s %#9.1<-sum>"; in "-sum %=s %#9.1<-sum>";
|
||||||
|
out "nsum8 %s %#9.1<nsum8>"; in "nsum8 %=s %#9.1<nsum8>";
|
||||||
|
out "negsum8 %s %#9.1<negsum8>"; in "negsum8 %=s %#9.1<negsum8>";
|
||||||
|
out "-sum8 %s %#9.1<-sum8>"; in "-sum8 %=s %#9.1<-sum8>";
|
||||||
|
out "nsum16 %s %#9.1<nsum16>"; in "nsum16 %=s %#9.1<nsum16>";
|
||||||
|
out "negsum16 %s %#9.1<negsum1>"; in "negsum16 %=s %#9.1<negsum1>";
|
||||||
|
out "-sum16 %s %#9.1<-sum16>"; in "-sum16 %=s %#9.1<-sum16>";
|
||||||
|
out "nsum32 %s %#9.1<nsum32>"; in "nsum32 %=s %#9.1<nsum32>";
|
||||||
|
out "negsum32 %s %#9.1<negsum3>"; in "negsum32 %=s %#9.1<negsum3>";
|
||||||
|
out "-sum32 %s %#9.1<-sum32>"; in "-sum32 %=s %#9.1<-sum32>";
|
||||||
|
out "notsum %s %#9.1<notsum>"; in "notsum %=s %#9.1<notsum>";
|
||||||
|
out "~sum %s %#9.1<~sum>"; in "~sum %=s %#9.1<~sum>";
|
||||||
|
out "xor %s %#9.1<xor>"; in "xor %=s %#9.1<xor>";
|
||||||
|
out "xor8 %s %#9.1<xor8>"; in "xor8 %=s %#9.1<xor8>";
|
||||||
|
out "xor7 %s %#9.1<xor7>"; in "xor7 %=s %#9.1<xor7>";
|
||||||
|
out "crc8 %s %#9.1<crc8>"; in "crc8 %=s %#9.1<crc8>";
|
||||||
|
out "ccitt8 %s %#9.1<ccitt8>"; in "ccitt8 %=s %#9.1<ccitt8>";
|
||||||
|
out "crc16 %s %#9.1<crc16>"; in "crc16 %=s %#9.1<crc16>";
|
||||||
|
out "crc16r %s %#9.1<crc16r>"; in "crc16r %=s %#9.1<crc16r>";
|
||||||
|
out "ccitt16 %s %#9.1<ccitt16>"; in "ccitt16 %=s %#9.1<ccitt16>";
|
||||||
|
out "ccitt16a %s %#9.1<ccitt16a>"; in "ccitt16a %=s %#9.1<ccitt16a>";
|
||||||
|
out "ccitt16x %s %#9.1<ccitt16x>"; in "ccitt16x %=s %#9.1<ccitt16x>";
|
||||||
|
out "crc16c %s %#9.1<crc16c>"; in "crc16c %=s %#9.1<crc16c>";
|
||||||
|
out "xmodem %s %#9.1<xmodem>"; in "xmodem %=s %#9.1<xmodem>";
|
||||||
|
out "crc32 %s %#9.1<crc32>"; in "crc32 %=s %#9.1<crc32>";
|
||||||
|
out "crc32r %s %#9.1<crc32r>"; in "crc32r %=s %#9.1<crc32r>";
|
||||||
|
out "jamcrc %s %#9.1<jamcrc>"; in "jamcrc %=s %#9.1<jamcrc>";
|
||||||
|
out "adler32 %s %#9.1<adler32>"; in "adler32 %=s %#9.1<adler32>";
|
||||||
|
out "hexsum8 %s %#9.1<hexsum8>"; in "hexsum8 %=s %#9.1<hexsum8>";
|
||||||
|
|
||||||
|
out "sum %s %#09.1<sum>"; in "sum %=s %#09.1<sum>";
|
||||||
|
out "sum8 %s %#09.1<sum8>"; in "sum8 %=s %#09.1<sum8>";
|
||||||
|
out "sum16 %s %#09.1<sum16>"; in "sum16 %=s %#09.1<sum16>";
|
||||||
|
out "sum32 %s %#09.1<sum32>"; in "sum32 %=s %#09.1<sum32>";
|
||||||
|
out "nsum %s %#09.1<nsum>"; in "nsum %=s %#09.1<nsum>";
|
||||||
|
out "negsum %s %#09.1<negsum>"; in "negsum %=s %#09.1<negsum>";
|
||||||
|
out "-sum %s %#09.1<-sum>"; in "-sum %=s %#09.1<-sum>";
|
||||||
|
out "nsum8 %s %#09.1<nsum8>"; in "nsum8 %=s %#09.1<nsum8>";
|
||||||
|
out "negsum8 %s %#09.1<negsum8>"; in "negsum8 %=s %#09.1<negsum8>";
|
||||||
|
out "-sum8 %s %#09.1<-sum8>"; in "-sum8 %=s %#09.1<-sum8>";
|
||||||
|
out "nsum16 %s %#09.1<nsum16>"; in "nsum16 %=s %#09.1<nsum16>";
|
||||||
|
out "negsum16 %s %#09.1<negsum1>"; in "negsum16 %=s %#09.1<negsum1>";
|
||||||
|
out "-sum16 %s %#09.1<-sum16>"; in "-sum16 %=s %#09.1<-sum16>";
|
||||||
|
out "nsum32 %s %#09.1<nsum32>"; in "nsum32 %=s %#09.1<nsum32>";
|
||||||
|
out "negsum32 %s %#09.1<negsum3>"; in "negsum32 %=s %#09.1<negsum3>";
|
||||||
|
out "-sum32 %s %#09.1<-sum32>"; in "-sum32 %=s %#09.1<-sum32>";
|
||||||
|
out "notsum %s %#09.1<notsum>"; in "notsum %=s %#09.1<notsum>";
|
||||||
|
out "~sum %s %#09.1<~sum>"; in "~sum %=s %#09.1<~sum>";
|
||||||
|
out "xor %s %#09.1<xor>"; in "xor %=s %#09.1<xor>";
|
||||||
|
out "xor8 %s %#09.1<xor8>"; in "xor8 %=s %#09.1<xor8>";
|
||||||
|
out "xor7 %s %#09.1<xor7>"; in "xor7 %=s %#09.1<xor7>";
|
||||||
|
out "crc8 %s %#09.1<crc8>"; in "crc8 %=s %#09.1<crc8>";
|
||||||
|
out "ccitt8 %s %#09.1<ccitt8>"; in "ccitt8 %=s %#09.1<ccitt8>";
|
||||||
|
out "crc16 %s %#09.1<crc16>"; in "crc16 %=s %#09.1<crc16>";
|
||||||
|
out "crc16r %s %#09.1<crc16r>"; in "crc16r %=s %#09.1<crc16r>";
|
||||||
|
out "ccitt16 %s %#09.1<ccitt16>"; in "ccitt16 %=s %#09.1<ccitt16>";
|
||||||
|
out "ccitt16a %s %#09.1<ccitt16a>"; in "ccitt16a %=s %#09.1<ccitt16a>";
|
||||||
|
out "ccitt16x %s %#09.1<ccitt16x>"; in "ccitt16x %=s %#09.1<ccitt16x>";
|
||||||
|
out "crc16c %s %#09.1<crc16c>"; in "crc16c %=s %#09.1<crc16c>";
|
||||||
|
out "xmodem %s %#09.1<xmodem>"; in "xmodem %=s %#09.1<xmodem>";
|
||||||
|
out "crc32 %s %#09.1<crc32>"; in "crc32 %=s %#09.1<crc32>";
|
||||||
|
out "crc32r %s %#09.1<crc32r>"; in "crc32r %=s %#09.1<crc32r>";
|
||||||
|
out "jamcrc %s %#09.1<jamcrc>"; in "jamcrc %=s %#09.1<jamcrc>";
|
||||||
|
out "adler32 %s %#09.1<adler32>"; in "adler32 %=s %#09.1<adler32>";
|
||||||
|
out "hexsum8 %s %#09.1<hexsum8>"; in "hexsum8 %=s %#09.1<hexsum8>";
|
||||||
|
|
||||||
|
out "sum %s %#-9.1<sum>"; in "sum %=s %#-9.1<sum>";
|
||||||
|
out "sum8 %s %#-9.1<sum8>"; in "sum8 %=s %#-9.1<sum8>";
|
||||||
|
out "sum16 %s %#-9.1<sum16>"; in "sum16 %=s %#-9.1<sum16>";
|
||||||
|
out "sum32 %s %#-9.1<sum32>"; in "sum32 %=s %#-9.1<sum32>";
|
||||||
|
out "nsum %s %#-9.1<nsum>"; in "nsum %=s %#-9.1<nsum>";
|
||||||
|
out "negsum %s %#-9.1<negsum>"; in "negsum %=s %#-9.1<negsum>";
|
||||||
|
out "-sum %s %#-9.1<-sum>"; in "-sum %=s %#-9.1<-sum>";
|
||||||
|
out "nsum8 %s %#-9.1<nsum8>"; in "nsum8 %=s %#-9.1<nsum8>";
|
||||||
|
out "negsum8 %s %#-9.1<negsum8>"; in "negsum8 %=s %#-9.1<negsum8>";
|
||||||
|
out "-sum8 %s %#-9.1<-sum8>"; in "-sum8 %=s %#-9.1<-sum8>";
|
||||||
|
out "nsum16 %s %#-9.1<nsum16>"; in "nsum16 %=s %#-9.1<nsum16>";
|
||||||
|
out "negsum16 %s %#-9.1<negsum1>"; in "negsum16 %=s %#-9.1<negsum1>";
|
||||||
|
out "-sum16 %s %#-9.1<-sum16>"; in "-sum16 %=s %#-9.1<-sum16>";
|
||||||
|
out "nsum32 %s %#-9.1<nsum32>"; in "nsum32 %=s %#-9.1<nsum32>";
|
||||||
|
out "negsum32 %s %#-9.1<negsum3>"; in "negsum32 %=s %#-9.1<negsum3>";
|
||||||
|
out "-sum32 %s %#-9.1<-sum32>"; in "-sum32 %=s %#-9.1<-sum32>";
|
||||||
|
out "notsum %s %#-9.1<notsum>"; in "notsum %=s %#-9.1<notsum>";
|
||||||
|
out "~sum %s %#-9.1<~sum>"; in "~sum %=s %#-9.1<~sum>";
|
||||||
|
out "xor %s %#-9.1<xor>"; in "xor %=s %#-9.1<xor>";
|
||||||
|
out "xor8 %s %#-9.1<xor8>"; in "xor8 %=s %#-9.1<xor8>";
|
||||||
|
out "xor7 %s %#-9.1<xor7>"; in "xor7 %=s %#-9.1<xor7>";
|
||||||
|
out "crc8 %s %#-9.1<crc8>"; in "crc8 %=s %#-9.1<crc8>";
|
||||||
|
out "ccitt8 %s %#-9.1<ccitt8>"; in "ccitt8 %=s %#-9.1<ccitt8>";
|
||||||
|
out "crc16 %s %#-9.1<crc16>"; in "crc16 %=s %#-9.1<crc16>";
|
||||||
|
out "crc16r %s %#-9.1<crc16r>"; in "crc16r %=s %#-9.1<crc16r>";
|
||||||
|
out "ccitt16 %s %#-9.1<ccitt16>"; in "ccitt16 %=s %#-9.1<ccitt16>";
|
||||||
|
out "ccitt16a %s %#-9.1<ccitt16a>"; in "ccitt16a %=s %#-9.1<ccitt16a>";
|
||||||
|
out "ccitt16x %s %#-9.1<ccitt16x>"; in "ccitt16x %=s %#-9.1<ccitt16x>";
|
||||||
|
out "crc16c %s %#-9.1<crc16c>"; in "crc16c %=s %#-9.1<crc16c>";
|
||||||
|
out "xmodem %s %#-9.1<xmodem>"; in "xmodem %=s %#-9.1<xmodem>";
|
||||||
|
out "crc32 %s %#-9.1<crc32>"; in "crc32 %=s %#-9.1<crc32>";
|
||||||
|
out "crc32r %s %#-9.1<crc32r>"; in "crc32r %=s %#-9.1<crc32r>";
|
||||||
|
out "jamcrc %s %#-9.1<jamcrc>"; in "jamcrc %=s %#-9.1<jamcrc>";
|
||||||
|
out "adler32 %s %#-9.1<adler32>"; in "adler32 %=s %#-9.1<adler32>";
|
||||||
|
out "hexsum8 %s %#-9.1<hexsum8>"; in "hexsum8 %=s %#-9.1<hexsum8>";
|
||||||
|
out "DONE";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set startup {
|
set startup {
|
||||||
@ -24,7 +242,432 @@ set startup {
|
|||||||
set debug 0
|
set debug 0
|
||||||
|
|
||||||
startioc
|
startioc
|
||||||
ioccmd {dbpf DZ:test1 "1"}
|
ioccmd {dbpf DZ:test1 "123456789"}
|
||||||
assure "\x55\x40\x04\x00\x00z;\x4e"
|
assure "sum 123456789 \xDD\n"
|
||||||
|
send "sum 123456789 \xDD\n"
|
||||||
|
assure "sum8 123456789 \xDD\n"
|
||||||
|
send "sum8 123456789 \xDD\n"
|
||||||
|
assure "sum16 123456789 \x01\xDD\n"
|
||||||
|
send "sum16 123456789 \x01\xDD\n"
|
||||||
|
assure "sum32 123456789 \x00\x00\x01\xDD\n"
|
||||||
|
send "sum32 123456789 \x00\x00\x01\xDD\n"
|
||||||
|
assure "nsum 123456789 \x23\n"
|
||||||
|
send "nsum 123456789 \x23\n"
|
||||||
|
assure "negsum 123456789 \x23\n"
|
||||||
|
send "negsum 123456789 \x23\n"
|
||||||
|
assure "-sum 123456789 \x23\n"
|
||||||
|
send "-sum 123456789 \x23\n"
|
||||||
|
assure "nsum8 123456789 \x23\n"
|
||||||
|
send "nsum8 123456789 \x23\n"
|
||||||
|
assure "negsum8 123456789 \x23\n"
|
||||||
|
send "negsum8 123456789 \x23\n"
|
||||||
|
assure "-sum8 123456789 \x23\n"
|
||||||
|
send "-sum8 123456789 \x23\n"
|
||||||
|
assure "nsum16 123456789 \xFE\x23\n"
|
||||||
|
send "nsum16 123456789 \xFE\x23\n"
|
||||||
|
assure "negsum16 123456789 \xFE\x23\n"
|
||||||
|
send "negsum16 123456789 \xFE\x23\n"
|
||||||
|
assure "-sum16 123456789 \xFE\x23\n"
|
||||||
|
send "-sum16 123456789 \xFE\x23\n"
|
||||||
|
assure "nsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||||
|
send "nsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||||
|
assure "negsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||||
|
send "negsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||||
|
assure "-sum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||||
|
send "-sum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||||
|
assure "notsum 123456789 \x22\n"
|
||||||
|
send "notsum 123456789 \x22\n"
|
||||||
|
assure "~sum 123456789 \x22\n"
|
||||||
|
send "~sum 123456789 \x22\n"
|
||||||
|
assure "xor 123456789 \x31\n"
|
||||||
|
send "xor 123456789 \x31\n"
|
||||||
|
assure "xor8 123456789 \x31\n"
|
||||||
|
send "xor8 123456789 \x31\n"
|
||||||
|
assure "xor7 123456789 \x31\n"
|
||||||
|
send "xor7 123456789 \x31\n"
|
||||||
|
assure "crc8 123456789 \xF4\n"
|
||||||
|
send "crc8 123456789 \xF4\n"
|
||||||
|
assure "ccitt8 123456789 \xA1\n"
|
||||||
|
send "ccitt8 123456789 \xA1\n"
|
||||||
|
assure "crc16 123456789 \xFE\xE8\n"
|
||||||
|
send "crc16 123456789 \xFE\xE8\n"
|
||||||
|
assure "crc16r 123456789 \xBB\x3D\n"
|
||||||
|
send "crc16r 123456789 \xBB\x3D\n"
|
||||||
|
assure "ccitt16 123456789 \x29\xB1\n"
|
||||||
|
send "ccitt16 123456789 \x29\xB1\n"
|
||||||
|
assure "ccitt16a 123456789 \xE5\xCC\n"
|
||||||
|
send "ccitt16a 123456789 \xE5\xCC\n"
|
||||||
|
assure "ccitt16x 123456789 \x31\xC3\n"
|
||||||
|
send "ccitt16x 123456789 \x31\xC3\n"
|
||||||
|
assure "crc16c 123456789 \x31\xC3\n"
|
||||||
|
send "crc16c 123456789 \x31\xC3\n"
|
||||||
|
assure "xmodem 123456789 \x31\xC3\n"
|
||||||
|
send "xmodem 123456789 \x31\xC3\n"
|
||||||
|
assure "crc32 123456789 \xFC\x89\x19\x18\n"
|
||||||
|
send "crc32 123456789 \xFC\x89\x19\x18\n"
|
||||||
|
assure "crc32r 123456789 \xCB\xF4\x39\x26\n"
|
||||||
|
send "crc32r 123456789 \xCB\xF4\x39\x26\n"
|
||||||
|
assure "jamcrc 123456789 \x34\x0B\xC6\xD9\n"
|
||||||
|
send "jamcrc 123456789 \x34\x0B\xC6\xD9\n"
|
||||||
|
assure "adler32 123456789 \x09\x1E\x01\xDE\n"
|
||||||
|
send "adler32 123456789 \x09\x1E\x01\xDE\n"
|
||||||
|
assure "hexsum8 123456789 \x2D\n"
|
||||||
|
send "hexsum8 123456789 \x2D\n"
|
||||||
|
|
||||||
|
assure "sum 123456789 DD\n"
|
||||||
|
send "sum 123456789 DD\n"
|
||||||
|
assure "sum8 123456789 DD\n"
|
||||||
|
send "sum8 123456789 DD\n"
|
||||||
|
assure "sum16 123456789 01DD\n"
|
||||||
|
send "sum16 123456789 01DD\n"
|
||||||
|
assure "sum32 123456789 000001DD\n"
|
||||||
|
send "sum32 123456789 000001DD\n"
|
||||||
|
assure "nsum 123456789 23\n"
|
||||||
|
send "nsum 123456789 23\n"
|
||||||
|
assure "negsum 123456789 23\n"
|
||||||
|
send "negsum 123456789 23\n"
|
||||||
|
assure "-sum 123456789 23\n"
|
||||||
|
send "-sum 123456789 23\n"
|
||||||
|
assure "nsum8 123456789 23\n"
|
||||||
|
send "nsum8 123456789 23\n"
|
||||||
|
assure "negsum8 123456789 23\n"
|
||||||
|
send "negsum8 123456789 23\n"
|
||||||
|
assure "-sum8 123456789 23\n"
|
||||||
|
send "-sum8 123456789 23\n"
|
||||||
|
assure "nsum16 123456789 FE23\n"
|
||||||
|
send "nsum16 123456789 FE23\n"
|
||||||
|
assure "negsum16 123456789 FE23\n"
|
||||||
|
send "negsum16 123456789 FE23\n"
|
||||||
|
assure "-sum16 123456789 FE23\n"
|
||||||
|
send "-sum16 123456789 FE23\n"
|
||||||
|
assure "nsum32 123456789 FFFFFE23\n"
|
||||||
|
send "nsum32 123456789 FFFFFE23\n"
|
||||||
|
assure "negsum32 123456789 FFFFFE23\n"
|
||||||
|
send "negsum32 123456789 FFFFFE23\n"
|
||||||
|
assure "-sum32 123456789 FFFFFE23\n"
|
||||||
|
send "-sum32 123456789 FFFFFE23\n"
|
||||||
|
assure "notsum 123456789 22\n"
|
||||||
|
send "notsum 123456789 22\n"
|
||||||
|
assure "~sum 123456789 22\n"
|
||||||
|
send "~sum 123456789 22\n"
|
||||||
|
assure "xor 123456789 31\n"
|
||||||
|
send "xor 123456789 31\n"
|
||||||
|
assure "xor8 123456789 31\n"
|
||||||
|
send "xor8 123456789 31\n"
|
||||||
|
assure "xor7 123456789 31\n"
|
||||||
|
send "xor7 123456789 31\n"
|
||||||
|
assure "crc8 123456789 F4\n"
|
||||||
|
send "crc8 123456789 F4\n"
|
||||||
|
assure "ccitt8 123456789 A1\n"
|
||||||
|
send "ccitt8 123456789 A1\n"
|
||||||
|
assure "crc16 123456789 FEE8\n"
|
||||||
|
send "crc16 123456789 FEE8\n"
|
||||||
|
assure "crc16r 123456789 BB3D\n"
|
||||||
|
send "crc16r 123456789 BB3D\n"
|
||||||
|
assure "ccitt16 123456789 29B1\n"
|
||||||
|
send "ccitt16 123456789 29B1\n"
|
||||||
|
assure "ccitt16a 123456789 E5CC\n"
|
||||||
|
send "ccitt16a 123456789 E5CC\n"
|
||||||
|
assure "ccitt16x 123456789 31C3\n"
|
||||||
|
send "ccitt16x 123456789 31C3\n"
|
||||||
|
assure "crc16c 123456789 31C3\n"
|
||||||
|
send "crc16c 123456789 31C3\n"
|
||||||
|
assure "xmodem 123456789 31C3\n"
|
||||||
|
send "xmodem 123456789 31C3\n"
|
||||||
|
assure "crc32 123456789 FC891918\n"
|
||||||
|
send "crc32 123456789 FC891918\n"
|
||||||
|
assure "crc32r 123456789 CBF43926\n"
|
||||||
|
send "crc32r 123456789 CBF43926\n"
|
||||||
|
assure "jamcrc 123456789 340BC6D9\n"
|
||||||
|
send "jamcrc 123456789 340BC6D9\n"
|
||||||
|
assure "adler32 123456789 091E01DE\n"
|
||||||
|
send "adler32 123456789 091E01DE\n"
|
||||||
|
assure "hexsum8 123456789 2D\n"
|
||||||
|
send "hexsum8 123456789 2D\n"
|
||||||
|
|
||||||
|
assure "sum 123456789 \x3D\x3D\n"
|
||||||
|
send "sum 123456789 \x3D\x3D\n"
|
||||||
|
assure "sum8 123456789 \x3D\x3D\n"
|
||||||
|
send "sum8 123456789 \x3D\x3D\n"
|
||||||
|
assure "sum16 123456789 \x30\x31\x3D\x3D\n"
|
||||||
|
send "sum16 123456789 \x30\x31\x3D\x3D\n"
|
||||||
|
assure "sum32 123456789 \x30\x30\x30\x30\x30\x31\x3D\x3D\n"
|
||||||
|
send "sum32 123456789 \x30\x30\x30\x30\x30\x31\x3D\x3D\n"
|
||||||
|
assure "nsum 123456789 \x32\x33\n"
|
||||||
|
send "nsum 123456789 \x32\x33\n"
|
||||||
|
assure "negsum 123456789 \x32\x33\n"
|
||||||
|
send "negsum 123456789 \x32\x33\n"
|
||||||
|
assure "-sum 123456789 \x32\x33\n"
|
||||||
|
send "-sum 123456789 \x32\x33\n"
|
||||||
|
assure "nsum8 123456789 \x32\x33\n"
|
||||||
|
send "nsum8 123456789 \x32\x33\n"
|
||||||
|
assure "negsum8 123456789 \x32\x33\n"
|
||||||
|
send "negsum8 123456789 \x32\x33\n"
|
||||||
|
assure "-sum8 123456789 \x32\x33\n"
|
||||||
|
send "-sum8 123456789 \x32\x33\n"
|
||||||
|
assure "nsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||||
|
send "nsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||||
|
assure "negsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||||
|
send "negsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||||
|
assure "-sum16 123456789 \x3F\x3E\x32\x33\n"
|
||||||
|
send "-sum16 123456789 \x3F\x3E\x32\x33\n"
|
||||||
|
assure "nsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||||
|
send "nsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||||
|
assure "negsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||||
|
send "negsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||||
|
assure "-sum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||||
|
send "-sum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||||
|
assure "notsum 123456789 \x32\x32\n"
|
||||||
|
send "notsum 123456789 \x32\x32\n"
|
||||||
|
assure "~sum 123456789 \x32\x32\n"
|
||||||
|
send "~sum 123456789 \x32\x32\n"
|
||||||
|
assure "xor 123456789 \x33\x31\n"
|
||||||
|
send "xor 123456789 \x33\x31\n"
|
||||||
|
assure "xor8 123456789 \x33\x31\n"
|
||||||
|
send "xor8 123456789 \x33\x31\n"
|
||||||
|
assure "xor7 123456789 \x33\x31\n"
|
||||||
|
send "xor7 123456789 \x33\x31\n"
|
||||||
|
assure "crc8 123456789 \x3F\x34\n"
|
||||||
|
send "crc8 123456789 \x3F\x34\n"
|
||||||
|
assure "ccitt8 123456789 \x3A\x31\n"
|
||||||
|
send "ccitt8 123456789 \x3A\x31\n"
|
||||||
|
assure "crc16 123456789 \x3F\x3E\x3E\x38\n"
|
||||||
|
send "crc16 123456789 \x3F\x3E\x3E\x38\n"
|
||||||
|
assure "crc16r 123456789 \x3B\x3B\x33\x3D\n"
|
||||||
|
send "crc16r 123456789 \x3B\x3B\x33\x3D\n"
|
||||||
|
assure "ccitt16 123456789 \x32\x39\x3B\x31\n"
|
||||||
|
send "ccitt16 123456789 \x32\x39\x3B\x31\n"
|
||||||
|
assure "ccitt16a 123456789 \x3E\x35\x3C\x3C\n"
|
||||||
|
send "ccitt16a 123456789 \x3E\x35\x3C\x3C\n"
|
||||||
|
assure "ccitt16x 123456789 \x33\x31\x3C\x33\n"
|
||||||
|
send "ccitt16x 123456789 \x33\x31\x3C\x33\n"
|
||||||
|
assure "crc16c 123456789 \x33\x31\x3C\x33\n"
|
||||||
|
send "crc16c 123456789 \x33\x31\x3C\x33\n"
|
||||||
|
assure "xmodem 123456789 \x33\x31\x3C\x33\n"
|
||||||
|
send "xmodem 123456789 \x33\x31\x3C\x33\n"
|
||||||
|
assure "crc32 123456789 \x3F\x3C\x38\x39\x31\x39\x31\x38\n"
|
||||||
|
send "crc32 123456789 \x3F\x3C\x38\x39\x31\x39\x31\x38\n"
|
||||||
|
assure "crc32r 123456789 \x3C\x3B\x3F\x34\x33\x39\x32\x36\n"
|
||||||
|
send "crc32r 123456789 \x3C\x3B\x3F\x34\x33\x39\x32\x36\n"
|
||||||
|
assure "jamcrc 123456789 \x33\x34\x30\x3B\x3C\x36\x3D\x39\n"
|
||||||
|
send "jamcrc 123456789 \x33\x34\x30\x3B\x3C\x36\x3D\x39\n"
|
||||||
|
assure "adler32 123456789 \x30\x39\x31\x3E\x30\x31\x3D\x3E\n"
|
||||||
|
send "adler32 123456789 \x30\x39\x31\x3E\x30\x31\x3D\x3E\n"
|
||||||
|
assure "hexsum8 123456789 \x32\x3D\n"
|
||||||
|
send "hexsum8 123456789 \x32\x3D\n"
|
||||||
|
|
||||||
|
assure "sum 123456789 \xDD\n"
|
||||||
|
send "sum 123456789 \xDD\n"
|
||||||
|
assure "sum8 123456789 \xDD\n"
|
||||||
|
send "sum8 123456789 \xDD\n"
|
||||||
|
assure "sum16 123456789 \xDD\x01\n"
|
||||||
|
send "sum16 123456789 \xDD\x01\n"
|
||||||
|
assure "sum32 123456789 \xDD\x01\x00\x00\n"
|
||||||
|
send "sum32 123456789 \xDD\x01\x00\x00\n"
|
||||||
|
assure "nsum 123456789 \x23\n"
|
||||||
|
send "nsum 123456789 \x23\n"
|
||||||
|
assure "negsum 123456789 \x23\n"
|
||||||
|
send "negsum 123456789 \x23\n"
|
||||||
|
assure "-sum 123456789 \x23\n"
|
||||||
|
send "-sum 123456789 \x23\n"
|
||||||
|
assure "nsum8 123456789 \x23\n"
|
||||||
|
send "nsum8 123456789 \x23\n"
|
||||||
|
assure "negsum8 123456789 \x23\n"
|
||||||
|
send "negsum8 123456789 \x23\n"
|
||||||
|
assure "-sum8 123456789 \x23\n"
|
||||||
|
send "-sum8 123456789 \x23\n"
|
||||||
|
assure "nsum16 123456789 \x23\xFE\n"
|
||||||
|
send "nsum16 123456789 \x23\xFE\n"
|
||||||
|
assure "negsum16 123456789 \x23\xFE\n"
|
||||||
|
send "negsum16 123456789 \x23\xFE\n"
|
||||||
|
assure "-sum16 123456789 \x23\xFE\n"
|
||||||
|
send "-sum16 123456789 \x23\xFE\n"
|
||||||
|
assure "nsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||||
|
send "nsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||||
|
assure "negsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||||
|
send "negsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||||
|
assure "-sum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||||
|
send "-sum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||||
|
assure "notsum 123456789 \x22\n"
|
||||||
|
send "notsum 123456789 \x22\n"
|
||||||
|
assure "~sum 123456789 \x22\n"
|
||||||
|
send "~sum 123456789 \x22\n"
|
||||||
|
assure "xor 123456789 \x31\n"
|
||||||
|
send "xor 123456789 \x31\n"
|
||||||
|
assure "xor8 123456789 \x31\n"
|
||||||
|
send "xor8 123456789 \x31\n"
|
||||||
|
assure "xor7 123456789 \x31\n"
|
||||||
|
send "xor7 123456789 \x31\n"
|
||||||
|
assure "crc8 123456789 \xF4\n"
|
||||||
|
send "crc8 123456789 \xF4\n"
|
||||||
|
assure "ccitt8 123456789 \xA1\n"
|
||||||
|
send "ccitt8 123456789 \xA1\n"
|
||||||
|
assure "crc16 123456789 \xE8\xFE\n"
|
||||||
|
send "crc16 123456789 \xE8\xFE\n"
|
||||||
|
assure "crc16r 123456789 \x3D\xBB\n"
|
||||||
|
send "crc16r 123456789 \x3D\xBB\n"
|
||||||
|
assure "ccitt16 123456789 \xB1\x29\n"
|
||||||
|
send "ccitt16 123456789 \xB1\x29\n"
|
||||||
|
assure "ccitt16a 123456789 \xCC\xE5\n"
|
||||||
|
send "ccitt16a 123456789 \xCC\xE5\n"
|
||||||
|
assure "ccitt16x 123456789 \xC3\x31\n"
|
||||||
|
send "ccitt16x 123456789 \xC3\x31\n"
|
||||||
|
assure "crc16c 123456789 \xC3\x31\n"
|
||||||
|
send "crc16c 123456789 \xC3\x31\n"
|
||||||
|
assure "xmodem 123456789 \xC3\x31\n"
|
||||||
|
send "xmodem 123456789 \xC3\x31\n"
|
||||||
|
assure "crc32 123456789 \x18\x19\x89\xFC\n"
|
||||||
|
send "crc32 123456789 \x18\x19\x89\xFC\n"
|
||||||
|
assure "crc32r 123456789 \x26\x39\xF4\xCB\n"
|
||||||
|
send "crc32r 123456789 \x26\x39\xF4\xCB\n"
|
||||||
|
assure "jamcrc 123456789 \xD9\xC6\x0B\x34\n"
|
||||||
|
send "jamcrc 123456789 \xD9\xC6\x0B\x34\n"
|
||||||
|
assure "adler32 123456789 \xDE\x01\x1E\x09\n"
|
||||||
|
send "adler32 123456789 \xDE\x01\x1E\x09\n"
|
||||||
|
assure "hexsum8 123456789 \x2D\n"
|
||||||
|
send "hexsum8 123456789 \x2D\n"
|
||||||
|
|
||||||
|
assure "sum 123456789 DD\n"
|
||||||
|
send "sum 123456789 DD\n"
|
||||||
|
assure "sum8 123456789 DD\n"
|
||||||
|
send "sum8 123456789 DD\n"
|
||||||
|
assure "sum16 123456789 DD01\n"
|
||||||
|
send "sum16 123456789 DD01\n"
|
||||||
|
assure "sum32 123456789 DD010000\n"
|
||||||
|
send "sum32 123456789 DD010000\n"
|
||||||
|
assure "nsum 123456789 23\n"
|
||||||
|
send "nsum 123456789 23\n"
|
||||||
|
assure "negsum 123456789 23\n"
|
||||||
|
send "negsum 123456789 23\n"
|
||||||
|
assure "-sum 123456789 23\n"
|
||||||
|
send "-sum 123456789 23\n"
|
||||||
|
assure "nsum8 123456789 23\n"
|
||||||
|
send "nsum8 123456789 23\n"
|
||||||
|
assure "negsum8 123456789 23\n"
|
||||||
|
send "negsum8 123456789 23\n"
|
||||||
|
assure "-sum8 123456789 23\n"
|
||||||
|
send "-sum8 123456789 23\n"
|
||||||
|
assure "nsum16 123456789 23FE\n"
|
||||||
|
send "nsum16 123456789 23FE\n"
|
||||||
|
assure "negsum16 123456789 23FE\n"
|
||||||
|
send "negsum16 123456789 23FE\n"
|
||||||
|
assure "-sum16 123456789 23FE\n"
|
||||||
|
send "-sum16 123456789 23FE\n"
|
||||||
|
assure "nsum32 123456789 23FEFFFF\n"
|
||||||
|
send "nsum32 123456789 23FEFFFF\n"
|
||||||
|
assure "negsum32 123456789 23FEFFFF\n"
|
||||||
|
send "negsum32 123456789 23FEFFFF\n"
|
||||||
|
assure "-sum32 123456789 23FEFFFF\n"
|
||||||
|
send "-sum32 123456789 23FEFFFF\n"
|
||||||
|
assure "notsum 123456789 22\n"
|
||||||
|
send "notsum 123456789 22\n"
|
||||||
|
assure "~sum 123456789 22\n"
|
||||||
|
send "~sum 123456789 22\n"
|
||||||
|
assure "xor 123456789 31\n"
|
||||||
|
send "xor 123456789 31\n"
|
||||||
|
assure "xor8 123456789 31\n"
|
||||||
|
send "xor8 123456789 31\n"
|
||||||
|
assure "xor7 123456789 31\n"
|
||||||
|
send "xor7 123456789 31\n"
|
||||||
|
assure "crc8 123456789 F4\n"
|
||||||
|
send "crc8 123456789 F4\n"
|
||||||
|
assure "ccitt8 123456789 A1\n"
|
||||||
|
send "ccitt8 123456789 A1\n"
|
||||||
|
assure "crc16 123456789 E8FE\n"
|
||||||
|
send "crc16 123456789 E8FE\n"
|
||||||
|
assure "crc16r 123456789 3DBB\n"
|
||||||
|
send "crc16r 123456789 3DBB\n"
|
||||||
|
assure "ccitt16 123456789 B129\n"
|
||||||
|
send "ccitt16 123456789 B129\n"
|
||||||
|
assure "ccitt16a 123456789 CCE5\n"
|
||||||
|
send "ccitt16a 123456789 CCE5\n"
|
||||||
|
assure "ccitt16x 123456789 C331\n"
|
||||||
|
send "ccitt16x 123456789 C331\n"
|
||||||
|
assure "crc16c 123456789 C331\n"
|
||||||
|
send "crc16c 123456789 C331\n"
|
||||||
|
assure "xmodem 123456789 C331\n"
|
||||||
|
send "xmodem 123456789 C331\n"
|
||||||
|
assure "crc32 123456789 181989FC\n"
|
||||||
|
send "crc32 123456789 181989FC\n"
|
||||||
|
assure "crc32r 123456789 2639F4CB\n"
|
||||||
|
send "crc32r 123456789 2639F4CB\n"
|
||||||
|
assure "jamcrc 123456789 D9C60B34\n"
|
||||||
|
send "jamcrc 123456789 D9C60B34\n"
|
||||||
|
assure "adler32 123456789 DE011E09\n"
|
||||||
|
send "adler32 123456789 DE011E09\n"
|
||||||
|
assure "hexsum8 123456789 2D\n"
|
||||||
|
send "hexsum8 123456789 2D\n"
|
||||||
|
|
||||||
|
assure "sum 123456789 \x3D\x3D\n"
|
||||||
|
send "sum 123456789 \x3D\x3D\n"
|
||||||
|
assure "sum8 123456789 \x3D\x3D\n"
|
||||||
|
send "sum8 123456789 \x3D\x3D\n"
|
||||||
|
assure "sum16 123456789 \x3D\x3D\x30\x31\n"
|
||||||
|
send "sum16 123456789 \x3D\x3D\x30\x31\n"
|
||||||
|
assure "sum32 123456789 \x3D\x3D\x30\x31\x30\x30\x30\x30\n"
|
||||||
|
send "sum32 123456789 \x3D\x3D\x30\x31\x30\x30\x30\x30\n"
|
||||||
|
assure "nsum 123456789 \x32\x33\n"
|
||||||
|
send "nsum 123456789 \x32\x33\n"
|
||||||
|
assure "negsum 123456789 \x32\x33\n"
|
||||||
|
send "negsum 123456789 \x32\x33\n"
|
||||||
|
assure "-sum 123456789 \x32\x33\n"
|
||||||
|
send "-sum 123456789 \x32\x33\n"
|
||||||
|
assure "nsum8 123456789 \x32\x33\n"
|
||||||
|
send "nsum8 123456789 \x32\x33\n"
|
||||||
|
assure "negsum8 123456789 \x32\x33\n"
|
||||||
|
send "negsum8 123456789 \x32\x33\n"
|
||||||
|
assure "-sum8 123456789 \x32\x33\n"
|
||||||
|
send "-sum8 123456789 \x32\x33\n"
|
||||||
|
assure "nsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||||
|
send "nsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||||
|
assure "negsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||||
|
send "negsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||||
|
assure "-sum16 123456789 \x32\x33\x3F\x3E\n"
|
||||||
|
send "-sum16 123456789 \x32\x33\x3F\x3E\n"
|
||||||
|
assure "nsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||||
|
send "nsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||||
|
assure "negsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||||
|
send "negsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||||
|
assure "-sum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||||
|
send "-sum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||||
|
assure "notsum 123456789 \x32\x32\n"
|
||||||
|
send "notsum 123456789 \x32\x32\n"
|
||||||
|
assure "~sum 123456789 \x32\x32\n"
|
||||||
|
send "~sum 123456789 \x32\x32\n"
|
||||||
|
assure "xor 123456789 \x33\x31\n"
|
||||||
|
send "xor 123456789 \x33\x31\n"
|
||||||
|
assure "xor8 123456789 \x33\x31\n"
|
||||||
|
send "xor8 123456789 \x33\x31\n"
|
||||||
|
assure "xor7 123456789 \x33\x31\n"
|
||||||
|
send "xor7 123456789 \x33\x31\n"
|
||||||
|
assure "crc8 123456789 \x3F\x34\n"
|
||||||
|
send "crc8 123456789 \x3F\x34\n"
|
||||||
|
assure "ccitt8 123456789 \x3A\x31\n"
|
||||||
|
send "ccitt8 123456789 \x3A\x31\n"
|
||||||
|
assure "crc16 123456789 \x3E\x38\x3F\x3E\n"
|
||||||
|
send "crc16 123456789 \x3E\x38\x3F\x3E\n"
|
||||||
|
assure "crc16r 123456789 \x33\x3D\x3B\x3B\n"
|
||||||
|
send "crc16r 123456789 \x33\x3D\x3B\x3B\n"
|
||||||
|
assure "ccitt16 123456789 \x3B\x31\x32\x39\n"
|
||||||
|
send "ccitt16 123456789 \x3B\x31\x32\x39\n"
|
||||||
|
assure "ccitt16a 123456789 \x3C\x3C\x3E\x35\n"
|
||||||
|
send "ccitt16a 123456789 \x3C\x3C\x3E\x35\n"
|
||||||
|
assure "ccitt16x 123456789 \x3C\x33\x33\x31\n"
|
||||||
|
send "ccitt16x 123456789 \x3C\x33\x33\x31\n"
|
||||||
|
assure "crc16c 123456789 \x3C\x33\x33\x31\n"
|
||||||
|
send "crc16c 123456789 \x3C\x33\x33\x31\n"
|
||||||
|
assure "xmodem 123456789 \x3C\x33\x33\x31\n"
|
||||||
|
send "xmodem 123456789 \x3C\x33\x33\x31\n"
|
||||||
|
assure "crc32 123456789 \x31\x38\x31\x39\x38\x39\x3F\x3C\n"
|
||||||
|
send "crc32 123456789 \x31\x38\x31\x39\x38\x39\x3F\x3C\n"
|
||||||
|
assure "crc32r 123456789 \x32\x36\x33\x39\x3F\x34\x3C\x3B\n"
|
||||||
|
send "crc32r 123456789 \x32\x36\x33\x39\x3F\x34\x3C\x3B\n"
|
||||||
|
assure "jamcrc 123456789 \x3D\x39\x3C\x36\x30\x3B\x33\x34\n"
|
||||||
|
send "jamcrc 123456789 \x3D\x39\x3C\x36\x30\x3B\x33\x34\n"
|
||||||
|
assure "adler32 123456789 \x3D\x3E\x30\x31\x31\x3E\x30\x39\n"
|
||||||
|
send "adler32 123456789 \x3D\x3E\x30\x31\x31\x3E\x30\x39\n"
|
||||||
|
assure "hexsum8 123456789 \x32\x3D\n"
|
||||||
|
send "hexsum8 123456789 \x32\x3D\n"
|
||||||
|
assure "DONE\n"
|
||||||
|
|
||||||
finish
|
finish
|
||||||
|
@ -41,12 +41,10 @@ set protocol {
|
|||||||
set startup {
|
set startup {
|
||||||
}
|
}
|
||||||
|
|
||||||
set debug 0
|
|
||||||
|
|
||||||
startioc
|
startioc
|
||||||
|
|
||||||
set inf [format %f inf]
|
set inf [format %f inf]
|
||||||
set nan [format %f nan]
|
if [catch {set nan [format %f nan]}] {set nan nan}
|
||||||
|
|
||||||
ioccmd {dbpf DZ:test1.PROC 1}
|
ioccmd {dbpf DZ:test1.PROC 1}
|
||||||
send "3.14159265359\n"
|
send "3.14159265359\n"
|
||||||
|
@ -50,7 +50,7 @@ set protocol {
|
|||||||
in {in "%{zero|one|two}bla"; out "%d";}
|
in {in "%{zero|one|two}bla"; out "%d";}
|
||||||
out1 {out "%#{zero|one|two}bla";}
|
out1 {out "%#{zero|one|two}bla";}
|
||||||
in1 {in "%#{zero|one|two}bla"; out "%d";}
|
in1 {in "%#{zero|one|two}bla"; out "%d";}
|
||||||
out2 {out "%#{zero=-1|one|two=5}bla";}
|
out2 {out "%#{zero=-1|one|two=5|default=?}bla";}
|
||||||
in2 {in "%#{zero=-1|one|two=5}bla"; out "%d";}
|
in2 {in "%#{zero=-1|one|two=5}bla"; out "%d";}
|
||||||
in3 {in "%{\x00|\r|}bla"; out "%d";}
|
in3 {in "%{\x00|\r|}bla"; out "%d";}
|
||||||
}
|
}
|
||||||
@ -81,6 +81,8 @@ ioccmd {dbpf DZ:testout2 0}
|
|||||||
assure "onebla\n"
|
assure "onebla\n"
|
||||||
ioccmd {dbpf DZ:testout2 5}
|
ioccmd {dbpf DZ:testout2 5}
|
||||||
assure "twobla\n"
|
assure "twobla\n"
|
||||||
|
ioccmd {dbpf DZ:testout2 17}
|
||||||
|
assure "defaultbla\n"
|
||||||
|
|
||||||
ioccmd {dbpf DZ:testin.PROC 1}
|
ioccmd {dbpf DZ:testin.PROC 1}
|
||||||
send "zerobla\n"
|
send "zerobla\n"
|
||||||
|
@ -30,11 +30,6 @@ set records {
|
|||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
field (OUT, "@test.proto bcd device")
|
field (OUT, "@test.proto bcd device")
|
||||||
}
|
}
|
||||||
record (stringout, "DZ:chksum")
|
|
||||||
{
|
|
||||||
field (DTYP, "stream")
|
|
||||||
field (OUT, "@test.proto chksum device")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set protocol {
|
set protocol {
|
||||||
@ -43,13 +38,6 @@ set protocol {
|
|||||||
ao {out "%.2f %.2e %.2E %.2g %.2G %i %d %u %o %04x %#.2f %#.2e %#.2E %#.2g %#.2G %#i %#d %#u %#o %#06x";}
|
ao {out "%.2f %.2e %.2E %.2g %.2G %i %d %u %o %04x %#.2f %#.2e %#.2E %#.2g %#.2G %#i %#d %#u %#o %#06x";}
|
||||||
lo {out "%d %(VAL)d %06d %x %06X %b %06b %.6b %B.! %06B.!";}
|
lo {out "%d %(VAL)d %06d %x %06X %b %06b %.6b %B.! %06B.!";}
|
||||||
bcd {out "%D %6D %.2D %.4D %.6D %.8D %#D %#6D %#.2D %#.4D %#.6D";}
|
bcd {out "%D %6D %.2D %.4D %.6D %.8D %#D %#6D %#.2D %#.4D %#.6D";}
|
||||||
chksum {out "%s%<xor>";
|
|
||||||
out "%s%0<sum>";
|
|
||||||
out "%s%0<crc8>";
|
|
||||||
out "%s%0<crc16>";
|
|
||||||
out "%s%0<crc32>";
|
|
||||||
out "%s%0<adler32>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set startup {
|
set startup {
|
||||||
@ -80,15 +68,15 @@ ioccmd {dbpf DZ:lo 12345}
|
|||||||
assure "12345 12345 012345 3039 003039 11000000111001 11000000111001 111001 !!......!!!..! !!......!!!..!\n"
|
assure "12345 12345 012345 3039 003039 11000000111001 11000000111001 111001 !!......!!!..! !!......!!!..!\n"
|
||||||
ioccmd {dbpf DZ:lo -1}
|
ioccmd {dbpf DZ:lo -1}
|
||||||
if {$tcl_platform(machine) == "x86_64"} {
|
if {$tcl_platform(machine) == "x86_64"} {
|
||||||
assure "-1 -1 -00001 ffffffffffffffff FFFFFFFFFFFFFFFF 1111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
assure "-1 -1 -00001 ffffffffffffffff FFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
} else {
|
} else {
|
||||||
assure "-1 -1 -00001 ffffffff FFFFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
assure "-1 -1 -00001 ffffffff FFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
}
|
}
|
||||||
ioccmd {dbpf DZ:lo -1234}
|
ioccmd {dbpf DZ:lo -1234}
|
||||||
if {$tcl_platform(machine) == "x86_64"} {
|
if {$tcl_platform(machine) == "x86_64"} {
|
||||||
assure "-1234 -1234 -01234 fffffffffffffb2e FFFFFFFFFFFFFB2E 1111111111111111111111111111111111111111111111111111101100101110 1111111111111111111111111111111111111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
assure "-1234 -1234 -01234 fffffffffffffb2e FFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
||||||
} else {
|
} else {
|
||||||
assure "-1234 -1234 -01234 fffffb2e FFFFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
assure "-1234 -1234 -01234 fffffb2e FFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
||||||
}
|
}
|
||||||
ioccmd {dbpf DZ:lo 255}
|
ioccmd {dbpf DZ:lo 255}
|
||||||
assure "255 255 000255 ff 0000FF 11111111 11111111 111111 !!!!!!!! !!!!!!!!\n"
|
assure "255 255 000255 ff 0000FF 11111111 11111111 111111 !!!!!!!! !!!!!!!!\n"
|
||||||
@ -100,11 +88,4 @@ assure "\0\0\0\0\1\2\3\4 \0\0\0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1\0\0\0
|
|||||||
} else {
|
} else {
|
||||||
assure "\1\2\3\4 \0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1 \4\3\2\1\0\0 \4 \4\3 \4\3\2\n"
|
assure "\1\2\3\4 \0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1 \4\3\2\1\0\0 \4 \4\3 \4\3\2\n"
|
||||||
}
|
}
|
||||||
ioccmd {dbpf DZ:chksum "123456789"}
|
|
||||||
assure "1234567891\n"
|
|
||||||
assure "123456789DD\n"
|
|
||||||
assure "123456789F4\n"
|
|
||||||
assure "123456789FEE8\n"
|
|
||||||
assure "123456789FC891918\n"
|
|
||||||
assure "123456789091E01DE\n"
|
|
||||||
finish
|
finish
|
||||||
|
@ -10,16 +10,19 @@ set records {
|
|||||||
record (ai, "DZ:test1")
|
record (ai, "DZ:test1")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test1 device")
|
field (INP, "@test.proto test1 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test2")
|
record (ai, "DZ:test2")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test2 device")
|
field (INP, "@test.proto test2 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test3")
|
record (ai, "DZ:test3")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test3 device")
|
field (INP, "@test.proto test3 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test4")
|
record (ai, "DZ:test4")
|
||||||
@ -30,26 +33,31 @@ set records {
|
|||||||
record (ai, "DZ:test5")
|
record (ai, "DZ:test5")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test5 device")
|
field (INP, "@test.proto test5 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test6")
|
record (ai, "DZ:test6")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test6 device")
|
field (INP, "@test.proto test6 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test7")
|
record (ai, "DZ:test7")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test7 device")
|
field (INP, "@test.proto test7 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test8")
|
record (ai, "DZ:test8")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test8 device")
|
field (INP, "@test.proto test8 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test9")
|
record (ai, "DZ:test9")
|
||||||
{
|
{
|
||||||
field (DTYP, "stream")
|
field (DTYP, "stream")
|
||||||
|
field (LINR, "LINEAR")
|
||||||
field (INP, "@test.proto test9 device")
|
field (INP, "@test.proto test9 device")
|
||||||
}
|
}
|
||||||
record (ai, "DZ:test10")
|
record (ai, "DZ:test10")
|
||||||
|
33
streamApp/tests/testStrangesum
Executable file
33
streamApp/tests/testStrangesum
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env tclsh
|
||||||
|
source streamtestlib.tcl
|
||||||
|
|
||||||
|
# Define records, protocol and startup (text goes to files)
|
||||||
|
# The asynPort "device" is connected to a network TCP socket
|
||||||
|
# Talk to the socket with send/receive/assure
|
||||||
|
# Send commands to the ioc shell with ioccmd
|
||||||
|
|
||||||
|
set records {
|
||||||
|
record (stringout, "DZ:test1")
|
||||||
|
{
|
||||||
|
field (DTYP, "stream")
|
||||||
|
field (OUT, "@test.proto test1 device")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set protocol {
|
||||||
|
Terminator="\r\n";
|
||||||
|
test1 {
|
||||||
|
out ":%s%01<-hexsum8>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set startup {
|
||||||
|
}
|
||||||
|
|
||||||
|
set debug 0
|
||||||
|
|
||||||
|
startioc
|
||||||
|
ioccmd {dbpf DZ:test1 "010304010001"}
|
||||||
|
assure ":010304010001F6\r\n"
|
||||||
|
|
||||||
|
finish
|
@ -53,13 +53,22 @@ int main () {
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
g++ -I ../../src ../../src/O.$EPICS_HOST_ARCH/StreamBuffer.o test.cc -o test.exe
|
if [ "$1" = "-sls" ]
|
||||||
|
|
||||||
test.exe
|
|
||||||
if [ $? != 0 ]
|
|
||||||
then
|
then
|
||||||
echo -e "\033[31;7mTest failed.\033[0m"
|
O=../../O.*_$EPICS_HOST_ARCH/StreamBuffer.o
|
||||||
exit 1
|
else
|
||||||
|
O=../../src/O.$EPICS_HOST_ARCH/StreamBuffer.o
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
for o in $O
|
||||||
|
do
|
||||||
|
g++ -I ../../src $o test.cc -o test.exe
|
||||||
|
test.exe
|
||||||
|
if [ $? != 0 ]
|
||||||
|
then
|
||||||
|
echo -e "\033[31;7mTest failed.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
rm test.*
|
rm test.*
|
||||||
echo -e "\033[32mTest passed.\033[0m"
|
echo -e "\033[32mTest passed.\033[0m"
|
||||||
|
Reference in New Issue
Block a user