allow () inside protocol parameters
This commit is contained in:
@ -29,6 +29,9 @@
|
||||
|
||||
#ifdef EPICS_3_13
|
||||
extern "C" {
|
||||
|
||||
static char* epicsStrDup(const char *s) { char* c = (char*)malloc(strlen(s)+1); strcpy(c, s); return c; }
|
||||
|
||||
#endif
|
||||
|
||||
#define epicsAlarmGLOBAL
|
||||
@ -161,10 +164,7 @@ class Stream : protected StreamCore
|
||||
Stream(dbCommon* record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData);
|
||||
~Stream();
|
||||
long parseLink(const struct link *ioLink, char* filename, char* protocol,
|
||||
char* busname, int* addr, char* busparam);
|
||||
long initRecord(const char* filename, const char* protocol,
|
||||
const char* busname, int addr, const char* busparam);
|
||||
long initRecord(char* linkstring);
|
||||
bool print(format_t *format, va_list ap);
|
||||
ssize_t scan(format_t *format, void* pvalue, size_t maxStringSize);
|
||||
bool process();
|
||||
@ -534,12 +534,7 @@ long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData)
|
||||
{
|
||||
long status;
|
||||
char filename[256];
|
||||
char protocol[256];
|
||||
char busname[256];
|
||||
int addr = -1;
|
||||
char busparam[256];
|
||||
memset(busparam, 0 ,sizeof(busparam));
|
||||
char* linkstring;
|
||||
|
||||
debug("streamInitRecord(%s): SEVR=%d\n", record->name, record->sevr);
|
||||
Stream* stream = static_cast<Stream*>(record->dpvt);
|
||||
@ -556,19 +551,30 @@ long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
||||
record->name);
|
||||
stream->finishProtocol(Stream::Abort);
|
||||
}
|
||||
// scan the i/o link
|
||||
debug("streamInitRecord(%s): parse link \"%s\"\n",
|
||||
record->name, ioLink->value.instio.string);
|
||||
status = stream->parseLink(ioLink, filename, protocol,
|
||||
busname, &addr, busparam);
|
||||
// (re)initialize bus and protocol
|
||||
if (status == 0)
|
||||
if (ioLink->type != INST_IO)
|
||||
{
|
||||
error("%s: Wrong I/O link type %s\n", record->name,
|
||||
pamaplinkType[ioLink->type].strvalue);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
if (!ioLink->value.instio.string[0])
|
||||
{
|
||||
error("%s: Empty I/O link. "
|
||||
"Forgot the leading '@' or confused INP with OUT or link is too long ?\n",
|
||||
record->name);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
// (re)initialize bus and protocol
|
||||
linkstring = epicsStrDup(ioLink->value.instio.string);
|
||||
if (!linkstring)
|
||||
{
|
||||
error("%s: Out of memory", record->name);
|
||||
return S_dev_noMemory;
|
||||
}
|
||||
debug("streamInitRecord(%s): calling initRecord\n",
|
||||
record->name);
|
||||
status = stream->initRecord(filename, protocol,
|
||||
busname, addr, busparam);
|
||||
}
|
||||
status = stream->initRecord(linkstring);
|
||||
free(linkstring);
|
||||
if (status != OK && status != DO_NOT_CONVERT)
|
||||
{
|
||||
error("%s: Record initialization failed\n", record->name);
|
||||
@ -698,71 +704,71 @@ Stream::
|
||||
}
|
||||
|
||||
long Stream::
|
||||
parseLink(const struct link *ioLink, char* filename,
|
||||
char* protocol, char* busname, int* addr, char* busparam)
|
||||
initRecord(char* linkstring /* modifiable copy */)
|
||||
{
|
||||
// parse link parameters: filename protocol busname addr busparam
|
||||
int n1, n2;
|
||||
if (ioLink->type != INST_IO)
|
||||
{
|
||||
error("%s: Wrong I/O link type %s\n", name(),
|
||||
pamaplinkType[ioLink->type].strvalue);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
if (0 >= sscanf(ioLink->value.instio.string, "%s%n", filename, &n1))
|
||||
{
|
||||
error("%s: Empty I/O link. "
|
||||
"Forgot the leading '@' or confused INP with OUT or link is too long ?\n",
|
||||
name());
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
if (0 >= sscanf(ioLink->value.instio.string+n1, " %[^ \t(] %n", protocol, &n2))
|
||||
{
|
||||
error("%s: Missing protocol name\n"
|
||||
" expect \"@file protocol[(arg1,...)] bus [addr] [params]\"\n"
|
||||
" in \"@%s\"\n", name(),
|
||||
ioLink->value.instio.string);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
n1+=n2;
|
||||
if (ioLink->value.instio.string[n1] == '(')
|
||||
{
|
||||
n2 = 0;
|
||||
sscanf(ioLink->value.instio.string+n1, " %[^)] %n", protocol+strlen(protocol), &n2);
|
||||
n1+=n2;
|
||||
if (ioLink->value.instio.string[n1++] != ')')
|
||||
{
|
||||
error("%s: Missing ')' after protocol arguments '%s'\n"
|
||||
" expect \"@file protocol(arg1,...) bus [addr] [params]\"\n"
|
||||
" in \"@%s\"\n", name(), protocol,
|
||||
ioLink->value.instio.string);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
strcat(protocol, ")");
|
||||
}
|
||||
if (0 >= sscanf(ioLink->value.instio.string+n1, "%s %i %99c", busname, addr, busparam))
|
||||
{
|
||||
error("%s: Missing bus name\n"
|
||||
" expect \"@file protocol[(arg1,...)] bus [addr] [params]\"\n"
|
||||
" in \"@%s\"\n", name(),
|
||||
ioLink->value.instio.string);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
char *filename;
|
||||
char *protocol;
|
||||
char *busname;
|
||||
char *busparam;
|
||||
long addr = -1;
|
||||
|
||||
long Stream::
|
||||
initRecord(const char* filename, const char* protocol,
|
||||
const char* busname, int addr, const char* busparam)
|
||||
debug("Stream::initRecord %s: parse link string \"%s\"\n", name(), linkstring);
|
||||
|
||||
while (isspace(*linkstring)) linkstring++;
|
||||
filename = linkstring;
|
||||
while (*linkstring && !isspace(*linkstring)) linkstring++;
|
||||
if (*linkstring) *linkstring++ = 0;
|
||||
|
||||
while (isspace(*linkstring)) linkstring++;
|
||||
protocol = linkstring;
|
||||
while (*linkstring && !isspace(*linkstring) && *linkstring != '(') linkstring++;
|
||||
while (isspace(*linkstring)) linkstring++;
|
||||
if (*linkstring == '(') {
|
||||
int brackets = 0;
|
||||
while(*++linkstring) {
|
||||
if (*linkstring == '(') brackets++;
|
||||
else if (*linkstring == ')') brackets--;
|
||||
else if (*linkstring == '\\' && !*++linkstring) break;
|
||||
else if (isspace(*linkstring) && brackets < 0) break;
|
||||
}
|
||||
}
|
||||
else if (*linkstring) linkstring--;
|
||||
if (*linkstring) *linkstring++ = 0;
|
||||
|
||||
while (isspace(*linkstring)) linkstring++;
|
||||
busname = linkstring;
|
||||
while (*linkstring && !isspace(*linkstring)) linkstring++;
|
||||
if (*linkstring) *linkstring++ = 0;
|
||||
|
||||
if (linkstring) addr = strtol(linkstring, &linkstring, 0);
|
||||
while (isspace(*linkstring)) linkstring++;
|
||||
busparam = linkstring;
|
||||
|
||||
debug("Stream::initRecord %s: filename=\"%s\" protocol=\"%s\" bus=\"%s\" addr=%ld params=\"%s\"\n",
|
||||
name(), filename, protocol, busname, addr, busparam);
|
||||
|
||||
if (!*filename)
|
||||
{
|
||||
// It is safe to call this function again with different arguments
|
||||
error("%s: Missing protocol file name\n", name());
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
if (!*protocol)
|
||||
{
|
||||
error("%s: Missing protocol name\n", name());
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
if (!*busname)
|
||||
{
|
||||
error("%s: Missing bus name\n", name());
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
|
||||
// attach to bus interface
|
||||
debug("Stream::initRecord %s: attachBus(%s, %d, \"%s\")\n",
|
||||
debug("Stream::initRecord %s: attachBus(%s, %ld, \"%s\")\n",
|
||||
name(), busname, addr, busparam);
|
||||
if (!attachBus(busname, addr, busparam))
|
||||
{
|
||||
error("%s: Can't attach to bus %s %d\n",
|
||||
error("%s: Can't attach to bus %s %ld\n",
|
||||
name(), busname, addr);
|
||||
return S_dev_noDevice;
|
||||
}
|
||||
|
32
streamApp/tests/testParenthesesInParameters
Executable file
32
streamApp/tests/testParenthesesInParameters
Executable file
@ -0,0 +1,32 @@
|
||||
#!/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:test1")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto test1(ARG(10)) device")
|
||||
}
|
||||
}
|
||||
|
||||
set protocol {
|
||||
Terminator = LF;
|
||||
test1 { out "VAL:\$1:%d"}
|
||||
}
|
||||
|
||||
set startup {
|
||||
}
|
||||
|
||||
set debug 0
|
||||
|
||||
startioc
|
||||
|
||||
put DZ:test1 "1"
|
||||
assure "VAL:ARG(10):1\n"
|
||||
|
||||
finish
|
Reference in New Issue
Block a user