diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 2d6fa31..c9f4bcc 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -312,7 +312,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) } int16_t splitnum = splitValues(p, com, opcode=='M' || opcode=='P'); - if (splitnum<- || splitnum>=MAX_COMMAND_PARAMS) { + if (splitnum<0 || splitnum>=MAX_COMMAND_PARAMS) { DIAG(F("Too many parameters")); return; } @@ -379,7 +379,7 @@ bool DCCEXParser::funcmap(int16_t cab, byte value, byte fstart, byte fstop) } bool DCCEXParser::execute(byte * com,Print *stream, byte opcode,byte params, int16_t p[], RingStream * ringStream) { - +bool accessoryCommandReverse = false; // TODO ZZBEGIN ZZ(#) StringFormatter::send(stream, F("<# %d>\n"), MAX_LOCOS); ZZ(t,cab) CHECK(cab>0) @@ -480,7 +480,7 @@ ZZ(I,id,position) // - rotate a DCC turntable ZZ(I,id,DCC,home) auto tto = Turntable::get(id); CHECK(tto) - CHECK(home >-0 0 && home <= 3600) + CHECK(home >=0 && home <= 3600) CHECK(DCCTurntable::create(id)) tto = Turntable::get(id); CHECK(tto) @@ -538,7 +538,7 @@ ZZ(Z,id,pin,iflag) // CHECK(id > 0 && iflag >= 0 && iflag <= 7 ) CHECK(Output::create(id,pin,iflag, 1)) StringFormatter::send(stream, F("\n")); -Z(Z,id) CHECK(Output::remove(id)) +ZZ(Z,id) CHECK(Output::remove(id)) StringFormatter::send(stream, F("\n")); ZZ(Z) // list Output definitions @@ -592,7 +592,7 @@ ZZ(C,SPEED28) DCC::setGlobalSpeedsteps(28); DIAG(F("28 Speedsteps")); ZZ(C,SPEED128) DCC::setGlobalSpeedsteps(128); DIAG(F("128 Speedsteps")); ZZ(C,RAILCOM,ON) DIAG(F("Railcom %S"),DCCWaveform::setRailcom(true,false)?F("ON"):F("OFF")); ZZ(C,RAILCOM,OFF) DIAG(F("Railcom OFF")); DCCWaveform::setRailcom(false,false); -ZZ(C,RAILCOM,DEBUG) DIAG(F("Railcom %S") DCCWaveform::setRailcom(true,true)?F("ON"):F("OFF")); +ZZ(C,RAILCOM,DEBUG) DIAG(F("Railcom %S"), DCCWaveform::setRailcom(true,true)?F("ON"):F("OFF")); #ifndef DISABLE_PROG ZZ(D,ACK,LIMIT,value) DCCACK::setAckLimit(value); LCD(1, F("Ack Limit=%dmA"), value); diff --git a/DCCEXParserMacros.h b/DCCEXParserMacros.h index fee45c7..d1c8604 100644 --- a/DCCEXParserMacros.h +++ b/DCCEXParserMacros.h @@ -1,36 +1,31 @@ -// Macro for printing a single argument -#define ZZARG(arg) \ - auto arg=p[_xix]; (void)arg;\ - if ( #arg[0]<='Z' && p[_xix]!=CONCAT(#arg,_hk)) break; \ - _xix++; - -#define FOR_EACH_IMPL_1(x) ZZARG(x) -#define FOR_EACH_IMPL_2(x, ...) ZZARG(x) FOR_EACH_IMPL_1(__VA_ARGS__) -#define FOR_EACH_IMPL_3(x, ...) ZZARG(x) FOR_EACH_IMPL_2(__VA_ARGS__) -#define FOR_EACH_IMPL_4(x, ...) ZZARG(x) FOR_EACH_IMPL_3(__VA_ARGS__) -#define FOR_EACH_IMPL_5(x, ...) ZZARG(x) FOR_EACH_IMPL_4(__VA_ARGS__) -#define FOR_EACH_IMPL_6(x, ...) ZZARG(x) FOR_EACH_IMPL_5(__VA_ARGS__) -#define FOR_EACH_IMPL_7(x, ...) ZZARG(x) FOR_EACH_IMPL_6(__VA_ARGS__) -// Add more levels if needed... -// Step 1: Count the number of arguments -#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__,7, 6, 5, 4, 3, 2, 1) -#define FOR_EACH_NARG_(_1, _2, _3, _4, _5, _6, _7, N, ...) N +// Count the number of arguments +#define FOR_EACH_NARG(...) FOR_EACH_NARG_HELPER(__VA_ARGS__,8,7, 6,5,4, 3, 2, 1, 0) +#define FOR_EACH_NARG_HELPER(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N // Step 2: Force proper expansion (extra indirection to resolve `##`) #define EXPAND(x) x #define CONCAT(a, b) a##b -// Step 3: Dispatch to the correct implementation -#define FOR_EACH_IMPL(count, ...) EXPAND(CONCAT(FOR_EACH_IMPL_, count))(__VA_ARGS__) -// Step 4: Main macro to process arguments -#define FOR_EACH(...) FOR_EACH_IMPL(FOR_EACH_NARG(__VA_ARGS__), __VA_ARGS__) +#define ZZZ(_i,_arg) \ + if ( #_arg[0]<='Z' && p[_i]!=CONCAT(#_arg,_hk)) break; \ + auto _arg=p[_i]; (void) _arg; -#define ZZ(op,...) return true; }\ -if (opcode==#op[0] && params==FOR_EACH_NARG(__VA_ARGS__)) for (auto _xix=0;;) { \ - FOR_EACH(__VA_ARGS__) +// Each ZZ terminates the previous one +#define ZPREP(op,count) return true; } if (opcode==#op[0] && params==count) for (;;) { +#define Z1(op) ZPREP(op,0) +#define Z2(op,_1) ZPREP(op,1) ZZZ(0,_1) +#define Z3(op,_1,_2) ZPREP(op,2) ZZZ(0,_1) ZZZ(1,_2) +#define Z4(op,_1,_2,_3) ZPREP(op,3) ZZZ(0,_1) ZZZ(1,_2) ZZZ(2,_3) +#define Z5(op,_1,_2,_3,_4) ZPREP(op,4) ZZZ(0,_1) ZZZ(1,_2) ZZZ(2,_3) ZZZ(3,_4) +#define Z6(op,_1,_2,_3,_4,_5) ZPREP(op,5) ZZZ(0,_1) ZZZ(1,_2) ZZZ(2,_3) ZZZ(3,_4) ZZZ(4,_5) +#define Z7(op,_1,_2,_3,_4,_5,_6) ZPREP(op,6) ZZZ(0,_1) ZZZ(1,_2) ZZZ(2,_3) ZZZ(3,_4) ZZZ(4,_5) ZZZ(5,_6) +#define Z8(op,_1,_2,_3,_4,_5,_6,_7) ZPREP(op,7) ZZZ(0,_1) ZZZ(1,_2) ZZZ(2,_3) ZZZ(3,_4) ZZZ(4,_5) ZZZ(5,_6) ZZZ(6,_7) +#define ZRIP(count) CONCAT(Z,count) +#define ZZ(...) ZRIP(FOR_EACH_NARG(__VA_ARGS__))(__VA_ARGS__) + #define ZZBEGIN if (false) { #define ZZEND return true; } return false; #define CHECK(x) if (!(x)) return false;