After a lot of Googling, coding, swearing, recoding, more swearing and so on, I have devised what I think is a reasonably elegant solution to the "How do you get tables of flash strings without having to individually name every string?" question.
CAVEATS:
- requires a recent version of GCC (4.9.x+) as present in Arduino IDE
- is not even slightly portable, as it uses COUNTER and variadic macros
- the syntax is LISP like, i.e. it really, really sucks.
Here is sample of how you use it:
MAINSCREEN_STRING_TABLE(
MAINSCREEN_STRING_ENTRY("1. Initialize Sprongles",
MAINSCREEN_STRING_ENTRY("2. Terminate dubrificator",
MAINSCREEN_STRING_ENTRY("3. Vorpalise quadrangulators",
MAINSCREEN_STRING_TABLE_END(mainmenu)))));
void setup()
{
Serial.println((const __FlashStringHelper *)mainmenu[0]);
Serial.println((const __FlashStringHelper *)mainmenu[1]);
Serial.println((const __FlashStringHelper *)mainmenu[2]);
}
Notice how the actual name of the table comes at the end of the declaration. Obviously, these macros become a lot more useful when you loop through the table.
And here are the macros that actually do the work:
// (c) 2017 Stephen Parry, MIT v2 License
#define MAINSCREEN_STRING_TABLE_END(t) t,,
#define _MSTE2(s,n,t,v,...) t, v char const PROGMEM t ## _ ## n [] = s; , t ## _ ## n, __VA_ARGS__
#define _MSTE1(...) _MSTE2(__VA_ARGS__)
#define MAINSCREEN_STRING_ENTRY(s,next) _MSTE1(s,__COUNTER__,next)
#define _MST2(t,v,...) v; const char* const t[] PROGMEM = {__VA_ARGS__};
#define _MST1(...) _MST2(__VA_ARGS__)
#define MAINSCREEN_STRING_TABLE(p) _MST1(p)
The macros create the sequence of strings variables (mainmenu_1 etc.) automatically, although I think the numbers come out in reverse.
Comments, suggestions welcome.
Feel free to use in your own code.