Hi Ralph,
Ø
Doesn't Windows use ';' (semicolon) to separate elements in path variables?
Ø
I would have difficulties parsing this. How does StreamDevice do that?
I was wondering that myself. Here is the relevant part of the code in StreamProtocol.cc:
#ifdef windows
const char pathseparator = ';';
const char dirseparator = '\\';
#else
const char pathseparator = ':';
const char dirseparator = '/';
#endif
Note that the code is checking if “windows” is defined. That seems unusual. According to the MSVC documentation that is not something their compiler defines:
https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019
The next question is whether “windows” is defined on the compiler command line. This is the output when I build. I added line breaks for clarity, and omitted a bunch of the –I directories.
cl -EHsc -GR
-nologo -FC
-D__STDC__=0
-D_CRT_SECURE_NO_DEPRECATE
-D_CRT_NONSTDC_NO_DEPRECATE
-DUSE_TYPED_RSET -DSTREAM_INTERNAL
-Ox -Oy-
-W3 -w44355 -w44344 -w44251
-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
-MT -TP
-I. -I../O.Common -I. -I. -I.. -I../../../include/compiler/msvc
-I../../../include/os/WIN32 -I../../../include
-IJ:/epics/devel/include -IH:/epics-devel/base-7.0.4/include/compiler/msvc
-IH:/epics-devel/base-7.0.4/include/os/WIN32 -IH:/epics-devel/base-7.0.4/include
-IJ:/epics/devel/alive-1-1-1/include -IJ:/epics/devel/allenBradley-2-3/include
…
-IJ:/epics/devel/tpmac-3-11dls5/include
-IJ:/epics/devel/vac-1-9/include
-IJ:/epics/devel/vme-2-9-2/include
-IJ:/epics/devel/xspress3-2-2/include
-c ../StreamProtocol.cc
I don’t see “windows” being defined there.
I set the iocsh variable streamDebug to 1 and started the IOC. StreamProtocol will print the full path to the protocol file when it tries to open it in each of the directories in STREAM_PROTOCOL_PATH until it
succeeds. If it cannot find the file it will print an error message. This is what I see:
2020/07/21 11:44:36.989409 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try 'J/LQExcel.proto'
2020/07/21 11:44:36.996306 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try '/epics/devel/ip-2-20-1/db/LQExcel.proto'
2020/07/21 11:44:37.005726 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try 'J/LQExcel.proto'
2020/07/21 11:44:37.014293 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try '/epics/devel/CARS/db/LQExcel.proto'
2020/07/21 11:44:37.024689 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:573: StreamProtocolParser::readToken: Special ' '
2020/07/21 11:44:37.029678 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:265: StreamProtocolParser::parseProtocol: token=' '
2020/07/21 11:44:37.039544 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:579: StreamProtocolParser::readToken: word
2020/07/21 11:44:37.044808 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:590: StreamProtocolParser::readToken: word='on' c=' '
2020/07/21 11:44:37.050567 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:265: StreamProtocolParser::parseProtocol: token='on<00><08><00><00><00>'
2020/07/21 11:44:37.058528 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:763: new Protocol(name="on", line=8)
2020/07/21 11:44:37.063879 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:778: StreamProtocolParser::Protocol::Protocol $0="on"
2020/07/21 11:44:37.069036 win4b28 j:\epics\devel\stream-2-8-14\src\streamprotocol.cc:573: StreamProtocolParser::readToken: Special ' '
It is stripping out the : characters, and using / as the directory separator. So “windows” is clearly not defined and it is using the wrong pathseparator and dirseparator.
But the bizarre thing is that somehow it works! It is finding LQExcel.proto using this path '/epics/devel/CARS/db/LQExcel.proto’. That looks very weird, but I just figured out what is happening. Windows is interpreting
that path as an absolute path on the current drive, J:. Indeed J:/epics/devel/CARS/db/LQExcel.proto is the correct path.
So the answer as to why it works is 2 errors that cancelled, and 1 coincidence!
-
Error #1: StreamDevice is testing the macro “windows” which is not defined so it is using the wrong pathseparator and dirseparator.
-
Error #2: I was using ‘;’ rather than ‘;’ as the path separator.
-
Coincidence: The protocol file happened to be on the current default Windows drive, J:.
I then changed StreamProtocol.cc as follows:
corvette:~/devel/stream/src>git diff .
diff --git a/src/StreamProtocol.cc b/src/StreamProtocol.cc
index 77741b9..a60b6b0 100644
--- a/src/StreamProtocol.cc
+++ b/src/StreamProtocol.cc
@@ -157,7 +157,7 @@ StreamProtocolParser* StreamProtocolParser::
readFile(const char* filename)
{
FILE* file;
-#ifdef windows
+#ifdef _WIN32
const char pathseparator = ';';
const char dirseparator = '\\';
#else
Now when I start the IOC still using ‘:’ as the path separator it fails as it should:
epicsEnvSet(STREAM_PROTOCOL_PATH, J:/epics/devel/ip-2-20-1/db:J:/epics/devel/CARS/db)
2020/07/21 12:34:02.309651 win1fe4 j:\epics\devel\stream\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try 'J:/epics/devel/ip-2-20-1/db:J:/epics/devel/CARS/db\LQExcel.proto'
2020/07/21 12:34:02.322569 win1fe4 Can't find readable file 'LQExcel.proto' in 'J:/epics/devel/ip-2-20-1/db:J:/epics/devel/CARS/db'
2020/07/21 12:34:02.329335 win1fe4 while reading protocol 'PowerOut' for '13LQE1:L1PowerOut'
2020/07/21 12:34:02.332623 win1fe4 13LQE1:L1PowerOut: Protocol parse error
2020/07/21 12:34:02.338519 win1fe4 13LQE1:L1PowerOut: Record initialization failed
I then changed the path separator to ‘;’ and now it works correctly:
epicsEnvSet(STREAM_PROTOCOL_PATH, J:/epics/devel/ip-2-20-1/db;J:/epics/devel/CARS/db)
…
2020/07/21 12:37:38.633552 win3804 j:\epics\devel\stream\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try 'J:/epics/devel/ip-2-20-1/db\LQExcel.proto'
2020/07/21 12:37:38.643656 win3804 j:\epics\devel\stream\src\streamprotocol.cc:187: StreamProtocolParser::readFile: try 'J:/epics/devel/CARS/db\LQExcel.proto'
2020/07/21 12:37:38.668548 win3804 j:\epics\devel\stream\src\streamprotocol.cc:573: StreamProtocolParser::readToken: Special ' '
2020/07/21 12:37:38.675654 win3804 j:\epics\devel\stream\src\streamprotocol.cc:265: StreamProtocolParser::parseProtocol: token=' '
2020/07/21 12:37:38.683407 win3804 j:\epics\devel\stream\src\streamprotocol.cc:579: StreamProtocolParser::readToken: word
2020/07/21 12:37:38.688735 win3804 j:\epics\devel\stream\src\streamprotocol.cc:590: StreamProtocolParser::readToken: word='on' c=' '
2020/07/21 12:37:38.696055 win3804 j:\epics\devel\stream\src\streamprotocol.cc:265: StreamProtocolParser::parseProtocol: token='on<00><08><00><00><00>'
2020/07/21 12:37:38.706280 win3804 j:\epics\devel\stream\src\streamprotocol.cc:763: new Protocol(name="on", line=8)
2020/07/21 12:37:38.713675 win3804 j:\epics\devel\stream\src\streamprotocol.cc:778: StreamProtocolParser::Protocol::Protocol $0="on"
Mark
From: Tech-talk <tech-talk-bounces at aps.anl.gov>
On Behalf Of Ralph Lange via Tech-talk
Sent: Tuesday, July 21, 2020 10:50 AM
To: EPICS Tech Talk <tech-talk at aps.anl.gov>
Subject: Re: RE: SteamDevice 2.8.x build on Windows issue
[...]
epicsEnvSet(STREAM_PROTOCOL_PATH, J:/epics/devel/ip-2-20-1/db:J:/epics/devel/CARS/db)
Doesn't Windows use ';' (semicolon) to separate elements in path variables?
I would have difficulties parsing this. How does StreamDevice do that?