Suggestion to allow macros that don't expand within "string"

Daniel Goldman <[email protected]> Wed, 18 Jun 2014 14:10:54 -0700
Newsgroups gmane.comp.gnu.m4.general
Message-ID <[email protected]>
For some future m4 version, I'd like to suggest an alternative 
"m4_define2" (or other more clever name) that is the same as m4_define, 
but the newly defined macro does not expand if within a double-quoted 
"string". This would be useful for me, and I think for others too.

To clarify, current m4_define works as follows:

m4_define(foo, bar)     foo -> bar     "foo" -> "bar"

Proposed alternative would work as follows:

m4_define2(foo, bar)    foo -> bar     "foo" -> "foo"

Perhaps the strongest, most obvious, argument for this addition is that 
cpp does not substitute a macro when it occurs within quotes:

#define foo bar         foo -> bar     "foo" -> "foo"

There is a reason cpp has this behavior - it's useful. I use it to 
display names of macros and their values in a diagnostic log file. I 
think it's a flaw that m4 lacks the cpp behavior (and a flaw that cpp 
lacks the m4 behavior, which is also useful). I think m4 could give the 
user both choices.

As a workaround, the input file can (possibly) be modified to produce 
the needed results. It seems the diagnostic macros I use might need to 
be modified to add another argument with double quote delimiters. In 
other words, DIAG_INT(MACRO_1) might need to be changed to something 
like DIAG_INT(MACRO_1, ``MACRO_1''). But this is tedious, and puts the 
effort on the user. And I already tried it. It's not trivial getting it 
to work correctly. Instead of making the user flail around, I think it's 
better to improve m4.

The only reason I see against making this change is that it's work to 
modify the m4 source code. But since cpp already does the behavior, it's 
doable, and the cpp source might help figure out the logic.

Perhaps there are some special conditions or complications that need to 
be taken into account that I am not aware of. But on the face of it, the 
logic seems maybe simple:

** Maintain a field in the macro data structure (I'm assuming there is 
such a data structure!) to store whether the macro is defined with 
m4_define or m4_define2. ** Add "in_quote" variable to the C function 
that reads input tokens. ** For each line of input read, in_quote starts 
out FALSE. ** Each input token is either within a quoted string or not. 
** When we encounter un-escaped " character on the input line, toggle 
in_quote variable. ** If in_quote is TRUE and the macro is defined by 
m4_define2, don't expand the macro. Otherwise, expand it.

Thanks,
Daniel