Compare commits
25 Commits
stream_2_5
...
stream_2_5
Author | SHA1 | Date | |
---|---|---|---|
31dae22428 | |||
1d5c7adb61 | |||
c138442a95 | |||
a672ab1234 | |||
c550cc01be | |||
7db71589d8 | |||
910cf77d97 | |||
807fe825d6 | |||
ff46c9a4a7 | |||
a42fbc9c6c | |||
74d950ab2d | |||
9049baf730 | |||
050a165a82 | |||
1428b85a34 | |||
e4f8a6ed40 | |||
5a5b42cb67 | |||
e62553eca6 | |||
0846c1dd5b | |||
774e88241a | |||
03a04a51b6 | |||
103e74be03 | |||
129cc61759 | |||
70073e1b69 | |||
c94c1a1e70 | |||
07026b03ae |
@ -205,7 +205,7 @@ class AsynDriverInterface : StreamBusInterface
|
||||
void connectHandler();
|
||||
void disconnectHandler();
|
||||
bool connectToAsynPort();
|
||||
void asynReadHandler(const char *data, int numchars, int eomReason);
|
||||
void asynReadHandler(const char *data, size_t numchars, int eomReason);
|
||||
asynQueuePriority priority() {
|
||||
return static_cast<asynQueuePriority>
|
||||
(StreamBusInterface::priority());
|
||||
@ -502,6 +502,26 @@ connectToAsynPort()
|
||||
clientName(), pasynUser->errorMessage);
|
||||
return false;
|
||||
}
|
||||
// Is it really connected?
|
||||
if (connected && !pasynGpib)
|
||||
{
|
||||
size_t received;
|
||||
int eomReason;
|
||||
char buffer[8];
|
||||
|
||||
pasynUser->timeout = 0.0;
|
||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||
buffer, 0, &received, &eomReason);
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
||||
"read(..., 0, ...) [timeout=%f seconds] = %s\n",
|
||||
clientName(), pasynUser->timeout,
|
||||
asynStatusStr[status]);
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
||||
"device was %sconnected!\n",
|
||||
clientName(),connected?"":"dis");
|
||||
}
|
||||
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s) is %s connected\n",
|
||||
clientName(), connected ? "already" : "not yet");
|
||||
if (!connected)
|
||||
@ -534,15 +554,6 @@ lockHandler()
|
||||
debug("AsynDriverInterface::lockHandler(%s)\n",
|
||||
clientName());
|
||||
pasynManager->blockProcessCallback(pasynUser, false);
|
||||
|
||||
#ifndef ASYN_VERSION // asyn < 4.14
|
||||
asynStatus status;
|
||||
status = pasynManager->lockPort(pasynUser);
|
||||
if(status!=asynSuccess) {
|
||||
debug("Failed locking port");
|
||||
}
|
||||
#endif
|
||||
|
||||
connected = connectToAsynPort();
|
||||
lockCallback(connected ? StreamIoSuccess : StreamIoFault);
|
||||
}
|
||||
@ -553,15 +564,6 @@ unlock()
|
||||
{
|
||||
debug("AsynDriverInterface::unlock(%s)\n",
|
||||
clientName());
|
||||
|
||||
#ifndef ASYN_VERSION // asyn < 4.14
|
||||
asynStatus status;
|
||||
status = pasynManager->unlockPort(pasynUser);
|
||||
if (status != asynSuccess) {
|
||||
debug("Failed unlocking port");
|
||||
}
|
||||
#endif
|
||||
|
||||
pasynManager->unblockProcessCallback(pasynUser, false);
|
||||
return true;
|
||||
}
|
||||
@ -640,6 +642,25 @@ writeHandler()
|
||||
}
|
||||
status = pasynOctet->write(pvtOctet, pasynUser,
|
||||
outputBuffer, outputSize, &written);
|
||||
debug("AsynDriverInterface::writeHandler(%s): "
|
||||
"write(..., outputSize=%ld, written=%ld) "
|
||||
"[timeout=%f seconds] = %s\n",
|
||||
clientName(), (long)outputSize, (long)written,
|
||||
pasynUser->timeout, asynStatusStr[status]);
|
||||
|
||||
// Up to asyn 4.17 I can't see when the server has disconnected. Why?
|
||||
int connected;
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("AsynDriverInterface::writeHandler(%s): "
|
||||
"device is %sconnected\n",
|
||||
clientName(),connected?"":"dis");
|
||||
if (!connected) {
|
||||
error("%s: connection closed in write\n",
|
||||
clientName());
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldeoslen >= 0) // restore asyn terminator
|
||||
{
|
||||
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
||||
@ -757,40 +778,46 @@ readHandler()
|
||||
streameos = getInTerminator(streameoslen);
|
||||
deveos = streameos;
|
||||
deveoslen = streameoslen;
|
||||
if (streameos) do // streameos == NULL means: don't change eos
|
||||
if (streameos) // streameos == NULL means: don't change eos
|
||||
{
|
||||
asynStatus status;
|
||||
status = pasynOctet->getInputEos(pvtOctet,
|
||||
pasynUser, oldeos, sizeof(oldeos)-1, &oldeoslen);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
oldeoslen = -1;
|
||||
// No EOS support?
|
||||
}
|
||||
// device (e.g. GPIB) might not accept full eos length
|
||||
if (pasynOctet->setInputEos(pvtOctet, pasynUser,
|
||||
deveos, deveoslen) == asynSuccess)
|
||||
{
|
||||
#ifndef NO_TEMPORARY
|
||||
if (ioAction != AsyncRead)
|
||||
if (streameos[0])
|
||||
{
|
||||
debug("AsynDriverInterface::readHandler(%s) "
|
||||
"input EOS set to %s\n",
|
||||
clientName(),
|
||||
StreamBuffer(deveos, deveoslen).expand()());
|
||||
error("%s: warning: No input EOS support.\n",
|
||||
clientName());
|
||||
}
|
||||
oldeoslen = -1;
|
||||
} else do {
|
||||
// device (e.g. GPIB) might not accept full eos length
|
||||
if (pasynOctet->setInputEos(pvtOctet, pasynUser,
|
||||
deveos, deveoslen) == asynSuccess)
|
||||
{
|
||||
#ifndef NO_TEMPORARY
|
||||
if (ioAction != AsyncRead)
|
||||
{
|
||||
debug("AsynDriverInterface::readHandler(%s) "
|
||||
"input EOS set to %s\n",
|
||||
clientName(),
|
||||
StreamBuffer(deveos, deveoslen).expand()());
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
deveos++; deveoslen--;
|
||||
if (!deveoslen)
|
||||
{
|
||||
error("%s: warning: pasynOctet->setInputEos() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
}
|
||||
} while (deveoslen);
|
||||
break;
|
||||
}
|
||||
deveos++; deveoslen--;
|
||||
if (!deveoslen)
|
||||
{
|
||||
error("%s: warning: pasynOctet->setInputEos() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
}
|
||||
} while (deveoslen);
|
||||
}
|
||||
|
||||
int bytesToRead = peeksize;
|
||||
long bytesToRead = peeksize;
|
||||
long buffersize;
|
||||
|
||||
if (expectedLength > 0)
|
||||
@ -824,6 +851,7 @@ readHandler()
|
||||
int eomReason;
|
||||
asynStatus status;
|
||||
long readMore;
|
||||
int connected;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -836,9 +864,20 @@ readHandler()
|
||||
if (ioAction == Read || status != asynTimeout)
|
||||
{
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"read(..., bytesToRead=%d, ...) [timeout=%f seconds] = %s\n",
|
||||
clientName(), bytesToRead, pasynUser->timeout,
|
||||
asynStatusStr[status]);
|
||||
"read(..., bytesToRead=%ld, received=%ld...) "
|
||||
"[timeout=%f seconds] = %s\n",
|
||||
clientName(), bytesToRead, (long)received,
|
||||
pasynUser->timeout, asynStatusStr[status]);
|
||||
}
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"device is %sconnected\n",
|
||||
clientName(),connected?"":"dis");
|
||||
if (!connected) {
|
||||
error("%s: connection closed in read\n",
|
||||
clientName());
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
}
|
||||
// pasynOctet->read() has already cut off terminator.
|
||||
|
||||
@ -859,10 +898,10 @@ readHandler()
|
||||
{
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"AsyncRead poll: received %d of %d bytes \"%s\" "
|
||||
"AsyncRead poll: received %ld of %ld bytes \"%s\" "
|
||||
"eomReason=%s [data ignored]\n",
|
||||
clientName(), (int)received, bytesToRead,
|
||||
StreamBuffer(buffer, (int)received).expand()(),
|
||||
clientName(), (long)received, bytesToRead,
|
||||
StreamBuffer(buffer, received).expand()(),
|
||||
eomReasonStr[eomReason&0x7]);
|
||||
#endif
|
||||
// ignore what we got from here.
|
||||
@ -873,10 +912,10 @@ readHandler()
|
||||
}
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"received %d of %d bytes \"%s\" "
|
||||
"received %ld of %ld bytes \"%s\" "
|
||||
"eomReason=%s\n",
|
||||
clientName(), (int)received, bytesToRead,
|
||||
StreamBuffer(buffer, (int)received).expand()(),
|
||||
clientName(), (long)received, bytesToRead,
|
||||
StreamBuffer(buffer, received).expand()(),
|
||||
eomReasonStr[eomReason&0x7]);
|
||||
#endif
|
||||
// asynOctet->read() cuts off terminator, but:
|
||||
@ -932,9 +971,10 @@ readHandler()
|
||||
// read timeout
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"ioAction=%s, timeout [%f seconds] after %d of %d bytes \"%s\"\n",
|
||||
"ioAction=%s, timeout [%f seconds] "
|
||||
"after %ld of %ld bytes \"%s\"\n",
|
||||
clientName(), ioActionStr[ioAction], pasynUser->timeout,
|
||||
(int)received, bytesToRead,
|
||||
(long)received, bytesToRead,
|
||||
StreamBuffer(buffer, received).expand()());
|
||||
#endif
|
||||
if (ioAction == AsyncRead || ioAction == AsyncReadMore)
|
||||
@ -971,18 +1011,18 @@ readHandler()
|
||||
case asynDisconnected:
|
||||
error("%s: asynDisconnected in read: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
case asynDisabled:
|
||||
error("%s: asynDisconnected in read: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
error("%s: unknown asyn error in read: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
}
|
||||
if (!readMore) break;
|
||||
@ -995,7 +1035,7 @@ readHandler()
|
||||
bytesToRead = inputBuffer.capacity();
|
||||
}
|
||||
debug("AsynDriverInterface::readHandler(%s) "
|
||||
"readMore=%ld bytesToRead=%d\n",
|
||||
"readMore=%ld bytesToRead=%ld\n",
|
||||
clientName(), readMore, bytesToRead);
|
||||
pasynUser->timeout = readTimeout;
|
||||
waitForReply = false;
|
||||
@ -1027,7 +1067,7 @@ void intrCallbackOctet(void* /*pvt*/, asynUser *pasynUser,
|
||||
|
||||
// get asynchronous input
|
||||
void AsynDriverInterface::
|
||||
asynReadHandler(const char *buffer, int received, int eomReason)
|
||||
asynReadHandler(const char *buffer, size_t received, int eomReason)
|
||||
{
|
||||
// Due to multithreading, timerExpired() might come at any time.
|
||||
// It queues the next poll request which is now useless because
|
||||
@ -1043,9 +1083,9 @@ asynReadHandler(const char *buffer, int received, int eomReason)
|
||||
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::asynReadHandler(%s, buffer=\"%s\", "
|
||||
"received=%d eomReason=%s) ioAction=%s\n",
|
||||
"received=%ld eomReason=%s) ioAction=%s\n",
|
||||
clientName(), StreamBuffer(buffer, received).expand()(),
|
||||
received, eomReasonStr[eomReason&0x7], ioActionStr[ioAction]);
|
||||
(long)received, eomReasonStr[eomReason&0x7], ioActionStr[ioAction]);
|
||||
#endif
|
||||
|
||||
ioAction = None;
|
||||
@ -1101,7 +1141,7 @@ asynReadHandler(const char *buffer, int received, int eomReason)
|
||||
// set by stream, cut it off now.
|
||||
status = pasynOctet->getInputEos(pvtOctet,
|
||||
pasynUser, deveos, sizeof(deveos)-1, &deveoslen);
|
||||
if (status == asynSuccess && received >= deveoslen)
|
||||
if (status == asynSuccess && (long)received >= (long)deveoslen)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i <= deveoslen; i++)
|
||||
|
20
src/Makefile
20
src/Makefile
@ -65,7 +65,8 @@ ifdef PCRE
|
||||
LIB_LIBS += pcre
|
||||
else
|
||||
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||
LIB_SYS_LIBS += pcre
|
||||
LIB_SYS_LIBS_DEFAULT += pcre
|
||||
LIB_SYS_LIBS_WIN32 += $(PCRE_LIB)\\pcre
|
||||
SHRLIB_DEPLIB_DIRS += $(PCRE_LIB)
|
||||
endif
|
||||
endif
|
||||
@ -86,22 +87,11 @@ FORCE:
|
||||
StreamCore$(OBJ): streamReferences
|
||||
|
||||
streamReferences: ../CONFIG_STREAM
|
||||
@for i in $(BUSSES); \
|
||||
do echo "extern void* ref_$${i}Interface;"; \
|
||||
echo "void* p$$i = ref_$${i}Interface;"; \
|
||||
done > $@
|
||||
@for i in $(FORMATS); \
|
||||
do echo "extern void* ref_$${i}Converter;"; \
|
||||
echo "void* p$$i = ref_$${i}Converter;"; \
|
||||
done >> $@
|
||||
$(PERL) ../makeref.pl Interface $(BUSSES) > $@
|
||||
$(PERL) ../makeref.pl Converter $(FORMATS) >> $@
|
||||
|
||||
# create stream.dbd from all RECORDS
|
||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM
|
||||
@for r in $(RECORDS); \
|
||||
do echo "device($$r,INST_IO,dev$${r}Stream,\"stream\")"; \
|
||||
done > $@
|
||||
@echo "driver(stream)" >> $@
|
||||
@echo "variable(streamDebug, int)" >> $@
|
||||
@echo "registrar(streamRegistrar)" >> $@
|
||||
$(PERL) ../makedbd.pl $(RECORDS) > $@
|
||||
|
||||
endif
|
||||
|
@ -109,7 +109,7 @@ grow(long minsize)
|
||||
memset(newbuffer+len, 0, newcap-len);
|
||||
if (buffer != local)
|
||||
{
|
||||
delete buffer;
|
||||
delete [] buffer;
|
||||
}
|
||||
buffer = newbuffer;
|
||||
cap = newcap;
|
||||
@ -219,7 +219,7 @@ replace(long remstart, long remlen, const void* ins, long inslen)
|
||||
memset(newbuffer+newlen, 0, newcap-newlen);
|
||||
if (buffer != local)
|
||||
{
|
||||
delete buffer;
|
||||
delete [] buffer;
|
||||
}
|
||||
buffer = newbuffer;
|
||||
cap = newcap;
|
||||
|
@ -650,9 +650,12 @@ formatOutput()
|
||||
unsigned short addrlen = extract<unsigned short>(commandIndex);
|
||||
fieldAddress.set(commandIndex, addrlen);
|
||||
commandIndex += addrlen;
|
||||
goto normal_format;
|
||||
}
|
||||
case StreamProtocolParser::format:
|
||||
{
|
||||
fieldAddress.clear();
|
||||
normal_format:
|
||||
// code layout:
|
||||
// formatstring <eos> StreamFormat [info]
|
||||
formatstring = commandIndex;
|
||||
@ -696,7 +699,6 @@ formatOutput()
|
||||
name(), formatstr.expand()());
|
||||
return false;
|
||||
}
|
||||
fieldAddress.clear();
|
||||
continue;
|
||||
}
|
||||
case StreamProtocolParser::whitespace:
|
||||
@ -823,10 +825,16 @@ lockCallback(StreamIoStatus status)
|
||||
}
|
||||
flags &= ~LockPending;
|
||||
flags |= BusOwner;
|
||||
if (status != StreamIoSuccess)
|
||||
switch (status)
|
||||
{
|
||||
finishProtocol(LockTimeout);
|
||||
return;
|
||||
case StreamIoSuccess:
|
||||
break;
|
||||
case StreamIoTimeout:
|
||||
finishProtocol(LockTimeout);
|
||||
return;
|
||||
default:
|
||||
finishProtocol(Fault);
|
||||
return;
|
||||
}
|
||||
flags |= WritePending;
|
||||
if (!busWriteRequest(outputLine(), outputLine.length(), writeTimeout))
|
||||
@ -1169,9 +1177,12 @@ matchInput()
|
||||
unsigned short addrlen = extract<unsigned short>(commandIndex);
|
||||
fieldAddress.set(commandIndex, addrlen);
|
||||
commandIndex += addrlen;
|
||||
goto normal_format;
|
||||
}
|
||||
case StreamProtocolParser::format:
|
||||
{
|
||||
fieldAddress.clear();
|
||||
normal_format:
|
||||
int consumed;
|
||||
// code layout:
|
||||
// formatstring <eos> StreamFormat [info]
|
||||
@ -1310,7 +1321,6 @@ matchInput()
|
||||
return false;
|
||||
}
|
||||
// matchValue() has already removed consumed bytes from inputBuffer
|
||||
fieldAddress.clear();
|
||||
break;
|
||||
}
|
||||
case StreamProtocolParser::skip:
|
||||
@ -1332,12 +1342,12 @@ matchInput()
|
||||
while (commandIndex[i] >= ' ') i++;
|
||||
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
|
||||
{
|
||||
error("%s: Input \"%s%s\" too short.",
|
||||
error("%s: Input \"%s%s\" too short.\n",
|
||||
name(),
|
||||
inputLine.length() > 20 ? "..." : "",
|
||||
inputLine.expand(-20)());
|
||||
#ifndef NO_TEMPORARY
|
||||
error(" No match for \"%s\"\n",
|
||||
error("No match for \"%s\"\n",
|
||||
StreamBuffer(commandIndex-1,i+1).expand()());
|
||||
#endif
|
||||
}
|
||||
|
@ -690,6 +690,7 @@ process()
|
||||
debug("Stream::process(%s): could not start, status=%d\n",
|
||||
name(), status);
|
||||
(void) recGblSetSevr(record, status, INVALID_ALARM);
|
||||
record->pact = false;
|
||||
return false;
|
||||
}
|
||||
debug("Stream::process(%s): protocol started\n", name());
|
||||
@ -1053,30 +1054,43 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
buffer = fieldBuffer.clear().reserve(size);
|
||||
for (nord = 0; nord < nelem; nord++)
|
||||
{
|
||||
debug("Stream::matchValue(%s): buffer before: %s\n", name(), fieldBuffer.expand()());
|
||||
switch (format.type)
|
||||
{
|
||||
case long_format:
|
||||
{
|
||||
consumed = scanValue(format, lval);
|
||||
if (consumed >= 0) ((epicsInt32*)buffer)[nord] = lval;
|
||||
debug("Stream::matchValue(%s): %s[%li] = %li\n",
|
||||
name(), pdbaddr->precord->name, nord, lval);
|
||||
break;
|
||||
}
|
||||
case enum_format:
|
||||
{
|
||||
consumed = scanValue(format, lval);
|
||||
if (consumed >= 0) ((epicsUInt16*)buffer)[nord] = (epicsUInt16)lval;
|
||||
debug("Stream::matchValue(%s): %s[%li] = %li\n",
|
||||
name(), pdbaddr->precord->name, nord, lval);
|
||||
break;
|
||||
}
|
||||
case double_format:
|
||||
{
|
||||
consumed = scanValue(format, dval);
|
||||
if (consumed >= 0) ((epicsFloat64*)buffer)[nord] = dval;
|
||||
// Direct assignment to buffer fails fith gcc 3.4.3 for xscale_be
|
||||
// Optimization bug?
|
||||
epicsFloat64 f64=dval;
|
||||
if (consumed >= 0) memcpy(((epicsFloat64*)buffer)+nord, &f64, sizeof(f64));
|
||||
debug("Stream::matchValue(%s): %s[%li] = %#g %#g\n",
|
||||
name(), pdbaddr->precord->name, nord, dval,
|
||||
((epicsFloat64*)buffer)[nord]);
|
||||
break;
|
||||
}
|
||||
case string_format:
|
||||
{
|
||||
consumed = scanValue(format,
|
||||
buffer+MAX_STRING_SIZE*nord, MAX_STRING_SIZE);
|
||||
debug("Stream::matchValue(%s): %s[%li] = \"%.*s\"\n",
|
||||
name(), pdbaddr->precord->name, nord, MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1084,6 +1098,7 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
"Illegal format type\n", name());
|
||||
return false;
|
||||
}
|
||||
debug("Stream::matchValue(%s): buffer after: %s\n", name(), fieldBuffer.expand()());
|
||||
if (consumed < 0) break;
|
||||
consumedInput += consumed;
|
||||
}
|
||||
@ -1127,12 +1142,13 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
{
|
||||
// write into own record, thus don't process it
|
||||
// in @init we must not process other record
|
||||
debug("Stream::matchValue(%s): dbPut(%s.%s,...)\n",
|
||||
debug("Stream::matchValue(%s): dbPut(%s.%s,%s)\n",
|
||||
name(),
|
||||
pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name);
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
fieldBuffer.expand()());
|
||||
putfunc = "dbPut";
|
||||
status = dbPut(pdbaddr, dbfMapping[format.type], fieldBuffer(), nord);
|
||||
status = dbPut(pdbaddr, dbfMapping[format.type], buffer, nord);
|
||||
if (INIT_RUN && pdbaddr->precord != record)
|
||||
{
|
||||
// clean error status of other record in @init
|
||||
@ -1144,12 +1160,13 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
else
|
||||
{
|
||||
// write into other record, thus process it
|
||||
debug("Stream::matchValue(%s): dbPutField(%s.%s,...)\n",
|
||||
debug("Stream::matchValue(%s): dbPutField(%s.%s,%s)\n",
|
||||
name(),
|
||||
pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name);
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
fieldBuffer.expand()());
|
||||
putfunc = "dbPutField";
|
||||
status = dbPutField(pdbaddr, dbfMapping[format.type], fieldBuffer(), nord);
|
||||
status = dbPutField(pdbaddr, dbfMapping[format.type], buffer, nord);
|
||||
}
|
||||
if (status != 0)
|
||||
{
|
||||
|
@ -227,7 +227,7 @@ getProtocol(const StreamBuffer& protocolAndParams)
|
||||
return new Protocol(*protocol, name, 0);
|
||||
}
|
||||
error("Protocol '%s' not found in protocol file '%s'\n",
|
||||
name(), filename());
|
||||
protocolAndParams(), filename());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -44,10 +44,10 @@ static long readData (dbCommon *record, format_t *format)
|
||||
switch (aai->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
((double *)aai->bptr)[aai->nord] = dval;
|
||||
((epicsFloat64 *)aai->bptr)[aai->nord] = (epicsFloat64)dval;
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
((float *)aai->bptr)[aai->nord] = (float)dval;
|
||||
((epicsFloat32 *)aai->bptr)[aai->nord] = (epicsFloat32)dval;
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -67,23 +67,23 @@ static long readData (dbCommon *record, format_t *format)
|
||||
switch (aai->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
((double *)aai->bptr)[aai->nord] = lval;
|
||||
((epicsFloat64 *)aai->bptr)[aai->nord] = (epicsFloat64)lval;
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
((float *)aai->bptr)[aai->nord] = (float)lval;
|
||||
((epicsFloat32 *)aai->bptr)[aai->nord] = (epicsFloat32)lval;
|
||||
break;
|
||||
case DBF_LONG:
|
||||
case DBF_ULONG:
|
||||
((long *)aai->bptr)[aai->nord] = lval;
|
||||
((epicsInt32 *)aai->bptr)[aai->nord] = (epicsInt32)lval;
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
((short *)aai->bptr)[aai->nord] = (short)lval;
|
||||
((epicsInt16 *)aai->bptr)[aai->nord] = (epicsInt16)lval;
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
((char *)aai->bptr)[aai->nord] = (char)lval;
|
||||
((epicsInt8 *)aai->bptr)[aai->nord] = (epicsInt8)lval;
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -157,29 +157,29 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
switch (aai->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
dval = ((double *)aai->bptr)[nowd];
|
||||
dval = ((epicsFloat64 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
dval = ((float *)aai->bptr)[nowd];
|
||||
dval = ((epicsFloat32 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_LONG:
|
||||
dval = ((long *)aai->bptr)[nowd];
|
||||
dval = ((epicsInt32 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
dval = ((unsigned long *)aai->bptr)[nowd];
|
||||
dval = ((epicsUInt32 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
dval = ((short *)aai->bptr)[nowd];
|
||||
dval = ((epicsInt16 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
dval = ((unsigned short *)aai->bptr)[nowd];
|
||||
dval = ((epicsUInt16 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
dval = ((char *)aai->bptr)[nowd];
|
||||
dval = ((epicsInt8 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
dval = ((unsigned char *)aai->bptr)[nowd];
|
||||
dval = ((epicsUInt8 *)aai->bptr)[nowd];
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -197,21 +197,23 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
switch (aai->ftvl)
|
||||
{
|
||||
case DBF_LONG:
|
||||
lval = ((epicsInt32 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
lval = ((long *)aai->bptr)[nowd];
|
||||
lval = ((epicsUInt32 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
lval = ((short *)aai->bptr)[nowd];
|
||||
lval = ((epicsInt16 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
lval = ((unsigned short *)aai->bptr)[nowd];
|
||||
lval = ((epicsUInt16 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
lval = ((char *)aai->bptr)[nowd];
|
||||
lval = ((epicsInt8 *)aai->bptr)[nowd];
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
lval = ((unsigned char *)aai->bptr)[nowd];
|
||||
lval = ((epicsUInt8 *)aai->bptr)[nowd];
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
|
@ -44,10 +44,10 @@ static long readData (dbCommon *record, format_t *format)
|
||||
switch (aao->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
((double *)aao->bptr)[aao->nord] = dval;
|
||||
((epicsFloat64 *)aao->bptr)[aao->nord] = (epicsFloat64)dval;
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
((float *)aao->bptr)[aao->nord] = (float)dval;
|
||||
((epicsFloat32 *)aao->bptr)[aao->nord] = (epicsFloat32)dval;
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -67,23 +67,23 @@ static long readData (dbCommon *record, format_t *format)
|
||||
switch (aao->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
((double *)aao->bptr)[aao->nord] = lval;
|
||||
((epicsFloat64 *)aao->bptr)[aao->nord] = (epicsFloat64)lval;
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
((float *)aao->bptr)[aao->nord] = (float)lval;
|
||||
((epicsFloat32 *)aao->bptr)[aao->nord] = (epicsFloat32)lval;
|
||||
break;
|
||||
case DBF_LONG:
|
||||
case DBF_ULONG:
|
||||
((long *)aao->bptr)[aao->nord] = lval;
|
||||
((epicsInt32 *)aao->bptr)[aao->nord] = (epicsInt32)lval;
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
((short *)aao->bptr)[aao->nord] = (short)lval;
|
||||
((epicsInt16 *)aao->bptr)[aao->nord] = (epicsInt16)lval;
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
((char *)aao->bptr)[aao->nord] = (char)lval;
|
||||
((epicsInt8 *)aao->bptr)[aao->nord] = (epicsInt8)lval;
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -157,29 +157,29 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
switch (aao->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
dval = ((double *)aao->bptr)[nowd];
|
||||
dval = ((epicsFloat64 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
dval = ((float *)aao->bptr)[nowd];
|
||||
dval = ((epicsFloat32 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_LONG:
|
||||
dval = ((long *)aao->bptr)[nowd];
|
||||
dval = ((epicsInt32 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
dval = ((unsigned long *)aao->bptr)[nowd];
|
||||
dval = ((epicsUInt32 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
dval = ((short *)aao->bptr)[nowd];
|
||||
dval = ((epicsInt16 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
dval = ((unsigned short *)aao->bptr)[nowd];
|
||||
dval = ((epicsUInt16 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
dval = ((char *)aao->bptr)[nowd];
|
||||
dval = ((epicsInt8 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
dval = ((unsigned char *)aao->bptr)[nowd];
|
||||
dval = ((epicsUInt8 *)aao->bptr)[nowd];
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -197,21 +197,23 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
switch (aao->ftvl)
|
||||
{
|
||||
case DBF_LONG:
|
||||
lval = ((epicsInt32 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
lval = ((long *)aao->bptr)[nowd];
|
||||
lval = ((epicsUInt32 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
lval = ((short *)aao->bptr)[nowd];
|
||||
lval = ((epicsInt16 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
lval = ((unsigned short *)aao->bptr)[nowd];
|
||||
lval = ((epicsUInt16 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
lval = ((char *)aao->bptr)[nowd];
|
||||
lval = ((epicsInt8 *)aao->bptr)[nowd];
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
lval = ((unsigned char *)aao->bptr)[nowd];
|
||||
lval = ((epicsUInt8 *)aao->bptr)[nowd];
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
|
@ -44,10 +44,10 @@ static long readData (dbCommon *record, format_t *format)
|
||||
switch (wf->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
((double *)wf->bptr)[wf->nord] = dval;
|
||||
((epicsFloat64 *)wf->bptr)[wf->nord] = (epicsFloat64)dval;
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
((float *)wf->bptr)[wf->nord] = (float)dval;
|
||||
((epicsFloat32 *)wf->bptr)[wf->nord] = (epicsFloat32)dval;
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -67,23 +67,23 @@ static long readData (dbCommon *record, format_t *format)
|
||||
switch (wf->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
((double *)wf->bptr)[wf->nord] = (double)lval;
|
||||
((epicsFloat64 *)wf->bptr)[wf->nord] = (epicsFloat64)lval;
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
((float *)wf->bptr)[wf->nord] = (float)lval;
|
||||
((epicsFloat32 *)wf->bptr)[wf->nord] = (epicsFloat32)lval;
|
||||
break;
|
||||
case DBF_LONG:
|
||||
case DBF_ULONG:
|
||||
((long *)wf->bptr)[wf->nord] = lval;
|
||||
((epicsInt32 *)wf->bptr)[wf->nord] = (epicsInt32)lval;
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
((short *)wf->bptr)[wf->nord] = (short)lval;
|
||||
((epicsInt16 *)wf->bptr)[wf->nord] = (epicsInt16)lval;
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
((char *)wf->bptr)[wf->nord] = (char)lval;
|
||||
((epicsInt8 *)wf->bptr)[wf->nord] = (epicsInt8)lval;
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -157,29 +157,29 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
switch (wf->ftvl)
|
||||
{
|
||||
case DBF_DOUBLE:
|
||||
dval = ((double *)wf->bptr)[nowd];
|
||||
dval = ((epicsFloat64 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
dval = ((float *)wf->bptr)[nowd];
|
||||
dval = ((epicsFloat32 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_LONG:
|
||||
dval = ((long *)wf->bptr)[nowd];
|
||||
dval = ((epicsInt32 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
dval = ((unsigned long *)wf->bptr)[nowd];
|
||||
dval = ((epicsUInt32 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
dval = ((short *)wf->bptr)[nowd];
|
||||
dval = ((epicsInt16 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
dval = ((unsigned short *)wf->bptr)[nowd];
|
||||
dval = ((epicsUInt16 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
dval = ((char *)wf->bptr)[nowd];
|
||||
dval = ((epicsInt8 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
dval = ((unsigned char *)wf->bptr)[nowd];
|
||||
dval = ((epicsUInt8 *)wf->bptr)[nowd];
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
@ -197,21 +197,23 @@ static long writeData (dbCommon *record, format_t *format)
|
||||
switch (wf->ftvl)
|
||||
{
|
||||
case DBF_LONG:
|
||||
lval = ((epicsInt32 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
lval = ((long *)wf->bptr)[nowd];
|
||||
lval = ((epicsUInt32 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
lval = ((short *)wf->bptr)[nowd];
|
||||
lval = ((epicsInt16 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
lval = ((unsigned short *)wf->bptr)[nowd];
|
||||
lval = ((epicsUInt16 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
lval = ((char *)wf->bptr)[nowd];
|
||||
lval = ((epicsInt8 *)wf->bptr)[nowd];
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
lval = ((unsigned char *)wf->bptr)[nowd];
|
||||
lval = ((epicsUInt8 *)wf->bptr)[nowd];
|
||||
break;
|
||||
default:
|
||||
errlogSevPrintf (errlogFatal,
|
||||
|
6
src/makedbd.pl
Normal file
6
src/makedbd.pl
Normal file
@ -0,0 +1,6 @@
|
||||
for (@ARGV) {
|
||||
print "device($_,INST_IO,dev${_}Stream,\"stream\")\n";
|
||||
}
|
||||
print "driver(stream)\n";
|
||||
print "variable(streamDebug, int)\n";
|
||||
print "registrar(streamRegistrar)\n";
|
6
src/makeref.pl
Normal file
6
src/makeref.pl
Normal file
@ -0,0 +1,6 @@
|
||||
$t=@ARGV[0];
|
||||
shift;
|
||||
for (@ARGV) {
|
||||
print "extern void* ref_${_}$t;\n";
|
||||
print "void* p$_ = ref_${_}$t;\n";
|
||||
}
|
19
stream.dbd
Normal file
19
stream.dbd
Normal file
@ -0,0 +1,19 @@
|
||||
device(aai,INST_IO,devaaiStream,"stream")
|
||||
device(aao,INST_IO,devaaoStream,"stream")
|
||||
device(ao,INST_IO,devaoStream,"stream")
|
||||
device(ai,INST_IO,devaiStream,"stream")
|
||||
device(bo,INST_IO,devboStream,"stream")
|
||||
device(bi,INST_IO,devbiStream,"stream")
|
||||
device(mbbo,INST_IO,devmbboStream,"stream")
|
||||
device(mbbi,INST_IO,devmbbiStream,"stream")
|
||||
device(mbboDirect,INST_IO,devmbboDirectStream,"stream")
|
||||
device(mbbiDirect,INST_IO,devmbbiDirectStream,"stream")
|
||||
device(longout,INST_IO,devlongoutStream,"stream")
|
||||
device(longin,INST_IO,devlonginStream,"stream")
|
||||
device(stringout,INST_IO,devstringoutStream,"stream")
|
||||
device(stringin,INST_IO,devstringinStream,"stream")
|
||||
device(waveform,INST_IO,devwaveformStream,"stream")
|
||||
device(calcout,INST_IO,devcalcoutStream,"stream")
|
||||
driver(stream)
|
||||
variable(streamDebug, int)
|
||||
registrar(streamRegistrar)
|
@ -25,21 +25,10 @@ PROD_SRCS_vxWorks = -nil-
|
||||
|
||||
PROD_LIBS = stream
|
||||
|
||||
ifdef PCRE
|
||||
# With local PCRE package
|
||||
PROD_LIBS += pcre
|
||||
else
|
||||
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||
# With system wide PCRE installation
|
||||
PROD_SYS_LIBS += pcre
|
||||
PROD_DEPLIB_DIRS += $(PCRE_LIB)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef ASYN
|
||||
# Which types of asyn busses do you have?
|
||||
ifneq ($(OS_CLASS), WIN32)
|
||||
# asynDriver up to version 4-8 does not support serial port for Windows!
|
||||
# asynDriver up to version 4-16 does not support serial port for Windows!
|
||||
streamApp_DBD += drvAsynSerialPort.dbd
|
||||
endif
|
||||
streamApp_DBD += drvAsynIPPort.dbd
|
||||
@ -59,6 +48,16 @@ endif
|
||||
|
||||
streamApp_DBD += stream.dbd
|
||||
|
||||
ifdef PCRE
|
||||
LIB_LIBS += pcre
|
||||
else
|
||||
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||
PROD_SYS_LIBS_DEFAULT += pcre
|
||||
PROD_SYS_LIBS_WIN32 += $(PCRE_LIB)\\pcre
|
||||
SHRLIB_DEPLIB_DIRS += $(PCRE_LIB)
|
||||
endif
|
||||
endif
|
||||
|
||||
PROD_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
# Write StreamDevice debug output to this file
|
||||
@ -69,7 +68,7 @@ include $(TOP)/configure/RULES
|
||||
clean:: myclean
|
||||
|
||||
myclean:
|
||||
rm -f core* StreamDebug.log
|
||||
$(RM) core* StreamDebug.log
|
||||
|
||||
endif
|
||||
|
||||
|
@ -74,6 +74,9 @@ proc receiveHandler {sock} {
|
||||
set l [split $a]
|
||||
if [catch {
|
||||
switch -- [lindex $l 0] {
|
||||
"exit" {
|
||||
exit
|
||||
}
|
||||
"disconnect" {
|
||||
sendReply $sock [string range $a 11 end]
|
||||
destroy .$sock
|
||||
|
@ -158,19 +158,22 @@ proc assure {args} {
|
||||
}
|
||||
|
||||
proc escape {string} {
|
||||
while {![string is print -failindex index $string]} {
|
||||
set char [string index $string $index]
|
||||
scan $char "%c" code
|
||||
switch $char {
|
||||
"\r" { set escaped "\\r" }
|
||||
"\n" { set escaped "\\n" }
|
||||
"\a" { set escaped "\\a" }
|
||||
"\t" { set escaped "\\t" }
|
||||
default { set escaped [format "<%02x>" $code] }
|
||||
set result ""
|
||||
set length [string length $string]
|
||||
for {set i 0} {$i < $length} {incr i} {
|
||||
set c [string index $string $i]
|
||||
scan $c %c n
|
||||
if {$n == 13} {
|
||||
append result "\\r"
|
||||
} elseif {$n == 10} {
|
||||
append result "\\n"
|
||||
} elseif {($n & 127) < 32} {
|
||||
append result [format "<%02x>" $n]
|
||||
} else {
|
||||
append result $c
|
||||
}
|
||||
set string [string replace $string $index $index $escaped]
|
||||
}
|
||||
return $string
|
||||
return $result
|
||||
}
|
||||
|
||||
proc finish {} {
|
||||
|
@ -45,6 +45,9 @@ set debug 0
|
||||
|
||||
startioc
|
||||
|
||||
set inf [format %f inf]
|
||||
set nan [format %f nan]
|
||||
|
||||
ioccmd {dbpf DZ:test1.PROC 1}
|
||||
send "3.14159265359\n"
|
||||
assure "|3.141593| 3.141593|3.14| 3.14159 | 3.141593|+3.141593|3.1 |3.141593|\n"
|
||||
@ -56,10 +59,10 @@ send "0\n"
|
||||
assure "|0.000000| 0.000000|0.00| 0.00000 | 0.000000|+0.000000|0.0 |0.000000|\n"
|
||||
ioccmd {dbpf DZ:test1.PROC 1}
|
||||
send "NAN\n"
|
||||
assure "|nan| nan|nan| nan | nan|+nan|nan |nan|\n"
|
||||
assure "|$nan| $nan|$nan| $nan | $nan|+$nan|$nan |$nan|\n"
|
||||
ioccmd {dbpf DZ:test1.PROC 1}
|
||||
send "-Inf\n"
|
||||
assure "|-inf| -inf|-inf|-inf |-inf|-inf|-inf |-inf|\n"
|
||||
assure "|-$inf| -$inf|-$inf|-$inf |-$inf|-$inf|-$inf |-$inf|\n"
|
||||
ioccmd {dbpf DZ:test1.PROC 1}
|
||||
send "1e6\n"
|
||||
assure "|1000000.000000|1000000.000000|1000000.00| 1000000.00000| 1000000.000000|+1000000.000000|1000000.0|1000000.000000|\n"
|
||||
|
@ -1,75 +0,0 @@
|
||||
#!/usr/bin/env tclsh
|
||||
source streamtestlib.tcl
|
||||
|
||||
# Define records, protocol and startup (text goes to files)
|
||||
# The asynPort "dummy" is not connected to any I/O
|
||||
# Send commands to the ioc shell with ioccmd
|
||||
|
||||
set records {
|
||||
record (ao, "DZ:test1")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto test1 dummy")
|
||||
}
|
||||
}
|
||||
|
||||
set protocol {
|
||||
Terminator = LF;
|
||||
test1 {exec "dbpr %(NAME)s %i >testDummyInterface.out";}
|
||||
}
|
||||
|
||||
set startup {
|
||||
}
|
||||
|
||||
set debug 0
|
||||
|
||||
startioc
|
||||
|
||||
ioccmd {dbpf DZ:test1 3}
|
||||
|
||||
after 1000
|
||||
|
||||
if [catch {
|
||||
set fd [open testDummyInterface.out]
|
||||
set output [read $fd]
|
||||
close $fd
|
||||
} msg] {
|
||||
puts stderr $msg
|
||||
incr faults
|
||||
}
|
||||
|
||||
set expected {ACKS: NO_ALARM ACKT: YES ADEL: 0 ALST: 0
|
||||
AOFF: 0 ASG: ASLO: 0 BKPT: 00
|
||||
DESC: DISA: 0 DISP: 0 DISS: NO_ALARM
|
||||
DISV: 1 DOL:CONSTANT DRVH: 0 DRVL: 0
|
||||
DTYP: stream EGU: EGUF: 0 EGUL: 0
|
||||
EOFF: 0 ESLO: 1 EVNT: 0 FLNK:CONSTANT 0
|
||||
HHSV: NO_ALARM HIGH: 0 HIHI: 0 HOPR: 0
|
||||
HSV: NO_ALARM HYST: 0 INIT: 1
|
||||
IVOA: Continue normally IVOV: 0 LALM: 3
|
||||
LBRK: 0 LCNT: 0 LINR: NO CONVERSION LLSV: NO_ALARM
|
||||
LOLO: 0 LOPR: 0 LOW: 0 LSV: NO_ALARM
|
||||
MDEL: 0 MLST: 0 NAME: DZ:test1 NSEV: NO_ALARM
|
||||
NSTA: NO_ALARM OIF: Full OMOD: 1 OMSL: supervisory
|
||||
ORAW: 0 ORBV: 0 OROC: 0
|
||||
OUT:INST_IO @test.proto test1 dummy OVAL: 3 PACT: 1
|
||||
PHAS: 0 PINI: NO PREC: 0 PRIO: LOW
|
||||
PROC: 0 PUTF: 1 PVAL: 3 RBV: 0
|
||||
ROFF: 0 RPRO: 0 RVAL: 3 SCAN: Passive
|
||||
SDIS:CONSTANT SEVR: INVALID SIML:CONSTANT SIMM: NO
|
||||
SIMS: NO_ALARM SIOL:CONSTANT STAT: UDF TIME: <undefined>
|
||||
TPRO: 0 TSE: 0 TSEL:CONSTANT UDF: 0
|
||||
VAL: 3
|
||||
}
|
||||
|
||||
if {"$output" != "$expected"} {
|
||||
puts stderr "Wrong output:"
|
||||
puts stderr "$output"
|
||||
puts stderr "instead of:"
|
||||
puts stderr "$expected"
|
||||
incr faults
|
||||
} else {
|
||||
file delete testDummyInterface.out
|
||||
}
|
||||
|
||||
finish
|
41
streamApp/tests/testParallelAccess
Executable file
41
streamApp/tests/testParallelAccess
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env tclsh
|
||||
source streamtestlib.tcl
|
||||
|
||||
# Define records, protocol and startup (text goes to files)
|
||||
# The asynPort "device" is connected to a network TCP socket
|
||||
# Talk to the socket with send/receive/assure
|
||||
# Send commands to the ioc shell with ioccmd
|
||||
|
||||
set records {
|
||||
record (ao, "DZ:slow")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto slow device")
|
||||
}
|
||||
record (ao, "DZ:fast")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto fast device")
|
||||
}
|
||||
}
|
||||
|
||||
set protocol {
|
||||
Terminator = LF;
|
||||
slow { out "slow start"; wait 1000; out "slow finished";}
|
||||
fast { out "fast"; }
|
||||
}
|
||||
|
||||
set startup {
|
||||
}
|
||||
|
||||
set debug 0
|
||||
|
||||
startioc
|
||||
|
||||
ioccmd {dbpf DZ:slow 1}
|
||||
ioccmd {dbpf DZ:fast 1}
|
||||
assure "slow start\n"
|
||||
assure "slow finished\n"
|
||||
assure "fast\n"
|
||||
|
||||
finish
|
@ -12,10 +12,26 @@ set records {
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto test1 device")
|
||||
}
|
||||
record (longin, "DZ:test2")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (INP, "@test.proto test2 device")
|
||||
}
|
||||
record (longin, "DZ:test3")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (INP, "@test.proto test3 device")
|
||||
}
|
||||
record (longin, "DZ:test4")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (INP, "@test.proto test4 device")
|
||||
}
|
||||
}
|
||||
|
||||
set protocol {
|
||||
Terminator = LF;
|
||||
OutTerminator = LF;
|
||||
MaxInput = 4;
|
||||
test1 {
|
||||
out "%r"; out "%.1r"; out "%.2r"; out "%.3r"; out "%.4r"; out "%.5r";
|
||||
out "%#r"; out "%#.1r"; out "%#.2r"; out "%#.3r"; out "%#.4r"; out "%#.5r";
|
||||
@ -23,6 +39,18 @@ set protocol {
|
||||
out "%0r"; out "%01r"; out "%02r"; out "%03r"; out "%04r"; out "%05r";
|
||||
out "%#0r"; out "%#01r"; out "%#02r"; out "%#03r"; out "%#04r"; out "%#05r";
|
||||
};
|
||||
test2 {
|
||||
in "%04.4r";
|
||||
out "%08x";
|
||||
}
|
||||
test3{
|
||||
in "%#3r\?";
|
||||
out "%08x";
|
||||
}
|
||||
test4{
|
||||
in "%#03r\?";
|
||||
out "%08x";
|
||||
}
|
||||
}
|
||||
|
||||
set startup {
|
||||
@ -192,6 +220,35 @@ assure "\xef\x00\x00\n"
|
||||
assure "\xef\x00\x00\x00\n"
|
||||
assure "\xef\x00\x00\x00\x00\n"
|
||||
|
||||
ioccmd {dbpf DZ:test2.PROC 1}
|
||||
send "\x01\x02\x03\x04"
|
||||
assure "01020304\n"
|
||||
ioccmd {dbpf DZ:test2.PROC 1}
|
||||
send "\xde\xad\xbe\xef"
|
||||
assure "deadbeef\n"
|
||||
ioccmd {dbpf DZ:test2.PROC 1}
|
||||
send "\x00\x00\x00\x00"
|
||||
assure "00000000\n"
|
||||
|
||||
ioccmd {dbpf DZ:test3.PROC 1}
|
||||
send "\x04\x03\x02\x01"
|
||||
assure "00020304\n"
|
||||
ioccmd {dbpf DZ:test3.PROC 1}
|
||||
send "\xde\xad\xbe\xef"
|
||||
assure "ffbeadde\n"
|
||||
ioccmd {dbpf DZ:test3.PROC 1}
|
||||
send "\x00\x00\x00\x00"
|
||||
assure "00000000\n"
|
||||
|
||||
ioccmd {dbpf DZ:test4.PROC 1}
|
||||
send "\x04\x03\x02\x01"
|
||||
assure "00020304\n"
|
||||
ioccmd {dbpf DZ:test4.PROC 1}
|
||||
send "\xde\xad\xbe\xef"
|
||||
assure "00beadde\n"
|
||||
ioccmd {dbpf DZ:test4.PROC 1}
|
||||
send "\x00\x00\x00\x00"
|
||||
assure "00000000\n"
|
||||
|
||||
|
||||
finish
|
||||
|
@ -48,6 +48,7 @@ int main () {
|
||||
assert (haystack.find(needle) == 0);
|
||||
haystack.clear();
|
||||
assert (haystack.find(needle) == 0);
|
||||
haystack.reserve(10000);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
@ -1,3 +1,4 @@
|
||||
rm -f test.* *.out *.ioclog StreamDebug.log
|
||||
for i in test*
|
||||
do
|
||||
if [ $i != testall -a -x $i ]
|
||||
@ -6,7 +7,7 @@ do
|
||||
if ! $i "$@"
|
||||
then
|
||||
echo -e "\033[31;7mFailed.\033[0m"
|
||||
(( fail++ ))
|
||||
(( fail+=1 ))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
Reference in New Issue
Block a user