Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
880a399e4e | |||
592146a648 | |||
e03285b9a9 | |||
fb3d20bfd9 | |||
3363f4f525 | |||
ed300116bd | |||
f912e0b370 | |||
b84655e4de | |||
ece1e01d21 | |||
26877dedbd | |||
7aa1802ec6 | |||
eb9f565aec | |||
04906a5835 | |||
acf7efcff2 | |||
d873d220dc | |||
9ef1653e73 | |||
d1d65344af | |||
a76adc31ab | |||
a2fcbc81c8 | |||
fa51c376c1 | |||
483530f053 | |||
8f34dd2c84 | |||
493dc19d8b | |||
3b64242ffd | |||
280cb7765a | |||
835e68bd76 | |||
92903361d0 | |||
fb937316aa | |||
ae6ebc4106 | |||
0f0dd31a0d | |||
189e61bbe8 | |||
d8f88c340a | |||
2ef5c47f19 | |||
cb4d490fb6 |
13
GNUmakefile
13
GNUmakefile
@ -11,12 +11,8 @@ DOCUDIR = docs
|
|||||||
|
|
||||||
PCRE=1
|
PCRE=1
|
||||||
ASYN=1
|
ASYN=1
|
||||||
ifdef EPICSVERSION
|
-include ../src/CONFIG_STREAM
|
||||||
ifndef RECORDTYPES
|
-include src/CONFIG_STREAM
|
||||||
include src/CONFIG_STREAM
|
|
||||||
export RECORDTYPES BUSSES FORMATS
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
SOURCES += $(RECORDTYPES:%=src/dev%Stream.c)
|
SOURCES += $(RECORDTYPES:%=src/dev%Stream.c)
|
||||||
SOURCES += $(FORMATS:%=src/%Converter.cc)
|
SOURCES += $(FORMATS:%=src/%Converter.cc)
|
||||||
@ -32,9 +28,8 @@ HEADERS += StreamError.h
|
|||||||
StreamCore.o StreamCore.d: streamReferences
|
StreamCore.o StreamCore.d: streamReferences
|
||||||
|
|
||||||
# Update version string (contains __DATE__ and __TIME__)
|
# Update version string (contains __DATE__ and __TIME__)
|
||||||
# each time make runs.
|
# each time anything changes.
|
||||||
StreamVersion.o: FORCE
|
StreamVersion.o: $(filter-out StreamVersion.o stream_exportAddress.o,$(LIBOBJS))
|
||||||
FORCE:
|
|
||||||
|
|
||||||
streamReferences:
|
streamReferences:
|
||||||
$(PERL) ../src/makeref.pl Interface $(BUSSES) > $@
|
$(PERL) ../src/makeref.pl Interface $(BUSSES) > $@
|
||||||
|
@ -14,14 +14,21 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
|||||||
# define INSTALL_LOCATION_APP here
|
# define INSTALL_LOCATION_APP here
|
||||||
#INSTALL_LOCATION_APP=<fullpathname>
|
#INSTALL_LOCATION_APP=<fullpathname>
|
||||||
|
|
||||||
|
# For SynApps:
|
||||||
|
SUPPORT=
|
||||||
|
|
||||||
EPICS_BASE=/usr/local/epics/base-3.16.1
|
EPICS_BASE=/usr/local/epics/base-7.0.1
|
||||||
ASYN=~/top-3.16/asyn4-30
|
ASYN=~/top-7/asyn4-33
|
||||||
CALC=~/top-3.16/SynApps/calc-2-8
|
CALC=~/top-7/SynApps/calc-2-8
|
||||||
PCRE=~/top-3.16/pcre-7-2
|
PCRE=~/top-7/pcre-7-2
|
||||||
PCRE_INCLUDE_SL6-x86=/usr/include
|
|
||||||
PCRE_INCLUDE_SL6-x86_64=/usr/include
|
#EPICS_BASE=/usr/local/epics/base-3.16.1
|
||||||
PCRE_INCLUDE_SL6-x86_64-clang=/usr/include
|
#ASYN=~/top-3.16/asyn4-30
|
||||||
|
#CALC=~/top-3.16/SynApps/calc-2-8
|
||||||
|
#PCRE=~/top-3.16/pcre-7-2
|
||||||
|
#PCRE_INCLUDE_SL6-x86=/usr/include
|
||||||
|
#PCRE_INCLUDE_SL6-x86_64=/usr/include
|
||||||
|
#PCRE_INCLUDE_SL6-x86_64-clang=/usr/include
|
||||||
|
|
||||||
#EPICS_BASE=/usr/local/epics/base-3.15.5
|
#EPICS_BASE=/usr/local/epics/base-3.15.5
|
||||||
#ASYN=~/top-3.15/asyn4-30
|
#ASYN=~/top-3.15/asyn4-30
|
||||||
|
@ -69,7 +69,7 @@ class MyInterface : StreamBusInterface
|
|||||||
bool <a href="#lock">lockRequest</a>(unsigned long lockTimeout_ms);
|
bool <a href="#lock">lockRequest</a>(unsigned long lockTimeout_ms);
|
||||||
bool <a href="#lock">unlock</a>();
|
bool <a href="#lock">unlock</a>();
|
||||||
bool <a href="#write">writeRequest</a>(const void* output, size_t size, unsigned long writeTimeout_ms);
|
bool <a href="#write">writeRequest</a>(const void* output, size_t size, unsigned long writeTimeout_ms);
|
||||||
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms, unsigned long readTimeout_ms, long expectedLength, bool async);
|
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms, unsigned long readTimeout_ms, size_t expectedLength, bool async);
|
||||||
bool <a href="#read">supportsAsyncRead</a>();
|
bool <a href="#read">supportsAsyncRead</a>();
|
||||||
bool <a href="#event">supportsEvent</a>();
|
bool <a href="#event">supportsEvent</a>();
|
||||||
bool <a href="#event">acceptEvent</a>(unsigned long mask, unsigned long timeout_ms);
|
bool <a href="#event">acceptEvent</a>(unsigned long mask, unsigned long timeout_ms);
|
||||||
@ -118,7 +118,7 @@ bool <a href="#write">writeRequest</a>(const void* output,
|
|||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms,
|
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms,
|
||||||
unsigned long readTimeout_ms,
|
unsigned long readTimeout_ms,
|
||||||
long expectedLength, bool async);
|
size_t expectedLength, bool async);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool <a href="#read">supportsAsyncRead</a>();
|
bool <a href="#read">supportsAsyncRead</a>();
|
||||||
@ -460,7 +460,7 @@ The client may request more I/O or call <code>unlock()</code> after
|
|||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool readRequest(unsigned long replyTimeout_ms,
|
bool readRequest(unsigned long replyTimeout_ms,
|
||||||
unsigned long readTimeout_ms,
|
unsigned long readTimeout_ms,
|
||||||
long expectedLength, bool async);
|
size_t expectedLength, bool async);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
ssize_t readCallback(IoStatus status,
|
ssize_t readCallback(IoStatus status,
|
||||||
|
@ -37,6 +37,14 @@ A format converter consists of
|
|||||||
<li>Additional information required by some converters</li>
|
<li>Additional information required by some converters</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p class="new">
|
||||||
|
An exception is the sequence <code>%%</code> which stands for a single
|
||||||
|
literal <code>%</code>.
|
||||||
|
This has been added for compatibility with the C functions
|
||||||
|
<em>printf()</em> and <em>scanf()</em>.
|
||||||
|
It behaves the same as the escaped percent <code>\%</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<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>.
|
||||||
@ -83,8 +91,6 @@ formatted (like for output) and then compared to the input.
|
|||||||
The <code>!</code> flag demands that input is exactly <em>width</em>
|
The <code>!</code> flag demands that input is exactly <em>width</em>
|
||||||
bytes long (normally <em>width</em> defines the maximum number of
|
bytes long (normally <em>width</em> defines the maximum number of
|
||||||
bytes read in many formats).
|
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.
|
This feature has been added by Klemen Vodopivec, SNS.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -118,6 +124,14 @@ This feature has been added by Klemen Vodopivec, SNS.
|
|||||||
<td><code>in "%=.3f";</code></td>
|
<td><code>in "%=.3f";</code></td>
|
||||||
<td>Assure that the input is equal to the current value formatted as a float with precision 3</td>
|
<td>Assure that the input is equal to the current value formatted as a float with precision 3</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>in "%!5d";</code></td>
|
||||||
|
<td>Expect exactly 5 decimal digits. Fewer digits are considered loss of data and make the format fail.
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>in "%d%%";</code></td>
|
||||||
|
<td>Read a decimal number followed by a % sign</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<a name="types"></a>
|
<a name="types"></a>
|
||||||
@ -587,7 +601,7 @@ It is only available if a PCRE library is installed.
|
|||||||
<div class="box">
|
<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="https://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 support module.
|
to compile it like a normal EPICS support module.
|
||||||
@ -642,6 +656,13 @@ Matches of the <em>regex</em> are replaced by the string <em>subst</em> with all
|
|||||||
<code>\1</code> through <code>\9</code> replaced with the match of the corresponding
|
<code>\1</code> through <code>\9</code> replaced with the match of the corresponding
|
||||||
sub-expression <span class="new"> if such a sub-expression exists.
|
sub-expression <span class="new"> if such a sub-expression exists.
|
||||||
|
|
||||||
|
Occurrences of <code>\U<i>n</i></code>, <code>\L<i>n</i></code>, <code>\u<i>n</i></code>,
|
||||||
|
or <code>\l<i>n</i></code> with <code><i>n</i></code> being a number <code>0</code>
|
||||||
|
through <code>9</code> or <code>&</code> are replaced with the corresponding sub-expression
|
||||||
|
converted to all upper case, all lower case, first letter upper case, or first letter lower
|
||||||
|
case, respectively.</span>
|
||||||
|
</p>
|
||||||
|
<p><span class="new">
|
||||||
Due to limitations of the parser, <code>\1</code> and <code>\x01</code> are the same
|
Due to limitations of the parser, <code>\1</code> and <code>\x01</code> are the same
|
||||||
which makes it difficult to use literal bytes with values lower than 10 in <em>subst</em>.
|
which makes it difficult to use literal bytes with values lower than 10 in <em>subst</em>.
|
||||||
Therefore <code>\0</code> aways means a literal byte (incompatible change from earlier version!)
|
Therefore <code>\0</code> aways means a literal byte (incompatible change from earlier version!)
|
||||||
@ -666,6 +687,13 @@ Otherwise <em>precision</em> is the index (counting from 1) of the match to repl
|
|||||||
Without <em>precision</em> (or 0), all matches are replaced.
|
Without <em>precision</em> (or 0), all matches are replaced.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
When replacing multiple matches, the next match is searched directly after the currently
|
||||||
|
replaced string, so that the <em>subst</em> string itself will never be modified recursively.
|
||||||
|
<span class="new">
|
||||||
|
However if an empty string is matched, searching advances by 1 character in order to
|
||||||
|
avoid matching the same empty string again.</span>
|
||||||
|
</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.
|
||||||
@ -701,6 +729,9 @@ which is not at the end of a word.
|
|||||||
<code>%#/([^+-])*([+-])/\2\1/</code> moves a postfix sign to the front.
|
<code>%#/([^+-])*([+-])/\2\1/</code> moves a postfix sign to the front.
|
||||||
(<code>1.23-</code> becomes <code>-1.23</code>)<br>
|
(<code>1.23-</code> becomes <code>-1.23</code>)<br>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="indent">
|
||||||
|
<code>%#-2/.*/\U0/</code> converts the previous 2 characters to upper case.
|
||||||
|
</div>
|
||||||
<a name="mantexp"></a>
|
<a name="mantexp"></a>
|
||||||
<h2>15. MantissaExponent DOUBLE converter (<code>%m</code>)</h2>
|
<h2>15. MantissaExponent DOUBLE converter (<code>%m</code>)</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -98,10 +98,10 @@ come in a predictible order to be parsable by <em>StreamDevice</em>.
|
|||||||
IOC Application Developer's Guide:
|
IOC Application Developer's Guide:
|
||||||
<a href="https://epics.anl.gov/base/R3-14/12-docs/AppDevGuide/"
|
<a href="https://epics.anl.gov/base/R3-14/12-docs/AppDevGuide/"
|
||||||
target="ex">R3.14.12</a>,
|
target="ex">R3.14.12</a>,
|
||||||
<a href="https://epics.anl.gov/base/R3-15/5-docs/AppDevGuide/AppDevGuide.html"
|
<a href="https://epics.anl.gov/base/R3-15/6-docs/AppDevGuide/AppDevGuide.html"
|
||||||
target="ex">R3.15.5</a>,
|
target="ex">R3.15.6</a>,
|
||||||
<a href="https://epics.anl.gov/base/R3-16/1-docs/AppDevGuide/AppDevGuide.html"
|
<a href="https://epics.anl.gov/base/R3-16/2-docs/AppDevGuide/AppDevGuide.html"
|
||||||
target="ex">R3.16.1</a>
|
target="ex">R3.16.2</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14"
|
<a href="https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14"
|
||||||
|
20
docs/makepdf
20
docs/makepdf
@ -20,17 +20,21 @@ ai.html
|
|||||||
ao.html
|
ao.html
|
||||||
bi.html
|
bi.html
|
||||||
bo.html
|
bo.html
|
||||||
mbbi.html
|
calcout.html
|
||||||
mbbo.html
|
int64in.html
|
||||||
mbbiDirect.html
|
int64out.html
|
||||||
mbboDirect.html
|
|
||||||
stringin.html
|
|
||||||
stringout.html
|
|
||||||
longin.html
|
longin.html
|
||||||
longout.html
|
longout.html
|
||||||
waveform.html
|
lsi.html
|
||||||
calcout.html
|
lso.html
|
||||||
|
mbbiDirect.html
|
||||||
|
mbboDirect.html
|
||||||
|
mbbi.html
|
||||||
|
mbbo.html
|
||||||
scalcout.html
|
scalcout.html
|
||||||
|
stringin.html
|
||||||
|
stringout.html
|
||||||
|
waveform.html
|
||||||
tipsandtricks.html
|
tipsandtricks.html
|
||||||
recordinterface.html
|
recordinterface.html
|
||||||
businterface.html
|
businterface.html
|
||||||
|
@ -23,7 +23,7 @@ written or read value.
|
|||||||
<dd>
|
<dd>
|
||||||
Not allowed.
|
Not allowed.
|
||||||
</dd>
|
</dd>
|
||||||
<dt>LONG format (e.g. <code>%i</code>):</dt>
|
<dt>LONG <span class=new>or ENUM</span> format (e.g. <code>%i</code>):</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>If any of <code>ZRVL</code> ... <code>FFVL</code> is set
|
<dt>If any of <code>ZRVL</code> ... <code>FFVL</code> is set
|
||||||
@ -41,17 +41,12 @@ written or read value.
|
|||||||
</dd>
|
</dd>
|
||||||
<dt>If none of <code>ZRVL</code> ... <code>FFVL</code> is set
|
<dt>If none of <code>ZRVL</code> ... <code>FFVL</code> is set
|
||||||
(all are <code>0</code>):</dt>
|
(all are <code>0</code>):</dt>
|
||||||
<dd>
|
<dd class=new>
|
||||||
<u>Output:</u> <code><i>x</i>=VAL</code><br>
|
<u>Output:</u> <code><i>x</i>=(VAL<<SHFT)&MASK</code><br>
|
||||||
<u>Input:</u> <code>VAL=<i>x</i></code><br>
|
<u>Input:</u> <code>VAL=(RBV=(<i>x</i>&MASK))>>SHFT</code><br>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
|
||||||
<dd>
|
|
||||||
<u>Output:</u> <code><i>x</i>=VAL</code><br>
|
|
||||||
<u>Input:</u> <code>VAL=<i>x</i></code><br>
|
|
||||||
</dd>
|
|
||||||
<dt>STRING format (e.g. <code>%s</code>):</dt>
|
<dt>STRING format (e.g. <code>%s</code>):</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<u>Output:</u> Depending on <code>VAL</code>, one of <code>ZRST</code>
|
<u>Output:</u> Depending on <code>VAL</code>, one of <code>ZRST</code>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<a href="https://epics.anl.gov/base/index.php">EPICS base</a>
|
<a href="https://epics.anl.gov/base/index.php">EPICS base</a>
|
||||||
versions from R3.14.6 on, tested up to 7.0.1.
|
versions from R3.14.6 on, tested up to 7.0.1.
|
||||||
It also works (with limitations) with older
|
It also works (with limitations) with older
|
||||||
<a href="https://www.aps.anl.gov/epics/base/R3-13.php">R3.13</a>
|
<a href="https://epics.anl.gov/base/R3-13.php">R3.13</a>
|
||||||
versions from R3.13.7 on.
|
versions from R3.13.7 on.
|
||||||
How to use <em>StreamDevice</em> with EPICS R3.13 is described on a
|
How to use <em>StreamDevice</em> with EPICS R3.13 is described on a
|
||||||
<a href="epics3_13.html">separate page</a>.
|
<a href="epics3_13.html">separate page</a>.
|
||||||
|
@ -69,6 +69,10 @@ h4 {
|
|||||||
margin-bottom:0.25ex;
|
margin-bottom:0.25ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4 {
|
||||||
|
page-break-after:avoid;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-top:0.75ex;
|
margin-top:0.75ex;
|
||||||
margin-bottom:0.75ex;
|
margin-bottom:0.75ex;
|
||||||
|
@ -457,10 +457,6 @@ connectToBus(const char* portname, int addr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable asyn errors to avoid flooding when device is disconnected
|
|
||||||
// user can re-enable later
|
|
||||||
pasynTrace->setTraceMask(pasynUser, 0);
|
|
||||||
|
|
||||||
asynInterface* pasynInterface;
|
asynInterface* pasynInterface;
|
||||||
|
|
||||||
// find the asynCommon interface
|
// find the asynCommon interface
|
||||||
|
37
src/Makefile
37
src/Makefile
@ -35,6 +35,10 @@ endif
|
|||||||
LIBRARY_DEFAULT = stream
|
LIBRARY_DEFAULT = stream
|
||||||
|
|
||||||
DBD += $(LIBRARY_DEFAULT).dbd
|
DBD += $(LIBRARY_DEFAULT).dbd
|
||||||
|
DBD += $(LIBRARY_DEFAULT)-base.dbd
|
||||||
|
ifdef CALC
|
||||||
|
DBD += $(LIBRARY_DEFAULT)-scalcout.dbd
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef ASYN
|
ifdef ASYN
|
||||||
LIB_LIBS += asyn
|
LIB_LIBS += asyn
|
||||||
@ -74,7 +78,7 @@ CPPFLAGS += -DUSE_TYPED_RSET
|
|||||||
-include $(TOP)/configure/RULES
|
-include $(TOP)/configure/RULES
|
||||||
|
|
||||||
# Update version string whenever something changes
|
# Update version string whenever something changes
|
||||||
StreamVersion$(OBJ): ../*.c ../*.h ../*.cc ../CONFIG_STREAM
|
StreamVersion$(OBJ): $(filter-out StreamVersion.o,$(LIBOBJS)$(LIBRARY_OBJS))
|
||||||
|
|
||||||
# Add references to all registrars to main file to avoid
|
# Add references to all registrars to main file to avoid
|
||||||
# missing initialization.
|
# missing initialization.
|
||||||
@ -84,12 +88,29 @@ streamReferences: ../CONFIG_STREAM
|
|||||||
$(PERL) ../makeref.pl Interface $(BUSSES) > $@
|
$(PERL) ../makeref.pl Interface $(BUSSES) > $@
|
||||||
$(PERL) ../makeref.pl Converter $(FORMATS) >> $@
|
$(PERL) ../makeref.pl Converter $(FORMATS) >> $@
|
||||||
|
|
||||||
# create stream.dbd from all RECORDTYPES
|
# create stream-base.dbd from all RECORDTYPES except scalcout record
|
||||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM
|
$(COMMON_DIR)/$(LIBRARY_DEFAULT)-base.dbd: ../CONFIG_STREAM
|
||||||
$(PERL) ../makedbd.pl $(RECORDTYPES) > $@
|
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(filter-out scalcout, $(RECORDTYPES)) > $@
|
||||||
ifdef ASYN
|
|
||||||
echo "registrar(AsynDriverInterfaceRegistrar)" >> $@
|
$(LIBRARY_DEFAULT)-base.dbd$(DEP): ../CONFIG_STREAM
|
||||||
|
echo $(LIBRARY_DEFAULT)-base.dbd: $< > $@
|
||||||
|
|
||||||
|
STREAM_DBD_FILES = $(LIBRARY_DEFAULT)-base.dbd
|
||||||
|
|
||||||
|
ifdef CALC
|
||||||
|
# create stream-scalcout.dbd for scalcout record
|
||||||
|
$(COMMON_DIR)/$(LIBRARY_DEFAULT)-scalcout.dbd: ../CONFIG_STREAM
|
||||||
|
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) scalcout > $@
|
||||||
|
|
||||||
|
$(LIBRARY_DEFAULT)-scalcout.dbd$(DEP): ../CONFIG_STREAM
|
||||||
|
echo $(LIBRARY_DEFAULT)-scalcout.dbd: $< > $@
|
||||||
|
|
||||||
|
STREAM_DBD_FILES += $(LIBRARY_DEFAULT)-scalcout.dbd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(LIBRARY_DEFAULT).dbd$(DEP): ../CONFIG_STREAM
|
# create stream.dbd for all record types
|
||||||
echo $(LIBRARY_DEFAULT).dbd: $< > $@
|
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: $(addprefix $(COMMON_DIR)/, $(STREAM_DBD_FILES))
|
||||||
|
cat $? > $@
|
||||||
|
|
||||||
|
$(LIBRARY_DEFAULT).dbd$(DEP):
|
||||||
|
echo "$(LIBRARY_DEFAULT).dbd: $(STREAM_DBD_FILES)" > $@
|
||||||
|
@ -20,9 +20,10 @@
|
|||||||
|
|
||||||
#include "StreamFormatConverter.h"
|
#include "StreamFormatConverter.h"
|
||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
#include "string.h"
|
|
||||||
#include "pcre.h"
|
#include "pcre.h"
|
||||||
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#define Z PRINTF_SIZE_T_PREFIX
|
#define Z PRINTF_SIZE_T_PREFIX
|
||||||
|
|
||||||
@ -197,14 +198,15 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
|
|||||||
debug("pcre_exec: no match\n");
|
debug("pcre_exec: no match\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!(fmt.flags & sign_flag) && n < fmt.prec) // without + flag
|
|
||||||
{
|
|
||||||
// do not yet replace this match
|
|
||||||
c += ovector[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// replace subexpressions
|
|
||||||
l = ovector[1] - ovector[0];
|
l = ovector[1] - ovector[0];
|
||||||
|
|
||||||
|
// no prec: replace all matches
|
||||||
|
// prec with + flag: replace first prec matches
|
||||||
|
// prec without + flag: replace only match number prec
|
||||||
|
|
||||||
|
if ((fmt.flags & sign_flag) || n >= fmt.prec)
|
||||||
|
{
|
||||||
|
// replace subexpressions
|
||||||
debug("before [%d]= \"%s\"\n", ovector[0], buffer.expand(start+c,ovector[0])());
|
debug("before [%d]= \"%s\"\n", ovector[0], buffer.expand(start+c,ovector[0])());
|
||||||
debug("match [%d]= \"%s\"\n", l, buffer.expand(start+c+ovector[0],l)());
|
debug("match [%d]= \"%s\"\n", l, buffer.expand(start+c+ovector[0],l)());
|
||||||
for (r = 1; r < rc; r++)
|
for (r = 1; r < rc; r++)
|
||||||
@ -218,9 +220,40 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
|
|||||||
if (s[r] == esc)
|
if (s[r] == esc)
|
||||||
{
|
{
|
||||||
unsigned char ch = s[r+1];
|
unsigned char ch = s[r+1];
|
||||||
debug("found escaped \\%u, in range 1-%d?\n", ch, rc-1);
|
if (strchr("ulUL", ch))
|
||||||
if (ch != 0 && ch < rc) // escaped 1 - 9 : replace with subexpr
|
|
||||||
{
|
{
|
||||||
|
unsigned char br = s[r+2] - '0';
|
||||||
|
if (br == (unsigned char)('&'-'0')) br = 0;
|
||||||
|
debug("found case conversion \\%c%u\n", ch, br);
|
||||||
|
if (br >= rc)
|
||||||
|
{
|
||||||
|
s.remove(r, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
br *= 2;
|
||||||
|
rl = ovector[br+1] - ovector[br];
|
||||||
|
s.replace(r, 3, buffer(start+c+ovector[br]), rl);
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
if (islower(s[r])) s[r] = toupper(s[r]);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (isupper(s[r])) s[r] = tolower(s[r]);
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
for (int i = 0; i < rl; i++)
|
||||||
|
if (islower(s[r+i])) s[r+i] = toupper(s[r+i]);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
for (int i = 0; i < rl; i++)
|
||||||
|
if (isupper(s[r+i])) s[r+i] = tolower(s[r+i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch != 0 && ch < rc) // escaped 1 - 9 : replace with subexpr
|
||||||
|
{
|
||||||
|
debug("found escaped \\%u\n", ch);
|
||||||
ch *= 2;
|
ch *= 2;
|
||||||
rl = ovector[ch+1] - ovector[ch];
|
rl = ovector[ch+1] - ovector[ch];
|
||||||
debug("yes, replace \\%d: \"%s\"\n", ch/2, buffer.expand(start+c+ovector[ch], rl)());
|
debug("yes, replace \\%d: \"%s\"\n", ch/2, buffer.expand(start+c+ovector[ch], rl)());
|
||||||
@ -229,7 +262,7 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug("no, use literal \\%u\n", ch);
|
debug("use literal \\%u\n", ch);
|
||||||
s.remove(r, 1); // just remove escape
|
s.remove(r, 1); // just remove escape
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,8 +276,16 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
|
|||||||
debug("subs = \"%s\"\n", s.expand()());
|
debug("subs = \"%s\"\n", s.expand()());
|
||||||
}
|
}
|
||||||
buffer.replace(start+c+ovector[0], l, s);
|
buffer.replace(start+c+ovector[0], l, s);
|
||||||
length += s.length() - l;
|
length -= l;
|
||||||
c += ovector[0] + s.length();
|
length += s.length();
|
||||||
|
c += s.length();
|
||||||
|
}
|
||||||
|
c += ovector[0];
|
||||||
|
if (l == 0)
|
||||||
|
{
|
||||||
|
debug("pcre_exec: empty match\n");
|
||||||
|
c++; // Empty strings may lead to an endless loop. Match them only once.
|
||||||
|
}
|
||||||
if (n == fmt.prec) // max match reached
|
if (n == fmt.prec) // max match reached
|
||||||
{
|
{
|
||||||
debug("pcre_exec: max match %d reached\n", n);
|
debug("pcre_exec: max match %d reached\n", n);
|
||||||
|
@ -17,6 +17,11 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
|
// Make sure that vsnprintf is available
|
||||||
|
#ifndef _BSD_SOURCE
|
||||||
|
#define _BSD_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "StreamBuffer.h"
|
#include "StreamBuffer.h"
|
||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
|
|
||||||
@ -24,10 +29,47 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#if defined(__vxworks) || defined(vxWorks) || defined(_WIN32) || defined(__rtems__)
|
#ifdef vxWorks
|
||||||
// These systems have no vsnprintf
|
#include <version.h>
|
||||||
#define vsnprintf(p,l,f,v) vsprintf(p,f,v)
|
#ifndef _WRS_VXWORKS_MAJOR
|
||||||
#endif
|
// VxWorks 5 has no vsnprintf
|
||||||
|
// Implementation taken from EPICS 3.14
|
||||||
|
|
||||||
|
#include <vxWorks.h>
|
||||||
|
#include <fioLib.h>
|
||||||
|
|
||||||
|
struct outStr_s {
|
||||||
|
char *str;
|
||||||
|
int free;
|
||||||
|
};
|
||||||
|
|
||||||
|
static STATUS outRoutine(char *buffer, int nchars, int outarg) {
|
||||||
|
struct outStr_s *poutStr = (struct outStr_s *) outarg;
|
||||||
|
int free = poutStr->free;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (free < 1) { /*let fioFormatV continue to count length*/
|
||||||
|
return OK;
|
||||||
|
} else if (free > 1) {
|
||||||
|
len = min(free-1, nchars);
|
||||||
|
strncpy(poutStr->str, buffer, len);
|
||||||
|
poutStr->str += len;
|
||||||
|
poutStr->free -= len;
|
||||||
|
}
|
||||||
|
/*make sure final string is null terminated*/
|
||||||
|
*poutStr->str = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
||||||
|
struct outStr_s outStr;
|
||||||
|
|
||||||
|
outStr.str = str;
|
||||||
|
outStr.free = size;
|
||||||
|
return fioFormatV(format, ap, (FUNCPTR)outRoutine, (int)&outStr);
|
||||||
|
}
|
||||||
|
#endif // ! _WRS_VXWORKS_MAJOR
|
||||||
|
#endif // vxWorks
|
||||||
|
|
||||||
#define P PRINTF_SIZE_T_PREFIX
|
#define P PRINTF_SIZE_T_PREFIX
|
||||||
|
|
||||||
@ -296,7 +338,7 @@ StreamBuffer StreamBuffer::expand(ssize_t start, ssize_t length) const
|
|||||||
{
|
{
|
||||||
c = buffer[i];
|
c = buffer[i];
|
||||||
if (c < 0x20 || c >= 0x7f)
|
if (c < 0x20 || c >= 0x7f)
|
||||||
result.print("\033[1m<%02x>\033[22m", c & 0xff);
|
result.print("\033[7m<%02x>\033[27m", c & 0xff);
|
||||||
else
|
else
|
||||||
result.append(c);
|
result.append(c);
|
||||||
}
|
}
|
||||||
@ -316,7 +358,7 @@ dump() const
|
|||||||
c = buffer[i];
|
c = buffer[i];
|
||||||
if (offs && i == offs) result.append("\033[0m");
|
if (offs && i == offs) result.append("\033[0m");
|
||||||
if (c < 0x20 || c >= 0x7f)
|
if (c < 0x20 || c >= 0x7f)
|
||||||
result.print("\033[1m<%02x>\033[22m", c & 0xff);
|
result.print("\033[7m<%02x>\033[27m", c & 0xff);
|
||||||
else
|
else
|
||||||
result.append(c);
|
result.append(c);
|
||||||
if (i == offs+len-1) result.append("\033[47m");
|
if (i == offs+len-1) result.append("\033[47m");
|
||||||
|
@ -25,12 +25,10 @@
|
|||||||
|
|
||||||
#define Z PRINTF_SIZE_T_PREFIX
|
#define Z PRINTF_SIZE_T_PREFIX
|
||||||
|
|
||||||
ENUM (Commands,
|
|
||||||
end, in, out, wait, event, exec, connect, disconnect);
|
|
||||||
|
|
||||||
/// debug functions /////////////////////////////////////////////
|
/// debug functions /////////////////////////////////////////////
|
||||||
|
|
||||||
static char* printCommands(StreamBuffer& buffer, const char* c)
|
char* StreamCore::
|
||||||
|
printCommands(StreamBuffer& buffer, const char* c)
|
||||||
{
|
{
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long eventnumber;
|
unsigned long eventnumber;
|
||||||
@ -919,14 +917,12 @@ evalIn()
|
|||||||
busUnlock();
|
busUnlock();
|
||||||
flags &= ~BusOwner;
|
flags &= ~BusOwner;
|
||||||
}
|
}
|
||||||
busReadRequest(pollPeriod, readTimeout,
|
return busReadRequest(pollPeriod, readTimeout,
|
||||||
expectedInput, true);
|
expectedInput, true);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
busReadRequest(replyTimeout, readTimeout,
|
return busReadRequest(replyTimeout, readTimeout,
|
||||||
expectedInput, false);
|
expectedInput, false);
|
||||||
// continue with readCallback() in another thread
|
// continue with readCallback() in another thread
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t StreamCore::
|
ssize_t StreamCore::
|
||||||
|
@ -107,6 +107,9 @@ protected:
|
|||||||
ENUM(StartMode,
|
ENUM(StartMode,
|
||||||
StartNormal, StartInit, StartAsync);
|
StartNormal, StartInit, StartAsync);
|
||||||
|
|
||||||
|
ENUM (Commands,
|
||||||
|
end, in, out, wait, event, exec, connect, disconnect);
|
||||||
|
|
||||||
class MutexLock
|
class MutexLock
|
||||||
{
|
{
|
||||||
StreamCore* stream;
|
StreamCore* stream;
|
||||||
@ -221,6 +224,9 @@ public:
|
|||||||
void printProtocol(FILE* = stdout);
|
void printProtocol(FILE* = stdout);
|
||||||
const char* name() { return streamname; }
|
const char* name() { return streamname; }
|
||||||
void printStatus(StreamBuffer& buffer);
|
void printStatus(StreamBuffer& buffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* printCommands(StreamBuffer& buffer, const char* c);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1088,7 +1088,7 @@ getFieldAddress(const char* fieldname, StreamBuffer& address)
|
|||||||
// FIELD in this record or VAL in other record
|
// FIELD in this record or VAL in other record
|
||||||
StreamBuffer fullname;
|
StreamBuffer fullname;
|
||||||
fullname.print("%s.%s", name(), fieldname);
|
fullname.print("%s.%s", name(), fieldname);
|
||||||
if (dbNameToAddr(fullname(), &dbaddr) != OK)
|
if (dbNameToAddr(fullname(), &dbaddr) != OK || strcmp(((dbFldDes*)dbaddr.pfldDes)->name, fieldname) != 0)
|
||||||
{
|
{
|
||||||
// VAL in other record
|
// VAL in other record
|
||||||
fullname.clear().print("%s.VAL", fieldname);
|
fullname.clear().print("%s.VAL", fieldname);
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
#include "StreamError.h"
|
#include "StreamError.h"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -39,6 +42,18 @@ FILE *StreamDebugFile = NULL;
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define localtime_r(timet,tm) localtime_s(tm,timet)
|
#define localtime_r(timet,tm) localtime_s(tm,timet)
|
||||||
|
|
||||||
|
/* Enable ANSI colors in Windows console */
|
||||||
|
static int win_console_init() {
|
||||||
|
DWORD dwMode = 0;
|
||||||
|
HANDLE hCons = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
GetConsoleMode(hCons, &dwMode);
|
||||||
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
SetConsoleMode(hCons, dwMode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int s = win_console_init();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* You can globally change the printTimestamp function
|
/* You can globally change the printTimestamp function
|
||||||
@ -115,4 +130,3 @@ print(const char* fmt, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1124,6 +1124,13 @@ compileString(StreamBuffer& buffer, const char*& source,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c == '%') {
|
if (c == '%') {
|
||||||
|
if (buffer[formatpos+1] == '%') {
|
||||||
|
// treat %% as literal % like printf/scanf do
|
||||||
|
// replace with escaped %
|
||||||
|
buffer[formatpos] = esc;
|
||||||
|
formatpos+=2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
debug("StreamProtocolParser::Protocol::compileString "
|
debug("StreamProtocolParser::Protocol::compileString "
|
||||||
"format=\"%s\"\n", buffer.expand(formatpos)());
|
"format=\"%s\"\n", buffer.expand(formatpos)());
|
||||||
nformats++;
|
nformats++;
|
||||||
|
@ -32,7 +32,6 @@ extern "C" {
|
|||||||
|
|
||||||
#define STREAM_MAJOR 2
|
#define STREAM_MAJOR 2
|
||||||
#define STREAM_MINOR 8
|
#define STREAM_MINOR 8
|
||||||
#define STREAM_PATCHLEVEL 0
|
|
||||||
|
|
||||||
#ifndef OK
|
#ifndef OK
|
||||||
#define OK 0
|
#define OK 0
|
||||||
|
@ -33,11 +33,12 @@ static long readData(dbCommon *record, format_t *format)
|
|||||||
{
|
{
|
||||||
case DBF_ULONG:
|
case DBF_ULONG:
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
|
case DBF_ENUM:
|
||||||
{
|
{
|
||||||
if (streamScanf(record, format, &val) == ERROR) return ERROR;
|
if (streamScanf(record, format, &val) == ERROR) return ERROR;
|
||||||
|
if (mbbo->mask) val &= mbbo->mask;
|
||||||
mbbo->rbv = val;
|
mbbo->rbv = val;
|
||||||
mbbo->rval = val;
|
mbbo->rval = val;
|
||||||
if (mbbo->mask) val &= mbbo->mask;
|
|
||||||
if (mbbo->shft > 0) val >>= mbbo->shft;
|
if (mbbo->shft > 0) val >>= mbbo->shft;
|
||||||
/* read VAL or RBV? Look if any value is defined */
|
/* read VAL or RBV? Look if any value is defined */
|
||||||
if (mbbo->sdef)
|
if (mbbo->sdef)
|
||||||
@ -56,17 +57,12 @@ static long readData(dbCommon *record, format_t *format)
|
|||||||
mbbo->val = (epicsEnum16)val;
|
mbbo->val = (epicsEnum16)val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DBF_ENUM:
|
|
||||||
{
|
|
||||||
if (streamScanf(record, format, &val) == ERROR) return ERROR;
|
|
||||||
mbbo->val = (epicsEnum16)val;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DBF_STRING:
|
case DBF_STRING:
|
||||||
{
|
{
|
||||||
char buffer[sizeof(mbbo->zrst)];
|
char buffer[sizeof(mbbo->zrst)];
|
||||||
if (streamScanfN(record, format, buffer, sizeof(buffer)) == ERROR)
|
if (streamScanfN(record, format, buffer, sizeof(buffer)) == ERROR)
|
||||||
return ERROR;
|
return ERROR;
|
||||||
|
mbbo->val = 65535; /* initalize to unknown state*/
|
||||||
for (val = 0; val < 16; val++)
|
for (val = 0; val < 16; val++)
|
||||||
{
|
{
|
||||||
if (strcmp ((&mbbo->zrst)[val], buffer) == 0)
|
if (strcmp ((&mbbo->zrst)[val], buffer) == 0)
|
||||||
@ -75,6 +71,7 @@ static long readData(dbCommon *record, format_t *format)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return ERROR;
|
return ERROR;
|
||||||
@ -82,6 +79,15 @@ static long readData(dbCommon *record, format_t *format)
|
|||||||
if (record->pact) return DO_NOT_CONVERT;
|
if (record->pact) return DO_NOT_CONVERT;
|
||||||
/* In @init handler, no processing, enforce monitor updates. */
|
/* In @init handler, no processing, enforce monitor updates. */
|
||||||
monitor_mask = recGblResetAlarms(record);
|
monitor_mask = recGblResetAlarms(record);
|
||||||
|
if (mbbo->val > 15) {
|
||||||
|
recGblSetSevr(record, STATE_ALARM, mbbo->unsv);
|
||||||
|
} else {
|
||||||
|
recGblSetSevr(record, STATE_ALARM, (&(mbbo->zrsv))[mbbo->val]);
|
||||||
|
}
|
||||||
|
mbbo->lalm = mbbo->val;
|
||||||
|
if (mbbo->val != mbbo->lalm) {
|
||||||
|
if (!recGblSetSevr(record, COS_ALARM, mbbo->cosv)) mbbo->lalm = mbbo->val;
|
||||||
|
}
|
||||||
if (mbbo->mlst != mbbo->val)
|
if (mbbo->mlst != mbbo->val)
|
||||||
{
|
{
|
||||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||||
@ -110,39 +116,38 @@ static long writeData(dbCommon *record, format_t *format)
|
|||||||
switch (format->type)
|
switch (format->type)
|
||||||
{
|
{
|
||||||
case DBF_ULONG:
|
case DBF_ULONG:
|
||||||
|
case DBF_ENUM:
|
||||||
/* print VAL or RVAL ? */
|
/* print VAL or RVAL ? */
|
||||||
val = mbbo->val;
|
val = mbbo->val;
|
||||||
|
if (mbbo->shft > 0) val <<= mbbo->shft;
|
||||||
if (mbbo->sdef) for (i=0; i<16; i++)
|
if (mbbo->sdef) for (i=0; i<16; i++)
|
||||||
{
|
{
|
||||||
if ((&mbbo->zrvl)[i])
|
if ((&mbbo->zrvl)[i])
|
||||||
{
|
{
|
||||||
/* any values defined ? */
|
/* any values defined ? */
|
||||||
val = mbbo->rval;
|
val = mbbo->rval;
|
||||||
if (mbbo->mask) val &= mbbo->mask;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mbbo->mask) val &= mbbo->mask;
|
||||||
return streamPrintf(record, format, val);
|
return streamPrintf(record, format, val);
|
||||||
case DBF_LONG:
|
case DBF_LONG:
|
||||||
{
|
{
|
||||||
/* print VAL or RVAL ? */
|
/* print VAL or RVAL ? */
|
||||||
val = (epicsInt16)mbbo->val;
|
val = (epicsInt16)mbbo->val;
|
||||||
|
if (mbbo->shft > 0) val <<= mbbo->shft;
|
||||||
if (mbbo->sdef) for (i=0; i<16; i++)
|
if (mbbo->sdef) for (i=0; i<16; i++)
|
||||||
{
|
{
|
||||||
if ((&mbbo->zrvl)[i])
|
if ((&mbbo->zrvl)[i])
|
||||||
{
|
{
|
||||||
/* any values defined ? */
|
/* any values defined ? */
|
||||||
val = (epicsInt32)mbbo->rval;
|
val = (epicsInt32)mbbo->rval;
|
||||||
if (mbbo->mask) val &= mbbo->mask;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mbbo->mask) val &= mbbo->mask;
|
||||||
return streamPrintf(record, format, val);
|
return streamPrintf(record, format, val);
|
||||||
}
|
}
|
||||||
case DBF_ENUM:
|
|
||||||
{
|
|
||||||
return streamPrintf(record, format, mbbo->val);
|
|
||||||
}
|
|
||||||
case DBF_STRING:
|
case DBF_STRING:
|
||||||
{
|
{
|
||||||
if (mbbo->val >= 16) return ERROR;
|
if (mbbo->val >= 16) return ERROR;
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
if (@ARGV[0] == "-3.13") {
|
if (@ARGV[0] eq "--with-asyn") {
|
||||||
|
shift;
|
||||||
|
$asyn = 1;
|
||||||
|
}
|
||||||
|
if (@ARGV[0] eq "-3.13") {
|
||||||
shift;
|
shift;
|
||||||
} else {
|
} else {
|
||||||
print "variable(streamDebug, int)\n";
|
print "variable(streamDebug, int)\n";
|
||||||
print "variable(streamError, int)\n";
|
print "variable(streamError, int)\n";
|
||||||
print "registrar(streamRegistrar)\n";
|
print "registrar(streamRegistrar)\n";
|
||||||
|
if ($asyn) { print "registrar(AsynDriverInterfaceRegistrar)\n"; }
|
||||||
}
|
}
|
||||||
print "driver(stream)\n";
|
print "driver(stream)\n";
|
||||||
for (@ARGV) {
|
for (@ARGV) {
|
||||||
|
@ -40,8 +40,9 @@ ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
|||||||
# With synApps scalcout record
|
# With synApps scalcout record
|
||||||
streamApp_DBD += calcSupport.dbd
|
streamApp_DBD += calcSupport.dbd
|
||||||
PROD_LIBS += calc
|
PROD_LIBS += calc
|
||||||
# older calc versions require sscan
|
ifneq ($(words $(SSCAN) $(SYNAPPS)), 0)
|
||||||
#PROD_LIBS += sscan
|
PROD_LIBS += sscan
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
streamApp_DBD += stream.dbd
|
streamApp_DBD += stream.dbd
|
||||||
|
@ -54,8 +54,6 @@ set debug 0
|
|||||||
startioc
|
startioc
|
||||||
|
|
||||||
# Some formats give different results on 32 bit and 64 bit machines.
|
# Some formats give different results on 32 bit and 64 bit machines.
|
||||||
# This occurs when printing negative numbers with unsigned formats.
|
|
||||||
# This is normal. E.g. -1 HAS a different number of 1 bits.
|
|
||||||
# Specify the width field in the format if this is a problem.
|
# Specify the width field in the format if this is a problem.
|
||||||
|
|
||||||
put DZ:percent 1
|
put DZ:percent 1
|
||||||
@ -75,17 +73,9 @@ assure "12345 12345 012345 3039 003039 11000000111001 11000000111001 111001 !!..
|
|||||||
put DZ:lo 2147483647
|
put DZ:lo 2147483647
|
||||||
assure "2147483647 2147483647 2147483647 7fffffff FFFFFF 1111111111111111111111111111111 1111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
assure "2147483647 2147483647 2147483647 7fffffff FFFFFF 1111111111111111111111111111111 1111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
put DZ:lo -1
|
put DZ:lo -1
|
||||||
if {$tcl_platform(machine) == "x86_64"} {
|
|
||||||
assure "-1 -1 -00001 ffffffffffffffff FFFFFF 1111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
|
||||||
} else {
|
|
||||||
assure "-1 -1 -00001 ffffffff FFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
assure "-1 -1 -00001 ffffffff FFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
}
|
|
||||||
put DZ:lo -1234
|
put DZ:lo -1234
|
||||||
if {$tcl_platform(machine) == "x86_64"} {
|
|
||||||
assure "-1234 -1234 -01234 fffffffffffffb2e FFFB2E 1111111111111111111111111111111111111111111111111111101100101110 1111111111111111111111111111111111111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
|
||||||
} else {
|
|
||||||
assure "-1234 -1234 -01234 fffffb2e FFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
assure "-1234 -1234 -01234 fffffb2e FFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
|
||||||
}
|
|
||||||
put DZ:lo 255
|
put DZ:lo 255
|
||||||
assure "255 255 000255 ff 0000FF 11111111 11111111 111111 !!!!!!!! !!!!!!!!\n"
|
assure "255 255 000255 ff 0000FF 11111111 11111111 111111 !!!!!!!! !!!!!!!!\n"
|
||||||
put DZ:lo 65535
|
put DZ:lo 65535
|
||||||
|
Reference in New Issue
Block a user