Do some macro magic to convert enums to strings

This commit is contained in:
2018-07-17 10:09:00 +02:00
parent d22955a1c5
commit fe075c3bbd
7 changed files with 167 additions and 133 deletions

View File

@ -41,6 +41,7 @@ extern "C" {
#include "asynGpibDriver.h" #include "asynGpibDriver.h"
#include "devStream.h" #include "devStream.h"
#include "MacroMagic.h"
#define Z PRINTF_SIZE_T_PREFIX #define Z PRINTF_SIZE_T_PREFIX
@ -117,20 +118,16 @@ static void intrCallbackUInt32(void* pvt, asynUser *pasynUser,
epicsUInt32 data); epicsUInt32 data);
} }
enum IoAction { ENUM (IoAction,
None, Lock, Write, Read, AsyncRead, AsyncReadMore, None, Lock, Write, Read, AsyncRead, AsyncReadMore,
ReceiveEvent, Connect, Disconnect ReceiveEvent, Connect, Disconnect);
};
static const char* ioActionStr[] = { inline const char* toStr(asynStatus status)
"None", "Lock", "Write", "Read", {
"AsyncRead", "AsyncReadMore", const char* asynStatusStr[] = {
"ReceiveEvent", "Connect", "Disconnect"
};
static const char* asynStatusStr[] = {
"asynSuccess", "asynTimeout", "asynOverflow", "asynError", "asynSuccess", "asynTimeout", "asynOverflow", "asynError",
"asynDisconnected", "asynDisabled" "asynDisconnected", "asynDisabled"};
return status > 5 ? "unknown" : asynStatusStr[status];
}; };
static const char* eomReasonStr[] = { static const char* eomReasonStr[] = {
@ -451,7 +448,7 @@ connectToBus(const char* portname, int addr)
debug("%s: AsynDriverInterface::connectToBus(%s, %d): " debug("%s: AsynDriverInterface::connectToBus(%s, %d): "
"pasynManager->connectDevice(%p, %s, %d) = %s\n", "pasynManager->connectDevice(%p, %s, %d) = %s\n",
clientName(), portname, addr, pasynUser,portname, addr, clientName(), portname, addr, pasynUser,portname, addr,
asynStatusStr[status]); toStr(status));
if (status != asynSuccess) if (status != asynSuccess)
{ {
// asynDriver does not know this portname/address // asynDriver does not know this portname/address
@ -546,7 +543,7 @@ connectToAsynPort()
status = pasynManager->isConnected(pasynUser, &connected); status = pasynManager->isConnected(pasynUser, &connected);
debug("%s: AsynDriverInterface::connectToAsynPort: " debug("%s: AsynDriverInterface::connectToAsynPort: "
"pasynManager->isConnected(%p, %p) = %s => %s\n", "pasynManager->isConnected(%p, %p) = %s => %s\n",
clientName(), pasynUser, &connected, asynStatusStr[status], clientName(), pasynUser, &connected, toStr(status),
connected ? "yes" : "no"); connected ? "yes" : "no");
if (status != asynSuccess) if (status != asynSuccess)
{ {
@ -570,7 +567,7 @@ connectToAsynPort()
debug("AsynDriverInterface::connectToAsynPort(%s): " debug("AsynDriverInterface::connectToAsynPort(%s): "
"read(..., 0, ...) [timeout=%g sec] = %s\n", "read(..., 0, ...) [timeout=%g sec] = %s\n",
clientName(), pasynUser->timeout, clientName(), pasynUser->timeout,
asynStatusStr[status]); toStr(status));
pasynManager->isConnected(pasynUser, &connected); pasynManager->isConnected(pasynUser, &connected);
debug("AsynDriverInterface::connectToAsynPort(%s): " debug("AsynDriverInterface::connectToAsynPort(%s): "
"device was %sconnected!\n", "device was %sconnected!\n",
@ -585,7 +582,7 @@ connectToAsynPort()
status = pasynCommon->connect(pvtCommon, pasynUser); status = pasynCommon->connect(pvtCommon, pasynUser);
debug("AsynDriverInterface::connectToAsynPort(%s): " debug("AsynDriverInterface::connectToAsynPort(%s): "
"status=%s\n", "status=%s\n",
clientName(), asynStatusStr[status]); clientName(), toStr(status));
reportAsynStatus(status, "connectToAsynPort"); reportAsynStatus(status, "connectToAsynPort");
return (status == asynSuccess); return (status == asynSuccess);
} }
@ -734,7 +731,7 @@ writeHandler()
clientName(), clientName(),
StreamBuffer(outputBuffer, outputSize).expand()(), StreamBuffer(outputBuffer, outputSize).expand()(),
outputSize, written, outputSize, written,
pasynUser->timeout, asynStatusStr[status], pasynUser->timeout, toStr(status),
pasynUser->errorMessage); pasynUser->errorMessage);
// When devices goes offline, we get an error only at next write. // When devices goes offline, we get an error only at next write.
@ -837,7 +834,7 @@ readRequest(unsigned long replyTimeout_ms, unsigned long readTimeout_ms,
debug("AsynDriverInterface::readRequest %s: " debug("AsynDriverInterface::readRequest %s: "
"queueRequest(..., priority=%d, queueTimeout=%g sec) = %s [async=%s] %s\n", "queueRequest(..., priority=%d, queueTimeout=%g sec) = %s [async=%s] %s\n",
clientName(), priority(), queueTimeout, clientName(), priority(), queueTimeout,
asynStatusStr[status], async? "true" : "false", toStr(status), async? "true" : "false",
status!=asynSuccess ? pasynUser->errorMessage : ""); status!=asynSuccess ? pasynUser->errorMessage : "");
if (!async) if (!async)
{ {
@ -963,7 +960,7 @@ readHandler()
debug("AsynDriverInterface::readHandler(%s): ioAction=%s " debug("AsynDriverInterface::readHandler(%s): ioAction=%s "
"read(..., bytesToRead=%" Z "u, ...) " "read(..., bytesToRead=%" Z "u, ...) "
"[timeout=%g sec]\n", "[timeout=%g sec]\n",
clientName(), ioActionStr[ioAction], clientName(), toStr(ioAction),
bytesToRead, pasynUser->timeout); bytesToRead, pasynUser->timeout);
status = pasynOctet->read(pvtOctet, pasynUser, status = pasynOctet->read(pvtOctet, pasynUser,
buffer, bytesToRead, &received, &eomReason); buffer, bytesToRead, &received, &eomReason);
@ -971,7 +968,7 @@ readHandler()
debug("AsynDriverInterface::readHandler(%s): " debug("AsynDriverInterface::readHandler(%s): "
"read returned %s: ioAction=%s received=%" Z "d, " "read returned %s: ioAction=%s received=%" Z "d, "
"eomReason=%s, buffer=\"%s\"\n", "eomReason=%s, buffer=\"%s\"\n",
clientName(), asynStatusStr[status], ioActionStr[ioAction], clientName(), toStr(status), toStr(ioAction),
received,eomReasonStr[eomReason&0x7], received,eomReasonStr[eomReason&0x7],
StreamBuffer(buffer, received).expand()()); StreamBuffer(buffer, received).expand()());
pasynManager->isConnected(pasynUser, &connected); pasynManager->isConnected(pasynUser, &connected);
@ -1074,7 +1071,7 @@ readHandler()
debug("AsynDriverInterface::readHandler(%s): " debug("AsynDriverInterface::readHandler(%s): "
"ioAction=%s, timeout [%g sec] " "ioAction=%s, timeout [%g sec] "
"after %" Z "d of %" Z "u bytes \"%s\"\n", "after %" Z "d of %" Z "u bytes \"%s\"\n",
clientName(), ioActionStr[ioAction], pasynUser->timeout, clientName(), toStr(ioAction), pasynUser->timeout,
received, bytesToRead, received, bytesToRead,
StreamBuffer(buffer, received).expand()()); StreamBuffer(buffer, received).expand()());
if (ioAction == AsyncRead || ioAction == AsyncReadMore) if (ioAction == AsyncRead || ioAction == AsyncReadMore)
@ -1189,7 +1186,7 @@ asynReadHandler(const char *buffer, size_t received, int eomReason)
debug("AsynDriverInterface::asynReadHandler(%s, buffer=\"%s\", " debug("AsynDriverInterface::asynReadHandler(%s, buffer=\"%s\", "
"received=%ld eomReason=%s) ioAction=%s\n", "received=%ld eomReason=%s) ioAction=%s\n",
clientName(), StreamBuffer(buffer, received).expand()(), clientName(), StreamBuffer(buffer, received).expand()(),
(long)received, eomReasonStr[eomReason&0x7], ioActionStr[ioAction]); (long)received, eomReasonStr[eomReason&0x7], toStr(ioAction));
ioAction = None; ioAction = None;
ssize_t readMore = 1; ssize_t readMore = 1;
@ -1270,7 +1267,7 @@ asynReadHandler(const char *buffer, size_t received, int eomReason)
startTimer(readTimeout); startTimer(readTimeout);
} }
debug("AsynDriverInterface::asynReadHandler(%s) readMore=%" Z "d, ioAction=%s \n", debug("AsynDriverInterface::asynReadHandler(%s) readMore=%" Z "d, ioAction=%s \n",
clientName(), readMore, ioActionStr[ioAction]); clientName(), readMore, toStr(ioAction));
} }
// interface function: we want to receive an event // interface function: we want to receive an event
@ -1373,7 +1370,7 @@ timerExpired()
// if this fails, we are already queued by another thread // if this fails, we are already queued by another thread
debug("AsynDriverInterface::timerExpired %s: " debug("AsynDriverInterface::timerExpired %s: "
"queueRequest(..., priority=Low, queueTimeout=-1) = %s %s\n", "queueRequest(..., priority=Low, queueTimeout=-1) = %s %s\n",
clientName(), asynStatusStr[status], clientName(), toStr(status),
status!=asynSuccess ? pasynUser->errorMessage : ""); status!=asynSuccess ? pasynUser->errorMessage : "");
if (status != asynSuccess) startTimer(replyTimeout); if (status != asynSuccess) startTimer(replyTimeout);
// continues with: // continues with:
@ -1382,7 +1379,7 @@ timerExpired()
return; return;
default: default:
error("INTERNAL ERROR (%s): timerExpired() unexpected ioAction %s\n", error("INTERNAL ERROR (%s): timerExpired() unexpected ioAction %s\n",
clientName(), ioActionStr[ioAction]); clientName(), toStr(ioAction));
return; return;
} }
} }
@ -1492,7 +1489,7 @@ void handleRequest(asynUser* pasynUser)
static_cast<AsynDriverInterface*>(pasynUser->userPvt); static_cast<AsynDriverInterface*>(pasynUser->userPvt);
interface->cancelTimer(); interface->cancelTimer();
debug("AsynDriverInterface::handleRequest(%s) %s\n", debug("AsynDriverInterface::handleRequest(%s) %s\n",
interface->clientName(), ioActionStr[interface->ioAction]); interface->clientName(), toStr(interface->ioAction));
switch (interface->ioAction) switch (interface->ioAction)
{ {
case None: case None:
@ -1519,7 +1516,7 @@ void handleRequest(asynUser* pasynUser)
default: default:
error("INTERNAL ERROR (%s): " error("INTERNAL ERROR (%s): "
"handleRequest() unexpected ioAction %s\n", "handleRequest() unexpected ioAction %s\n",
interface->clientName(), ioActionStr[interface->ioAction]); interface->clientName(), toStr(interface->ioAction));
} }
} }
@ -1555,7 +1552,7 @@ void handleTimeout(asynUser* pasynUser)
default: default:
error("INTERNAL ERROR (%s): handleTimeout() " error("INTERNAL ERROR (%s): handleTimeout() "
"unexpected ioAction %s\n", "unexpected ioAction %s\n",
interface->clientName(), ioActionStr[interface->ioAction]); interface->clientName(), toStr(interface->ioAction));
} }
} }

72
src/MacroMagic.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef _MacroMagic_h
#define _MacroMagic_h
#if defined __GNUC__ && __GNUC__ < 3
/* Using old GCC variadic macros */
#define _NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, args...) N
#define _fe_0(_call, args...)
#define _fe_1(_call, x) _call(x)
#define _fe_2(_call, x, args...) _call(x) _fe_1(_call, args)
#define _fe_3(_call, x, args...) _call(x) _fe_2(_call, args)
#define _fe_4(_call, x, args...) _call(x) _fe_3(_call, args)
#define _fe_5(_call, x, args...) _call(x) _fe_4(_call, args)
#define _fe_6(_call, x, args...) _call(x) _fe_5(_call, args)
#define _fe_7(_call, x, args...) _call(x) _fe_6(_call, args)
#define _fe_8(_call, x, args...) _call(x) _fe_7(_call, args)
#define _fe_9(_call, x, args...) _call(x) _fe_8(_call, args)
#define _fe_10(_call, x, args...) _call(x) _fe_9(_call, args)
#define MACRO_FOR_EACH(x, args...) \
_NTH_ARG(_, ##args, \
_fe_10, _fe_9, _fe_8, _fe_7, _fe_6, _fe_5, _fe_4, _fe_3, _fe_2, _fe_1, _fe_0) \
(x, ##args)
/* Enum to string magic */
#define ENUM(type, args...) \
enum type { args }; \
static inline const char* type##ToStr(int x) {switch(x){MACRO_FOR_EACH(_CASE_LINE,args)default: return "invalid";}}\
_ENUM_CAST(type)
#else
/* Using ISO C variadic macros */
#define _NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, ...) N
#define _fe_0(_call, ...)
#define _fe_1(_call, x) _call(x)
#define _fe_2(_call, x, ...) _call(x) _fe_1(_call, __VA_ARGS__)
#define _fe_3(_call, x, ...) _call(x) _fe_2(_call, __VA_ARGS__)
#define _fe_4(_call, x, ...) _call(x) _fe_3(_call, __VA_ARGS__)
#define _fe_5(_call, x, ...) _call(x) _fe_4(_call, __VA_ARGS__)
#define _fe_6(_call, x, ...) _call(x) _fe_5(_call, __VA_ARGS__)
#define _fe_7(_call, x, ...) _call(x) _fe_6(_call, __VA_ARGS__)
#define _fe_8(_call, x, ...) _call(x) _fe_7(_call, __VA_ARGS__)
#define _fe_9(_call, x, ...) _call(x) _fe_8(_call, __VA_ARGS__)
#define _fe_10(_call, x, ...) _call(x) _fe_9(_call, __VA_ARGS__)
#define MACRO_FOR_EACH(x, ...) \
_NTH_ARG(_, ##__VA_ARGS__, \
_fe_10, _fe_9, _fe_8, _fe_7, _fe_6, _fe_5, _fe_4, _fe_3, _fe_2, _fe_1, _fe_0) \
(x, ##__VA_ARGS__)
/* Enum to string magic */
#define ENUM(type,...) \
enum type { __VA_ARGS__ }; \
static inline const char* type##ToStr(int x) {switch(x){MACRO_FOR_EACH(_CASE_LINE,__VA_ARGS__) default: return "invalid";}} \
_ENUM_CAST(type)
#endif
#define _CASE_LINE(x) case x: return #x;
#ifdef __cplusplus
#define _ENUM_CAST(type) ; static inline const char* toStr(type x) {return type##ToStr(x);}
#else
#define _ENUM_CAST(type)
#endif
#endif

View File

@ -20,8 +20,6 @@
#include "StreamBusInterface.h" #include "StreamBusInterface.h"
#include "StreamError.h" #include "StreamError.h"
StreamIoStatusStrClass StreamIoStatusStr;
StreamBusInterfaceRegistrarBase* StreamBusInterfaceRegistrarBase::first; StreamBusInterfaceRegistrarBase* StreamBusInterfaceRegistrarBase::first;
StreamBusInterfaceRegistrarBase:: StreamBusInterfaceRegistrarBase::

View File

@ -22,25 +22,11 @@
#include <stddef.h> #include <stddef.h>
#include "StreamBuffer.h" #include "StreamBuffer.h"
#include "MacroMagic.h"
enum StreamIoStatus { ENUM (StreamIoStatus,
StreamIoSuccess, StreamIoTimeout, StreamIoNoReply, StreamIoSuccess, StreamIoTimeout, StreamIoNoReply,
StreamIoEnd, StreamIoFault StreamIoEnd, StreamIoFault);
};
class StreamIoStatusStrClass {
public:
const char* operator [] (int index) {
switch (index) {
case StreamIoSuccess: return "StreamIoSuccess";
case StreamIoTimeout: return "StreamIoTimeout";
case StreamIoNoReply: return "StreamIoNoReply";
case StreamIoEnd: return "StreamIoEnd";
case StreamIoFault: return "StreamIoFault";
default: return "illegal status";
}
}
} extern StreamIoStatusStr;
class StreamBusInterface class StreamBusInterface
{ {

View File

@ -25,15 +25,8 @@
#define Z PRINTF_SIZE_T_PREFIX #define Z PRINTF_SIZE_T_PREFIX
enum Commands { end_cmd, in_cmd, out_cmd, wait_cmd, event_cmd, exec_cmd, ENUM (Commands,
connect_cmd, disconnect_cmd }; end, in, out, wait, event, exec, connect, disconnect);
const char* commandStr[] = { "end", "in", "out", "wait", "event", "exec",
"connect", "disconnect" };
inline const char* commandName(unsigned char i)
{
return i >= sizeof(commandStr)/sizeof(char*) ? "invalid" : commandStr[i];
}
/// debug functions ///////////////////////////////////////////// /// debug functions /////////////////////////////////////////////
@ -45,37 +38,37 @@ static char* printCommands(StreamBuffer& buffer, const char* c)
{ {
switch(*c++) switch(*c++)
{ {
case end_cmd: case end:
return buffer(); return buffer();
case in_cmd: case in:
buffer.append(" in \""); buffer.append(" in \"");
c = StreamProtocolParser::printString(buffer, c); c = StreamProtocolParser::printString(buffer, c);
buffer.append("\";\n"); buffer.append("\";\n");
break; break;
case out_cmd: case out:
buffer.append(" out \""); buffer.append(" out \"");
c = StreamProtocolParser::printString(buffer, c); c = StreamProtocolParser::printString(buffer, c);
buffer.append("\";\n"); buffer.append("\";\n");
break; break;
case wait_cmd: case wait:
timeout = extract<unsigned long>(c); timeout = extract<unsigned long>(c);
buffer.print(" wait %ld; # ms\n", timeout); buffer.print(" wait %ld; # ms\n", timeout);
break; break;
case event_cmd: case event:
eventnumber = extract<unsigned long>(c); eventnumber = extract<unsigned long>(c);
timeout = extract<unsigned long>(c); timeout = extract<unsigned long>(c);
buffer.print(" event(%ld) %ld; # ms\n", eventnumber, timeout); buffer.print(" event(%ld) %ld; # ms\n", eventnumber, timeout);
break; break;
case exec_cmd: case exec:
buffer.append(" exec \""); buffer.append(" exec \"");
c = StreamProtocolParser::printString(buffer, c); c = StreamProtocolParser::printString(buffer, c);
buffer.append("\";\n"); buffer.append("\";\n");
break; break;
case connect_cmd: case connect:
timeout = extract<unsigned long>(c); timeout = extract<unsigned long>(c);
buffer.print(" connect %ld; # ms\n", timeout); buffer.print(" connect %ld; # ms\n", timeout);
break; break;
case disconnect_cmd: case disconnect:
buffer.append(" disconnect;\n"); buffer.append(" disconnect;\n");
break; break;
default: default:
@ -289,9 +282,9 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
{ {
unsigned long timeout = 0; unsigned long timeout = 0;
if (strcmp(command, commandStr[in_cmd]) == 0) if (strcmp(command, "in") == 0)
{ {
buffer.append(in_cmd); buffer.append(in);
if (!protocol->compileString(buffer, args, if (!protocol->compileString(buffer, args,
ScanFormat, this)) ScanFormat, this))
{ {
@ -300,9 +293,9 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
buffer.append(StreamProtocolParser::eos); buffer.append(StreamProtocolParser::eos);
return true; return true;
} }
if (strcmp(command, commandStr[out_cmd]) == 0) if (strcmp(command, "out") == 0)
{ {
buffer.append(out_cmd); buffer.append(out);
if (!protocol->compileString(buffer, args, if (!protocol->compileString(buffer, args,
PrintFormat, this)) PrintFormat, this))
{ {
@ -311,9 +304,9 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
buffer.append(StreamProtocolParser::eos); buffer.append(StreamProtocolParser::eos);
return true; return true;
} }
if (strcmp(command, commandStr[wait_cmd]) == 0) if (strcmp(command, "wait") == 0)
{ {
buffer.append(wait_cmd); buffer.append(wait);
if (!protocol->compileNumber(timeout, args)) if (!protocol->compileNumber(timeout, args))
{ {
return false; return false;
@ -321,7 +314,7 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
buffer.append(&timeout, sizeof(timeout)); buffer.append(&timeout, sizeof(timeout));
return true; return true;
} }
if (strcmp(command, commandStr[event_cmd]) == 0) if (strcmp(command, "event") == 0)
{ {
if (!busSupportsEvent()) if (!busSupportsEvent())
{ {
@ -330,7 +323,7 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
return false; return false;
} }
unsigned long eventmask = 0xffffffff; unsigned long eventmask = 0xffffffff;
buffer.append(event_cmd); buffer.append(event);
if (*args == '(') if (*args == '(')
{ {
if (!protocol->compileNumber(eventmask, ++args)) if (!protocol->compileNumber(eventmask, ++args))
@ -357,9 +350,9 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
buffer.append(&timeout, sizeof(timeout)); buffer.append(&timeout, sizeof(timeout));
return true; return true;
} }
if (strcmp(command, commandStr[exec_cmd]) == 0) if (strcmp(command, "exec") == 0)
{ {
buffer.append(exec_cmd); buffer.append(exec);
if (!protocol->compileString(buffer, args, if (!protocol->compileString(buffer, args,
PrintFormat, this)) PrintFormat, this))
{ {
@ -368,9 +361,9 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
buffer.append(StreamProtocolParser::eos); buffer.append(StreamProtocolParser::eos);
return true; return true;
} }
if (strcmp(command, commandStr[connect_cmd]) == 0) if (strcmp(command, "connect") == 0)
{ {
buffer.append(connect_cmd); buffer.append(connect);
if (!protocol->compileNumber(timeout, args)) if (!protocol->compileNumber(timeout, args))
{ {
return false; return false;
@ -378,9 +371,9 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
buffer.append(&timeout, sizeof(timeout)); buffer.append(&timeout, sizeof(timeout));
return true; return true;
} }
if (strcmp(command, commandStr[disconnect_cmd]) == 0) if (strcmp(command, "disconnect") == 0)
{ {
buffer.append(disconnect_cmd); buffer.append(disconnect);
return true; return true;
} }
@ -411,10 +404,8 @@ bool StreamCore::
startProtocol(StartMode startMode) startProtocol(StartMode startMode)
{ {
MutexLock lock(this); MutexLock lock(this);
debug("StreamCore::startProtocol(%s, startMode=%s)\n", name(), debug("StreamCore::startProtocol(%s, startMode=%s)\n",
startMode == StartNormal ? "StartNormal" : name(), toStr(startMode));
startMode == StartInit ? "StartInit" :
startMode == StartAsync ? "StartAsync" : "Invalid");
if (!businterface) if (!businterface)
{ {
error("%s: No businterface attached\n", name()); error("%s: No businterface attached\n", name());
@ -489,7 +480,7 @@ finishProtocol(ProtocolResult status)
case ScanError: case ScanError:
handler = onMismatch(); handler = onMismatch();
/* reparse old input if first command in handler is 'in' */ /* reparse old input if first command in handler is 'in' */
if (*handler == in_cmd) if (*handler == in)
{ {
debug("reparsing input \"%s\"\n", debug("reparsing input \"%s\"\n",
inputLine.expand()()); inputLine.expand()());
@ -519,17 +510,7 @@ finishProtocol(ProtocolResult status)
} }
} }
debug("StreamCore::finishProtocol(%s, status=%s) %sbus owner\n", debug("StreamCore::finishProtocol(%s, status=%s) %sbus owner\n",
name(), name(), toStr(status), flags & BusOwner ? "" : "not ");
status==0 ? "Success" :
status==1 ? "LockTimeout" :
status==2 ? "WriteTimeout" :
status==3 ? "ReplyTimeout" :
status==4 ? "ReadTimeout" :
status==5 ? "ScanError" :
status==6 ? "FormatError" :
status==7 ? "Abort" :
status==8 ? "Fault" : "Invalid",
flags & BusOwner ? "" : "not ");
if (flags & BusOwner) if (flags & BusOwner)
{ {
busUnlock(); busUnlock();
@ -554,29 +535,29 @@ evalCommand()
} }
activeCommand = commandIndex; activeCommand = commandIndex;
debug("StreamCore::evalCommand(%s): activeCommand = %s\n", debug("StreamCore::evalCommand(%s): activeCommand = %s\n",
name(), commandName(*activeCommand)); name(), CommandsToStr(*activeCommand));
switch (*commandIndex++) switch (*commandIndex++)
{ {
case out_cmd: case out:
//// flags &= ~(AcceptInput|AcceptEvent); //// flags &= ~(AcceptInput|AcceptEvent);
return evalOut(); return evalOut();
case in_cmd: case in:
//// flags &= ~AcceptEvent; //// flags &= ~AcceptEvent;
return evalIn(); return evalIn();
case wait_cmd: case wait:
//// flags &= ~(AcceptInput|AcceptEvent); //// flags &= ~(AcceptInput|AcceptEvent);
return evalWait(); return evalWait();
case event_cmd: case event:
//// flags &= ~AcceptInput; //// flags &= ~AcceptInput;
return evalEvent(); return evalEvent();
case exec_cmd: case exec:
return evalExec(); return evalExec();
case end_cmd: case end:
finishProtocol(Success); finishProtocol(Success);
return true; return true;
case connect_cmd: case connect:
return evalConnect(); return evalConnect();
case disconnect_cmd: case disconnect:
return evalDisconnect(); return evalDisconnect();
default: default:
error("INTERNAL ERROR (%s): illegal command code 0x%02x\n", error("INTERNAL ERROR (%s): illegal command code 0x%02x\n",
@ -602,11 +583,11 @@ evalOut()
} }
outputLine.append(outTerminator); outputLine.append(outTerminator);
debug ("StreamCore::evalOut: outputLine = \"%s\"\n", outputLine.expand()()); debug ("StreamCore::evalOut: outputLine = \"%s\"\n", outputLine.expand()());
if (*commandIndex == in_cmd) // prepare for early input if (*commandIndex == in) // prepare for early input
{ {
flags |= AcceptInput; flags |= AcceptInput;
} }
if (*commandIndex == event_cmd) // prepare for early event if (*commandIndex == event) // prepare for early event
{ {
flags |= AcceptEvent; flags |= AcceptEvent;
} }
@ -817,7 +798,7 @@ lockCallback(StreamIoStatus status)
{ {
MutexLock lock(this); MutexLock lock(this);
debug("StreamCore::lockCallback(%s, status=%s)\n", debug("StreamCore::lockCallback(%s, status=%s)\n",
name(), StreamIoStatusStr[status]); name(), ::toStr(status));
if (!(flags & LockPending)) if (!(flags & LockPending))
{ {
error("StreamCore::lockCallback(%s) called unexpectedly\n", error("StreamCore::lockCallback(%s) called unexpectedly\n",
@ -844,7 +825,7 @@ lockCallback(StreamIoStatus status)
return; return;
default: default:
error("StreamCore::lockCallback(%s) unexpected status %s\n", error("StreamCore::lockCallback(%s) unexpected status %s\n",
name(), StreamIoStatusStr[status]); name(), ::toStr(status));
flags &= ~BusOwner; flags &= ~BusOwner;
finishProtocol(Fault); finishProtocol(Fault);
return; return;
@ -861,7 +842,7 @@ writeCallback(StreamIoStatus status)
{ {
MutexLock lock(this); MutexLock lock(this);
debug("StreamCore::writeCallback(%s, status=%s)\n", debug("StreamCore::writeCallback(%s, status=%s)\n",
name(), status ? "Timeout" : "Success"); name(), ::toStr(status));
if (!(flags & WritePending)) if (!(flags & WritePending))
{ {
error("StreamCore::writeCallback(%s) called unexpectedly\n", error("StreamCore::writeCallback(%s) called unexpectedly\n",
@ -949,13 +930,13 @@ readCallback(StreamIoStatus status,
lastInputStatus = status; lastInputStatus = status;
debug("StreamCore::readCallback(%s, status=%s input=\"%s\", size=%" Z "u)\n", debug("StreamCore::readCallback(%s, status=%s input=\"%s\", size=%" Z "u)\n",
name(), StreamIoStatusStr[status], name(), ::toStr(status),
StreamBuffer(input, size).expand()(), size); StreamBuffer(input, size).expand()(), size);
if (!(flags & AcceptInput)) if (!(flags & AcceptInput))
{ {
error("StreamCore::readCallback(%s, %s, \"%s\") called unexpectedly\n", error("StreamCore::readCallback(%s, %s, \"%s\") called unexpectedly\n",
name(), StreamIoStatusStr[status], name(), ::toStr(status),
StreamBuffer(input, size).expand()()); StreamBuffer(input, size).expand()());
return 0; return 0;
} }
@ -1000,7 +981,7 @@ readCallback(StreamIoStatus status,
inputBuffer.append(input, size); inputBuffer.append(input, size);
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %" Z "u\n", debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %" Z "u\n",
name(), inputBuffer.expand()(), inputBuffer.length()); name(), inputBuffer.expand()(), inputBuffer.length());
if (*activeCommand != in_cmd) if (*activeCommand != in)
{ {
// early input, stop here and wait for in command // early input, stop here and wait for in command
// -- Should we limit size of inputBuffer? -- // -- Should we limit size of inputBuffer? --
@ -1239,7 +1220,7 @@ normal_format:
} }
else else
{ {
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
error("%s: Input \"%s%s\" does not match format \"%%%s\"\n", error("%s: Input \"%s%s\" does not match format \"%%%s\"\n",
name(), inputLine.expand(consumedInput, 20)(), name(), inputLine.expand(consumedInput, 20)(),
@ -1271,7 +1252,7 @@ normal_format:
outputLine.length())(), outputLine.expand()()); outputLine.length())(), outputLine.expand()());
if (inputLine.length() - consumedInput < outputLine.length()) if (inputLine.length() - consumedInput < outputLine.length())
{ {
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
error("%s: Input \"%s%s\" too short." error("%s: Input \"%s%s\" too short."
" No match for format \"%%%s\" (\"%s\")\n", " No match for format \"%%%s\" (\"%s\")\n",
@ -1285,7 +1266,7 @@ normal_format:
} }
if (!outputLine.startswith(inputLine(consumedInput),outputLine.length())) if (!outputLine.startswith(inputLine(consumedInput),outputLine.length()))
{ {
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
error("%s: Input \"%s%s\" does not match format \"%%%s\" (\"%s\")\n", error("%s: Input \"%s%s\" does not match format \"%%%s\" (\"%s\")\n",
name(), inputLine.expand(consumedInput, 20)(), name(), inputLine.expand(consumedInput, 20)(),
@ -1301,7 +1282,7 @@ normal_format:
flags &= ~Separator; flags &= ~Separator;
if (!matchValue(fmt, fieldAddress ? fieldAddress() : NULL)) if (!matchValue(fmt, fieldAddress ? fieldAddress() : NULL))
{ {
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
if (flags & ScanTried) if (flags & ScanTried)
error("%s: Input \"%s%s\" does not match format \"%%%s\"\n", error("%s: Input \"%s%s\" does not match format \"%%%s\"\n",
@ -1334,7 +1315,7 @@ normal_format:
{ {
int i = 0; int i = 0;
while (commandIndex[i] >= ' ') i++; while (commandIndex[i] >= ' ') i++;
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
error("%s: Input \"%s%s\" too short.\n", error("%s: Input \"%s%s\" too short.\n",
name(), name(),
@ -1347,7 +1328,7 @@ normal_format:
} }
if (command != inputLine[consumedInput]) if (command != inputLine[consumedInput])
{ {
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
int i = 0; int i = 0;
while (commandIndex[i] >= ' ') i++; while (commandIndex[i] >= ' ') i++;
@ -1374,7 +1355,7 @@ normal_format:
size_t surplus = inputLine.length()-consumedInput; size_t surplus = inputLine.length()-consumedInput;
if (surplus > 0 && !(flags & IgnoreExtraInput)) if (surplus > 0 && !(flags & IgnoreExtraInput))
{ {
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) if (!(flags & AsyncMode) && onMismatch[0] != in)
{ {
error("%s: %" Z "d byte%s surplus input \"%s%s\"\n", error("%s: %" Z "d byte%s surplus input \"%s%s\"\n",
name(), surplus, surplus==1 ? "" : "s", name(), surplus, surplus==1 ? "" : "s",
@ -1596,7 +1577,7 @@ eventCallback(StreamIoStatus status)
return; return;
} }
debug("StreamCore::eventCallback(%s, status=%s)\n", debug("StreamCore::eventCallback(%s, status=%s)\n",
name(), StreamIoStatusStr[status]); name(), ::toStr(status));
MutexLock lock(this); MutexLock lock(this);
flags &= ~AcceptEvent; flags &= ~AcceptEvent;
switch (status) switch (status)
@ -1610,7 +1591,7 @@ eventCallback(StreamIoStatus status)
return; return;
default: default:
error("%s: Event error from device: %s\n", error("%s: Event error from device: %s\n",
name(), StreamIoStatusStr[status]); name(), ::toStr(status));
finishProtocol(Fault); finishProtocol(Fault);
return; return;
} }
@ -1751,7 +1732,7 @@ void StreamCore::
printStatus(StreamBuffer& buffer) printStatus(StreamBuffer& buffer)
{ {
buffer.print("active command=%s ", buffer.print("active command=%s ",
activeCommand ? commandName(*activeCommand) : "none"); activeCommand ? CommandsToStr(*activeCommand) : "none");
buffer.print("flags=0x%04lx ", flags); buffer.print("flags=0x%04lx ", flags);
if (flags & IgnoreExtraInput) buffer.append("IgnoreExtraInput "); if (flags & IgnoreExtraInput) buffer.append("IgnoreExtraInput ");
if (flags & InitRun) buffer.append("InitRun "); if (flags & InitRun) buffer.append("InitRun ");

View File

@ -70,6 +70,8 @@ void acceptEvent(unsigned short mask, unsigned short timeout)
***************************************/ ***************************************/
#include "MacroMagic.h"
enum Flags { enum Flags {
// 0x00FFFFFF reserved for StreamCore // 0x00FFFFFF reserved for StreamCore
None = 0x0000, None = 0x0000,
@ -97,14 +99,12 @@ class StreamCore :
StreamBusInterface::Client StreamBusInterface::Client
{ {
protected: protected:
enum ProtocolResult {
Success, LockTimeout, WriteTimeout, ReplyTimeout, ReadTimeout,
ScanError, FormatError, Abort, Fault
};
enum StartMode { ENUM(ProtocolResult,
StartNormal, StartInit, StartAsync Success, LockTimeout, WriteTimeout, ReplyTimeout, ReadTimeout, ScanError, FormatError, Abort, Fault, Offline);
};
ENUM(StartMode,
StartNormal, StartInit, StartAsync);
class MutexLock class MutexLock
{ {

View File

@ -23,17 +23,17 @@
#include <stdio.h> #include <stdio.h>
#include "StreamBuffer.h" #include "StreamBuffer.h"
#include "MacroMagic.h"
enum FormatType {NoFormat, ScanFormat, PrintFormat}; ENUM (FormatType,
NoFormat, ScanFormat, PrintFormat);
class StreamProtocolParser class StreamProtocolParser
{ {
public: public:
enum Codes ENUM (Codes,
{ eos, skip, whitespace, format, format_field, last_function_code);
eos = 0, skip, whitespace, format, format_field, last_function_code
};
class Client; class Client;