Compare commits
16 Commits
stream_2_7
...
stream_2_7
Author | SHA1 | Date | |
---|---|---|---|
19467bd5d5 | |||
d69c74bc8f | |||
e09506c2bb | |||
343eef324b | |||
a798cf2f21 | |||
23f3e806e2 | |||
56b6c9a627 | |||
2830f07324 | |||
abd8daafc3 | |||
489e783872 | |||
10d1fa8b02 | |||
c8bffebfc6 | |||
0a90eb3d9c | |||
0936ac7840 | |||
704ece6231 | |||
5c6e98127e |
@ -44,7 +44,7 @@ ifneq (${EPICS_BASETYPE},3.13)
|
||||
RECORDTYPES += calcout
|
||||
endif
|
||||
|
||||
StreamCore.o: streamReferences
|
||||
StreamCore.o StreamCore.d: streamReferences
|
||||
|
||||
streamReferences:
|
||||
perl ../src/makeref.pl Interface $(BUSSES) > $@
|
||||
|
@ -564,8 +564,8 @@ in architecture specific RELEASE.Common.<em>arch</em> files.
|
||||
If the regular expression is not anchored, i.e. does not start with
|
||||
<code>^</code>, leading non-matching input is skipped.
|
||||
A maximum of <em>width</em> bytes is matched, if specified.
|
||||
If <em>precision</em> is given, it specifies the sub-expression whose match
|
||||
is retuned.
|
||||
If <em>precision</em> is given, it specifies the sub-expression in <code>()</code>
|
||||
whose match is retuned.
|
||||
Otherwise the complete match is returned.
|
||||
In any case, the complete match is consumed from the input buffer.
|
||||
If the expression contains a <code>/</code> it must be escaped like <code>\/</code>.
|
||||
@ -586,12 +586,19 @@ as a post-processor for output.
|
||||
</p>
|
||||
<p>
|
||||
Matches of the <em>regex</em> are replaced by the string <em>subst</em> with all
|
||||
<code>&</code> or <code>\0</code> in <em>subst</em> replaced with the match itself and all
|
||||
<code>\1</code> through <code>\9</code> replaced with the match of the corresponding sub-expression.
|
||||
<code>&</code> in <em>subst</em> replaced with the match itself and all
|
||||
<code>\1</code> through <code>\9</code> replaced with the match of the corresponding
|
||||
sub-expression <span class="new"> if such a sub-expression exists.
|
||||
|
||||
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>.
|
||||
Therefore <code>\0</code> aways means a literal byte (incompatible change from earlier version!)
|
||||
and <code>\1</code> through <code>\9</code> mean literal bytes if they are larger than
|
||||
the number of sub-expressions.
|
||||
</span>
|
||||
|
||||
To get a literal <code>&</code> or <code>\</code> or <code>/</code> in the substitution write
|
||||
<code>\&</code> or <code>\\</code> or <code>\/</code>.
|
||||
There is no way to specify literal bytes with values less or equal to 9 in the
|
||||
substitution!
|
||||
</p>
|
||||
<p>
|
||||
If <em>width</em> is specified, it limits the number of characters processed.
|
||||
|
@ -562,13 +562,7 @@ connectToAsynPort()
|
||||
clientName(), connected ? "already" : "not yet");
|
||||
if (!connected)
|
||||
{
|
||||
printf ("%s: AsynDriverInterface::connectToAsynPort: "
|
||||
"pasynCommon->connect(%p, %p)\n",
|
||||
clientName(), pvtCommon, pasynUser);
|
||||
status = pasynCommon->connect(pvtCommon, pasynUser);
|
||||
printf ("%s: AsynDriverInterface::connectToAsynPort: "
|
||||
"pasynCommon->connect(%p, %p) = %s\n",
|
||||
clientName(), pvtCommon, pasynUser, asynStatusStr[status]);
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
||||
"status=%s\n",
|
||||
clientName(), asynStatusStr[status]);
|
||||
@ -718,13 +712,19 @@ writeHandler()
|
||||
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
||||
NULL, 0);
|
||||
}
|
||||
pasynUser->errorMessage[0] = 0;
|
||||
status = pasynOctet->write(pvtOctet, pasynUser,
|
||||
outputBuffer, outputSize, &written);
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::writeHandler(%s): "
|
||||
"write(..., outputSize=%ld, written=%ld) "
|
||||
"[timeout=%g sec] = %s\n",
|
||||
clientName(), (long)outputSize, (long)written,
|
||||
pasynUser->timeout, asynStatusStr[status]);
|
||||
"write(..., \"%s\", outputSize=%ld, written=%ld) "
|
||||
"[timeout=%g sec] = %s (%s)\n",
|
||||
clientName(),
|
||||
StreamBuffer(outputBuffer, outputSize).expand()(),
|
||||
(long)outputSize, (long)written,
|
||||
pasynUser->timeout, asynStatusStr[status],
|
||||
pasynUser->errorMessage);
|
||||
#endif
|
||||
|
||||
if (oldeoslen >= 0) // restore asyn terminator
|
||||
{
|
||||
@ -769,34 +769,34 @@ writeHandler()
|
||||
writeCallback(StreamIoSuccess);
|
||||
return;
|
||||
case asynTimeout:
|
||||
error("%s: asynTimeout (%g sec) in write. Asyn says: %s\n",
|
||||
error("%s: asynTimeout (%g sec) in write. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->timeout, pasynUser->errorMessage);
|
||||
writeCallback(StreamIoTimeout);
|
||||
return;
|
||||
case asynOverflow:
|
||||
error("%s: asynOverflow in write. Asyn driver says: %s\n",
|
||||
error("%s: asynOverflow in write. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
case asynError:
|
||||
error("%s: asynError in write. Asyn driver says: %s\n",
|
||||
error("%s: asynError in write. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
#ifdef ASYN_VERSION // asyn >= 4.14
|
||||
case asynDisconnected:
|
||||
error("%s: asynDisconnected in write. Asyn driver says: %s\n",
|
||||
error("%s: asynDisconnected in write. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
case asynDisabled:
|
||||
error("%s: asynDisconnected in write. Asyn driver says: %s\n",
|
||||
error("%s: asynDisconnected in write. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
error("%s: unknown asyn error in write. Asyn driver says: %s\n",
|
||||
error("%s: unknown asyn error in write. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
@ -887,6 +887,11 @@ readHandler()
|
||||
oldeoslen = -1;
|
||||
} else do {
|
||||
// device (e.g. GPIB) might not accept full eos length
|
||||
if ((int)deveoslen == oldeoslen && strcmp(deveos, oldeos) == 0)
|
||||
{
|
||||
// nothing to do: old and new eos are the same
|
||||
break;
|
||||
}
|
||||
if (pasynOctet->setInputEos(pvtOctet, pasynUser,
|
||||
deveos, deveoslen) == asynSuccess)
|
||||
{
|
||||
@ -894,8 +899,9 @@ readHandler()
|
||||
if (ioAction != AsyncRead)
|
||||
{
|
||||
debug("AsynDriverInterface::readHandler(%s) "
|
||||
"input EOS set to %s\n",
|
||||
"input EOS changed from \"%s\" to \"%s\"\n",
|
||||
clientName(),
|
||||
StreamBuffer(oldeos, oldeoslen).expand()(),
|
||||
StreamBuffer(deveos, deveoslen).expand()());
|
||||
}
|
||||
#endif
|
||||
@ -951,6 +957,7 @@ readHandler()
|
||||
readMore = 0;
|
||||
received = 0;
|
||||
eomReason = 0;
|
||||
pasynUser->errorMessage[0] = 0;
|
||||
|
||||
debug("AsynDriverInterface::readHandler(%s): ioAction=%s "
|
||||
"read(..., bytesToRead=%ld, ...) "
|
||||
@ -959,12 +966,13 @@ readHandler()
|
||||
bytesToRead, pasynUser->timeout);
|
||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||
buffer, bytesToRead, &received, &eomReason);
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"read returned %s: ioAction=%s received=%ld, eomReason=%s, buffer=\"%s\"\n",
|
||||
clientName(), asynStatusStr[status], ioActionStr[ioAction],
|
||||
(long)received,eomReasonStr[eomReason&0x7],
|
||||
StreamBuffer(buffer, received).expand()());
|
||||
|
||||
#endif
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"device is now %sconnected\n",
|
||||
@ -1094,29 +1102,29 @@ readHandler()
|
||||
}
|
||||
peeksize = inputBuffer.capacity();
|
||||
// deliver whatever we could save
|
||||
error("%s: asynOverflow in read. Asyn driver says: %s\n",
|
||||
error("%s: asynOverflow in read. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault, buffer, received);
|
||||
break;
|
||||
case asynError:
|
||||
error("%s: asynError in read. Asyn driver says: %s\n",
|
||||
error("%s: asynError in read. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault, buffer, received);
|
||||
break;
|
||||
#ifdef ASYN_VERSION // asyn >= 4.14
|
||||
case asynDisconnected:
|
||||
error("%s: asynDisconnected in read. Asyn driver says: %s\n",
|
||||
error("%s: asynDisconnected in read. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
case asynDisabled:
|
||||
error("%s: asynDisconnected in read. Asyn driver says: %s\n",
|
||||
error("%s: asynDisconnected in read. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
error("%s: unknown asyn error in read. Asyn driver says: %s\n",
|
||||
error("%s: unknown asyn error in read. Asyn driver says: \"%s\"\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
@ -1138,10 +1146,16 @@ readHandler()
|
||||
}
|
||||
|
||||
// restore original EOS
|
||||
if (oldeoslen >= 0)
|
||||
if (oldeoslen >= 0 && oldeoslen != (int)deveoslen && strcmp(deveos, oldeos) != 0)
|
||||
{
|
||||
pasynOctet->setInputEos(pvtOctet, pasynUser,
|
||||
oldeos, oldeoslen);
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::readHandler(%s) "
|
||||
"input EOS restored to \"%s\"\n",
|
||||
clientName(),
|
||||
StreamBuffer(oldeos, oldeoslen).expand()());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
run-time leak.
|
||||
- A maximum of 9 subexpressions is supported. Only one of them can
|
||||
be the result of the match.
|
||||
- vxWorks and maybe other OS don't have a PCRE library. Provide one?
|
||||
*/
|
||||
|
||||
class RegexpConverter : public StreamFormatConverter
|
||||
@ -54,9 +53,9 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
}
|
||||
if (fmt.prec > 9)
|
||||
{
|
||||
error("Subexpression index %d too big (>9)\n", fmt.prec);
|
||||
error("Sub-expression index %d too big (>9)\n", fmt.prec);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
StreamBuffer pattern;
|
||||
while (*source != '/')
|
||||
@ -81,22 +80,30 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
}
|
||||
source++;
|
||||
debug("regexp = \"%s\"\n", pattern.expand()());
|
||||
|
||||
|
||||
const char* errormsg;
|
||||
int eoffset;
|
||||
pcre* code = pcre_compile(pattern(), 0,
|
||||
&errormsg, &eoffset, NULL);
|
||||
int nsubexpr;
|
||||
|
||||
pcre* code = pcre_compile(pattern(), 0, &errormsg, &eoffset, NULL);
|
||||
if (!code)
|
||||
{
|
||||
error("%s after \"%s\"\n", errormsg, pattern.expand(0, eoffset)());
|
||||
return false;
|
||||
}
|
||||
pcre_fullinfo(code, NULL, PCRE_INFO_CAPTURECOUNT, &nsubexpr);
|
||||
if (fmt.prec > nsubexpr)
|
||||
{
|
||||
error("Sub-expression index is %d but pattern has only %d sub-expression\n", fmt.prec, nsubexpr);
|
||||
return false;
|
||||
}
|
||||
info.append(&code, sizeof(code));
|
||||
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
StreamBuffer subst;
|
||||
debug("check for subst in \"%s\"\n", StreamBuffer(source).expand()());
|
||||
|
||||
debug("check for subst in \"%s\"\n", StreamBuffer(source).expand()());
|
||||
while (*source != '/')
|
||||
{
|
||||
if (!*source) {
|
||||
@ -122,15 +129,15 @@ scanString(const StreamFormat& fmt, const char* input,
|
||||
int ovector[30];
|
||||
int rc;
|
||||
unsigned int l;
|
||||
|
||||
|
||||
const char* info = fmt.info;
|
||||
pcre* code = extract<pcre*>(info);
|
||||
int length = fmt.width > 0 ? fmt.width : strlen(input);
|
||||
int subexpr = fmt.prec > 0 ? fmt.prec : 0;
|
||||
|
||||
|
||||
debug("input = \"%s\"\n", input);
|
||||
debug("length=%d\n", length);
|
||||
|
||||
|
||||
rc = pcre_exec(code, NULL, input, length, 0, 0, ovector, 30);
|
||||
debug("pcre_exec match \"%.*s\" result = %d\n", length, input, rc);
|
||||
if ((subexpr && rc <= subexpr) || rc < 0)
|
||||
@ -152,7 +159,7 @@ scanString(const StreamFormat& fmt, const char* input,
|
||||
}
|
||||
memcpy(value, input + ovector[subexpr*2], l);
|
||||
value[l] = '\0';
|
||||
return ovector[1]; // consume input until end of match
|
||||
return ovector[1]; // consume input until end of match
|
||||
}
|
||||
|
||||
static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
@ -167,19 +174,19 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
length = buffer.length() - start;
|
||||
if (fmt.width && fmt.width < length)
|
||||
length = fmt.width;
|
||||
if (fmt.flags & sign_flag)
|
||||
if (fmt.flags & left_flag)
|
||||
start = buffer.length() - length;
|
||||
|
||||
debug("regsubst buffer=\"%s\", start=%ld, length=%ld, subst = \"%s\"\n",
|
||||
buffer.expand()(), start, length, subst);
|
||||
|
||||
buffer.expand()(), start, length, StreamBuffer(subst).expand()());
|
||||
|
||||
for (c = 0, n = 1; c < length; n++)
|
||||
{
|
||||
rc = pcre_exec(code, NULL, buffer(start+c), length-c, 0, 0, ovector, 30);
|
||||
debug("pcre_exec match \"%.*s\" result = %d\n", (int)length-c, buffer(start+c), rc);
|
||||
if (rc < 0) // no match
|
||||
debug("pcre_exec match \"%s\" result = %d\n", buffer.expand(start+c, length-c)(), rc);
|
||||
if (rc < 0) // no match
|
||||
return;
|
||||
|
||||
|
||||
if (!(fmt.flags & sign_flag) && n < fmt.prec) // without + flag
|
||||
{
|
||||
// do not yet replace this match
|
||||
@ -188,24 +195,24 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
}
|
||||
// replace & by match in subst
|
||||
l = ovector[1] - ovector[0];
|
||||
debug("start = \"%s\"\n", buffer(start+c));
|
||||
debug("match = \"%.*s\"\n", l, buffer(start+c+ovector[0]));
|
||||
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)());
|
||||
for (r = 1; r < rc; r++)
|
||||
debug("sub%d = \"%.*s\"\n", r, ovector[r*2+1]-ovector[r*2], buffer(start+c+ovector[r*2]));
|
||||
debug("rest = \"%s\"\n", buffer(start+c+ovector[1]));
|
||||
debug("sub%d = \"%s\"\n", r, buffer.expand(start+c+ovector[r*2], ovector[r*2+1]-ovector[r*2])());
|
||||
debug("after = \"%s\"\n", buffer.expand(start+c+ovector[1])());
|
||||
s = subst;
|
||||
debug("subs = \"%s\"\n", s.expand()());
|
||||
debug("subs = \"%s\"\n", s.expand()());
|
||||
for (r = 0; r < s.length(); r++)
|
||||
{
|
||||
debug("check \"%s\"\n", s.expand(r)());
|
||||
if (s[r] == esc)
|
||||
{
|
||||
unsigned char ch = s[r+1];
|
||||
if (ch < 9) // escaped 0 - 9 : replace with subexpr
|
||||
if (c != 0 && ch < rc) // escaped 1 - 9 : replace with subexpr
|
||||
{
|
||||
ch *= 2;
|
||||
rl = ovector[ch+1] - ovector[ch];
|
||||
debug("replace \\%d: \"%.*s\"\n", ch/2, rl, buffer(start+c+ovector[ch]));
|
||||
debug("replace \\%d: \"%s\"\n", ch/2, buffer.expand(start+c+ovector[ch], rl)());
|
||||
s.replace(r, 2, buffer(start+c+ovector[ch]), rl);
|
||||
r += rl - 1;
|
||||
}
|
||||
@ -214,16 +221,16 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
}
|
||||
else if (s[r] == '&') // unescaped & : replace with match
|
||||
{
|
||||
debug("replace &: \"%.*s\"\n", l, buffer(start+c+ovector[0]));
|
||||
debug("replace &: \"%s\"\n", buffer.expand(start+c+ovector[0], l)());
|
||||
s.replace(r, 1, buffer(start+c+ovector[0]), l);
|
||||
r += l - 1;
|
||||
}
|
||||
else continue;
|
||||
debug("subs = \"%s\"\n", s());
|
||||
debug("subs = \"%s\"\n", s.expand()());
|
||||
}
|
||||
buffer.replace(start+c+ovector[0], l, s);
|
||||
length += s.length() - l;
|
||||
c += s.length();
|
||||
c += ovector[0] + s.length();
|
||||
if (n == fmt.prec) // max match reached
|
||||
return;
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ StreamBuffer StreamBuffer::expand(ssize_t start, ssize_t length) const
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
c = buffer[i];
|
||||
if ((c & 0x7f) < 0x20 || (c & 0x7f) == 0x7f)
|
||||
if (c < 0x20 || c >= 0x7f)
|
||||
{
|
||||
result.print("<%02x>", c & 0xff);
|
||||
}
|
||||
|
@ -460,7 +460,7 @@ finishProtocol(ProtocolResult status)
|
||||
status = Fault;
|
||||
}
|
||||
//// flags &= ~(AcceptInput|AcceptEvent);
|
||||
if (runningHandler)
|
||||
if (runningHandler || flags & InitRun)
|
||||
{
|
||||
// get original error status
|
||||
if (status == Success) status = runningHandler;
|
||||
@ -832,7 +832,7 @@ lockCallback(StreamIoStatus status)
|
||||
case StreamIoSuccess:
|
||||
break;
|
||||
case StreamIoTimeout:
|
||||
debug("%s: length, within %ld ms, device seems to be busy\n",
|
||||
debug("%s: Cannot lock device within %ld ms, device seems to be busy\n",
|
||||
name(), lockTimeout);
|
||||
flags &= ~BusOwner;
|
||||
finishProtocol(LockTimeout);
|
||||
|
@ -180,6 +180,7 @@ public:
|
||||
#ifndef EPICS_3_13
|
||||
extern "C" {
|
||||
epicsExportAddress(int, streamDebug);
|
||||
epicsExportAddress(int, streamError);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -195,8 +196,12 @@ extern "C" long streamReload(char* recordname)
|
||||
dbCommon* record;
|
||||
long status;
|
||||
|
||||
int oldStreamError = streamError;
|
||||
streamError = 1;
|
||||
|
||||
if(!pdbbase) {
|
||||
error("No database has been loaded\n");
|
||||
streamError = oldStreamError;
|
||||
return ERROR;
|
||||
}
|
||||
debug("streamReload(%s)\n", recordname);
|
||||
@ -233,6 +238,7 @@ extern "C" long streamReload(char* recordname)
|
||||
}
|
||||
dbFinishEntry(&dbentry);
|
||||
StreamProtocolParser::free();
|
||||
streamError = oldStreamError;
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -407,6 +413,7 @@ long streamInit(int after)
|
||||
{
|
||||
if (after)
|
||||
{
|
||||
streamError = 0; // Switch off errors after init in order not to spam messages when a device is down.
|
||||
StreamProtocolParser::free();
|
||||
}
|
||||
return OK;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int streamDebug = 0;
|
||||
int streamError = 1;
|
||||
extern "C" {
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
@ -74,6 +75,7 @@ void StreamError(int line, const char* file, const char* fmt, ...)
|
||||
void StreamVError(int line, const char* file, const char* fmt, va_list args)
|
||||
{
|
||||
char timestamp[40];
|
||||
if (!streamError) return; // Error logging disabled
|
||||
StreamPrintTimestampFunction(timestamp, 40);
|
||||
#ifdef va_copy
|
||||
if (StreamDebugFile)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#endif
|
||||
|
||||
extern int streamDebug;
|
||||
extern int streamError;
|
||||
extern void (*StreamPrintTimestampFunction)(char* buffer, int size);
|
||||
|
||||
void StreamError(int line, const char* file, const char* fmt, ...)
|
||||
|
@ -512,20 +512,31 @@ Each time newline is read, line is incremented.
|
||||
buffer(token));
|
||||
return false;
|
||||
}
|
||||
if (c == '$' && buffer[-1] == '\\')
|
||||
{
|
||||
// quoted variable reference
|
||||
// terminate string here and do variable in next pass
|
||||
buffer[-1] = quote;
|
||||
ungetc(c, file);
|
||||
break;
|
||||
}
|
||||
buffer.append(c);
|
||||
if (c == quote && buffer[-2] != '\\')
|
||||
if (c == quote)
|
||||
{
|
||||
quote = false;
|
||||
break;
|
||||
}
|
||||
if (c == '\\')
|
||||
{
|
||||
c = getc(file);
|
||||
if (c == '$')
|
||||
{
|
||||
// quoted variable reference
|
||||
// terminate string here and do variable in next pass
|
||||
buffer[-1] = quote;
|
||||
ungetc(c, file);
|
||||
break;
|
||||
}
|
||||
if (c == EOF || c == '\n')
|
||||
{
|
||||
error(line, filename(), "Backslash at end of line: %s\n",
|
||||
buffer(token));
|
||||
return false;
|
||||
}
|
||||
buffer.append(c);
|
||||
}
|
||||
c = getc(file);
|
||||
}
|
||||
buffer.append('\0').append(&l, sizeof(l)); // append line number
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#define STREAM_MAJOR 2
|
||||
#define STREAM_MINOR 7
|
||||
#define STREAM_PATCHLEVEL 7
|
||||
#define STREAM_PATCHLEVEL 13
|
||||
|
||||
#if defined(__vxworks) || defined(vxWorks)
|
||||
#include <vxWorks.h>
|
||||
@ -58,7 +58,6 @@ extern "C" {
|
||||
#include <dbCommon.h>
|
||||
#include <dbScan.h>
|
||||
#include <devSup.h>
|
||||
/* #include <dbFldTypes.h> */
|
||||
#include <dbAccess.h>
|
||||
|
||||
#ifdef devStream_epicsExportSharedSymbols
|
||||
|
@ -55,11 +55,14 @@ static long readData (dbCommon *record, format_t *format)
|
||||
ai->rval = rval;
|
||||
if (ai->linr == menuConvertNO_CONVERSION)
|
||||
{
|
||||
/* allow more bits than 32 */
|
||||
/* allow integers with more than 32 bits */
|
||||
double val;
|
||||
if (format->type == DBF_ULONG)
|
||||
ai->val = (unsigned long)rval;
|
||||
val = (unsigned long)rval;
|
||||
else
|
||||
ai->val = rval;
|
||||
val = rval;
|
||||
if (ai->aslo != 0.0 && ai->aslo != 1.0) val *= ai->aslo;
|
||||
ai->val = val + ai->aoff;
|
||||
return DO_NOT_CONVERT;
|
||||
}
|
||||
return OK;
|
||||
|
@ -46,11 +46,14 @@ static long readData (dbCommon *record, format_t *format)
|
||||
ao->rval = rval;
|
||||
if (ao->linr == menuConvertNO_CONVERSION)
|
||||
{
|
||||
/* allow more bits than 32 */
|
||||
/* allow integers with more than 32 bits */
|
||||
double val;
|
||||
if (format->type == DBF_ULONG)
|
||||
ao->val = (unsigned long)rval;
|
||||
val = (unsigned long)rval;
|
||||
else
|
||||
ao->val = rval;
|
||||
val = rval;
|
||||
if (ao->aslo != 0.0 && ao->aslo != 1.0) val *= ao->aslo;
|
||||
ao->val = val + ao->aoff;
|
||||
return DO_NOT_CONVERT;
|
||||
}
|
||||
return OK;
|
||||
@ -63,20 +66,21 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
{
|
||||
aoRecord *ao = (aoRecord *) record;
|
||||
|
||||
double val = (INIT_RUN ? ao->val : ao->oval) - ao->aoff;
|
||||
if (ao->aslo != 0.0 && ao->aslo != 1.0) val /= ao->aslo;
|
||||
|
||||
switch (format->type)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
{
|
||||
double val = (INIT_RUN ? ao->val : ao->oval) - ao->aoff;
|
||||
if (ao->aslo != 0.0 && ao->aslo != 1.0) val /= ao->aslo;
|
||||
return streamPrintf (record, format, val);
|
||||
}
|
||||
case DBF_ULONG:
|
||||
{
|
||||
if (ao->linr == menuConvertNO_CONVERSION)
|
||||
{
|
||||
/* allow more bits than 32 */
|
||||
return streamPrintf (record, format, (unsigned long)(INIT_RUN ? ao->val : ao->oval));
|
||||
/* allow integers with more than 32 bits */
|
||||
return streamPrintf (record, format, (unsigned long)val);
|
||||
}
|
||||
return streamPrintf (record, format, (unsigned long)ao->rval);
|
||||
}
|
||||
@ -84,8 +88,8 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
{
|
||||
if (ao->linr == menuConvertNO_CONVERSION)
|
||||
{
|
||||
/* allow more bits than 32 */
|
||||
return streamPrintf (record, format, (long)(INIT_RUN ? ao->val : ao->oval));
|
||||
/* allow integers with more than 32 bits */
|
||||
return streamPrintf (record, format, (long)val);
|
||||
}
|
||||
return streamPrintf (record, format, (long)ao->rval);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ if (@ARGV[0] == "-3.13") {
|
||||
shift;
|
||||
} else {
|
||||
print "variable(streamDebug, int)\n";
|
||||
print "variable(streamError, int)\n";
|
||||
print "registrar(streamRegistrar)\n";
|
||||
}
|
||||
print "driver(stream)\n";
|
||||
|
Reference in New Issue
Block a user