Compare commits

...

18 Commits

Author SHA1 Message Date
2cd969d643 allow assigned enums: %#{one=1|two|neg=-1} 2010-06-09 13:12:00 +00:00
0c9d4dc4c0 %m format renamed from Exponential to MantissaExponent 2010-06-09 08:11:05 +00:00
ef3b2ec9fd allow formats in exec 2010-06-09 08:10:33 +00:00
1fb402e838 Allow optional input %? format 2010-06-09 08:05:05 +00:00
eae987e7f1 Find byte order at run-time because there is no standard how to do this at compile-time. 2010-06-09 08:03:49 +00:00
93906dd022 Bugfix: prec too long had corrupted output 2010-06-09 08:02:22 +00:00
7e717c564d *** empty log message *** 2010-06-09 08:01:03 +00:00
14b60c210a renamed %m from Exponention to MantissaExponent 2010-06-09 08:00:08 +00:00
8dae0afa30 take care of early input (race condition device reply and start of in command) 2010-06-09 07:54:47 +00:00
95bf2c78c2 install headers to allow plugins (formats) in other projects 2010-06-09 07:44:51 +00:00
8c10e5395c Initial Import 2009-05-20 10:12:59 +00:00
69de0b9f31 bugfix: find() did not find 1 char strings 2008-09-16 07:29:26 +00:00
22ae510dca comments fixed 2008-09-16 07:28:47 +00:00
5fdf3912c8 avoid compiler warning on 64 bit machines 2008-09-16 07:27:27 +00:00
b50aec424f increase minor version number 2008-09-16 07:26:41 +00:00
4a1033b6dc allow for 64 bit machines 2008-09-16 07:26:02 +00:00
68e178d41b Use long constant 1L to allow for 64 bit machines 2008-09-16 07:25:03 +00:00
e83ceda41c get rid of writeRaw for asyn 4.10 2008-09-16 07:24:24 +00:00
23 changed files with 303 additions and 202 deletions

5
MODULE Normal file
View File

@ -0,0 +1,5 @@
# Please change the following email with yours.
Email: dirk.zimoch@psi.ch
Module-Name: StreamDevice2
Description: StreamDevice2
Project-Name:

View File

@ -15,7 +15,7 @@ FORMATS += RawFloat
FORMATS += Binary
FORMATS += Checksum
FORMATS += Regexp
FORMATS += Exponential
FORMATS += MantissaExponent
RECORDTYPES += aai aao
RECORDTYPES += ao ai
RECORDTYPES += bo bi
@ -32,6 +32,11 @@ SOURCES += $(wildcard src/Stream*.cc)
SOURCES += src/StreamVersion.c
SOURCES_3.14 += src/devcalcoutStream.c
HEADERS += StreamFormat.h
HEADERS += StreamFormatConverter.h
HEADERS += StreamBuffer.h
HEADERS += StreamError.h
ifeq (${EPICS_BASETYPE},3.13)
USR_INCLUDES += -include $(INSTALL_INCLUDE)/compat3_13.h
endif

View File

@ -59,12 +59,12 @@ writeRequest()
pasynManager->queueRequest()
when request is handled
pasynOctet->flush()
pasynOctet->writeRaw()
if writeRaw() times out
pasynOctet->write()
if write() times out
writeCallback(StreamIoTimeout)
if writeRaw fails otherwise
if write fails otherwise
writeCallback(StreamIoFault)
if writeRaw succeeds and all bytes have been written
if write succeeds and all bytes have been written
writeCallback(StreamIoSuccess)
if not all bytes can be written
pasynManager->queueRequest() to write next part
@ -605,15 +605,27 @@ writeHandler()
size_t streameoslen;
const char* streameos = getOutTerminator(streameoslen);
if (streameos) // stream has added eos
int oldeoslen = -1;
char oldeos[16];
if (streameos) // stream has already added eos, don't do it again in asyn
{
status = pasynOctet->writeRaw(pvtOctet, pasynUser,
outputBuffer, outputSize, &written);
// clear terminator for asyn
status = pasynOctet->getOutputEos(pvtOctet,
pasynUser, oldeos, sizeof(oldeos)-1, &oldeoslen);
if (status != asynSuccess)
{
oldeoslen = -1;
// No EOS support?
}
pasynOctet->setOutputEos(pvtOctet, pasynUser,
NULL, 0);
}
else // asyn should add eos
status = pasynOctet->write(pvtOctet, pasynUser,
outputBuffer, outputSize, &written);
if (oldeoslen >= 0) // restore asyn terminator
{
status = pasynOctet->write(pvtOctet, pasynUser,
outputBuffer, outputSize, &written);
pasynOctet->setOutputEos(pvtOctet, pasynUser,
oldeos, oldeoslen);
}
switch (status)
{
@ -773,7 +785,7 @@ readHandler()
pasynUser->timeout = replyTimeout;
}
bool waitForReply = true;
int received;
size_t received;
int eomReason;
asynStatus status;
long readMore;
@ -785,7 +797,7 @@ readHandler()
eomReason = 0;
status = pasynOctet->read(pvtOctet, pasynUser,
buffer, bytesToRead, (size_t*)&received, &eomReason);
buffer, bytesToRead, &received, &eomReason);
if (ioAction == Read || status != asynTimeout)
{
debug("AsynDriverInterface::readHandler(%s): "
@ -804,8 +816,8 @@ readHandler()
debug("AsynDriverInterface::readHandler(%s): "
"AsyncRead poll: received %d of %d bytes \"%s\" "
"eomReason=%s [data ignored]\n",
clientName(), received, bytesToRead,
StreamBuffer(buffer, received).expand()(),
clientName(), (int)received, bytesToRead,
StreamBuffer(buffer, (int)received).expand()(),
eomReasonStr[eomReason&0x7]);
#endif
// ignore what we got from here.
@ -818,8 +830,8 @@ readHandler()
debug("AsynDriverInterface::readHandler(%s): "
"received %d of %d bytes \"%s\" "
"eomReason=%s\n",
clientName(), received, bytesToRead,
StreamBuffer(buffer, received).expand()(),
clientName(), (int)received, bytesToRead,
StreamBuffer(buffer, (int)received).expand()(),
eomReasonStr[eomReason&0x7]);
#endif
// asynOctet->read() cuts off terminator, but:
@ -839,7 +851,7 @@ readHandler()
size_t i;
for (i = 0; i < deveoslen; i++, received++)
{
if (received >= 0) buffer[received] = deveos[i];
if ((int)received >= 0) buffer[received] = deveos[i];
// It is safe to add to buffer here, because
// the terminator was already there before
// asynOctet->read() had cut it.
@ -877,7 +889,7 @@ readHandler()
debug("AsynDriverInterface::readHandler(%s): "
"ioAction=%s, timeout after %d of %d bytes \"%s\"\n",
clientName(), ioActionStr[ioAction],
received, bytesToRead,
(int)received, bytesToRead,
StreamBuffer(buffer, received).expand()());
#endif
if (ioAction == AsyncRead || ioAction == AsyncReadMore)
@ -944,28 +956,11 @@ void intrCallbackOctet(void* /*pvt*/, asynUser *pasynUser,
// Problems here:
// 1. We get this message too when we are the poller.
// Thus we have to ignore what we got from polling.
// 2. We get this message multiple times when original reader
// reads in chunks.
// 3. eomReason=ASYN_EOM_CNT when message was too long for
// 2. eomReason=ASYN_EOM_CNT when message was too long for
// internal buffer of asynDriver.
if (!interruptAccept) return; // too early to process records
debug("AsynDriverInterface::intrCallbackOctet(%s) ioAction = %s\n",
interface->clientName(), ioActionStr[interface->ioAction]);
if (interface->ioAction == AsyncRead ||
interface->ioAction == AsyncReadMore)
{
interface->asynReadHandler(data, numchars, eomReason);
}
else
{
#ifndef NO_TEMPORARY
debug("AsynDriverInterface::intrCallbackOctet(%s, buffer=\"%s\", "
"received=%d eomReason=%s) ioAction=%s\n",
interface->clientName(), StreamBuffer(data, numchars).expand()(),
numchars, eomReasonStr[eomReason&0x7], ioActionStr[interface->ioAction]);
#endif
}
interface->asynReadHandler(data, numchars, eomReason);
}
// get asynchronous input

View File

@ -65,7 +65,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
{
// find number of significant bits
prec = sizeof (value) * 8;
while (prec && (value & (1 << (prec - 1))) == 0) prec--;
while (prec && (value & (1L << (prec - 1))) == 0) prec--;
}
if (prec == 0) prec++; // print at least one bit
int width = prec;
@ -75,7 +75,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
char fill = (format.flags & zero_flag) ? zero : ' ';
if (format.flags & alt_flag)
{
// little endian (least significan bit first)
// little endian (least significant bit first)
if (!(format.flags & left_flag))
{
// pad left
@ -99,7 +99,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
}
else
{
// big endian (most significan bit first)
// big endian (most significant bit first)
if (!(format.flags & left_flag))
{
// pad left
@ -111,7 +111,7 @@ printLong(const StreamFormat& format, StreamBuffer& output, long value)
}
while (prec--)
{
output.append((value & (1 << prec)) ? one : zero);
output.append((value & (1L << prec)) ? one : zero);
width--;
}
while (width--)

View File

@ -38,10 +38,10 @@ SYNAPPS_RECORDS += scalcout
FORMATS += Enum
FORMATS += BCD
FORMATS += Raw
FORMATS += RawFloat
FORMATS += Binary
FORMATS += Checksum
FORMATS += Exponential
FORMATS += RawFloat
FORMATS += MantissaExponent
# Want Perl regular expression matching?
# If PCRE is installed at the same location for all

View File

@ -21,6 +21,7 @@
#include "StreamFormatConverter.h"
#include "StreamError.h"
#include "StreamProtocol.h"
#include <stdlib.h>
// Enum %{string0|string1|...}
@ -31,44 +32,62 @@ class EnumConverter : public StreamFormatConverter
int scanLong(const StreamFormat&, const char*, long&);
};
// info format: <numEnums><index><string>0<index><string>0...
int EnumConverter::
parse(const StreamFormat& fmt, StreamBuffer& info,
const char*& source, bool)
{
if (fmt.flags & (left_flag|sign_flag|space_flag|zero_flag|alt_flag))
if (fmt.flags & (left_flag|sign_flag|space_flag|zero_flag))
{
error("Use of modifiers '-', '+', ' ', '0', '#'"
error("Use of modifiers '-', '+', ' ', '0' "
"not allowed with %%{ conversion\n");
return false;
}
int i = info.length(); // put maxValue here later
info.append('\0');
int maxValue = 0;
long numEnums = 0;
int n = info.length(); // put numEnums here later
info.append(&numEnums, sizeof(numEnums));
long index = 0;
int i = 0;
i = info.length(); // put index here later
info.append(&index, sizeof(index));
while (*source)
{
switch (*source)
if (*source == '=' && (fmt.flags & alt_flag))
{
case '|':
info.append('\0');
if (++maxValue > 255)
{
error("Too many enums (max 256)\n");
return false;
}
break;
case '}':
source++;
info.append('\0');
info[i] = maxValue;
debug("EnumConverter::parse %d choices: %s\n",
maxValue+1, info.expand(i+1)());
return enum_format;
case esc:
info.append(*source++);
default:
info.append(*source);
char* p;
index = strtol(++source, &p, 0);
if (p == source || (*p != '|' && *p != '}'))
{
error("Integer expected after '=' "
"in %%{ format conversion\n");
return false;
}
memcpy(info(i), &index, sizeof(index));
source = p;
}
if (*source == '|' || *source == '}')
{
numEnums++;
info.append('\0');
if (*source++ == '}')
{
memcpy(info(n), &numEnums, sizeof(numEnums));
debug("EnumConverter::parse %ld choices: %s\n",
numEnums, info.expand()());
return enum_format;
}
index ++;
i = info.length();
info.append(&index, sizeof(index));
}
else
{
if (*source == esc)
info.append(*source++);
info.append(*source++);
}
source++;
}
error("Missing '}' after %%{ format conversion\n");
return false;
@ -77,14 +96,10 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
bool EnumConverter::
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
{
long maxValue = fmt.info[0]; // number of enums
const char* s = fmt.info+1; // first enum string
if (value < 0 || value > maxValue)
{
error("Value %li out of range [0...%li]\n", value, maxValue);
return false;
}
while (value--)
const char* s = fmt.info;
long numEnums = extract<long>(s);
long index = extract<long>(s);
while (numEnums-- && (value != index))
{
while(*s)
{
@ -92,6 +107,12 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
s++;
}
s++;
index = extract<long>(s);
}
if (numEnums == -1)
{
error("Value %li not found in enum set\n", value);
return false;
}
while(*s)
{
@ -106,14 +127,16 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
{
debug("EnumConverter::scanLong(%%%c, \"%s\")\n",
fmt.conv, input);
long maxValue = fmt.info[0]; // number of enums
const char* s = fmt.info+1; // first enum string
const char* s = fmt.info;
long numEnums = extract<long>(s);
long index;
int length;
long val;
bool match;
for (val = 0; val <= maxValue; val++)
while (numEnums--)
{
debug("EnumConverter::scanLong: check #%ld \"%s\"\n", val, s);
index = extract<long>(s);
debug("EnumConverter::scanLong: check #%ld \"%s\"\n", index, s);
length = 0;
match = true;
while(*s)
@ -129,8 +152,8 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
}
if (match)
{
debug("EnumConverter::scanLong: value %ld matches\n", val);
value = val;
debug("EnumConverter::scanLong: value %ld matches\n", index);
value = index;
return length;
}
s++;

View File

@ -70,7 +70,7 @@ SHRLIB_DEPLIB_DIRS += $(PCRE_LIB)
endif
endif
LIB_LIBS += Com dbIoc dbStaticIoc registryIoc iocsh
LIB_LIBS += $(EPICS_BASE_IOC_LIBS)
ifeq ($(USE_MEMGUARD),YES)
# memguard looks for memory leaks (gcc only)

View File

@ -1,8 +1,7 @@
/***************************************************************
* StreamDevice Support *
* *
* (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) *
* (C) 2007 Dirk Zimoch (dirk.zimoch@psi.ch) *
* (C) 2008 Dirk Zimoch (dirk.zimoch@psi.ch) *
* *
* This is a custom exponential format converter for *
* StreamDevice. *
@ -32,26 +31,26 @@
// But why not +11000-04 ?
// For writing, I chose the following convention:
// Format precision defines number of digits in mantissa
// Number of digits in exponent is at least 2
// No leading '0' in mantissa (except for 0.0 of course)
// Number of digits in exponent is at least 2
// Format flags +, -, and space are supported in the usual way
// Flags #, 0 are not supported
class ExponentialConverter : public StreamFormatConverter
class MantissaExponentConverter : public StreamFormatConverter
{
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
virtual int scanDouble(const StreamFormat&, const char*, double&);
virtual bool printDouble(const StreamFormat&, StreamBuffer&, double);
};
int ExponentialConverter::
int MantissaExponentConverter::
parse(const StreamFormat& fmt, StreamBuffer& info,
const char*& source, bool scanFormat)
{
return double_format;
}
int ExponentialConverter::
int MantissaExponentConverter::
scanDouble(const StreamFormat& fmt, const char* input, double& value)
{
int mantissa;
@ -61,11 +60,11 @@ scanDouble(const StreamFormat& fmt, const char* input, double& value)
sscanf(input, "%d%d%n", &mantissa, &exponent, &length);
if (fmt.flags & skip_flag) return length;
if (length == -1) return -1;
value = (double)(mantissa) * pow(10, exponent);
value = (double)(mantissa) * pow(10.0, exponent);
return length;
}
bool ExponentialConverter::
bool MantissaExponentConverter::
printDouble(const StreamFormat& fmt, StreamBuffer& output, double value)
{
// Have to divide value into mantissa and exponent
@ -73,21 +72,23 @@ printDouble(const StreamFormat& fmt, StreamBuffer& output, double value)
// number of characters in exponent is at least 2
int spaces;
StreamBuffer buf;
int prec = fmt.prec;
buf.printf("%.*e", fmt.prec-1, fabs(value));
if (prec < 1) prec = 6;
buf.printf("%.*e", prec-1, fabs(value)/pow(10.0, prec-1));
buf.remove(1,1);
buf.remove(buf.find('e'),1);
spaces = fmt.width-buf.length();
if (fmt.flags & (space_flag|sign_flag) || value < 0) spaces--;
if (fmt.flags & (space_flag|sign_flag) || value < 0.0) spaces--;
if (spaces < 0) spaces = 0;
if (!(fmt.flags & left_flag))
output.append(' ', spaces);
if (fmt.flags & (space_flag|sign_flag) == space_flag && value >= 0)
if ((fmt.flags & (space_flag|sign_flag)) == space_flag && value >= 0.0)
output.append(' ');
if (fmt.flags & sign_flag && value >= 0)
if (fmt.flags & sign_flag && value >= 0.0)
output.append('+');
if (value <= 0)
if (value < 0.0)
output.append('-');
output.append(buf);
if (fmt.flags & left_flag)
@ -95,5 +96,5 @@ printDouble(const StreamFormat& fmt, StreamBuffer& output, double value)
return true;
}
RegisterConverter (ExponentialConverter, "m");
RegisterConverter (MantissaExponentConverter, "m");

View File

@ -40,10 +40,12 @@ parse(const StreamFormat&, StreamBuffer&,
bool RawConverter::
printLong(const StreamFormat& format, StreamBuffer& output, long value)
{
int prec = format.prec; // number of bytes from value
if (prec == -1) prec = 1; // default: 1 byte
int width = prec; // number of bytes in output
int prec = format.prec; // number of bytes from value
if (prec == -1) prec = 1; // default: 1 byte
int width = prec; // number of bytes in output
if (prec > (int)sizeof(long)) prec=sizeof(long);
if (format.width > width) width = format.width;
char byte = 0;
if (format.flags & alt_flag) // little endian (lsb first)
{

View File

@ -21,21 +21,7 @@
#include "StreamFormatConverter.h"
#include "StreamError.h"
#ifdef vxWorks
#include "vxWorks.h"
#define __BYTE_ORDER _BYTE_ORDER
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
#define __BIG_ENDIAN _BIG_ENDIAN
#else
// Let's hope all other architectures have endian.h
#include "endian.h"
#endif
#ifndef __BYTE_ORDER
#error define __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN
#endif
#if (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
static int endian = 0;
// Raw Float Converter %R
@ -50,6 +36,17 @@ int RawFloatConverter::
parse(const StreamFormat& format, StreamBuffer&,
const char*&, bool)
{
// Find out byte order
if (!endian) {
union {long l; char c [sizeof(long)];} u;
u.l=1;
if (u.c[0]) { endian = 1234;} // little endian
else if (u.c[sizeof(long)-1]) { endian = 4321;} // big endian
else {
error ("Cannot find out byte order for %%R format.\n");
return false;
}
}
// Assume IEEE formats with 4 or 8 bytes (default: 4)
if (format.width==0 || format.width==4 || format.width==8)
return double_format;
@ -76,15 +73,10 @@ printDouble(const StreamFormat& format, StreamBuffer& output, double value)
buffer.fval = value;
else
buffer.dval = value;
#if (__BYTE_ORDER == __BIG_ENDIAN)
bool swap = format.flags & alt_flag;
#else
bool swap = !(format.flags & alt_flag);
#endif
if (swap)
if (!(format.flags & alt_flag) ^ (endian == 4321))
{
// swap if byte orders differ
for (n = nbOfBytes-1; n >= 0; n--)
{
output.append(buffer.bytes[n]);
@ -119,14 +111,9 @@ scanDouble(const StreamFormat& format, const char* input, double& value)
return(nbOfBytes); // just skip input
}
#if (__BYTE_ORDER == __BIG_ENDIAN)
bool swap = format.flags & alt_flag;
#else
bool swap = !(format.flags & alt_flag);
#endif
if (swap)
if (!(format.flags & alt_flag) ^ (endian == 4321))
{
// swap if byte orders differ
for (n = nbOfBytes-1, i = 0; n >= 0; n--, i++)
{
buffer.bytes[n] = input[i];
@ -147,5 +134,3 @@ scanDouble(const StreamFormat& format, const char* input, double& value)
}
RegisterConverter (RawFloatConverter, "R");
#endif /* known byte order */

View File

@ -112,7 +112,7 @@ scanString(const StreamFormat& fmt, const char* input,
if (!(fmt.flags & sign_flag)) {
debug("Matching string \"%s\" too long (%d>%d bytes)\n",
StreamBuffer(input+ovector[subexpr*2], len).expand()(),
len, maxlen-1);
(int)len, (int)maxlen-1);
return -1;
}
len = maxlen-1;

View File

@ -135,7 +135,7 @@ find(const void* m, long size, long start) const
start += len;
if (start < 0) start = 0;
}
if (start >= len-size+1) return -1; // find nothing after end
if (start+size > len) return -1; // find nothing after end
if (!m || size <= 0) return start; // find empty string at start
const char* s = static_cast<const char*>(m);
char* b = buffer+offs;
@ -143,12 +143,12 @@ find(const void* m, long size, long start) const
long i;
while ((p = static_cast<char*>(memchr(p, s[0], b-p+len-size+1))))
{
i = 1;
while (p[i] == s[i])
for (i = 1; i < size; i++)
{
if (++i >= size) return p-b;
if (p[i] != s[i]) goto next;
}
p++;
return p-b;
next: p++;
}
return -1;
}

View File

@ -144,7 +144,7 @@ public:
StreamBuffer& replace(long pos, long length, const StreamBuffer& s)
{return replace(pos, length, s.buffer+s.offs, s.len);}
// replace: delete part of buffer
// remove: delete from start/pos
StreamBuffer& remove(long pos, long length)
{return replace(pos, length, NULL, 0);}
@ -152,7 +152,7 @@ public:
{if (length>len) length=len;
offs+=length; len-=length; return *this;}
// replace: delete end of buffer
// truncate: delete end of buffer
StreamBuffer& truncate(long pos)
{return replace(pos, len, NULL, 0);}

View File

@ -360,7 +360,7 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
{
buffer.append(exec_cmd);
if (!protocol->compileString(buffer, args,
NoFormat, this))
PrintFormat, this))
{
return false;
}
@ -390,6 +390,22 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
// Run the protocol
// Input and events may come asynchonously from the bus driver
// Especially in the sequence 'out "request"; in "reply";' the
// reply can come before the 'in' command has actually started.
// For asyncronous protocols, input can come at any time.
// Thus, we must always accept input and event while the protocol
// is running or when asyncronous mode is active.
// Early input and event must be buffered until 'in' or 'event'
// start. An 'out' command must discard any early input to avoid
// problems with late input from aborted protocols.
// Async mode ends on Abort or Error or if another command comes
// after the asynchronous 'in' command.
// Input can be discarded when it is not accepted any more, i.e.
// at the end of syncronous protocols and when an asynchronous
// mode ends (but not when 'in'-only protocol finishes normally).
bool StreamCore::
startProtocol(StartMode startMode)
{
@ -443,7 +459,7 @@ finishProtocol(ProtocolResult status)
flags & WaitPending ? "timerCallback()" : "");
status = Fault;
}
flags &= ~(AcceptInput|AcceptEvent);
//// flags &= ~(AcceptInput|AcceptEvent);
if (runningHandler)
{
// get original error status
@ -518,6 +534,7 @@ finishProtocol(ProtocolResult status)
flags &= ~BusOwner;
}
busFinish();
flags &= ~(AcceptInput|AcceptEvent);
protocolFinishHook(status);
}
@ -539,16 +556,16 @@ evalCommand()
switch (*commandIndex++)
{
case out_cmd:
flags &= ~(AcceptInput|AcceptEvent);
//// flags &= ~(AcceptInput|AcceptEvent);
return evalOut();
case in_cmd:
flags &= ~AcceptEvent;
//// flags &= ~AcceptEvent;
return evalIn();
case wait_cmd:
flags &= ~(AcceptInput|AcceptEvent);
//// flags &= ~(AcceptInput|AcceptEvent);
return evalWait();
case event_cmd:
flags &= ~AcceptInput;
//// flags &= ~AcceptInput;
return evalEvent();
case exec_cmd:
return evalExec();
@ -787,6 +804,8 @@ lockCallback(StreamIoStatus status)
flags |= BusOwner;
if (status != StreamIoSuccess)
{
error("%s: Lock timeout\n",
name());
finishProtocol(LockTimeout);
return;
}
@ -907,7 +926,7 @@ readCallback(StreamIoStatus status,
#endif
return 0;
}
flags &= ~AcceptInput;
//// flags &= ~AcceptInput;
unparsedInput = false;
switch (status)
{
@ -966,9 +985,15 @@ readCallback(StreamIoStatus status,
{
// look for terminator
end = inputBuffer.find(inTerminator);
if (end >= 0) termlen = inTerminator.length();
debug("StreamCore::readCallback(%s) inTerminator %sfound\n",
name(), end >= 0 ? "" : "not ");
if (end >= 0)
{
termlen = inTerminator.length();
debug("StreamCore::readCallback(%s) inTerminator %s at position %ld\n",
name(), inTerminator.expand()(), end);
} else {
debug("StreamCore::readCallback(%s) inTerminator %s not found\n",
name(), inTerminator.expand()());
}
}
if (status == StreamIoEnd && end < 0)
{
@ -990,6 +1015,12 @@ readCallback(StreamIoStatus status,
end = maxInput;
termlen = 0;
}
if (end >= 0)
{
// be forgiving with timeout because end is found
if (status == StreamIoTimeout)
status = StreamIoEnd;
}
if (end < 0)
{
// no end found
@ -1006,23 +1037,22 @@ readCallback(StreamIoStatus status,
}
// try to parse what we got
end = inputBuffer.length();
if (!(flags & AsyncMode))
if (flags & AsyncMode)
{
debug("StreamCore::readCallback(%s) async timeout: just restart\n",
name());
inputBuffer.clear();
commandIndex = commandStart;
evalIn();
return 0;
}
else
{
error("%s: Timeout after reading %ld byte%s \"%s%s\"\n",
name(), end, end==1 ? "" : "s", end > 20 ? "..." : "",
inputBuffer.expand(-20)());
}
}
if (status == StreamIoTimeout && (flags & AsyncMode))
{
debug("StreamCore::readCallback(%s) async timeout: just restart\n",
name());
inputBuffer.clear();
commandIndex = commandStart;
evalIn();
return 0;
}
inputLine.set(inputBuffer(), end);
debug("StreamCore::readCallback(%s) input line: \"%s\"\n",
@ -1063,7 +1093,7 @@ readCallback(StreamIoStatus status,
return 0;
}
// end input mode and do next command
flags &= ~(AsyncMode|AcceptInput);
//// flags &= ~(AsyncMode|AcceptInput);
// -- should we tell someone that input has finished? --
evalCommand();
return 0;
@ -1136,14 +1166,21 @@ matchInput()
}
if (consumed < 0)
{
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
if (fmt.flags & default_flag)
{
error("%s: Input \"%s%s\" does not match format %%%s\n",
name(), inputLine.expand(consumedInput, 20)(),
inputLine.length()-consumedInput > 20 ? "..." : "",
formatstring);
consumed = 0;
}
else
{
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
{
error("%s: Input \"%s%s\" does not match format %%%s\n",
name(), inputLine.expand(consumedInput, 20)(),
inputLine.length()-consumedInput > 20 ? "..." : "",
formatstring);
}
return false;
}
return false;
}
consumedInput += consumed;
break;
@ -1293,8 +1330,16 @@ scanValue(const StreamFormat& fmt, long& value)
scanLong(fmt, inputLine(consumedInput), value);
debug("StreamCore::scanValue(%s, format=%%%c, long) input=\"%s\"\n",
name(), fmt.conv, inputLine.expand(consumedInput)());
if (consumed < 0 ||
consumed > inputLine.length()-consumedInput) return -1;
if (consumed < 0)
{
if (fmt.flags & default_flag)
{
value = 0;
consumed = 0;
}
else return -1;
}
if (consumed > inputLine.length()-consumedInput) return -1;
debug("StreamCore::scanValue(%s) scanned %li\n",
name(), value);
flags |= GotValue;
@ -1316,8 +1361,16 @@ scanValue(const StreamFormat& fmt, double& value)
scanDouble(fmt, inputLine(consumedInput), value);
debug("StreamCore::scanValue(%s, format=%%%c, double) input=\"%s\"\n",
name(), fmt.conv, inputLine.expand(consumedInput)());
if (consumed < 0 ||
consumed > inputLine.length()-consumedInput) return -1;
if (consumed < 0)
{
if (fmt.flags & default_flag)
{
value = 0.0;
consumed = 0;
}
else return -1;
}
if (consumed > inputLine.length()-consumedInput) return -1;
debug("StreamCore::scanValue(%s) scanned %#g\n",
name(), value);
flags |= GotValue;
@ -1340,8 +1393,16 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen)
scanString(fmt, inputLine(consumedInput), value, maxlen);
debug("StreamCore::scanValue(%s, format=%%%c, char*, maxlen=%ld) input=\"%s\"\n",
name(), fmt.conv, maxlen, inputLine.expand(consumedInput)());
if (consumed < 0 ||
consumed > inputLine.length()-consumedInput) return -1;
if (consumed < 0)
{
if (fmt.flags & default_flag)
{
value[0] = 0;
consumed = 0;
}
else return -1;
}
if (consumed > inputLine.length()-consumedInput) return -1;
#ifndef NO_TEMPORARY
debug("StreamCore::scanValue(%s) scanned \"%s\"\n",
name(), StreamBuffer(value, maxlen).expand()());

View File

@ -501,8 +501,8 @@ long streamScanSep(dbCommon* record)
long streamScanfN(dbCommon* record, format_t *format,
void* value, size_t maxStringSize)
{
debug("streamScanfN(%s,format=%%%c,maxStringSize=%d)\n",
record->name, format->priv->conv, maxStringSize);
debug("streamScanfN(%s,format=%%%c,maxStringSize=%ld)\n",
record->name, format->priv->conv, (long)maxStringSize);
Stream* pstream = (Stream*)record->dpvt;
if (!pstream) return ERROR;
if (!pstream->scan(format, value, maxStringSize))

View File

@ -23,12 +23,13 @@
#define StreamFormat_h
typedef enum {
left_flag = 0x01,
sign_flag = 0x02,
space_flag = 0x04,
alt_flag = 0x08,
zero_flag = 0x10,
skip_flag = 0x20
left_flag = 0x01,
sign_flag = 0x02,
space_flag = 0x04,
alt_flag = 0x08,
zero_flag = 0x10,
skip_flag = 0x20,
default_flag = 0x40
} StreamFormatFlag;
typedef enum {

View File

@ -112,7 +112,7 @@ static void copyFormatString(StreamBuffer& info, const char* source)
const char* p = source - 1;
while (*p != '%' && *p != ')') p--;
info.append('%');
while (++p != source-1) info.append(*p);
while (++p != source-1) if (*p != '?') info.append(*p);
}
// Standard Long Converter for 'diouxX'
@ -160,7 +160,8 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
int length = -1;
if (fmt.flags & skip_flag)
{
/* on vxWorks, return value of sscanf with %*... is buggy */
/* can't use return value on vxWorks: sscanf with %* format
returns -1 at end of string whether value is found or not */
sscanf(input, fmt.info, &length);
}
else
@ -217,7 +218,8 @@ scanDouble(const StreamFormat& fmt, const char* input, double& value)
int length = -1;
if (fmt.flags & skip_flag)
{
/* on vxWorks, return value of sscanf with %*... is buggy */
/* can't use return value on vxWorks: sscanf with %* format
returns -1 at end of string whether value is found or not */
sscanf(input, fmt.info, &length);
}
else
@ -276,12 +278,13 @@ scanString(const StreamFormat& fmt, const char* input,
if (*input == '\0')
{
// match empty string
value[0] = '\0';
if (value) value[0] = '\0';
return 0;
}
if (fmt.flags & skip_flag)
{
/* on vxWorks, return value of sscanf with %*... is buggy */
/* can't use return value on vxWorks: sscanf with %* format
returns -1 at end of string whether value is found or not */
sscanf(input, fmt.info, &length);
}
else
@ -291,7 +294,7 @@ scanString(const StreamFormat& fmt, const char* input,
if (maxlen <= fmt.width || fmt.width == 0)
{
// assure not to read too much
sprintf(tmpformat, "%%%d%c%%n", maxlen-1, fmt.conv);
sprintf(tmpformat, "%%%ld%c%%n", (long)maxlen-1, fmt.conv);
f = tmpformat;
}
else
@ -409,7 +412,8 @@ scanString(const StreamFormat& fmt, const char* input,
int length = -1;
if (fmt.flags & skip_flag)
{
/* on vxWorks, return value of sscanf with %*... is buggy */
/* can't use return value on vxWorks: sscanf with %* format
returns -1 at end of string whether value is found or not */
sscanf(input, fmt.info, &length);
}
else
@ -420,7 +424,7 @@ scanString(const StreamFormat& fmt, const char* input,
{
const char *p = strchr (fmt.info, '[');
// assure not to read too much
sprintf(tmpformat, "%%%d%s", maxlen-1, p);
sprintf(tmpformat, "%%%ld%s", (long)maxlen-1, p);
f = tmpformat;
}
else

View File

@ -1504,6 +1504,16 @@ compileFormat(StreamBuffer& buffer, const char*& formatstr,
}
streamFormat.flags |= skip_flag;
break;
case '?':
if (formatType != ScanFormat)
{
errorMsg(line,
"Use of default modifier '?' "
"only allowed in input formats\n");
return false;
}
streamFormat.flags |= default_flag;
break;
default:
loop = false;
}

View File

@ -22,7 +22,7 @@
#define devStream_h
#define STREAM_MAJOR 2
#define STREAM_MINOR 3
#define STREAM_MINOR 4
#if defined(__vxworks) || defined(vxWorks)
#include <vxWorks.h>

View File

@ -25,12 +25,12 @@
static long readData (dbCommon *record, format_t *format)
{
aiRecord *ai = (aiRecord *) record;
double val;
switch (format->type)
{
case DBF_DOUBLE:
{
double val;
if (streamScanf (record, format, &val)) return ERROR;
if (ai->aslo != 0.0) val *= ai->aslo;
val += ai->aoff;
@ -43,7 +43,10 @@ static long readData (dbCommon *record, format_t *format)
}
case DBF_LONG:
{
return streamScanf (record, format, &ai->rval);
long rval;
if (streamScanf (record, format, &rval)) return ERROR;
ai->rval = rval;
return OK;
}
}
return ERROR;
@ -64,7 +67,7 @@ static long writeData (dbCommon *record, format_t *format)
}
case DBF_LONG:
{
return streamPrintf (record, format, ai->rval);
return streamPrintf (record, format, (long) ai->rval);
}
}
return ERROR;

View File

@ -51,12 +51,12 @@ static long readData (dbCommon *record, format_t *format)
static long writeData (dbCommon *record, format_t *format)
{
aoRecord *ao = (aoRecord *) record;
double val;
switch (format->type)
{
case DBF_DOUBLE:
{
double val;
if (INIT_RUN) val = ao->val;
else val = ao->oval;
val -= ao->aoff;
@ -65,7 +65,7 @@ static long writeData (dbCommon *record, format_t *format)
}
case DBF_LONG:
{
return streamPrintf (record, format, ao->rval);
return streamPrintf (record, format, (long) ao->rval);
}
}
return ERROR;

View File

@ -28,7 +28,10 @@ static long readData (dbCommon *record, format_t *format)
if (format->type == DBF_LONG || format->type == DBF_ENUM)
{
return streamScanf (record, format, &li->val);
long val;
if (streamScanf (record, format, &val)) return ERROR;
li->val = val;
return OK;
}
return ERROR;
}
@ -39,7 +42,7 @@ static long writeData (dbCommon *record, format_t *format)
if (format->type == DBF_LONG || format->type == DBF_ENUM)
{
return streamPrintf (record, format, li->val);
return streamPrintf (record, format, (long) li->val);
}
return ERROR;
}

View File

@ -29,7 +29,10 @@ static long readData (dbCommon *record, format_t *format)
if (format->type == DBF_LONG || format->type == DBF_ENUM)
{
return streamScanf (record, format, &lo->val);
long val;
if (streamScanf (record, format, &val)) return ERROR;
lo->val = val;
return OK;
}
return ERROR;
}
@ -40,7 +43,7 @@ static long writeData (dbCommon *record, format_t *format)
if (format->type == DBF_LONG || format->type == DBF_ENUM)
{
return streamPrintf (record, format, lo->val);
return streamPrintf (record, format, (long) lo->val);
}
return ERROR;
}