cpp hacking: bump FOO by 1
Fred Wright
fw at fwright.net
Wed Sep 2 23:42:17 UTC 2020
On Sun, 30 Aug 2020, Hal Murray via devel wrote:
> Is there any way to do something like
> #define FOO $FOO+1
>
> I want to keep track of the number of times a macro has been called. That
> seems like something that would happen often enough that there would be a
> standard recipe but I haven't seen it. (Or didn't recognize it.)
>
> ----------
>
> The context is the code in ntp_control that is responding to ntpq requests to
> read a variable. It needs to translate a string (name of variable to read) to
> a subroutine to print that variable. Current code looks like:
>
> #define CS_REFID 6
> { CS_REFID, RO|DEF, "refid" },
> #define CS_REFTIME 7
> { CS_REFTIME, RO|DEF, "reftime" },
> #define CS_POLL 8
> { CS_POLL, RO|DEF, "tc" },
> #define CS_PEERID 9
> { CS_PEERID, RO|DEF, "peer" },
>
> That sets up the table to search. The table is big (~100 slots) so it's a
> real pain to insert a new slot.
>
> Later on, there is a giant select that uses those CS_xxx tags:
>
> case CS_ROOTDELAY:
> ctl_putdbl(sys_var[CS_ROOTDELAY].text,
> sys_vars.sys_rootdelay * MS_PER_S);
> break;
>
> case CS_ROOTDISPERSION:
> ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
> sys_vars.sys_rootdisp * MS_PER_S);
> break;
>
> ---------
The usual way to do this sort of thing with the lame macro processor known
as cpp is as follows:
First define a "master macro" whose body is a series of invocations of an
entry macro, with all the necessary properties being provided as
arguments. Then, for each table or other use:
1) Define the entry macro to generate the appropriate content from the
appropriate arguments.
2) Invoke the master macro.
3) Undefine the entry macro (so it's ready for next time).
I can't make a precise example since you chose different entries for the
two parts of your example above, but for the first part one could have
something like this:
#define CS_ENTRIES \
CS_ENTRY(REFID, RO|DEF, "refid") \
CS_ENTRY(POLL, RO|DEF, "tc") \
CS_ENTRY(PEERID, RO|DEF, "peer") \
Then, to define the numeric codes:
#define CS_ENTRY(sym, flags, name) CS_##sym,
enum cs_index {
CS_ENTRIES
CS_MAXVAL // Maximum value +1
};
#undef CS_ENTRY
For a table of names:
#define CS_ENTRY(sym, flags, name) name,
static const char * const cs_names[] = {
CS_ENTRIES
};
#undef CS_ENTRY
> One approach would be to have an external program do the equivalent of the cpp
> processing that we would like to do. That would take some waf hacking, but
> shouldn't be a big deal.
An unnecessary complication.
Fred Wright
More information about the devel
mailing list