O< ?ack <command> SignallingPredictedProblem \
<problematic-train> <problematic-segment>|- : <error message>...
+ O< ?ack <command> CommandPreconditionsViolated direction
+ response to speed command which specified a direction, if the train
+ is actually facing the other direction
+
when these come through the multiplexer, everything which is a
result of _other_ clients' activities, between <executing> and
<ack> inclusive, is prefixed with `-' if they are not due to
CHIEF COMMANDS
- speed <trainpname> <step>
+ speed <trainpname> <step> [forwards|backwards]
!speed <trainpname> <step>
noop [<anything>...]
jmp_buf jb;
};
+typedef struct { const char *word; int backwards; int change; } DirectionInfo;
+static const DirectionInfo directioninfos[]= {
+ { "forwards", 0, 0 }, /* first two must be `forwards' and `backwards' */
+ { "backwards", 1, 0 }, /* for the benefit of cmd_speed */
+ { "change", -1, 1 },
+ { 0 }
+};
+
unsigned long nmra_argnumber(NmraParseEncodeCaller *pec, int argi) {
return pec->arg[argi];
}
static int cmd_speed(ParseState *ps, const CmdInfo *ci) {
long speed;
Train *tra;
+ const DirectionInfo *di= 0;
MUSTECR( ps_needtrain(ps,&tra) );
-
MUSTECR( ps_neednumber(ps,&speed,0,126,"speed step") );
+ if (ps->remain) {
+ di= some_needword_lookup_counted(ps,directioninfos,2,"direction");
+ if (!di) return EC_BadCmd;
+ }
MUSTECR( ps_neednoargs(ps) );
+ if (di && di->backwards != tra->backwards) {
+ ouprintf("ack %s CommandPreconditionsViolated direction\n", ci->name);
+ return EC_BadCmd;
+ }
+
if (ci->xarg & CIXF_FORCE) {
actual_speed(tra,speed);
} else {
static int cmd_direction(ParseState *ps, const CmdInfo *ci) {
Train *tra;
int backwards;
+ const DirectionInfo *di;
MUSTECR( ps_needtrain(ps,&tra) );
- MUSTECR( ps_needword(ps) );
- if (!thiswordstrcmp(ps,"forwards")) backwards= 0;
- else if (!thiswordstrcmp(ps,"backwards")) backwards= 1;
- else if (!thiswordstrcmp(ps,"change")) backwards= !tra->backwards;
- else return badcmd(ps, "direction must be forwards|backwards|change");
+ di= some_needword_lookup(ps,directioninfos,"direction");
+ if (!di) return EC_BadCmd;
+ backwards= di->change ? !tra->backwards : di->backwards;
+
MUSTECR( ps_neednoargs(ps) );
MUSTECRPREDICT( safety_setdirection(tra,backwards,CMDPPC) );
/*---------- macro for table lookups, with help from parseutils.c ----------*/
+#define some_lookup_counted(ps, infos, ninfos) \
+ ((const typeof(infos[0])*) \
+ any_lookup((ps),(infos),(ninfos),sizeof((infos)[0])))
+
#define some_lookup(ps, infos) \
- ((const typeof(infos[0])*) \
- any_lookup((ps),(infos),INT_MAX,sizeof((infos)[0])))
+ (some_lookup_counted((ps),(infos),INT_MAX))
-#define some_needword_lookup_counted(ps, infos, ninfos, what) \
- ((const typeof(infos[0])*) \
- any_needword_lookup((ps), \
- (infos), (ninfos), sizeof((infos)[0]), \
- (what)))
+#define some_needword_lookup_counted(ps, infos, ninfos, what) \
+ ((const typeof(infos[0])*) \
+ any_needword_lookup((ps),(infos),(ninfos),sizeof((infos)[0]),(what)))
#define some_needword_lookup(ps, infos, what) \
- ((const typeof(infos[0])*) \
- any_needword_lookup((ps),(infos),INT_MAX,sizeof((infos)[0]),(what)))
+ (some_needword_lookup_counted((ps),(infos),INT_MAX,(what)))
const void *any_lookup(ParseState *ps,
const void *infos, int ninfsmax, size_t infosz);
InvalidState
SignallingPredictedProblem
SignallingHorizonReached
+ CommandPreconditionsViolated
LimitExceeded
SystemFailed