Macro expansion

S

sandeep

One of the serious limitations of C is the fact that macro expansion is
not done recursively. Many powerful constructions would become possible
if this was allowed. It is also something that often trips up novices in
the language.

I would suggest that in the next release of the ISO Standard, it is
decried that the preprocessor shall be run repeatedly. In fact it shall
be run n times until the nth run does not change the source file.
 
S

Stefan Ram

sandeep said:
One of the serious limitations of C is the fact that macro expansion is
not done recursively.

You can add additional macro processors in front of the C compiler,
which - of course - is less portable.
Many powerful constructions would become possible if this was
allowed.

Yes, but they might also be less readable/maintainable.

The choice of C as a language might even express that one
does *not want* such »higher-order macros«. Otherwise, one
might have chosen Lisp.
I would suggest that in the next release of the ISO Standard,
it is decried that the preprocessor shall be run repeatedly.

This might break existing code. However, you can implement
it yourself by calling »cpp« (the C preprocessor) in this way
(in a script with »diff«).
 
I

Ian Collins

One of the serious limitations of C is the fact that macro expansion is
not done recursively. Many powerful constructions would become possible
if this was allowed. It is also something that often trips up novices in
the language.

I would suggest that in the next release of the ISO Standard, it is
decried that the preprocessor shall be run repeatedly. In fact it shall
be run n times until the nth run does not change the source file.

Why? Anything that encourages preprocessor overuse should be avoided!
 
S

Seebs

Why? Anything that encourages preprocessor overuse should be avoided!

I think at this point, it is safe to say that sandeep is just trolling us.

Think about the Stopped Clock. No one could possibly come up with this many
suggestions which are this bad without doing it on purpose.

-s
 
D

Default User

Keith Thompson said:
1. How much existing code would this break?

2. Do you really want to define a language feature that can easily cause
a compile-time infinite loop?

Has Sandeep ever had a proposed change to the language that made sense? I
decided he was a troll a long time ago, but others may feel differently.



Brian
 
K

Keith Thompson

sandeep said:
One of the serious limitations of C is the fact that macro expansion is
not done recursively. Many powerful constructions would become possible
if this was allowed. It is also something that often trips up novices in
the language.

I would suggest that in the next release of the ISO Standard, it is
decried that the preprocessor shall be run repeatedly. In fact it shall
be run n times until the nth run does not change the source file.

1. How much existing code would this break?

2. Do you really want to define a language feature that can easily cause
a compile-time infinite loop?
 
B

Ben Pfaff

sandeep said:
One of the serious limitations of C is the fact that macro expansion is
not done recursively. Many powerful constructions would become possible
if this was allowed. It is also something that often trips up novices in
the language.

Any recursive macro would recurse forever, wouldn't it?
 
S

Stefan Ram

Yes, but they might also be less readable/maintainable.

Actually, I /did/ built a preprocessor system with multiple
levels of macros myself. Here are some examples of the
source code (to judge their readability for the uninitiated):

This shows a function definition: It will write the
declaration to the header file and write the definition to
the implementation file. So one needs to change the
prototype only once in the source - not twice (in the header
file and in the implementation file):

@[h@*h
wchar_t * kdtxuc( register wchar_t * target, register const wchar_t * source )
@]¨#=writehead @=h@:h libkcfh libkc.c¨$[libkc.c
{ register wchar_t * result = target; while( *target++ = *source++ ); return result; }
$]libkc.c

The next example shows two blocks, labeled by an automatic
counter c (whose value is not visible here). The »¨@=@+c«
inserts the next block at this position, so:

@[@*c
{ IPersistFile * ppf;
hres = psl->lpVtbl->QueryInterface( psl, &IID_IPersistFile, &ppf );
if( SUCCEEDED( hres ))
{ @=@+c
¨ppf~>Release()¨; }
else{ printf( "QueryInterface failed, rc(%x),%x\n", hres, GetLastError()); }}¨@]

@[@*c
{ WORD wsz[ MAX_PATH ]; MultiByteToWideChar( CP_ACP, 0, LinkName, -1, wsz, MAX_PATH );
hres = ¨ppf~>Save( wsz, TRUE ); }¨@]

becomes

@[@*c
{ IPersistFile * ppf;
hres = psl->lpVtbl->QueryInterface( psl, &IID_IPersistFile, &ppf );
if( SUCCEEDED( hres ))
{ { WORD wsz[ MAX_PATH ]; MultiByteToWideChar( CP_ACP, 0, LinkName, -1, wsz, MAX_PATH );
hres = ¨ppf~>Save( wsz, TRUE ); }¨
¨ppf~>Release()¨; }
else{ printf( "QueryInterface failed, rc(%x),%x\n", hres, GetLastError()); }}¨@]

Thus, one can write (deeply) nested blocks as a /sequence/ of blocks.

It seems that ¨...¨ also means something. Possibly, it will
expand enclosed ¨~>¨ to something, but what this is, I have
forgotten now. Maybe ¨ppf~>Release()¨ became ¨Release( ppf )«?
 
I

ImpalerCore

Has Sandeep ever had a proposed change to the language that made sense? I
decided he was a troll a long time ago, but others may feel differently.

Yeah, but his trolling does sometimes provoke interesting discussion.
sandeep could have put a little more effort into his post, to make it
look a little bit more serious, like an example using some pseudocode
of what he intended it to do ...
 
T

Tim Rentsch

sandeep said:
One of the serious limitations of C is the fact that macro expansion is
not done recursively. Many powerful constructions would become possible
if this was allowed. It is also something that often trips up novices in
the language.

I would suggest that in the next release of the ISO Standard, it is
decried that the preprocessor shall be run repeatedly. In fact it shall
be run n times until the nth run does not change the source file.

I don't think we should wait - I'm ready to decry that suggestion
right now.
 
S

sandeep

I can't think of many common constructions that it would break - can you
give any examples?

There could be ways around this, e.g. abort the compiler if the source
code size expands exponentially for a predetermined number of iterations.
Has Sandeep ever had a proposed change to the language that made sense?
I decided he was a troll a long time ago, but others may feel
differently.

Look, I am writing a Masters thesis and my subject of expertise is "The
development of the ISO C Standard". It would be very helpful to have
examples of good peer recognition for changes proposed by me, but
unfortunately people in this group always look for the negatives!

I have plenty of ideas about how C can be improved, and lots of them are
fundamentally good ideas in my opinion.
 
K

Keith Thompson

Any recursive macro would recurse forever, wouldn't it?

I think you're right.

I think what sandeep is proposing is to delete C99 6.10.3.4p2:

If the name of the macro being replaced is found during this
scan of the replacement list (not including the rest of the
source file’s preprocessing tokens), it is not replaced.
Furthermore, if any nested replacements encounter the name of
the macro being replaced, it is not replaced. These nonreplaced
macro name preprocessing tokens are no longer available for
further replacement even if they are later (re)examined in
contexts in which that macro name preprocessing token would
otherwise have been replaced.

Recursive function calls require an if statement or equivalent to
prevent the recursion from becoming infinite. There's no way to
do that for a macro expansion.

Perhaps sandeep isn't aware that this restriction applies only to
the name of the macro being replaced; if a macro expansion includes
the name of a different macr, that's expanded when the sequence
is rescanned. Macro expansion can be arbitrarily deep; it's just
infinite recursion that's prohibited.

It's entirely possible that I'm missing something; I usually try
to avoid complex preprocessor magic.

sandeep, can you provide a concrete example of something that
produces one expansion in C as it currently exists, and would
produce a better expansion under your proposal?

In fact, it would be helpful if you could provide a few concrete
examples whenever you post a proposal for a change to the language.
It would help us understand just what you're proposing, and might
help you understand the pitfalls.
 
K

Keith Thompson

sandeep said:
I can't think of many common constructions that it would break - can you
give any examples?

I don't know about common constructions, but here's something
it would break:

#include <stdio.h>

void debug_puts(char *s)
{
printf("DEBUG: %s\n", s);
}

#ifdef DEBUGGING
#define puts(s) debug_puts(s)
#else
#define puts(s) puts(s)
#endif

int main(void)
{
puts("Hello");
return 0;
}

The #else clause is unnecessary anyway, so perhaps this isn't a great
example.
There could be ways around this, e.g. abort the compiler if the source
code size expands exponentially for a predetermined number of iterations.

Ok, can you give an example of a program that would make use of your
proposed new feature that *wouldn't* send the compiler into an infinite
loop?
Look, I am writing a Masters thesis and my subject of expertise is "The
development of the ISO C Standard". It would be very helpful to have
examples of good peer recognition for changes proposed by me, but
unfortunately people in this group always look for the negatives!

I have plenty of ideas about how C can be improved, and lots of them are
fundamentally good ideas in my opinion.

I'm afraid the evidence so far suggests otherwise.

Look, we're really not attacking your ideas because they're from you.
We're criticizing your ideas because they have serious problems.

Convince us that your ideas are useful. Start by showing us how they
can be used. If your ideas are at all sound, constructive criticism is
the best way to improve them.
 
J

J. J. Farrell

sandeep said:
One of the serious limitations of C is the fact that macro expansion is
not done recursively. Many powerful constructions would become possible
if this was allowed. It is also something that often trips up novices in
the language.

Please provide some illustrations of how and where this is a serious
limitation. For example, code which could be written more simply, or
become more understandable or more maintainable or more efficient if
this were provided. I'd also be interested to see examples of how the
current rules trip up novices.
I would suggest that in the next release of the ISO Standard, it is
decried that the preprocessor shall be run repeatedly. In fact it shall
be run n times until the nth run does not change the source file.

That suggestion needs to be made in comp.std.c rather than here,
preferably after a compiler implementing this feature has shown that it
is useful, harmless, and of value to programmers.
 
K

Keith Thompson

William Ahern said:

"Looping" is not an example.

My challenge for sandeep was to provide a concrete example of a C
program that would make use of his proposed new feature.
If the OP was serious about this feature perhaps he should study M4. I've
used it extensively in a few C projects for code generation.

As I recall, M4 has enough support for conditional expressions that it
can handle recursive expansion (by deciding when to end the recursion).
I don't believe the C preprocessor is sufficiently powerful to do that.
 
P

Peter Nilsson

In what way is that a _serious_ limitation?

Perhaps, but how useful are they. The preprocessing phase
serves a very simple purpose. It was never meant to be a
language in it's own right. Most other languages don't even
have one.

No, the order of replacement in the presense # and ## often
trips up novices.

It already is, in 6.10.3.4p1.
I can't think of many common constructions that it would
break

That _what_ would break? What is your proposal? There's a
good reason why 6.10.3.4p2 says macro expansion does not
recurse for the macro just expanded. Have you stopped to
think why?
- can you give any examples?

Can you?!
There could be ways around this,

Under what circumstances would the macro expansion either not
stop on the first substitution, or recurse indefinitely?
e.g. abort the compiler if the source
code size expands exponentially for a predetermined number of
iterations.


Look, I am writing a Masters thesis and my subject of expertise
is "The development of the ISO C Standard".

Strange subject. What can you add that WG14 can't and hasn't
already thought of?
It would be very helpful to have examples of good peer
recognition for changes proposed by me,

If you want good peer recognition, you might want to start by
actually thinking about your proposals and describing them in
detail, as opposed to blurting out brain farts.
but unfortunately people in this group always look for the
negatives!

That might be because there haven't been many positives to
your proprosals so far. You tell people there's a problem
they're not aware of. You tell them it's serious. You say
there's a solution, but it's up to someone else to come up
with it.

You're like a city slicker who walks into a small country
town that hasn't had an burglery or arrest in 20 years and
tells the community there's a crime wave and 40 riot police
should be posted immediately. And you wonder why the locals
are looking at you with furrowed brows?!
I have plenty of ideas about how C can be improved,

But clearly little experience in programming or implementing
C, let alone the ideas you propse.
and lots of them are fundamentally good ideas in my
opinion.

But are they fundamentally good ideas in practice? That is
(presumably) what your masters is meant to show.

Unfortunately, your ideas so far are nothing more than vague
ideas.

If you're capable of doing a Masters, then surely you're
capable of actually thinking about your ideas and fleshing
out your proposals in significantly more detail.
 
S

Seebs

My challenge for sandeep was to provide a concrete example of a C
program that would make use of his proposed new feature.

As-written, no currently valid C program would be changed by it.

(Because all the #defines would be gone in the resulting code, so
there'd be no macros to expand.)

-s
 
E

Eric Sosman

I can't think of many common constructions that it would break - can you
give any examples?

Any macro whose expansion produces the macro's own name is
well-defined today, and uncompilable under your proposal. That is,
any macro that relies on 6.10.3.4p2 and compiles today would be
uncompilable.
There could be ways around this, e.g. abort the compiler if the source
code size expands exponentially for a predetermined number of iterations.

The expansion needn't be exponential to be fatal. How long
would it take to compile

#define SANDEEP SANDEEP
SANDEEP

.... under your proposal? There's no growth at all (the expansion is
not longer than the macro), yet few people would have the patience to
wait for the completion of this infinite recursion.
Look, I am writing a Masters thesis and my subject of expertise is "The
development of the ISO C Standard". It would be very helpful to have
examples of good peer recognition for changes proposed by me, but
unfortunately people in this group always look for the negatives!

Looking is not required. The flaws in your proposals of late
have been too blatant to need a search. Really: Your proposals over
the last six months or so have been uniformly absurd.
I have plenty of ideas about how C can be improved, and lots of them are
fundamentally good ideas in my opinion.

I'd love to hear about fundamentally good ideas. When will you
post some?
 
S

Seebs

Any macro whose expansion produces the macro's own name is
well-defined today, and uncompilable under your proposal. That is,
any macro that relies on 6.10.3.4p2 and compiles today would be
uncompilable.

Not so!

The proposed action is re-running the preprocessor.

Since the first pass consumed all the #defines, there won't be any
more, unless the code was expanding to things which looked like #defines,
in which case it almost certainly didn't compile now.

So the further passes wouldn't *do* anything. The macro names
would no longer be macro names, because there'd be no macro definitions
to create macro names.

The proposal is actually completely harmless to just about any real
code -- except for possible issues with #line, I don't think it would
have ANY effect on real programs.

-s
 
A

Alan Curry

Not so!

The proposed action is re-running the preprocessor.

Since the first pass consumed all the #defines, there won't be any
more, unless the code was expanding to things which looked like #defines,
in which case it almost certainly didn't compile now.

In the spirit of creative preprocessor abuse... Below you will find a file
which, when passed through the preprocessor twice, changes the second time.
Your mission is to figure out how I did that before you get far enough to
read it.

There will be a few hints first.


Hint 1: There is no infinite recursion involved. Both invocations of the
preprocessor complete in finite time and generate finite output.


Hint 2: Line numbers aren't relevant. Each pass through the preprocessor
generates an actual substantive change.


Hint 3: No implementation-specific tricks are involved. I expect this would
work with any implementation which allows the preprocessor to be invoked
separately.


Hint 4: While the secret isn't anything deeply tricky, it's probably not
technically legal. gcc even warns about it without any -W options.

(warning: hint 5 will probably give it away. stop and think here!)

Hint 5: The second pass expands a macro which was already expanded once in
the first pass.

ANSWER:


#undef __STDC__
#define __STDC__ __STDC__
__STDC__
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top