Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
20dde4c1d8 | |||
f61e6404f5 | |||
9080d6ca8e | |||
13e7f2d3dc | |||
e87e093c84 | |||
7debc86514 | |||
668d1d5255 | |||
ae5ca0c45b | |||
b00099973f | |||
5bf5cb9a67 | |||
f6848f0503 | |||
1496089bc8 | |||
a090cd4d8f | |||
2b3e4189c1 | |||
211f689cdf | |||
793675bb12 | |||
922294bf6a | |||
942c4779c9 | |||
8ceee295ae | |||
c30e2a4e31 | |||
fc67fb8721 | |||
c123c5c8f7 | |||
8746dea7cf | |||
2915830b02 | |||
fdfa4d4695 | |||
4d717288da | |||
94721c2b0e | |||
bf0e755913 | |||
51e4a0749d | |||
4cdace3ffe | |||
d19b16d096 | |||
b1e0d63c6b | |||
d1b43b879c | |||
6b0ee5e946 | |||
a0d1b35862 | |||
dfbd308d46 |
1
.ci
Submodule
1
.ci
Submodule
Submodule .ci added at dead44c3cb
12
.ci-local/defaults.set
Normal file
12
.ci-local/defaults.set
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
MODULES=calc asyn
|
||||||
|
|
||||||
|
# EPICS Base
|
||||||
|
BASE_DIRNAME=base
|
||||||
|
BASE_REPONAME=epics-base
|
||||||
|
BASE_REPOOWNER=epics-base
|
||||||
|
BASE_VARNAME=EPICS_BASE
|
||||||
|
BASE_RECURSIVE=no
|
||||||
|
|
||||||
|
ASYN_REPOOWNER=epics-modules
|
||||||
|
|
||||||
|
CALC_REPOOWNER=epics-modules
|
164
.github/workflows/ci-scripts-build.yml
vendored
Normal file
164
.github/workflows/ci-scripts-build.yml
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
||||||
|
# (see: https://github.com/epics-base/ci-scripts)
|
||||||
|
|
||||||
|
# This is YAML - indentation levels are crucial
|
||||||
|
|
||||||
|
# Workflow name, shared by all branches
|
||||||
|
|
||||||
|
name: StreamDevice
|
||||||
|
|
||||||
|
# Trigger on pushes and PRs to any branch
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/*'
|
||||||
|
- '.gitattributes'
|
||||||
|
- '.gitignore'
|
||||||
|
- '**/*.html'
|
||||||
|
- '**/*.md'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/*'
|
||||||
|
- '.gitattributes'
|
||||||
|
- '.gitignore'
|
||||||
|
- '**/*.html'
|
||||||
|
- '**/*.md'
|
||||||
|
|
||||||
|
env:
|
||||||
|
SETUP_PATH: .ci-local:.ci
|
||||||
|
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
native:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
# Set environment variables from matrix parameters
|
||||||
|
env:
|
||||||
|
CMP: ${{ matrix.cmp }}
|
||||||
|
BCFG: ${{ matrix.configuration }}
|
||||||
|
BASE: ${{ matrix.base }}
|
||||||
|
WINE: ${{ matrix.wine }}
|
||||||
|
RTEMS: ${{ matrix.rtems }}
|
||||||
|
RTEMS_TARGET: ${{ matrix.rtems_target }}
|
||||||
|
TEST: ${{ matrix.test }}
|
||||||
|
EXTRA: ${{ matrix.extra }}
|
||||||
|
VV: "1"
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: Native Linux (WError)
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
base: "7.0"
|
||||||
|
extra: "CMD_CPPFLAGS=-Werror"
|
||||||
|
pcre: apt
|
||||||
|
|
||||||
|
- name: Cross mingw64 DLL
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
base: "7.0"
|
||||||
|
wine: "64"
|
||||||
|
pcre: no
|
||||||
|
|
||||||
|
- name: Cross mingw64 static
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: static
|
||||||
|
base: "7.0"
|
||||||
|
wine: "64"
|
||||||
|
pcre: no
|
||||||
|
|
||||||
|
- name: RTEMS 4.10
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
base: "7.0"
|
||||||
|
rtems: "4.10"
|
||||||
|
rtems_target: RTEMS-pc386-qemu
|
||||||
|
pcre: no
|
||||||
|
|
||||||
|
- name: Native Linux with clang
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: clang
|
||||||
|
configuration: default
|
||||||
|
base: "7.0"
|
||||||
|
pcre: apt
|
||||||
|
|
||||||
|
- name: Native Linux with 3.15
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
base: "3.15"
|
||||||
|
pcre: apt
|
||||||
|
|
||||||
|
- name: Native Linux with 3.14
|
||||||
|
os: ubuntu-20.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
base: "3.14"
|
||||||
|
pcre: apt
|
||||||
|
|
||||||
|
- name: OSX
|
||||||
|
os: macos-latest
|
||||||
|
cmp: clang
|
||||||
|
configuration: default
|
||||||
|
base: "7.0"
|
||||||
|
pcre: no
|
||||||
|
|
||||||
|
- name: vs2019 DLL
|
||||||
|
os: windows-2019
|
||||||
|
cmp: vs2019
|
||||||
|
configuration: debug
|
||||||
|
base: "7.0"
|
||||||
|
pcre: no
|
||||||
|
extra: "CMD_CFLAGS=-analysis CMD_CXXFLAGS=-analysis"
|
||||||
|
|
||||||
|
- name: vs2019 static
|
||||||
|
os: windows-2019
|
||||||
|
cmp: vs2019
|
||||||
|
configuration: static-debug
|
||||||
|
base: "7.0"
|
||||||
|
pcre: no
|
||||||
|
extra: "CMD_CFLAGS=-analysis CMD_CXXFLAGS=-analysis"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: Automatic core dumper analysis
|
||||||
|
uses: mdavidsaver/ci-core-dumper@master
|
||||||
|
- name: "apt-get install"
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
|
||||||
|
- name: Reset RELEASE
|
||||||
|
shell: bash
|
||||||
|
# 'make' on Mac doesn't understand "undefine PCRE"
|
||||||
|
# so replace the whole file
|
||||||
|
run: |
|
||||||
|
cat <<EOF > configure/RELEASE
|
||||||
|
-include \$(TOP)/../RELEASE.local
|
||||||
|
-include \$(TOP)/../RELEASE.\$(EPICS_HOST_ARCH).local
|
||||||
|
-include \$(TOP)/configure/RELEASE.local
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Prepare and compile dependencies
|
||||||
|
run: python .ci/cue.py prepare
|
||||||
|
|
||||||
|
- name: "apt-get install pcre"
|
||||||
|
if: matrix.pcre == 'apt'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y install libpcre3-dev
|
||||||
|
cat <<EOF >> configure/CONFIG_SITE.local
|
||||||
|
PCRE_INCLUDE=/usr/include
|
||||||
|
PCRE_LIB=/usr/lib
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Build main module
|
||||||
|
run: python .ci/cue.py build
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule ".ci"]
|
||||||
|
path = .ci
|
||||||
|
url = https://github.com/epics-base/ci-scripts.git
|
@ -24,11 +24,11 @@ HEADERS += src/StreamFormat.h
|
|||||||
HEADERS += src/StreamFormatConverter.h
|
HEADERS += src/StreamFormatConverter.h
|
||||||
HEADERS += src/StreamBuffer.h
|
HEADERS += src/StreamBuffer.h
|
||||||
HEADERS += src/StreamError.h
|
HEADERS += src/StreamError.h
|
||||||
HEADERS += src/StreamVersion.h
|
|
||||||
HEADERS += src/StreamProtocol.h
|
HEADERS += src/StreamProtocol.h
|
||||||
HEADERS += src/StreamBusInterface.h
|
HEADERS += src/StreamBusInterface.h
|
||||||
HEADERS += src/StreamCore.h
|
HEADERS += src/StreamCore.h
|
||||||
HEADERS += src/MacroMagic.h
|
HEADERS += src/MacroMagic.h
|
||||||
|
HEADERS += $(COMMON_DIR)/StreamVersion.h
|
||||||
|
|
||||||
CPPFLAGS += -DSTREAM_INTERNAL -I$(COMMON_DIR)
|
CPPFLAGS += -DSTREAM_INTERNAL -I$(COMMON_DIR)
|
||||||
|
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
#CONFIG
|
# CONFIG - Load build configuration data
|
||||||
include $(TOP)/configure/CONFIG_APP
|
#
|
||||||
# Add any changes to make definitions here
|
# Do not make changes to this file!
|
||||||
|
|
||||||
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
|
# Allow user to override where the build rules come from
|
||||||
#CROSS_COMPILER_TARGET_ARCHS =
|
RULES = $(EPICS_BASE)
|
||||||
|
|
||||||
# Use this when your IOC and the host use different paths
|
# RELEASE files point to other application tops
|
||||||
# to access the application. Typically this will be
|
include $(TOP)/configure/RELEASE
|
||||||
# used with the Microsoft FTP server or with NFS mounts. Use
|
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
|
||||||
# is indicated by failure of the cdCommands script on
|
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
|
||||||
# vxWorks. You must rebuild in the iocBoot directory
|
ifdef T_A
|
||||||
# before this takes effect.
|
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
||||||
#IOCS_APPL_TOP = <the top of the application as seen by the IOC>
|
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||||
|
endif
|
||||||
|
|
||||||
|
CONFIG = $(RULES)/configure
|
||||||
|
include $(CONFIG)/CONFIG
|
||||||
|
|
||||||
|
# Override the Base definition:
|
||||||
|
INSTALL_LOCATION = $(TOP)
|
||||||
|
|
||||||
|
# CONFIG_SITE files contain other build configuration settings
|
||||||
|
include $(TOP)/configure/CONFIG_SITE
|
||||||
|
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||||
|
ifdef T_A
|
||||||
|
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
|
||||||
|
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||||
|
endif
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
# CONFIG_APP
|
|
||||||
|
|
||||||
include $(TOP)/configure/RELEASE
|
|
||||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
|
|
||||||
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
|
||||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
|
||||||
|
|
||||||
ifneq ($(wildcard $(EPICS_BASE)/configure),)
|
|
||||||
CONFIG=$(EPICS_BASE)/configure
|
|
||||||
else
|
|
||||||
CONFIG=$(EPICS_BASE)/config
|
|
||||||
DIRS += config
|
|
||||||
endif
|
|
||||||
include $(CONFIG)/CONFIG
|
|
||||||
|
|
||||||
INSTALL_LOCATION = $(TOP)
|
|
||||||
ifdef INSTALL_LOCATION_APP
|
|
||||||
INSTALL_LOCATION = $(INSTALL_LOCATION_APP)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef T_A
|
|
||||||
-include $(TOP)/configure/O.$(T_A)/CONFIG_APP_INCLUDE
|
|
||||||
endif
|
|
||||||
|
|
||||||
# dbst based database optimization (default: NO)
|
|
||||||
DB_OPT = NO
|
|
40
configure/CONFIG_SITE
Normal file
40
configure/CONFIG_SITE
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# CONFIG_SITE
|
||||||
|
|
||||||
|
-include $(SUPPORT)/configure/CONFIG_SITE
|
||||||
|
|
||||||
|
# Make any application-specific changes to the EPICS build
|
||||||
|
# configuration variables in this file.
|
||||||
|
#
|
||||||
|
# Host/target specific settings can be specified in files named
|
||||||
|
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||||
|
# CONFIG_SITE.Common.$(T_A)
|
||||||
|
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||||
|
|
||||||
|
# CHECK_RELEASE controls the consistency checking of the support
|
||||||
|
# applications pointed to by the RELEASE* files.
|
||||||
|
# Normally CHECK_RELEASE should be set to YES.
|
||||||
|
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||||
|
# Set CHECK_RELEASE to WARN to perform consistency checking but
|
||||||
|
# continue building even if conflicts are found.
|
||||||
|
CHECK_RELEASE = YES
|
||||||
|
|
||||||
|
# Set this when you only want to compile this application
|
||||||
|
# for a subset of the cross-compiled target architectures
|
||||||
|
# that Base is built for.
|
||||||
|
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32
|
||||||
|
|
||||||
|
# To install files into a location other than $(TOP) define
|
||||||
|
# INSTALL_LOCATION here.
|
||||||
|
#INSTALL_LOCATION=</absolute/path/to/install/top>
|
||||||
|
|
||||||
|
# Set this when the IOC and build host use different paths
|
||||||
|
# to the install location. This may be needed to boot from
|
||||||
|
# a Microsoft FTP server say, or on some NFS configurations.
|
||||||
|
#IOCS_APPL_TOP = </IOC's/absolute/path/to/install/top>
|
||||||
|
|
||||||
|
# These allow developers to override the CONFIG_SITE variable
|
||||||
|
# settings without having to modify the configure/CONFIG_SITE
|
||||||
|
# file itself.
|
||||||
|
-include $(TOP)/../CONFIG_SITE.local
|
||||||
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
-include $(TOP)/configure/CONFIG_SITE.local
|
@ -2,11 +2,7 @@
|
|||||||
|
|
||||||
TOP=..
|
TOP=..
|
||||||
|
|
||||||
include $(TOP)/configure/CONFIG_APP
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
# Set the following to NO to disable consistency checking of
|
|
||||||
# the support applications defined in $(TOP)/configure/RELEASE
|
|
||||||
CHECK_RELEASE = YES
|
|
||||||
|
|
||||||
TARGETS = $(CONFIG_TARGETS)
|
TARGETS = $(CONFIG_TARGETS)
|
||||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||||
|
@ -485,6 +485,12 @@ than 9.
|
|||||||
<p>
|
<p>
|
||||||
This is not a normal "converter", because no user data is converted.
|
This is not a normal "converter", because no user data is converted.
|
||||||
Instead, a checksum is calculated from the input or output.
|
Instead, a checksum is calculated from the input or output.
|
||||||
|
<span class="new">
|
||||||
|
Any pre-processing of input, e.g. by the <a href="#regsub">regsub</a> converter
|
||||||
|
is ignored for the calculation of the checksum.
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
The <em>width</em> field is the byte number from which to start
|
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
|
||||||
@ -594,6 +600,18 @@ In input, the next byte or bytes must match the checksum.
|
|||||||
href="https://en.wikipedia.org/wiki/Longitudinal_redundancy_check">Wikipedia</a>.</dd>
|
href="https://en.wikipedia.org/wiki/Longitudinal_redundancy_check">Wikipedia</a>.</dd>
|
||||||
<dt><code>%<hexlrc></code></dt>
|
<dt><code>%<hexlrc></code></dt>
|
||||||
<dd>One byte. The LRC for the hex digits. (Other characters are ignored.)</dd>
|
<dd>One byte. The LRC for the hex digits. (Other characters are ignored.)</dd>
|
||||||
|
<dt><code>%<leybold></code></dt>
|
||||||
|
<dd>One byte. Used by some Leybold products. 255-bytesum%255 (+32 if result would be <32)</dd>
|
||||||
|
<dt><code>%<brksCryo></code></dt>
|
||||||
|
<dd>One byte. Used by Brooks Cryopumps.</dd>
|
||||||
|
<dt><code>%<CPI></code></dt>
|
||||||
|
<dd>One byte. Used by TRIUMF CPI RF amplifier.</dd>
|
||||||
|
<dt><code>%<bitsum></code> or <code>%<bitsum8></code></dt>
|
||||||
|
<dd>One byte. Number of 1 bits in all characters.</dd>
|
||||||
|
<dt><code>%<bitsum16></code></dt>
|
||||||
|
<dd>Two bytes. Number of 1 bits in all characters.</dd>
|
||||||
|
<dt><code>%<bitsum32></code></dt>
|
||||||
|
<dd>Four bytes. Number of 1 bits in all characters.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<a name="regex"></a>
|
<a name="regex"></a>
|
||||||
@ -699,10 +717,14 @@ However if an empty string is matched, searching advances by 1 character in orde
|
|||||||
avoid matching the same empty string again.</span>
|
avoid matching the same empty string again.</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In input this converter pre-processes data received from the device before
|
In input, this converter pre-processes data received from the device before
|
||||||
following converters read it.
|
following converters read it.
|
||||||
Converters preceding this one will read unmodified input.
|
Converters preceding this one will read unmodified input.
|
||||||
Thus place this converter before those whose input should be pre-processed.
|
Thus place this converter before those whose input should be pre-processed.
|
||||||
|
<span class="new">
|
||||||
|
However, <a href="#chksum">checksum</a> converters will always use the unmodified
|
||||||
|
input as sent by the device because the modified input would not match the checksum.
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In output it post-processes data already formatted by preceding converters
|
In output it post-processes data already formatted by preceding converters
|
||||||
|
22
docs/makepdf
22
docs/makepdf
@ -1,10 +1,22 @@
|
|||||||
#/bin/sh
|
#/bin/sh
|
||||||
if ! wkhtmltopdf -V >/dev/null 2>&1
|
wkhtmltopdf --enable-local-file-access -V >/dev/null 2>&1
|
||||||
then
|
case $? in
|
||||||
|
127)
|
||||||
echo "wkhtmltopdf not installed." >&2
|
echo "wkhtmltopdf not installed." >&2
|
||||||
echo "See https://wkhtmltopdf.org" >&2
|
echo "See https://wkhtmltopdf.org" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
;;
|
||||||
|
0)
|
||||||
|
# have (and need) --enable-local-file-access
|
||||||
|
ENABLE_FILE_ACCESS=--enable-local-file-access
|
||||||
|
;;
|
||||||
|
1)
|
||||||
|
# have no (and need no) --enable-local-file-access
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Some error but I don't know what it means. Try anyway.
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
PAGES="
|
PAGES="
|
||||||
index.html
|
index.html
|
||||||
@ -43,5 +55,5 @@ osinterface.html
|
|||||||
"
|
"
|
||||||
|
|
||||||
rm -f stream.pdf
|
rm -f stream.pdf
|
||||||
wkhtmltopdf --print-media-type --dpi 1200 --zoom 0.85 --page-size Letter \
|
wkhtmltopdf --print-media-type --page-size Letter \
|
||||||
$PAGES stream.pdf
|
$ENABLE_FILE_ACCESS $PAGES stream.pdf
|
||||||
|
@ -85,7 +85,7 @@ Make sure that the <em>asyn</em> library can be found by adding the path to the
|
|||||||
ASYN=/home/epics/asyn4-30
|
ASYN=/home/epics/asyn4-30
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h4>Support for <em>sCalcout</em> record</h4>
|
<h4 id="scalcout">Support for <em>sCalcout</em> record</h4>
|
||||||
<p>
|
<p>
|
||||||
The <a
|
The <a
|
||||||
href="https://htmlpreview.github.io/?https://raw.githubusercontent.com/epics-modules/calc/R3-6-1/documentation/sCalcoutRecord.html"
|
href="https://htmlpreview.github.io/?https://raw.githubusercontent.com/epics-modules/calc/R3-6-1/documentation/sCalcoutRecord.html"
|
||||||
@ -109,7 +109,10 @@ modules. Release R2-8 or newer is recommended.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Support for the <em>sCalcout</em> is optional. <em>StreamDevice</em> works
|
Support for the <em>sCalcout</em> is optional. <em>StreamDevice</em> works
|
||||||
as well without <em>sCalcout</em> or <em>SynApps</em>.
|
as well without <em>sCalcout</em> or <em>SynApps</em>. If your application does
|
||||||
|
not need this record support, you may load <kbd>stream-base.dbd</kbd> instead of
|
||||||
|
<kbd>stream.dbd</kbd>, making it optional to include <em>calc</em> as an
|
||||||
|
application dependency.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h4>Support for regular expression matching</h4>
|
<h4>Support for regular expression matching</h4>
|
||||||
@ -185,13 +188,14 @@ Regular expressions are optional. If you don't want them, you don't need this.
|
|||||||
Go to the <em>StreamDevice</em> directory
|
Go to the <em>StreamDevice</em> directory
|
||||||
and run <code>make</code> (or <code>gmake</code>).
|
and run <code>make</code> (or <code>gmake</code>).
|
||||||
This will create and install the <em>stream</em> library and the
|
This will create and install the <em>stream</em> library and the
|
||||||
<kbd>stream.dbd</kbd> file and an example IOC application.
|
<em>StreamDevice</em> database definition files and an example IOC application.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To use <em>StreamDevice</em>, your own application must be built with the
|
To use <em>StreamDevice</em>, your own application must be built with the
|
||||||
<em>stream</em> and <em>asyn</em> (and optionally <em>pcre</em>) libraries
|
<em>stream</em> and <em>asyn</em> (and optionally <em>pcre</em>) libraries
|
||||||
and must load <kbd>asyn.dbd</kbd> and <kbd>stream.dbd</kbd>.
|
and must load <kbd>asyn.dbd</kbd> and <kbd>stream.dbd</kbd> (or alternatively
|
||||||
|
<kbd>stream-base.dbd</kbd>; see <a href="#scalcout">Support for sCalcout record</a>).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Include the following lines in your application <kbd>Makefile</kbd>:
|
Include the following lines in your application <kbd>Makefile</kbd>:
|
||||||
@ -385,35 +389,45 @@ See the <a href="protocol.html">next chapter</a> for protocol files in depth.
|
|||||||
Generation of debug and error messages is controlled with two shell variables,
|
Generation of debug and error messages is controlled with two shell variables,
|
||||||
<code>streamDebug</code> and <code>streamError</code>.
|
<code>streamDebug</code> and <code>streamError</code>.
|
||||||
Setting those variables to 1 (actually to any number but 0) enables the
|
Setting those variables to 1 (actually to any number but 0) enables the
|
||||||
messages.
|
messages. A few noisy and rarely useful debug messages are only enabled when
|
||||||
|
setting <code>streamDebug</code> to 2.
|
||||||
Per default debug messages are switched off and error messages are switched on.
|
Per default debug messages are switched off and error messages are switched on.
|
||||||
Errors occuring while loading protocol files are always shown.
|
Errors occuring while loading protocol files are always shown.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Warning: Enabling debug messages can create a lot of output!
|
Warning: Enabling debug messages this way can create a lot of output!
|
||||||
At the moment, there is no way to set filters on debug or error messages.
|
Therefore, some limited debugging can be enabled per record, independent of
|
||||||
|
the <code>streamDebug</code> variable using the <code>.TPRO</code> field of
|
||||||
|
the record. Currently, setting <code>.TPRO</code> to 1 or 2 enables some
|
||||||
|
basic information about the processing of a record and its i/o.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Debug output can be redirected to a file with the command
|
Debug output can be redirected to a file with the command
|
||||||
<code>streamSetLogfile("<var>filename</var>")</code>.
|
<code>streamSetLogfile("<var>filename</var>")</code>.
|
||||||
When called without a filename, debug output is directed back
|
If the file already exists, it will be overwritten, not appended to.
|
||||||
to the console.
|
While debug messages are only written to the defined log file, error messages
|
||||||
|
are still printed to <var>stderr</var> too.
|
||||||
|
Calling <code>streamSetLogfile</code> without a filename directs debug output
|
||||||
|
back to <var>stderr</var> and closes the log file.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
By default the debug/error output is set to be colored if the terminal allows
|
By default, error messages to the console are printed in red color if
|
||||||
it but this can be set to always colored or never colored by setting
|
<var>stderr</var> is a tty at startup time, using ANSI color codes. Some
|
||||||
<code>streamDebugColored</code> to 1 or 0 respectively.
|
terminals may not support this properly.
|
||||||
|
The variable <code>streamDebugColored</code> can be set to 0 or 1 to
|
||||||
|
disable or enable colored error messages explicitly.
|
||||||
|
Error messages written to a log file do not use colors.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Error and debug messages are prefixed with a time stamp unless the variable
|
Error and debug messages are prefixed with a time stamp unless the variable
|
||||||
<code>streamMsgTimeStamped</code> is set to 0.
|
<code>streamMsgTimeStamped</code> is set to 0.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
When a device is disconnected StreamDevice can produce many repeated timeout
|
when a device is unresponsive, StreamDevice may produce many repeated timeout
|
||||||
messages. To reduce this logging you can set <code>streamErrorDeadTime</code>
|
messages. To reduce this, you can set <code>streamErrorDeadTime</code>
|
||||||
to an integer number of seconds. When this is set repeated timeout messages
|
to an integer number of seconds. In this case, repeated timeout messages
|
||||||
will not be printed in the specified dead time after the last message. The
|
will not be printed during the specified dead time after the last printed
|
||||||
default dead time is 0, resulting in every message being printed.
|
message. The default dead time is 0, resulting in every message being printed.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Example (vxWorks):</h3>
|
<h3>Example (vxWorks):</h3>
|
||||||
|
179
docs/stream.css
179
docs/stream.css
@ -1,90 +1,104 @@
|
|||||||
a:link {color: #0000D0;}
|
a:link { color: #0000D0; }
|
||||||
a:visited {color: #0000D0;}
|
a:visited { color: #0000D0; }
|
||||||
a:hover {color: #FF0000;}
|
a:hover { color: #FF0000; }
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin-right:1em;
|
margin-right: 1em;
|
||||||
margin-left:15em;
|
margin-left: 15em;
|
||||||
margin-top:75px;
|
margin-top: 75px;
|
||||||
padding-top:1px;
|
padding-top: 1px;
|
||||||
font-family: Helvetica, Arial, sans-serif;
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
background-color:#ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
a[name] { position:relative; top:-11ex;}
|
a[name] {
|
||||||
|
position: relative;
|
||||||
|
top: -11ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, tt, kbd, code {
|
||||||
|
font-size: 95%;
|
||||||
|
font-family: Mono, "Lucida Console", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background-color:#f4f4f4;
|
background-color: #f4f4f4;
|
||||||
padding:1ex;
|
padding: 1ex;
|
||||||
border:1px solid #000000;
|
border: 1px solid #000000;
|
||||||
white-space:pre;
|
white-space: pre;
|
||||||
margin:2ex;
|
margin: 2ex;
|
||||||
page-break-inside:avoid;
|
page-break-inside: avoid;
|
||||||
|
font-size: 85%;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
kbd {
|
kbd {
|
||||||
font-weight:bold;
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: #008000;
|
||||||
}
|
}
|
||||||
|
|
||||||
dt {
|
dt {
|
||||||
margin-top:0.5ex;
|
margin-top: 0.5ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size:250%;
|
font-size: 250%;
|
||||||
margin-top:0;
|
margin-top: 0;
|
||||||
font-style:italic;
|
font-style: italic;
|
||||||
font-weight:bold;
|
font-weight: bold;
|
||||||
font-family:"Times New Roman", serif;
|
font-family: "Times New Roman", Times, serif;
|
||||||
text-align:center;
|
text-align: center;
|
||||||
position:fixed;
|
position: fixed;
|
||||||
top:0;
|
top: 0;
|
||||||
left:0;
|
left: 0;
|
||||||
width:100%;
|
width: 100%;
|
||||||
line-height:190%;
|
line-height: 190%;
|
||||||
background-color:white;
|
background-color: white;
|
||||||
border-width:0;
|
border-width: 0;
|
||||||
border-bottom:3px solid #1b4486;
|
border-bottom: 3px solid #1b4486;
|
||||||
white-space:nowrap;
|
white-space: nowrap;
|
||||||
background-image:url(PSI.png);
|
background-image: url(PSI.png);
|
||||||
background-repeat:no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position:10px 5px;
|
background-position: 10px 5px;
|
||||||
text-shadow:.1em .1em .1em darkgray;
|
text-shadow: .1em .1em .1em lightgray;
|
||||||
box-shadow:0 .3em .1em -.2em darkgray;
|
box-shadow: 0 .3em .1em -.2em darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size:150%;
|
font-size: 140%;
|
||||||
margin-bottom:0.5ex;
|
margin-bottom: 0.5ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size:120%;
|
font-size: 120%;
|
||||||
margin-bottom:0.25ex;
|
margin-bottom: 0.25ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-size:100%;
|
font-size: 100%;
|
||||||
margin-bottom:0.25ex;
|
margin-bottom: 0.25ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
h1, h2, h3, h4 {
|
||||||
page-break-after:avoid;
|
page-break-after: avoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-top:0.75ex;
|
margin-top: 0.75ex;
|
||||||
margin-bottom:0.75ex;
|
margin-bottom: 0.75ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
body h1 + p {
|
body h1 + p {
|
||||||
margin-top:1.5ex;
|
margin-top: 1.5ex;
|
||||||
margin-bottom:0.75ex;
|
margin-bottom: 0.75ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
font-size:75%;
|
font-size: 75%;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
border-top: 1px solid darkgray;
|
border-top: 1px solid darkgray;
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
@ -97,44 +111,40 @@ footer a:only-of-type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size:75%;
|
font-size: 75%;
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 125%;
|
|
||||||
color: #008000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.indent {
|
.indent {
|
||||||
text-indent:-4ex;
|
text-indent: -4ex;
|
||||||
margin-left:4ex;
|
margin-left: 4ex;
|
||||||
margin-top:0.5ex;
|
margin-top: 0.5ex;
|
||||||
text-align:left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
margin-left:1ex;
|
margin-left: 1ex;
|
||||||
margin-right:1ex;
|
margin-right: 1ex;
|
||||||
margin-top:0.5ex;
|
margin-top: 0.5ex;
|
||||||
padding: 0 1ex;
|
padding: 0 1ex;
|
||||||
border: 1px solid black;
|
border: thin solid black;
|
||||||
text-align:left;
|
text-align: left;
|
||||||
background-color:#f0f0f0;
|
background-color: #f0f0f0;
|
||||||
|
page-break-inside: avoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navleft {
|
#navleft {
|
||||||
position:fixed;
|
position: fixed;
|
||||||
left:0;
|
left: 0;
|
||||||
top:0;
|
top: 0;
|
||||||
padding-top:70px;
|
padding-top: 70px;
|
||||||
width:14em;
|
width: 14em;
|
||||||
height:100%;
|
height: 100%;
|
||||||
border-style:solid;
|
border-style: solid;
|
||||||
border-color:black;
|
border-color: black;
|
||||||
border-width:0 1px 0 0;
|
border-width: 0 1px 0 0;
|
||||||
background-color:#e3eaf6;
|
background-color: #e3eaf6;
|
||||||
overflow:hidden;
|
overflow: hidden;
|
||||||
z-index:0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new {
|
.new {
|
||||||
@ -142,17 +152,18 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a[target=ex]:after {
|
a[target=ex]:after {
|
||||||
content:" " url(ex.png);
|
content: " " url(ex.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
a[target=ex]:hover:after {
|
a[target=ex]:hover:after {
|
||||||
content: " " url(exr.png);
|
content: " " url(exr.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
a:link {text-decoration:none;}
|
a:link { text-decoration: none; }
|
||||||
a[target=ex]:after {content:" [" attr(href) "]";}
|
a[target=ex]:after { content:" [" attr(href) "]"; font-size: 75%; }
|
||||||
body {margin:0 4em;}
|
body { margin: 0 4em; }
|
||||||
h1 {position:relative; background-position:0 0;}
|
h1 { position: relative; background-position: 0 0; }
|
||||||
#navleft {display:none;}
|
#navleft { display: none; }
|
||||||
|
footer { display: none; }
|
||||||
}
|
}
|
||||||
|
@ -293,9 +293,10 @@ record (stringout, "$(DEVICE):clean_2") {<br>
|
|||||||
<a name="web"></a>
|
<a name="web"></a>
|
||||||
<h2>I need to read a web page</h2>
|
<h2>I need to read a web page</h2>
|
||||||
<p>
|
<p>
|
||||||
First you have to send a correctly formatted HTML request.
|
First you have to send a correctly formatted HTML header for a GET request.
|
||||||
Note that this request must contain the full URL like
|
Note that this header must contain the full URL like
|
||||||
"http://server/page" and must be terminated with <u>two</u> newlines.
|
"http://server/page" and must be terminated with <u>two</u>
|
||||||
|
CR LF sequences (<code>"\r\n\r\n"</code> or <code>CR LF CR LF</code>).
|
||||||
The server should be the same as in the
|
The server should be the same as in the
|
||||||
<a href="setup.html#sta"><code>drvAsynIPPortConfigure</code></a>
|
<a href="setup.html#sta"><code>drvAsynIPPortConfigure</code></a>
|
||||||
command (if not using a http proxy).
|
command (if not using a http proxy).
|
||||||
@ -313,17 +314,18 @@ Read the title of a web page.
|
|||||||
get_title {<br>
|
get_title {<br>
|
||||||
extrainput = ignore;<br>
|
extrainput = ignore;<br>
|
||||||
replyTimeout = 1000;<br>
|
replyTimeout = 1000;<br>
|
||||||
out "GET http://\$1\n\n";<br>
|
out "GET http://\$1\r\n\r\n";<br>
|
||||||
in "%+.1/(?im)<title>(.*)<\/title>/";<br>
|
in "%+.1/(?im)<title>(.*)<\/title>/";<br>
|
||||||
}
|
}
|
||||||
</code>
|
</code>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Terminate the request with two newlines, either explicit like here
|
Terminate the request with two carriage return + newlines, either explicit
|
||||||
<u>or</u> using an
|
like here <u>or</u> using an
|
||||||
<a href="protocol.html#sysvar"><code>outTerminator</code></a>.
|
<a href="protocol.html#sysvar"><code>outTerminator</code></a>.
|
||||||
The URI (without http:// but including the web server host name)
|
The URI (without http:// but including the web server host name)
|
||||||
is passed as <a href="protocol.html#argvar">argument</a> 1 to <code>\$1</code>.
|
is passed as <a href="protocol.html#argvar">argument</a> 1 to <code>\$1</code>
|
||||||
|
in this example.
|
||||||
Note that web servers may be slow, so allow some
|
Note that web servers may be slow, so allow some
|
||||||
<a href="protocol.html#argvar"><code>replyTimeout</code></a>.
|
<a href="protocol.html#argvar"><code>replyTimeout</code></a>.
|
||||||
</p>
|
</p>
|
||||||
@ -390,7 +392,7 @@ Then we read the number.
|
|||||||
get_title {<br>
|
get_title {<br>
|
||||||
extrainput = ignore;<br>
|
extrainput = ignore;<br>
|
||||||
replyTimeout = 1000;<br>
|
replyTimeout = 1000;<br>
|
||||||
out "GET http://\$1\n\n";<br>
|
out "GET http://\$1\r\n\r\n";<br>
|
||||||
in "%*/Interesting value:/%f more text";<br>
|
in "%*/Interesting value:/%f more text";<br>
|
||||||
}
|
}
|
||||||
</code>
|
</code>
|
||||||
|
170
src/ChecksumConverter.cc
Executable file → Normal file
170
src/ChecksumConverter.cc
Executable file → Normal file
@ -20,39 +20,59 @@
|
|||||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
#if defined(vxWorks)
|
#ifdef vxWorks
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
#if defined(_WRS_VXWORKS_MAJOR) && _WRS_VXWORKS_MAJOR > 6 || (_WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR > 8)
|
/* VxWorks has strncasecmp since version 6
|
||||||
#include <stdint.h>
|
but availability depends on configuration.
|
||||||
#define PRIX32 "X"
|
We cannot know.
|
||||||
#define PRIu32 "u"
|
*/
|
||||||
|
#define NEED_strncasecmp
|
||||||
|
/* VxWorks does not have inttypes.h and uint32_t differs between versions */
|
||||||
|
#if defined(_WRS_VXWORKS_MAJOR) && (_WRS_VXWORKS_MAJOR > 6 || (_WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR >= 9))
|
||||||
|
#define PRIX32 "X"
|
||||||
|
#define PRIu32 "u"
|
||||||
|
#else
|
||||||
|
#define PRIX32 "lX"
|
||||||
|
#define PRIu32 "lu"
|
||||||
|
#endif
|
||||||
|
#define PRIX8 "X"
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER < 1700
|
||||||
|
/* Visual Studio 2010 does not have inttypes.h */
|
||||||
|
#define PRIX32 "X"
|
||||||
|
#define PRIu32 "u"
|
||||||
|
#define PRIX8 "X"
|
||||||
#else
|
#else
|
||||||
#define PRIX32 "lX"
|
#define __STDC_FORMAT_MACROS
|
||||||
#define PRIu32 "lu"
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
#define PRIX8 "X"
|
|
||||||
#define uint_fast8_t uint8_t
|
|
||||||
#define int_fast8_t int8_t
|
|
||||||
#elif defined(_MSC_VER) && _MSC_VER < 1700 /* Visual Studio 2010 does not have inttypes.h */
|
|
||||||
#include <stdint.h>
|
|
||||||
#define PRIX32 "X"
|
|
||||||
#define PRIu32 "u"
|
|
||||||
#define PRIX8 "X"
|
|
||||||
#else
|
|
||||||
#define __STDC_FORMAT_MACROS
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#if defined(vxWorks) || defined(_WIN32) || defined(__rtems__)
|
#include <ctype.h>
|
||||||
// These systems have no strncasecmp
|
#include <stdlib.h>
|
||||||
static int strncasecmp(const char *s1, const char *s2, size_t n)
|
|
||||||
{
|
#if defined(__rtems__)
|
||||||
int r=0;
|
#include <rtems.h>
|
||||||
while (n && (r = toupper(*s1)-toupper(*s2)) == 0) { n--; s1++; s2++; };
|
#if __RTEMS_MAJOR__ < 5
|
||||||
return r;
|
/* RTEMS has strncasecmp since version 5 */
|
||||||
|
#define NEED_strncasecmp
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* Windows strncasecmp has a different name. */
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEED_strncasecmp
|
||||||
|
// Have no strncasecmp but avoid compiler errors in case it exists in future versions
|
||||||
|
extern "C" {
|
||||||
|
static int mystrncasecmp(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#define strncasecmp mystrncasecmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "StreamFormatConverter.h"
|
#include "StreamFormatConverter.h"
|
||||||
@ -83,6 +103,33 @@ static uint32_t xor7(const uint8_t* data, size_t len, uint32_t sum)
|
|||||||
return xor8(data, len, sum) & 0x7F;
|
return xor8(data, len, sum) & 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t bitsum(const uint8_t* data, size_t len, uint32_t sum)
|
||||||
|
{
|
||||||
|
// number of set bits in each byte
|
||||||
|
const uint8_t table[256] = {
|
||||||
|
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
|
||||||
|
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||||
|
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||||
|
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||||
|
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||||
|
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||||
|
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||||
|
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||||
|
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||||
|
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||||
|
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||||
|
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||||
|
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||||
|
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||||
|
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||||
|
4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
sum += table[*data++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t crc_0x07(const uint8_t* data, size_t len, uint32_t crc)
|
static uint32_t crc_0x07(const uint8_t* data, size_t len, uint32_t crc)
|
||||||
{
|
{
|
||||||
// x^8 + x^2 + x^1 + x^0 (0x07)
|
// x^8 + x^2 + x^1 + x^0 (0x07)
|
||||||
@ -501,6 +548,7 @@ static uint32_t leybold(const uint8_t* data, size_t len, uint32_t sum)
|
|||||||
sum += *data++;
|
sum += *data++;
|
||||||
}
|
}
|
||||||
sum = ~sum;
|
sum = ~sum;
|
||||||
|
sum &= 0xff;
|
||||||
if (sum < 32) sum+=32;
|
if (sum < 32) sum+=32;
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
@ -568,6 +616,16 @@ static uint32_t hexlrc(const uint8_t* data, size_t len, uint32_t sum)
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checksum used by Spellman High Voltage Supplies MPS
|
||||||
|
static uint32_t hv_mps(const uint8_t* data, size_t len, uint32_t sum)
|
||||||
|
{
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
sum += *data++;
|
||||||
|
}
|
||||||
|
return (~sum & 0x7F) | 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
struct checksum
|
struct checksum
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
@ -612,20 +670,25 @@ static checksum checksumMap[] =
|
|||||||
{"leybold", leybold, 0x00, 0x00, 1}, // 0x22
|
{"leybold", leybold, 0x00, 0x00, 1}, // 0x22
|
||||||
{"brksCryo",brksCryo, 0x00, 0x00, 1}, // 0x4A
|
{"brksCryo",brksCryo, 0x00, 0x00, 1}, // 0x4A
|
||||||
{"lrc", lrc, 0x00, 0x00, 1}, // 0x23
|
{"lrc", lrc, 0x00, 0x00, 1}, // 0x23
|
||||||
{"hexlrc", hexlrc, 0x00, 0x00, 1} // 0xA7
|
{"hexlrc", hexlrc, 0x00, 0x00, 1}, // 0xA7
|
||||||
|
{"bitsum", bitsum, 0x00, 0x00, 1}, // 0x21
|
||||||
|
{"bitsum8", bitsum, 0x00, 0x00, 1}, // 0x21
|
||||||
|
{"bitsum16",bitsum, 0x0000, 0x0000, 2}, // 0x0021
|
||||||
|
{"bitsum32",bitsum, 0x00000000, 0x00000000, 4}, // 0x00000021
|
||||||
|
{"hv_mps", hv_mps, 0xFF, 0x00, 1} // 0x63
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
static uint32_t mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||||
|
|
||||||
class ChecksumConverter : public StreamFormatConverter
|
class ChecksumConverter : public StreamFormatConverter
|
||||||
{
|
{
|
||||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
|
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool scanFormat);
|
||||||
bool printPseudo(const StreamFormat&, StreamBuffer&);
|
bool printPseudo(const StreamFormat&, StreamBuffer&);
|
||||||
ssize_t scanPseudo(const StreamFormat&, StreamBuffer&, size_t& cursor);
|
ssize_t scanPseudo(const StreamFormat&, StreamBuffer&, size_t& cursor);
|
||||||
};
|
};
|
||||||
|
|
||||||
int ChecksumConverter::
|
int ChecksumConverter::
|
||||||
parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool scanFormat)
|
||||||
{
|
{
|
||||||
const char* p = strchr(source, '>');
|
const char* p = strchr(source, '>');
|
||||||
if (!p)
|
if (!p)
|
||||||
@ -679,7 +742,7 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
|||||||
info.append(&xorout, sizeof(xorout));
|
info.append(&xorout, sizeof(xorout));
|
||||||
info.append(fnum);
|
info.append(fnum);
|
||||||
source = p+1;
|
source = p+1;
|
||||||
return pseudo_format;
|
return scanFormat ? needs_original_format : pseudo_format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,11 +757,16 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
|||||||
const char* info = format.info;
|
const char* info = format.info;
|
||||||
uint32_t init = extract<uint32_t>(info);
|
uint32_t init = extract<uint32_t>(info);
|
||||||
uint32_t xorout = extract<uint32_t>(info);
|
uint32_t xorout = extract<uint32_t>(info);
|
||||||
uint_fast8_t fnum = extract<uint8_t>(info);
|
uint8_t fnum = extract<uint8_t>(info);
|
||||||
|
|
||||||
size_t start = format.width;
|
size_t start = format.width;
|
||||||
size_t length = output.length()-format.width;
|
size_t length = output.length();
|
||||||
if (format.prec > 0) length -= format.prec;
|
if (length >= start) length -= start;
|
||||||
|
else length = 0;
|
||||||
|
if (format.prec > 0) {
|
||||||
|
if (length >= (size_t)format.prec) length -= format.prec;
|
||||||
|
else length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
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)());
|
||||||
@ -710,8 +778,8 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
|||||||
debug("ChecksumConverter %s: output checksum is 0x%" PRIX32 "\n",
|
debug("ChecksumConverter %s: output checksum is 0x%" PRIX32 "\n",
|
||||||
checksumMap[fnum].name, sum);
|
checksumMap[fnum].name, sum);
|
||||||
|
|
||||||
uint_fast8_t i;
|
uint8_t i;
|
||||||
uint_fast8_t outchar;
|
uint8_t outchar;
|
||||||
|
|
||||||
if (format.flags & sign_flag) // decimal
|
if (format.flags & sign_flag) // decimal
|
||||||
{
|
{
|
||||||
@ -770,15 +838,19 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
|
|||||||
uint32_t init = extract<uint32_t>(info);
|
uint32_t init = extract<uint32_t>(info);
|
||||||
uint32_t xorout = extract<uint32_t>(info);
|
uint32_t xorout = extract<uint32_t>(info);
|
||||||
size_t start = format.width;
|
size_t start = format.width;
|
||||||
uint_fast8_t fnum = extract<uint8_t>(info);
|
uint8_t fnum = extract<uint8_t>(info);
|
||||||
size_t length = cursor-format.width;
|
size_t length = cursor;
|
||||||
|
if (length >= start) length -= start;
|
||||||
|
else length = 0;
|
||||||
|
if (format.prec > 0) {
|
||||||
|
if (length >= (size_t)format.prec) length -= format.prec;
|
||||||
|
else length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
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)());
|
||||||
|
|
||||||
uint_fast8_t nDigits =
|
uint8_t nDigits =
|
||||||
// get number of decimal digits from number of bytes: ceil(bytes*2.5)
|
// 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 & sign_flag ? (checksumMap[fnum].bytes + 1) * 25 / 10 - 2 :
|
||||||
format.flags & (zero_flag|left_flag) ? 2 * checksumMap[fnum].bytes :
|
format.flags & (zero_flag|left_flag) ? 2 * checksumMap[fnum].bytes :
|
||||||
@ -787,8 +859,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
|
|||||||
|
|
||||||
if ((ssize_t)( input.length() - cursor ) < expectedLength)
|
if ((ssize_t)( input.length() - cursor ) < expectedLength)
|
||||||
{
|
{
|
||||||
debug("ChecksumConverter %s: Input '%s' too short for checksum\n",
|
debug("ChecksumConverter %s: Input '%s' too short (%zu-%zu<%zu) for checksum\n",
|
||||||
checksumMap[fnum].name, input.expand(cursor)());
|
checksumMap[fnum].name, input.expand(cursor)(), input.length(), cursor, expectedLength);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,7 +893,7 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
|
|||||||
else
|
else
|
||||||
if (format.flags & alt_flag) // lsb first (little endian)
|
if (format.flags & alt_flag) // lsb first (little endian)
|
||||||
{
|
{
|
||||||
uint_fast8_t i;
|
uint8_t i;
|
||||||
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
|
||||||
@ -864,8 +936,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
|
|||||||
}
|
}
|
||||||
else // msb first (big endian)
|
else // msb first (big endian)
|
||||||
{
|
{
|
||||||
int_fast8_t i;
|
int8_t i;
|
||||||
uint_fast8_t j;
|
uint8_t j;
|
||||||
for (i = checksumMap[fnum].bytes-1, j = 0; i >= 0; i--, j++)
|
for (i = checksumMap[fnum].bytes-1, j = 0; i >= 0; i--, j++)
|
||||||
{
|
{
|
||||||
if (format.flags & zero_flag) // ASCII
|
if (format.flags & zero_flag) // ASCII
|
||||||
|
39
src/Makefile
39
src/Makefile
@ -27,12 +27,12 @@ include $(TOP)/configure/CONFIG
|
|||||||
-include CONFIG_STREAM
|
-include CONFIG_STREAM
|
||||||
-include ../CONFIG_STREAM
|
-include ../CONFIG_STREAM
|
||||||
|
|
||||||
LIBRARY_DEFAULT = stream
|
LIBRARY_IOC = stream
|
||||||
|
|
||||||
DBD += $(LIBRARY_DEFAULT).dbd
|
DBD += stream.dbd
|
||||||
DBD += $(LIBRARY_DEFAULT)-base.dbd
|
DBD += stream-base.dbd
|
||||||
ifdef CALC
|
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||||
DBD += $(LIBRARY_DEFAULT)-scalcout.dbd
|
DBD += stream-scalcout.dbd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef ASYN
|
ifdef ASYN
|
||||||
@ -42,7 +42,7 @@ $(warning Asyn not included! Didn't you set ASYN in your RELEASE file?)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(LOADABLE_MODULE),YES)
|
ifeq ($(LOADABLE_MODULE),YES)
|
||||||
SRCS += $(LIBRARY_DEFAULT)_registerRecordDeviceDriver.cpp
|
SRCS += stream_registerRecordDeviceDriver.cpp
|
||||||
endif
|
endif
|
||||||
SRCS += $(BUSSES:%=%Interface.cc)
|
SRCS += $(BUSSES:%=%Interface.cc)
|
||||||
SRCS += $(FORMATS:%=%Converter.cc)
|
SRCS += $(FORMATS:%=%Converter.cc)
|
||||||
@ -60,6 +60,9 @@ ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
|||||||
LIB_SYS_LIBS_DEFAULT += pcre
|
LIB_SYS_LIBS_DEFAULT += pcre
|
||||||
LIB_SYS_LIBS_WIN32 += $(PCRE_LIB)\\pcre
|
LIB_SYS_LIBS_WIN32 += $(PCRE_LIB)\\pcre
|
||||||
SHRLIB_DEPLIB_DIRS += $(PCRE_LIB)
|
SHRLIB_DEPLIB_DIRS += $(PCRE_LIB)
|
||||||
|
ifdef ENABLE_STATIC
|
||||||
|
CPPFLAGS += -DPCRE_STATIC
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -98,28 +101,28 @@ streamReferences: ../CONFIG_STREAM
|
|||||||
$(PERL) ../makeref.pl Converter $(FORMATS) >> $@
|
$(PERL) ../makeref.pl Converter $(FORMATS) >> $@
|
||||||
|
|
||||||
# create stream-base.dbd from all RECORDTYPES except scalcout record
|
# create stream-base.dbd from all RECORDTYPES except scalcout record
|
||||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT)-base.dbd: ../CONFIG_STREAM
|
$(COMMON_DIR)/stream-base.dbd: ../CONFIG_STREAM
|
||||||
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(filter-out scalcout, $(RECORDTYPES)) > $@
|
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(filter-out scalcout, $(RECORDTYPES)) > $@
|
||||||
|
|
||||||
$(LIBRARY_DEFAULT)-base.dbd$(DEP): ../CONFIG_STREAM
|
stream-base.dbd$(DEP): ../CONFIG_STREAM
|
||||||
echo $(LIBRARY_DEFAULT)-base.dbd: $< > $@
|
echo stream-base.dbd: $< > $@
|
||||||
|
|
||||||
STREAM_DBD_FILES = $(LIBRARY_DEFAULT)-base.dbd
|
STREAM_DBD_FILES = stream-base.dbd
|
||||||
|
|
||||||
ifdef CALC
|
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||||
# create stream-scalcout.dbd for scalcout record
|
# create stream-scalcout.dbd for scalcout record
|
||||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT)-scalcout.dbd: ../CONFIG_STREAM
|
$(COMMON_DIR)/stream-scalcout.dbd: ../CONFIG_STREAM
|
||||||
$(PERL) ../makedbd.pl --rec-only scalcout > $@
|
$(PERL) ../makedbd.pl --rec-only scalcout > $@
|
||||||
|
|
||||||
$(LIBRARY_DEFAULT)-scalcout.dbd$(DEP): ../CONFIG_STREAM
|
stream-scalcout.dbd$(DEP): ../CONFIG_STREAM
|
||||||
echo $(LIBRARY_DEFAULT)-scalcout.dbd: $< > $@
|
echo stream-scalcout.dbd: $< > $@
|
||||||
|
|
||||||
STREAM_DBD_FILES += $(LIBRARY_DEFAULT)-scalcout.dbd
|
STREAM_DBD_FILES += stream-scalcout.dbd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# create stream.dbd for all record types
|
# create stream.dbd for all record types
|
||||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM
|
$(COMMON_DIR)/stream.dbd: ../CONFIG_STREAM
|
||||||
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(RECORDTYPES) > $@
|
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(RECORDTYPES) > $@
|
||||||
|
|
||||||
$(LIBRARY_DEFAULT).dbd$(DEP): ../CONFIG_STREAM
|
stream.dbd$(DEP): ../CONFIG_STREAM
|
||||||
echo $(LIBRARY_DEFAULT).dbd: $< > $@
|
echo stream.dbd: $< > $@
|
||||||
|
@ -102,7 +102,7 @@ init(const void* s, ssize_t minsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// How the buffer looks like:
|
// How the buffer looks like:
|
||||||
// |----free-----|####used####|--------00--------|
|
// |----junk-----|####used####|--------00--------|
|
||||||
///|<--- offs -->|<-- len --->|<- cap-offs-len ->|
|
///|<--- offs -->|<-- len --->|<- cap-offs-len ->|
|
||||||
// 0 offs offs+len cap
|
// 0 offs offs+len cap
|
||||||
// |<-------------- minsize --------------->
|
// |<-------------- minsize --------------->
|
||||||
@ -254,39 +254,71 @@ replace(ssize_t remstart, ssize_t remlen, const void* ins, ssize_t inslen)
|
|||||||
if (inslen < 0) inslen = 0;
|
if (inslen < 0) inslen = 0;
|
||||||
size_t remend = remstart+remlen;
|
size_t remend = remstart+remlen;
|
||||||
size_t newlen = len+inslen-remlen;
|
size_t newlen = len+inslen-remlen;
|
||||||
|
|
||||||
|
// How the buffer looks like before and after:
|
||||||
|
// |---junk---|##content_start##|/////////remove_this////////|##content_end##|0000|
|
||||||
|
// |<- offs ->|<-- remstart --->|<--------- remlen --------->| | |
|
||||||
|
// | |<--------------------- len ---------------------------------->| |
|
||||||
|
// 0 offs offs+remstart offs+remend offs+len cap
|
||||||
|
//
|
||||||
|
// If content size stays the same, no need to move old content:
|
||||||
|
// |---junk---|##content_start##|+++++++inserted_text++++++++|##content_end##|0000|
|
||||||
|
// |<----- inslen==remlen ----->| newlen==len
|
||||||
|
//
|
||||||
|
// If content shrinks (need to clear end of buffer): |< clear this >|
|
||||||
|
// |---junk---|##content_start##|inserted_text|##content_end##|00000000000000|0000|
|
||||||
|
// 0 offs |<- inslen -->| |< len-newlen >|
|
||||||
|
// offs+newlen offs+len
|
||||||
|
//
|
||||||
|
// If content grows but still fits (make sure to keep at least one 0 byte at end):
|
||||||
|
// |---junk---|##content_start##|++++++++inserted_text++++++++++|##content_end##|0|
|
||||||
|
// |<- offs ->|<--------------------- newlen ---------------------------------->| |
|
||||||
|
// 0 offs offs+newlen<cap
|
||||||
|
//
|
||||||
|
// If content would overflow, moving to offs 0 may help:
|
||||||
|
// May need to clear end if newlen < offs+len: |<clear>|
|
||||||
|
// |##content_start##|++++++++inserted_text++++++++++|##content_end##|0000000|0000|
|
||||||
|
// |<--------------------- newlen ---------------------------------->| |
|
||||||
|
// newlen offs+len
|
||||||
|
//
|
||||||
|
// Otherwise we need to copy to a new buffer.
|
||||||
|
|
||||||
|
|
||||||
if (cap <= newlen)
|
if (cap <= newlen)
|
||||||
{
|
{
|
||||||
// buffer too short
|
// buffer too short, copy to new buffer
|
||||||
size_t 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); // copy content start
|
||||||
memcpy(newbuffer+remstart, ins, inslen);
|
memcpy(newbuffer+remstart, ins, inslen); // insert
|
||||||
memcpy(newbuffer+remstart+inslen, buffer+offs+remend, len-remend);
|
memcpy(newbuffer+remstart+inslen, buffer+offs+remend, len-remend); // copy content end
|
||||||
memset(newbuffer+newlen, 0, newcap-newlen);
|
memset(newbuffer+newlen, 0, newcap-newlen); // clear buffer end
|
||||||
if (buffer != local)
|
if (buffer != local)
|
||||||
{
|
delete[] buffer;
|
||||||
delete [] buffer;
|
|
||||||
}
|
|
||||||
buffer = newbuffer;
|
buffer = newbuffer;
|
||||||
cap = newcap;
|
cap = newcap;
|
||||||
offs = 0;
|
offs = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (newlen+offs<=cap)
|
if (offs+newlen < cap)
|
||||||
{
|
{
|
||||||
// move to start of buffer
|
// modified content still fits with current offs, just move content end
|
||||||
memmove(buffer+offs+remstart+inslen, buffer+offs+remend, len-remend);
|
if (newlen != len)
|
||||||
memcpy(buffer+offs+remstart, ins, inslen);
|
memmove(buffer+offs+remstart+inslen, buffer+offs+remend, len-remend); // move old content end if necessary
|
||||||
if (newlen<len) memset(buffer+offs+newlen, 0, len-newlen);
|
memcpy(buffer+offs+remstart, ins, inslen); // insert before
|
||||||
|
if (newlen < len)
|
||||||
|
memset(buffer+offs+newlen, 0, len-newlen); // clear buffer end if content shrunk
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memmove(buffer,buffer+offs,remstart);
|
// move content to start of buffer
|
||||||
memmove(buffer+remstart+inslen, buffer+offs+remend, len-remend);
|
memmove(buffer, buffer+offs, remstart); // move content start to 0 offs
|
||||||
memcpy(buffer+remstart, ins, inslen);
|
memmove(buffer+remstart+inslen, buffer+offs+remend, len-remend); // move content end
|
||||||
if (newlen<len) memset(buffer+newlen, 0, len-newlen);
|
memcpy(buffer+remstart, ins, inslen); // insert in between
|
||||||
|
if (newlen < offs+len)
|
||||||
|
memset(buffer+newlen, 0, offs+len-newlen); // clear buffer end if necessary
|
||||||
offs = 0;
|
offs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,7 +390,7 @@ dump() const
|
|||||||
StreamBuffer result;
|
StreamBuffer result;
|
||||||
size_t i;
|
size_t i;
|
||||||
result.print("%" P "d,%" P "d,%" P "d:", offs, len, cap);
|
result.print("%" P "d,%" P "d,%" P "d:", offs, len, cap);
|
||||||
if (offs) result.print(ansiEscape(ANSI_BG_WHITE));
|
if (offs) result.print("%s", ansiEscape(ANSI_BG_WHITE));
|
||||||
char c;
|
char c;
|
||||||
for (i = 0; i < cap; i++)
|
for (i = 0; i < cap; i++)
|
||||||
{
|
{
|
||||||
|
@ -603,6 +603,7 @@ evalOut()
|
|||||||
// flush all unread input
|
// flush all unread input
|
||||||
unparsedInput = false;
|
unparsedInput = false;
|
||||||
inputBuffer.clear();
|
inputBuffer.clear();
|
||||||
|
inputLine.clear();
|
||||||
if (!formatOutput())
|
if (!formatOutput())
|
||||||
{
|
{
|
||||||
finishProtocol(FormatError);
|
finishProtocol(FormatError);
|
||||||
@ -1011,6 +1012,7 @@ readCallback(StreamIoStatus status,
|
|||||||
finishProtocol(Fault);
|
finishProtocol(Fault);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
inputHook(input, size);
|
||||||
inputBuffer.append(input, size);
|
inputBuffer.append(input, size);
|
||||||
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %" Z "u\n",
|
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %" Z "u\n",
|
||||||
name(), inputBuffer.expand()(), inputBuffer.length());
|
name(), inputBuffer.expand()(), inputBuffer.length());
|
||||||
@ -1130,7 +1132,7 @@ readCallback(StreamIoStatus status,
|
|||||||
inputBuffer.remove(end + termlen);
|
inputBuffer.remove(end + termlen);
|
||||||
if (inputBuffer)
|
if (inputBuffer)
|
||||||
{
|
{
|
||||||
debug("StreamCore::readCallback(%s) unpared input left: \"%s\"\n",
|
debug("StreamCore::readCallback(%s) unparsed input left: \"%s\"\n",
|
||||||
name(), inputBuffer.expand()());
|
name(), inputBuffer.expand()());
|
||||||
unparsedInput = true;
|
unparsedInput = true;
|
||||||
}
|
}
|
||||||
@ -1182,6 +1184,7 @@ matchInput()
|
|||||||
char command;
|
char command;
|
||||||
const char* fieldName = NULL;
|
const char* fieldName = NULL;
|
||||||
StreamBuffer formatstring;
|
StreamBuffer formatstring;
|
||||||
|
ssize_t delta = 0;
|
||||||
|
|
||||||
consumedInput = 0;
|
consumedInput = 0;
|
||||||
|
|
||||||
@ -1216,7 +1219,7 @@ normal_format:
|
|||||||
debug("StreamCore::matchInput(%s): format = \"%%%s\"\n",
|
debug("StreamCore::matchInput(%s): format = \"%%%s\"\n",
|
||||||
name(), formatstring());
|
name(), formatstring());
|
||||||
|
|
||||||
if (fmt.flags & skip_flag || fmt.type == pseudo_format)
|
if (fmt.flags & skip_flag || fmt.type == pseudo_format || fmt.type == needs_original_format)
|
||||||
{
|
{
|
||||||
long ldummy;
|
long ldummy;
|
||||||
double ddummy;
|
double ddummy;
|
||||||
@ -1238,9 +1241,20 @@ normal_format:
|
|||||||
scanString(fmt, inputLine(consumedInput), NULL, size);
|
scanString(fmt, inputLine(consumedInput), NULL, size);
|
||||||
break;
|
break;
|
||||||
case pseudo_format:
|
case pseudo_format:
|
||||||
// pass complete input
|
// pass complete input line for scan and/or re-write
|
||||||
|
size = inputLine.length();
|
||||||
consumed = StreamFormatConverter::find(fmt.conv)->
|
consumed = StreamFormatConverter::find(fmt.conv)->
|
||||||
scanPseudo(fmt, inputLine, consumedInput);
|
scanPseudo(fmt, inputLine, consumedInput);
|
||||||
|
delta += inputLine.length() - size; // track length changes
|
||||||
|
debug("after rewrite delta=%zi\n", delta);
|
||||||
|
break;
|
||||||
|
case needs_original_format:
|
||||||
|
// pass original input with adjusted current position
|
||||||
|
debug("before checksum delta=%zi\n", delta);
|
||||||
|
consumedInput -= delta; // correct for length changes
|
||||||
|
consumed = StreamFormatConverter::find(fmt.conv)->
|
||||||
|
scanPseudo(fmt, inputBuffer, consumedInput);
|
||||||
|
consumedInput += delta;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("INTERNAL ERROR (%s): illegal format.type 0x%02x\n",
|
error("INTERNAL ERROR (%s): illegal format.type 0x%02x\n",
|
||||||
|
@ -219,6 +219,7 @@ protected:
|
|||||||
|
|
||||||
// virtual methods
|
// virtual methods
|
||||||
virtual void protocolStartHook() {}
|
virtual void protocolStartHook() {}
|
||||||
|
virtual void inputHook(const void* input, size_t size) {};
|
||||||
virtual void protocolFinishHook(ProtocolResult) {}
|
virtual void protocolFinishHook(ProtocolResult) {}
|
||||||
virtual void startTimer(unsigned long timeout) = 0;
|
virtual void startTimer(unsigned long timeout) = 0;
|
||||||
virtual bool formatValue(const StreamFormat&, const void* fieldaddress) = 0;
|
virtual bool formatValue(const StreamFormat&, const void* fieldaddress) = 0;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined(vxWorks)
|
#if defined(vxWorks)
|
||||||
#include <symLib.h>
|
#include <symLib.h>
|
||||||
@ -136,6 +137,7 @@ class Stream : protected StreamCore
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// StreamCore methods
|
// StreamCore methods
|
||||||
|
void inputHook(const void* input, size_t size);
|
||||||
void protocolFinishHook(ProtocolResult);
|
void protocolFinishHook(ProtocolResult);
|
||||||
void startTimer(unsigned long timeout);
|
void startTimer(unsigned long timeout);
|
||||||
bool getFieldAddress(const char* fieldname,
|
bool getFieldAddress(const char* fieldname,
|
||||||
@ -435,6 +437,14 @@ long streamReportRecord(const char* recordname)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_WIN64)
|
||||||
|
static const char* epicsThreadGetNameSelfWrapper(void)
|
||||||
|
{
|
||||||
|
return epicsThreadGetNameSelf();
|
||||||
|
}
|
||||||
|
#define epicsThreadGetNameSelf epicsThreadGetNameSelfWrapper
|
||||||
|
#endif
|
||||||
|
|
||||||
long Stream::
|
long Stream::
|
||||||
drvInit()
|
drvInit()
|
||||||
{
|
{
|
||||||
@ -925,6 +935,10 @@ process()
|
|||||||
debug("Stream::process(%s) start\n", name());
|
debug("Stream::process(%s) start\n", name());
|
||||||
status = NO_ALARM;
|
status = NO_ALARM;
|
||||||
convert = OK;
|
convert = OK;
|
||||||
|
if (record->tpro)
|
||||||
|
{
|
||||||
|
StreamDebugClass(record->name).print("start protocol '%s'\n", protocolname());
|
||||||
|
}
|
||||||
if (!startProtocol(record->proc == 2 ? StreamCore::StartInit : StreamCore::StartNormal))
|
if (!startProtocol(record->proc == 2 ? StreamCore::StartInit : StreamCore::StartNormal))
|
||||||
{
|
{
|
||||||
debug("Stream::process(%s): could not start %sprotocol, status=%s (%d)\n",
|
debug("Stream::process(%s): could not start %sprotocol, status=%s (%d)\n",
|
||||||
@ -1019,11 +1033,26 @@ expire(const epicsTime&)
|
|||||||
|
|
||||||
// StreamCore virtual methods ////////////////////////////////////////////
|
// StreamCore virtual methods ////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Stream::
|
||||||
|
inputHook(const void* input, size_t size)
|
||||||
|
{
|
||||||
|
if (record->tpro > 1)
|
||||||
|
{
|
||||||
|
StreamDebugClass(record->name).print("received \"%s\"\n",
|
||||||
|
StreamBuffer(input, size).expand()());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Stream::
|
void Stream::
|
||||||
protocolFinishHook(ProtocolResult result)
|
protocolFinishHook(ProtocolResult result)
|
||||||
{
|
{
|
||||||
debug("Stream::protocolFinishHook(%s, %s)\n",
|
debug("Stream::protocolFinishHook(%s, %s)\n",
|
||||||
name(), toStr(result));
|
name(), toStr(result));
|
||||||
|
if (record->tpro)
|
||||||
|
{
|
||||||
|
StreamDebugClass(record->name).print("%s. out=\"%s\", in=\"%s\"\n",
|
||||||
|
toStr(result), outputLine.expand()(), inputLine.expand()());
|
||||||
|
}
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
case Success:
|
case Success:
|
||||||
|
@ -171,8 +171,6 @@ print(const char* fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
const char* f = strrchr(file, '/');
|
|
||||||
if (f) f++; else f = file;
|
|
||||||
FILE* fp = StreamDebugFile ? StreamDebugFile : stderr;
|
FILE* fp = StreamDebugFile ? StreamDebugFile : stderr;
|
||||||
if (streamMsgTimeStamped)
|
if (streamMsgTimeStamped)
|
||||||
{
|
{
|
||||||
@ -184,7 +182,13 @@ print(const char* fmt, ...)
|
|||||||
{
|
{
|
||||||
fprintf(fp, "%s ", StreamGetThreadNameFunction());
|
fprintf(fp, "%s ", StreamGetThreadNameFunction());
|
||||||
}
|
}
|
||||||
fprintf(fp, "%s:%d: ", f, line);
|
if (file) {
|
||||||
|
const char* f = strrchr(file, '/');
|
||||||
|
if (f) f++; else f = file;
|
||||||
|
fprintf(fp, "%s:", f);
|
||||||
|
if (line) fprintf(fp, "%d:", line);
|
||||||
|
fprintf(fp, " ");
|
||||||
|
}
|
||||||
vfprintf(fp, fmt, args);
|
vfprintf(fp, fmt, args);
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
@ -56,19 +56,15 @@ class StreamDebugClass
|
|||||||
const char* file;
|
const char* file;
|
||||||
int line;
|
int line;
|
||||||
public:
|
public:
|
||||||
StreamDebugClass(const char* file, int line) :
|
StreamDebugClass(const char* file = NULL, int line = 0) :
|
||||||
file(file), line(line) {}
|
file(file), line(line) {}
|
||||||
int print(const char* fmt, ...)
|
int print(const char* fmt, ...)
|
||||||
__attribute__((__format__(__printf__,2,3)));
|
__attribute__((__format__(__printf__,2,3)));
|
||||||
};
|
};
|
||||||
|
|
||||||
inline StreamDebugClass
|
|
||||||
StreamDebugObject(const char* file, int line)
|
|
||||||
{ return StreamDebugClass(file, line); }
|
|
||||||
|
|
||||||
#define error StreamError
|
#define error StreamError
|
||||||
#define debug (!streamDebug)?0:StreamDebugObject(__FILE__,__LINE__).print
|
#define debug (!streamDebug)?0:StreamDebugClass(__FILE__,__LINE__).print
|
||||||
#define debug2 (streamDebug<2)?0:StreamDebugObject(__FILE__,__LINE__).print
|
#define debug2 (streamDebug<2)?0:StreamDebugClass(__FILE__,__LINE__).print
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ANSI escape sequences for terminal output
|
* ANSI escape sequences for terminal output
|
||||||
|
@ -42,7 +42,8 @@ typedef enum {
|
|||||||
enum_format,
|
enum_format,
|
||||||
double_format,
|
double_format,
|
||||||
string_format,
|
string_format,
|
||||||
pseudo_format
|
pseudo_format,
|
||||||
|
needs_original_format
|
||||||
} StreamFormatType;
|
} StreamFormatType;
|
||||||
|
|
||||||
extern const char* StreamFormatTypeStr[];
|
extern const char* StreamFormatTypeStr[];
|
||||||
|
@ -43,7 +43,7 @@ static long readData(dbCommon *record, format_t *format)
|
|||||||
strncmp(so->oval, so->val, sizeof(so->val)))
|
strncmp(so->oval, so->val, sizeof(so->val)))
|
||||||
{
|
{
|
||||||
monitor_mask |= DBE_VALUE | DBE_LOG;
|
monitor_mask |= DBE_VALUE | DBE_LOG;
|
||||||
strncpy(so->oval, so->val, sizeof(so->val));
|
strncpy(so->oval, so->val, sizeof(so->oval));
|
||||||
}
|
}
|
||||||
if (monitor_mask)
|
if (monitor_mask)
|
||||||
db_post_events(record, so->val, monitor_mask);
|
db_post_events(record, so->val, monitor_mask);
|
||||||
|
@ -42,10 +42,12 @@ PROD_SRCS_vxWorks = -nil-
|
|||||||
PROD_LIBS = stream
|
PROD_LIBS = stream
|
||||||
|
|
||||||
ifdef ASYN
|
ifdef ASYN
|
||||||
# edit asynRegistrars.dbd if necessary
|
streamApp_DBD += asyn.dbd
|
||||||
streamApp_DBD += asynRegistrars.dbd
|
streamApp_DBD += drvAsynIPPort.dbd
|
||||||
# add asynRecord.dbd if you like
|
streamApp_DBD += drvAsynSerialPort.dbd
|
||||||
streamApp_DBD += asynRecord.dbd
|
# vxi11 support is optional in recent asyn versions
|
||||||
|
#streamApp_DBD += drvVxi11.dbd
|
||||||
|
|
||||||
PROD_LIBS += asyn
|
PROD_LIBS += asyn
|
||||||
# cygwin needs separate RPC library for asyn
|
# cygwin needs separate RPC library for asyn
|
||||||
PROD_SYS_LIBS_cygwin32 += $(CYGWIN_RPC_LIB)
|
PROD_SYS_LIBS_cygwin32 += $(CYGWIN_RPC_LIB)
|
||||||
@ -78,6 +80,13 @@ endif
|
|||||||
|
|
||||||
PROD_LIBS += $(EPICS_BASE_IOC_LIBS)
|
PROD_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||||
|
|
||||||
|
# Some linux systems moved RPC related symbols to libtirpc
|
||||||
|
# Define TIRPC in configure/CONFIG_SITE in this case
|
||||||
|
ifeq ($(TIRPC),YES)
|
||||||
|
USR_INCLUDES_Linux += -I/usr/include/tirpc
|
||||||
|
PROD_SYS_LIBS_DEFAULT += tirpc
|
||||||
|
endif
|
||||||
|
|
||||||
# switch off annoying rset warnings in 3.16+
|
# switch off annoying rset warnings in 3.16+
|
||||||
CPPFLAGS += -DUSE_TYPED_RSET
|
CPPFLAGS += -DUSE_TYPED_RSET
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
registrar(asynRegister)
|
|
||||||
registrar(asynInterposeFlushRegister)
|
|
||||||
registrar(asynInterposeEosRegister)
|
|
||||||
|
|
||||||
# asynDriver up to version 4-16 does not support serial port for Windows!
|
|
||||||
registrar(drvAsynSerialPortRegisterCommands)
|
|
||||||
registrar(drvAsynIPPortRegisterCommands)
|
|
||||||
registrar(drvAsynIPServerPortRegisterCommands)
|
|
||||||
registrar(vxi11RegisterCommands)
|
|
@ -19,7 +19,7 @@
|
|||||||
# along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
# along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||||
#########################################################################/
|
#########################################################################/
|
||||||
|
|
||||||
terminator = CR LF;
|
terminator = LF;
|
||||||
|
|
||||||
cmd {
|
cmd {
|
||||||
out "%s";
|
out "%s";
|
||||||
|
@ -52,7 +52,11 @@ set protocol {
|
|||||||
out "jamcrc %s %9.1<jamcrc>"; in "jamcrc %=s %9.1<jamcrc>";
|
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 "adler32 %s %9.1<adler32>"; in "adler32 %=s %9.1<adler32>";
|
||||||
out "hexsum8 %s %9.1<hexsum8>"; in "hexsum8 %=s %9.1<hexsum8>";
|
out "hexsum8 %s %9.1<hexsum8>"; in "hexsum8 %=s %9.1<hexsum8>";
|
||||||
|
out "bitsum %s %9.1<bitsum>"; in "bitsum %=s %9.1<bitsum>";
|
||||||
|
out "bitsum8 %s %9.1<bitsum8>"; in "bitsum8 %=s %9.1<bitsum8>";
|
||||||
|
out "bitsum16 %s %9.1<bitsum16>"; in "bitsum16 %=s %9.1<bitsum16>";
|
||||||
|
out "bitsum32 %s %9.1<bitsum32>"; in "bitsum32 %=s %9.1<bitsum32>";
|
||||||
|
|
||||||
out "sum %s %09.1<sum>"; in "sum %=s %09.1<sum>";
|
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 "sum8 %s %09.1<sum8>"; in "sum8 %=s %09.1<sum8>";
|
||||||
out "sum16 %s %09.1<sum16>"; in "sum16 %=s %09.1<sum16>";
|
out "sum16 %s %09.1<sum16>"; in "sum16 %=s %09.1<sum16>";
|
||||||
@ -88,6 +92,10 @@ set protocol {
|
|||||||
out "jamcrc %s %09.1<jamcrc>"; in "jamcrc %=s %09.1<jamcrc>";
|
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 "adler32 %s %09.1<adler32>"; in "adler32 %=s %09.1<adler32>";
|
||||||
out "hexsum8 %s %09.1<hexsum8>"; in "hexsum8 %=s %09.1<hexsum8>";
|
out "hexsum8 %s %09.1<hexsum8>"; in "hexsum8 %=s %09.1<hexsum8>";
|
||||||
|
out "bitsum %s %09.1<bitsum>"; in "bitsum %=s %09.1<bitsum>";
|
||||||
|
out "bitsum8 %s %09.1<bitsum8>"; in "bitsum8 %=s %09.1<bitsum8>";
|
||||||
|
out "bitsum16 %s %09.1<bitsum16>"; in "bitsum16 %=s %09.1<bitsum16>";
|
||||||
|
out "bitsum32 %s %09.1<bitsum32>"; in "bitsum32 %=s %09.1<bitsum32>";
|
||||||
|
|
||||||
out "sum %s %-9.1<sum>"; in "sum %=s %-9.1<sum>";
|
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 "sum8 %s %-9.1<sum8>"; in "sum8 %=s %-9.1<sum8>";
|
||||||
@ -124,6 +132,10 @@ set protocol {
|
|||||||
out "jamcrc %s %-9.1<jamcrc>"; in "jamcrc %=s %-9.1<jamcrc>";
|
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 "adler32 %s %-9.1<adler32>"; in "adler32 %=s %-9.1<adler32>";
|
||||||
out "hexsum8 %s %-9.1<hexsum8>"; in "hexsum8 %=s %-9.1<hexsum8>";
|
out "hexsum8 %s %-9.1<hexsum8>"; in "hexsum8 %=s %-9.1<hexsum8>";
|
||||||
|
out "bitsum %s %-9.1<bitsum>"; in "bitsum %=s %-9.1<bitsum>";
|
||||||
|
out "bitsum8 %s %-9.1<bitsum8>"; in "bitsum8 %=s %-9.1<bitsum8>";
|
||||||
|
out "bitsum16 %s %-9.1<bitsum16>"; in "bitsum16 %=s %-9.1<bitsum16>";
|
||||||
|
out "bitsum32 %s %-9.1<bitsum32>"; in "bitsum32 %=s %-9.1<bitsum32>";
|
||||||
|
|
||||||
out "sum %s %#9.1<sum>"; in "sum %=s %#9.1<sum>";
|
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 "sum8 %s %#9.1<sum8>"; in "sum8 %=s %#9.1<sum8>";
|
||||||
@ -160,7 +172,11 @@ set protocol {
|
|||||||
out "jamcrc %s %#9.1<jamcrc>"; in "jamcrc %=s %#9.1<jamcrc>";
|
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 "adler32 %s %#9.1<adler32>"; in "adler32 %=s %#9.1<adler32>";
|
||||||
out "hexsum8 %s %#9.1<hexsum8>"; in "hexsum8 %=s %#9.1<hexsum8>";
|
out "hexsum8 %s %#9.1<hexsum8>"; in "hexsum8 %=s %#9.1<hexsum8>";
|
||||||
|
out "bitsum %s %#9.1<bitsum>"; in "bitsum %=s %#9.1<bitsum>";
|
||||||
|
out "bitsum8 %s %#9.1<bitsum8>"; in "bitsum8 %=s %#9.1<bitsum8>";
|
||||||
|
out "bitsum16 %s %#9.1<bitsum16>"; in "bitsum16 %=s %#9.1<bitsum16>";
|
||||||
|
out "bitsum32 %s %#9.1<bitsum32>"; in "bitsum32 %=s %#9.1<bitsum32>";
|
||||||
|
|
||||||
out "sum %s %#09.1<sum>"; in "sum %=s %#09.1<sum>";
|
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 "sum8 %s %#09.1<sum8>"; in "sum8 %=s %#09.1<sum8>";
|
||||||
out "sum16 %s %#09.1<sum16>"; in "sum16 %=s %#09.1<sum16>";
|
out "sum16 %s %#09.1<sum16>"; in "sum16 %=s %#09.1<sum16>";
|
||||||
@ -196,7 +212,11 @@ set protocol {
|
|||||||
out "jamcrc %s %#09.1<jamcrc>"; in "jamcrc %=s %#09.1<jamcrc>";
|
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 "adler32 %s %#09.1<adler32>"; in "adler32 %=s %#09.1<adler32>";
|
||||||
out "hexsum8 %s %#09.1<hexsum8>"; in "hexsum8 %=s %#09.1<hexsum8>";
|
out "hexsum8 %s %#09.1<hexsum8>"; in "hexsum8 %=s %#09.1<hexsum8>";
|
||||||
|
out "bitsum %s %#09.1<bitsum>"; in "bitsum %=s %#09.1<bitsum>";
|
||||||
|
out "bitsum8 %s %#09.1<bitsum8>"; in "bitsum8 %=s %#09.1<bitsum8>";
|
||||||
|
out "bitsum16 %s %#09.1<bitsum16>"; in "bitsum16 %=s %#09.1<bitsum16>";
|
||||||
|
out "bitsum32 %s %#09.1<bitsum32>"; in "bitsum32 %=s %#09.1<bitsum32>";
|
||||||
|
|
||||||
out "sum %s %#-9.1<sum>"; in "sum %=s %#-9.1<sum>";
|
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 "sum8 %s %#-9.1<sum8>"; in "sum8 %=s %#-9.1<sum8>";
|
||||||
out "sum16 %s %#-9.1<sum16>"; in "sum16 %=s %#-9.1<sum16>";
|
out "sum16 %s %#-9.1<sum16>"; in "sum16 %=s %#-9.1<sum16>";
|
||||||
@ -232,6 +252,13 @@ set protocol {
|
|||||||
out "jamcrc %s %#-9.1<jamcrc>"; in "jamcrc %=s %#-9.1<jamcrc>";
|
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 "adler32 %s %#-9.1<adler32>"; in "adler32 %=s %#-9.1<adler32>";
|
||||||
out "hexsum8 %s %#-9.1<hexsum8>"; in "hexsum8 %=s %#-9.1<hexsum8>";
|
out "hexsum8 %s %#-9.1<hexsum8>"; in "hexsum8 %=s %#-9.1<hexsum8>";
|
||||||
|
out "bitsum %s %#-9.1<bitsum>"; in "bitsum %=s %#-9.1<bitsum>";
|
||||||
|
out "bitsum8 %s %#-9.1<bitsum8>"; in "bitsum8 %=s %#-9.1<bitsum8>";
|
||||||
|
out "bitsum16 %s %#-9.1<bitsum16>"; in "bitsum16 %=s %#-9.1<bitsum16>";
|
||||||
|
out "bitsum32 %s %#-9.1<bitsum32>"; in "bitsum32 %=s %#-9.1<bitsum32>";
|
||||||
|
|
||||||
|
# Check combination of regsub and checksum. Always check what the device sees.
|
||||||
|
out "crc8 %s%#/[0-9]{2}/&:/ %9.1<crc8>"; in "crc8 %#/[0-9]{2}/&:/%s %9.1<crc8>"; out "%s";
|
||||||
out "DONE";
|
out "DONE";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +340,15 @@ assure "adler32 123456789 \x09\x1E\x01\xDE\n"
|
|||||||
send "adler32 123456789 \x09\x1E\x01\xDE\n"
|
send "adler32 123456789 \x09\x1E\x01\xDE\n"
|
||||||
assure "hexsum8 123456789 \x2D\n"
|
assure "hexsum8 123456789 \x2D\n"
|
||||||
send "hexsum8 123456789 \x2D\n"
|
send "hexsum8 123456789 \x2D\n"
|
||||||
|
assure "bitsum 123456789 \x21\n"
|
||||||
|
send "bitsum 123456789 \x21\n"
|
||||||
|
assure "bitsum8 123456789 \x21\n"
|
||||||
|
send "bitsum8 123456789 \x21\n"
|
||||||
|
assure "bitsum16 123456789 \x00\x21\n"
|
||||||
|
send "bitsum16 123456789 \x00\x21\n"
|
||||||
|
assure "bitsum32 123456789 \x00\x00\x00\x21\n"
|
||||||
|
send "bitsum32 123456789 \x00\x00\x00\x21\n"
|
||||||
|
|
||||||
assure "sum 123456789 DD\n"
|
assure "sum 123456789 DD\n"
|
||||||
send "sum 123456789 DD\n"
|
send "sum 123456789 DD\n"
|
||||||
assure "sum8 123456789 DD\n"
|
assure "sum8 123456789 DD\n"
|
||||||
@ -384,7 +419,15 @@ assure "adler32 123456789 091E01DE\n"
|
|||||||
send "adler32 123456789 091E01DE\n"
|
send "adler32 123456789 091E01DE\n"
|
||||||
assure "hexsum8 123456789 2D\n"
|
assure "hexsum8 123456789 2D\n"
|
||||||
send "hexsum8 123456789 2D\n"
|
send "hexsum8 123456789 2D\n"
|
||||||
|
assure "bitsum 123456789 21\n"
|
||||||
|
send "bitsum 123456789 21\n"
|
||||||
|
assure "bitsum8 123456789 21\n"
|
||||||
|
send "bitsum8 123456789 21\n"
|
||||||
|
assure "bitsum16 123456789 0021\n"
|
||||||
|
send "bitsum16 123456789 0021\n"
|
||||||
|
assure "bitsum32 123456789 00000021\n"
|
||||||
|
send "bitsum32 123456789 00000021\n"
|
||||||
|
|
||||||
assure "sum 123456789 \x3D\x3D\n"
|
assure "sum 123456789 \x3D\x3D\n"
|
||||||
send "sum 123456789 \x3D\x3D\n"
|
send "sum 123456789 \x3D\x3D\n"
|
||||||
assure "sum8 123456789 \x3D\x3D\n"
|
assure "sum8 123456789 \x3D\x3D\n"
|
||||||
@ -455,7 +498,15 @@ assure "adler32 123456789 \x30\x39\x31\x3E\x30\x31\x3D\x3E\n"
|
|||||||
send "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"
|
assure "hexsum8 123456789 \x32\x3D\n"
|
||||||
send "hexsum8 123456789 \x32\x3D\n"
|
send "hexsum8 123456789 \x32\x3D\n"
|
||||||
|
assure "bitsum 123456789 \x32\x31\n"
|
||||||
|
send "bitsum 123456789 \x32\x31\n"
|
||||||
|
assure "bitsum8 123456789 \x32\x31\n"
|
||||||
|
send "bitsum8 123456789 \x32\x31\n"
|
||||||
|
assure "bitsum16 123456789 \x30\x30\x32\x31\n"
|
||||||
|
send "bitsum16 123456789 \x30\x30\x32\x31\n"
|
||||||
|
assure "bitsum32 123456789 \x30\x30\x30\x30\x30\x30\x32\x31\n"
|
||||||
|
send "bitsum32 123456789 \x30\x30\x30\x30\x30\x30\x32\x31\n"
|
||||||
|
|
||||||
assure "sum 123456789 \xDD\n"
|
assure "sum 123456789 \xDD\n"
|
||||||
send "sum 123456789 \xDD\n"
|
send "sum 123456789 \xDD\n"
|
||||||
assure "sum8 123456789 \xDD\n"
|
assure "sum8 123456789 \xDD\n"
|
||||||
@ -526,7 +577,15 @@ assure "adler32 123456789 \xDE\x01\x1E\x09\n"
|
|||||||
send "adler32 123456789 \xDE\x01\x1E\x09\n"
|
send "adler32 123456789 \xDE\x01\x1E\x09\n"
|
||||||
assure "hexsum8 123456789 \x2D\n"
|
assure "hexsum8 123456789 \x2D\n"
|
||||||
send "hexsum8 123456789 \x2D\n"
|
send "hexsum8 123456789 \x2D\n"
|
||||||
|
assure "bitsum 123456789 \x21\n"
|
||||||
|
send "bitsum 123456789 \x21\n"
|
||||||
|
assure "bitsum8 123456789 \x21\n"
|
||||||
|
send "bitsum8 123456789 \x21\n"
|
||||||
|
assure "bitsum16 123456789 \x21\x00\n"
|
||||||
|
send "bitsum16 123456789 \x21\x00\n"
|
||||||
|
assure "bitsum32 123456789 \x21\x00\x00\x00\n"
|
||||||
|
send "bitsum32 123456789 \x21\x00\x00\x00\n"
|
||||||
|
|
||||||
assure "sum 123456789 DD\n"
|
assure "sum 123456789 DD\n"
|
||||||
send "sum 123456789 DD\n"
|
send "sum 123456789 DD\n"
|
||||||
assure "sum8 123456789 DD\n"
|
assure "sum8 123456789 DD\n"
|
||||||
@ -597,7 +656,15 @@ assure "adler32 123456789 DE011E09\n"
|
|||||||
send "adler32 123456789 DE011E09\n"
|
send "adler32 123456789 DE011E09\n"
|
||||||
assure "hexsum8 123456789 2D\n"
|
assure "hexsum8 123456789 2D\n"
|
||||||
send "hexsum8 123456789 2D\n"
|
send "hexsum8 123456789 2D\n"
|
||||||
|
assure "bitsum 123456789 21\n"
|
||||||
|
send "bitsum 123456789 21\n"
|
||||||
|
assure "bitsum8 123456789 21\n"
|
||||||
|
send "bitsum8 123456789 21\n"
|
||||||
|
assure "bitsum16 123456789 2100\n"
|
||||||
|
send "bitsum16 123456789 2100\n"
|
||||||
|
assure "bitsum32 123456789 21000000\n"
|
||||||
|
send "bitsum32 123456789 21000000\n"
|
||||||
|
|
||||||
assure "sum 123456789 \x3D\x3D\n"
|
assure "sum 123456789 \x3D\x3D\n"
|
||||||
send "sum 123456789 \x3D\x3D\n"
|
send "sum 123456789 \x3D\x3D\n"
|
||||||
assure "sum8 123456789 \x3D\x3D\n"
|
assure "sum8 123456789 \x3D\x3D\n"
|
||||||
@ -668,6 +735,20 @@ assure "adler32 123456789 \x3D\x3E\x30\x31\x31\x3E\x30\x39\n"
|
|||||||
send "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"
|
assure "hexsum8 123456789 \x32\x3D\n"
|
||||||
send "hexsum8 123456789 \x32\x3D\n"
|
send "hexsum8 123456789 \x32\x3D\n"
|
||||||
|
assure "bitsum 123456789 \x32\x31\n"
|
||||||
|
send "bitsum 123456789 \x32\x31\n"
|
||||||
|
assure "bitsum8 123456789 \x32\x31\n"
|
||||||
|
send "bitsum8 123456789 \x32\x31\n"
|
||||||
|
assure "bitsum16 123456789 \x32\x31\x30\x30\n"
|
||||||
|
send "bitsum16 123456789 \x32\x31\x30\x30\n"
|
||||||
|
assure "bitsum32 123456789 \x32\x31\x30\x30\x30\x30\x30\x30\n"
|
||||||
|
send "bitsum32 123456789 \x32\x31\x30\x30\x30\x30\x30\x30\n"
|
||||||
|
|
||||||
|
# check regsub and checksums
|
||||||
|
assure "crc8 12:34:56:78:9 \x07\n" ;# modified output string and checksum
|
||||||
|
send "crc8 123456789 \xF4\n" ;# original input string and checksum
|
||||||
|
assure "12:34:56:78:9\n" ;# modified input string
|
||||||
|
|
||||||
assure "DONE\n"
|
assure "DONE\n"
|
||||||
|
|
||||||
finish
|
finish
|
||||||
|
Reference in New Issue
Block a user