#include __FILE__

F

Francois Grieu

Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__
#undef TABLE
};
int gNum[] = {
#define TABLE( str, num1, num2 ) (num1)*(num2),
#include __FILE__
#undef TABLE
};
#include <stdio.h>
int main( void )
{
int j;
for( j = 0; j < sizeof gStr / sizeof *gStr; ++j)
printf( "%s %d\n", gStr[j], gNum[j]);
return 0;
}
#else
TABLE( "the answer is", 6, 7 )
TABLE( "foo", 1, 1 )
TABLE( "bar", 2, 1 )
TABLE( "zoo", 3, 1 )
#endif
/* this is line 27, EOF on next line */


The technique works with at least 5 compilers that I use.
And I find the idiom somewhat useful, in particular
to transpose and rework a table at compile time, rather
than with an auxiliary program.

TIA,
Francois Grieu
 
T

Tim Rentsch

Francois Grieu said:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__
#undef TABLE
};
int gNum[] = {
#define TABLE( str, num1, num2 ) (num1)*(num2),
#include __FILE__
#undef TABLE
};
#include <stdio.h>
int main( void )
{
int j;
for( j = 0; j < sizeof gStr / sizeof *gStr; ++j)
printf( "%s %d\n", gStr[j], gNum[j]);
return 0;
}
#else
TABLE( "the answer is", 6, 7 )
TABLE( "foo", 1, 1 )
TABLE( "bar", 2, 1 )
TABLE( "zoo", 3, 1 )
#endif
/* this is line 27, EOF on next line */


The technique works with at least 5 compilers that I use.
And I find the idiom somewhat useful, in particular
to transpose and rework a table at compile time, rather
than with an auxiliary program.

I believe there's nothing wrong with it, providing
the file name is chosen appropriately (bad choice
of file name could cause the #include to fail on
some systems).
 
K

Keith Thompson

Eric Sosman said:
Francois said:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__

Sneaky, but I think there are at least two potential problems:

First, the mapping of __FILE__'s expansion to a header file name
is implementation-defined (6.10.2p4). So even if __FILE__ expands
to "foobar.h" it is not necessarily the case that #include __FILE__
and #include "foobar.h" work identically.

Second, the expansion of __FILE__ is only the "presumed" name of
the current source (6.10.8p1). A footnote suggests that "presumed"
is an allowance for #line directives, but there's also the possibility
that the source has no name, or no useful name. I recall a compiler
that could store headers in a "library file" containing individual
"members;" the library was a file and had a name, but the headers
themselves were not files and didn't have file names; __FILE__ in
such a header expanded to the concatenation of the library name and
the header name, like "HEADERS.TLB(FOOBAR)" for "foobar.h" found in
the HEADERS.TLB library.

So: Sneaky, cute, even ingenious, but ...

One of the winners of the 1988 IOCCC was the following entry by
Diomidis Spinellis:

#include "/dev/tty"

The point being that #include on the same name won't necessarily
give you the same content twice in a row.
 
T

Tim Rentsch

Eric Sosman said:
Francois said:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__

Sneaky, but I think there are at least two potential problems:

First, the mapping of __FILE__'s expansion to a header file name
is implementation-defined (6.10.2p4). So even if __FILE__ expands
to "foobar.h" it is not necessarily the case that #include __FILE__
and #include "foobar.h" work identically.

The provision in 6.10.2p4 doesn't apply. The __FILE__ macro
expands to a character string literal, not to a sequence of
preprocessing tokens with (") characters around it. Thus
it's already a single preprocessing-token, with no need to
have to combine anything to get a header name.

Second, the expansion of __FILE__ is only the "presumed" name of
the current source (6.10.8p1). A footnote suggests that "presumed"
is an allowance for #line directives, but there's also the possibility
that the source has no name, or no useful name. I recall a compiler
that could store headers in a "library file" containing individual
"members;" the library was a file and had a name, but the headers
themselves were not files and didn't have file names; __FILE__ in
such a header expanded to the concatenation of the library name and
the header name, like "HEADERS.TLB(FOOBAR)" for "foobar.h" found in
the HEADERS.TLB library.

Presumably this concern doesn't apply in this case, where the
source file is created by the programmer and not put into the
compiler's "library file". An implementation that expands a call
on __FILE__ into a name [*] that isn't a name that would work
with #include is arguably already non-conforming, but even if it
were allowed, such an implementation is brain-damaged and should
be avoided like the plague.

[*] assuming the name is "simple", eg, eight alphabetic
characters plus a single alphabetic character extension,
and the name hasn't been changed by a #line directive.

So: Sneaky, cute, even ingenious, but ...

.... portable only to that subset of C implementations that
are sane.
 
F

Francois Grieu

Eric Sosman a écrit :
Francois said:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__

Sneaky, but I think there are at least two potential problems:

First, the mapping of __FILE__'s expansion to a header file name
is implementation-defined (6.10.2p4). So even if __FILE__ expands
to "foobar.h" it is not necessarily the case that #include __FILE__
and #include "foobar.h" work identically.

Second, the expansion of __FILE__ is only the "presumed" name of
the current source (6.10.8p1). A footnote suggests that "presumed"
is an allowance for #line directives, but there's also the possibility
that the source has no name, or no useful name. I recall a compiler
that could store headers in a "library file" containing individual
"members;" the library was a file and had a name, but the headers
themselves were not files and didn't have file names; __FILE__ in
such a header expanded to the concatenation of the library name and
the header name, like "HEADERS.TLB(FOOBAR)" for "foobar.h" found in
the HEADERS.TLB library.

So: Sneaky, cute, even ingenious, but ...

OK, I see #include __FILE__ may not properly refer to the
current file; and that maybe there is no current file
(compiling from stdin..)
But, let use assume that I change that to #include "self.c"
and put my source in some file such that #include "self.c"
refers to that file (which is how I actually use this);
or equivalently that, on the system under consideration,
#include __FILE__ does refer to the current file.

Is there something wrong with the fact of including the
current file, and/or a file in the stack of currently
included files?

Francois Grieu
 
F

Francois Grieu

in said:
> In #include __FILE__ the stuff after #include is not a
> header-name preprocessing token, but an identifier (6.4.2),
> a macro name.
> Nor is its expansion a header-name, because __FILE__ expands
> to a string literal (6.10.8p1). A string literal is not a
> header-name (6.4p1, 6.4.5, 6.4.7), so it is necessary to apply
> some kind of transformation to the expansion of __FILE__ to
> make a header-name out of it. 6.10.2p4 says that the
> transformation is implementation-defined.

Which is very bad news for the construct in the subject.


And in this thread Eric Sosman also wrote :
Francois said:
[...]
But, let use assume that I change that to #include "self.c"
and put my source in some file such that #include "self.c"
refers to that file (which is how I actually use this);
or equivalently that, on the system under consideration,
#include __FILE__ does refer to the current file.

Is there something wrong with the fact of including the
current file, and/or a file in the stack of currently
included files?

Since the Standard doesn't forbid it, "recursive inclusion"
is permitted (subject to whatever nesting limits the
implementation might impose).

I was afraid it might not work in practice...
It's quite common to encounter such inclusions in
projects with a lot of interdependent headers [...]

But now I stand largely reassured, thanks.


Among the other semi-good reasons I use self-inclusion:

- I need to reformat or transpose a table (like in the
example I gave) that logically belongs to the
implementation of foo rather than to the interface of
foo, and would nicely fit a separate file that we could
#include multiple times, but some local make-like tool,
or coding rule, asks that foo.h contains the interface
to foo.c, and that foo.c include only standard libraries
and interface to C files designed according to that rule.

- I have foo.h that defines a struct, and want to alter it
so that the struct now has a filler to some fixed size at
the end, without hard-coding the size of the filler, nor
defining a macro expanding to the fields of the struct
(which could exceed the standard-mandated expanded-size
limit), nor duplicating the definition of the fields of
the struct, nor putting that struct in a union (because
I do not want to break existing code using foo.h that
refers to struct fields, and many C compiler do not
support anonymous members in unions).

#include __FILE__ would have been especially useful in the
later case, because I can't know it the guy using foo.h
will not put it in some folder and include it like
#include "folder/foo.h"

Francois Grieu
 
K

Keith Thompson

Eric Sosman said:
Tim said:
Eric Sosman said:
Francois Grieu wrote:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__
Sneaky, but I think there are at least two potential problems:

First, the mapping of __FILE__'s expansion to a header file name
is implementation-defined (6.10.2p4). So even if __FILE__ expands
to "foobar.h" it is not necessarily the case that #include __FILE__
and #include "foobar.h" work identically.

The provision in 6.10.2p4 doesn't apply. The __FILE__ macro
expands to a character string literal, not to a sequence of
preprocessing tokens with (") characters around it. Thus
it's already a single preprocessing-token, with no need to
have to combine anything to get a header name.

In #include "foobar.h" the stuff after #include is a header-name
preprocessing token, something that is recognized only in #include
directives (6.4.7p3).

In #include __FILE__ the stuff after #include is not a header-
name preprocessing token, but an identifier (6.4.2), a macro name.
Nor is its expansion a header-name, because __FILE__ expands to a
string literal (6.10.8p1). A string literal is not a header-name
(6.4p1, 6.4.5, 6.4.7), so it is necessary to apply some kind of
transformation to the expansion of __FILE__ to make a header-name
out of it.

Right so far.
6.10.2p4 says that the transformation is implementation-
defined.

Actually, 6.10.2p4 says:

The method by which a sequence of preprocessing tokens between a <
and a > preprocessing token pair or a pair of " characters is
combined into a single header name preprocessing token is
implementation-defined.

Since __FILE__ expands to a string literal, we don't have 'a sequence
of preprocessing tokens between ... a pair of " characters'.

It's obviously the intent that a macro expanding to a string literal
is permitted; the footnote:

Note that adjacent string literals are not concatenated into a
single string literal (see the translation phases in 5.1.1.2);
thus, an expansion that results in two string literals is an
invalid directive.

is, in the correct sense of the phrase, "the exception that proves the
rule" (i.e., the explicit statement of the exception implies that
there is a rule to which it is an exception).

C90's rules are the same. K&R1 refers to

#include "filename"

without saying that "filename" is a string literal. (It also doesn't
appear to any form other than #include "filename" or #include
Besides, if 6.10.2p4 did not apply, #include __FILE__ would be
an error right from the start. Delete 6.10.2p4 from the Standard,
and you're left with #include <foo.h> and #include "bar.h" as the
only two valid forms. #include __FILE__ matches neither.

Right.

My guess is that, when the C90 committee decided that "filename"
after #include couldn't be a string literal (allowing, for example,
"a\b.h" to refer to a file without a backspace in its name), but
instead is a double quote followed by a q-char-sequence followed by
another double quote, they didn't quite tidy up the wording 100%
correctly. There may have been a lingering assumption that the
output of the preprocessor is a sequence of characters rather than
of preprocessing tokens. In fact, translation phase 3 produces
a sequence of preprocessing tokens and whitespace characters;
#include directives are processed in phase 4.

I think there just needs to be an additional statement that there's an
implementation-defined mapping of a string literal to header name
preprocessing token. I would hope that this mapping would be required
to be the same as the mapping for an explicit #include "filename"
directive, so that this:

#include "filename"

and this:

#define HEADER "filename"
#include HEADER

are required to be equivalent.
 
R

Richard Tobin

Francois Grieu said:
#include __FILE__

This will not always work in practice. For example, with gcc on a
unix system, if the file is referred to on the command line as
"subdir/file.c", then in the #include statement that name will be
interpreted relative to subdir (i.e. as subdir/subdir/file.c),
resulting in the error

subdir/file.c:5:18: error: subdir/file.c: No such file or directory

If you have enough control over the compilation environment, this
may not be important.

-- Richard
 
P

Peter Nilsson

Francois Grieu said:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__
#undef TABLE};

int gNum[] = {
#define TABLE( str, num1, num2 ) (num1)*(num2),
#include __FILE__
#undef TABLE};

#include <stdio.h>
int main( void )
     {
     int j;
     for( j = 0; j < sizeof gStr / sizeof *gStr; ++j)
         printf( "%s %d\n", gStr[j], gNum[j]);
     return 0;
     }
#else
TABLE( "the answer is", 6, 7 )
TABLE( "foo", 1, 1 )
TABLE( "bar", 2, 1 )
TABLE( "zoo", 3, 1 )
#endif
/* this is line 27, EOF on next line */

The technique works with at least 5 compilers that I use.
And I find the idiom somewhat useful, in particular to
transpose and rework a table at compile time, rather than
with an auxiliary program.

Here's something that achieves the same basic result, but in
a (marginally) more maintainable way...

<http://groups.google.com/group/comp.lang.c/msg/780934c019352a78>

For a slightly more elaborate example...

<http://groups.google.com/group/comp.lang.c/msg/c4d3c508ca365fa8>
 
F

Francois Grieu

Peter said:
Here's something that achieves the same basic result, but in
a (marginally) more maintainable way... [snip]
Paraphrasing:

#define TABLE(macro) \
macro( "the answer is", 6, 7 )\
macro( "foo", 1, 1 )\
macro( "bar", 2, 1 )\
macro( "zoo", 3, 1 )\
#define TABLEstr( str, num1, num2 ) str,
char *gStr[] = {TABLE(TABLEstr)};
#define TABLEnum( str, num1, num2 ) (num1*num2),
int gNum[] = {TABLE(TABLEnum)};
#include <stdio.h>
int main( void )
{
int j;
for( j = 0; j < sizeof gStr / sizeof *gStr; ++j)
printf( "%s %d\n", gStr[j], gNum[j]);
return 0;
}


Trouble is, there can be some low implementation-defined limit to
the size of an expanded macro (although I admit that nowadays,
all compilers that I use have it so high that I do not hit that
wall). Self-inclusion has the bonus that it does not make a long
macro when the table grows.

Also, when applied to computing the size of a struct to define
the size of a final field bringing the struct to some fixed size,
self-inclusion can look sufficiently similar to something familiar
that both an external programmer and a development environment
like Visual Studio will recognize the bulk of the struct, and be
able to pinpoint where each fields is declared. I can't see how
to achieve this with the "macro" technique.

Francois Grieu
 
T

Tim Rentsch

Eric Sosman said:
Tim said:
Eric Sosman said:
Francois Grieu wrote:
Is the following program correct?

/* SOF on this line 1 */
#ifndef TABLE
char *gStr[] = {
#define TABLE( str, num1, num2 ) str,
#include __FILE__
Sneaky, but I think there are at least two potential problems:

First, the mapping of __FILE__'s expansion to a header file name
is implementation-defined (6.10.2p4). So even if __FILE__ expands
to "foobar.h" it is not necessarily the case that #include __FILE__
and #include "foobar.h" work identically.

The provision in 6.10.2p4 doesn't apply. The __FILE__ macro
expands to a character string literal, not to a sequence of
preprocessing tokens with (") characters around it. Thus
it's already a single preprocessing-token, with no need to
have to combine anything to get a header name.

In #include "foobar.h" the stuff after #include is a header-name
preprocessing token, something that is recognized only in #include
directives (6.4.7p3).

Also in #pragma directives in some cases, but close enough.

In #include __FILE__ the stuff after #include is not a header-
name preprocessing token, but an identifier (6.4.2), a macro name.
Nor is its expansion a header-name, because __FILE__ expands to a
string literal (6.10.8p1). A string literal is not a header-name
(6.4p1, 6.4.5, 6.4.7), so it is necessary to apply some kind of
transformation to the expansion of __FILE__ to make a header-name
out of it. 6.10.2p4 says that the transformation is implementation-
defined.

First, what Keith Thompson said -- 6.10.2p4 is not talking about
the case of string literals, because a string literal is a single
preprocessing token, not a sequence of preprocessing tokens between
a pair of " characters.

Second, I think you may be hallucinating. The syntax for #include
doesn't mention header-name anywhere. It just happens that a
header-name is a preprocessing token that happens to have the
right form. But a string literal preprocessing token also has the
right form (as long as it doesn't have a " in it). Hence, after
macro expansion, the directive matches one of the two previous
forms (specifically, the <<# include "q-char-sequence" new-line>>
form). So what happens with a single string literal after
macro expansion is well-defined.

Besides, if 6.10.2p4 did not apply, #include __FILE__ would be
an error right from the start. Delete 6.10.2p4 from the Standard,
and you're left with #include <foo.h> and #include "bar.h" as the
only two valid forms. #include __FILE__ matches neither.

When I said "The provision in 6.10.2p4 doesn't apply", the
provision I was talking about is the implementation-defined
mapping mentioned in the last sentence. Of course the previous
sentences apply.
 
T

Tim Rentsch

Keith Thompson said:
[ considering cases, eg, #define X "x.h" / #include X ]
I think there just needs to be an additional statement that there's an
implementation-defined mapping of a string literal to header name
preprocessing token. I would hope that this mapping would be required
to be the same as the mapping for an explicit #include "filename"
directive, so that this:

#include "filename"

and this:

#define HEADER "filename"
#include HEADER

are required to be equivalent.

As I explained in my last response, the Standard doesn't require a
header-name preprocessing token in a #include directive. A string
literal (that doesn't have a " in it) preprocessing token matches
the form described in 6.10.2p3, and no additional language is
needed to define what happens in such cases. Arguably the existing
text should be clarified, but at worst it's just unclear, not
incomplete.
 
T

Tim Rentsch

Francois Grieu said:
Which is very bad news for the construct in the subject.

This analysis is flawed; explanation given in my last
response and last last response in this thread. There
may be problems with finding the right file using
a #include __FILE__, but the point up to where the
search is started is well-defined, not implementation-defined.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
[ considering cases, eg, #define X "x.h" / #include X ]
I think there just needs to be an additional statement that there's an
implementation-defined mapping of a string literal to header name
preprocessing token. I would hope that this mapping would be required
to be the same as the mapping for an explicit #include "filename"
directive, so that this:

#include "filename"

and this:

#define HEADER "filename"
#include HEADER

are required to be equivalent.

As I explained in my last response, the Standard doesn't require a
header-name preprocessing token in a #include directive. A string
literal (that doesn't have a " in it) preprocessing token matches
the form described in 6.10.2p3, and no additional language is
needed to define what happens in such cases. Arguably the existing
text should be clarified, but at worst it's just unclear, not
incomplete.

Ok, but I think the existing text makes some implicit assumptions.
Let's see what happens in the course of the translation phases for the
following translation unit:

#define HEADER "foo.h"
#include HEADER

What happens in phases 1 and 2 isn't relevant to the current
discussion.

Phase 3 decomposes the translation unit into preprocessing tokens
and whitespace. The resulting preprocessing tokens are:

#
define
HEADER
"foo.h"
#
include
HEADER

where HEADER is an identifier and "foo.h" is a string literal. The
new-line after "foo.h" is retained.

In phase 4, preprocessing directives are executed. The execution of
the #define directive causes the macro HEADER to be defined. The #include
directive is processed in accordance with C99 6.10.2p4:

A preprocessing directive of the form
# include pp-tokens new-line
(that does not match one of the two previous forms) is
permitted. The preprocessing tokens after include in the
directive are processed just as in normal text. (Each identifier
currently defined as a macro name is replaced by its replacement
list of preprocessing tokens.) The directive resulting after
all replacements shall match one of the two previous forms.148)
The method by which a sequence of preprocessing tokens between
a < and a > preprocessing token pair or a pair of " characters
is combined into a single header name preprocessing token is
implementation-defined.

Footnote 148 (numbering is from N1256):

Note that adjacent string literals are not concatenated into a
single string literal (see the translation phases in 5.1.1.2);
thus, an expansion that results in two string literals is an
invalid directive.

HEADER is expanded to a single pp-token, the string literal "foo.h",
so the directive matches the specified form. But for this to be valid,
and equivalent to
#include "foo.h"
the single pp-token "foo.h" (a string literal) must "match"
"q-char-sequence"

It does "match" it in the sense that it's composed of the same
sequence of characters. I just find it slightly odd that, one
phase after the sequence of 7 characters "foo.h" has been converted
to a single pp-token, it apparently has to be converted *back* to
a sequence of 7 characters so it can be matched (or not) against
"q-char-sequence". And of course some string literals don't match
"q-char-sequence" (such as "foo\"bar"), and others that do match
might not or might not have the same meaning (such as "dir\foo.h").

Yes, this is nitpicking, and the intent (at least in most cases)
is crystal clear: the string literal that results from the macro
expansion is reinterpreted as "q-char-sequence". It's just that
the extra step of going back from a string literal to a sequence
of characters is implicitly assumed rather than stated.
 
P

Peter Nilsson

Francois Grieu said:
Peter said:
Here's something that achieves the same basic result, but
in a (marginally) more maintainable way... [snip]

Paraphrasing:

#define TABLE(macro) \
macro( "the answer is", 6, 7 )\
macro( "foo", 1, 1 )\
macro( "bar", 2, 1 )\
macro( "zoo", 3, 1 )\
#define TABLEstr( str, num1, num2 ) str,

I pass the delimiter as a second parameter. In C89, the
grammar does not cater for the last enumerator having a
comma. [C99 fixed this.]
...
Trouble is, there can be some low implementation-defined
limit to the size of an expanded macro (although I admit
that nowadays, all compilers that I use have it so high
that I do not hit that wall).

Indeed. Although I recall crashing gcc and lcc-win with
some simple (not entirely contrived) recursive macros.
Self-inclusion has the
bonus that it does not make a long macro when the table
grows.

But why does it have to be _self_ inclusion?

% type table.inc
TABLE_MACRO( "the answer is", 6, 7 )
TABLE_MACRO( "foo", 1, 1 )
TABLE_MACRO( "bar", 2, 1 )
TABLE_MACRO( "zoo", 3, 1 )

% type table.c
char *gStr[] =
{
#define TABLE_MACRO( str, num1, num2 ) str,
#include "table.inc"
#undef TABLE_MACRO
};

int gNum[] =
{
#define TABLE_MACRO( str, num1, num2 ) (num1*num2),
#include "table.inc"
#undef TABLE_MACRO
};

#include <stdio.h>

int main( void )
{
size_t j;
for (j = 0; j < sizeof gStr / sizeof *gStr; ++j)
printf( "%s %d\n", gStr[j], gNum[j]);

return 0;
}

% acc table.c -o table.exe

% table.exe
the answer is 42
foo 1
bar 2
zoo 3

%
Also, when applied to computing the size of a struct to
define the size of a final field bringing the struct to
some fixed size, self-inclusion can look sufficiently
similar to something familiar that both an external
programmer and a development environment like Visual
Studio will recognize the bulk of the struct, and be
able to pinpoint where each fields is declared. I can't
see how to achieve this with the "macro" technique.

I don't really understand the example you're trying to give.
Manually padding structs is difficult with or without macros.
The simple option is to use a union...

union x
{
struct x x;
char block_[2048];
};

But you can do things like...

#include <stdio.h>

/* your struct abc members */
#define pp_struct_abc(M, _) \
M( int, a, ) _ \
M( long double, b, ) _ \
M( int, c, )

#define pp_struct_abc_pad(M, _, N) \
pp_struct_abc(M, _) _ \
M( char, pad_, [N])

/* some utilities */
#define pp_as_struct(type_pp, name_pp, array_pp) \
type_pp name_pp array_pp

struct abc
{
pp_struct_abc(pp_as_struct, ;);
};

struct abc_pad
{
pp_struct_abc_pad(pp_as_struct, ;, 128 - sizeof(struct abc));
};

#define dump(x) \
printf("%s: %u\n", #x, (unsigned) (x))

int main(void)
{
dump(sizeof(struct abc));
dump(sizeof(struct abc_pad));
return 0;
}
 
F

Francois Grieu

Peter Nilsson wrote :
>>> Here's something that achieves the same basic result, but
>>> in a (marginally) more maintainable way... [snip]
>> Paraphrasing:
>>
>> #define TABLE(macro) \
>> macro( "the answer is", 6, 7 )\
>> macro( "foo", 1, 1 )\
>> macro( "bar", 2, 1 )\
>> macro( "zoo", 3, 1 )\
>> #define TABLEstr( str, num1, num2 ) str,
>
> I pass the delimiter as a second parameter. In C89, the
> grammar does not cater for the last enumerator having a
> comma. [C99 fixed this.]

All C compilers (including for embedded CPUs ) that I use
allow the final comma in constant declarations, even though
they claim only C89/C90 compatibility. And checking that
grammar, I read

3.5.7 Initialization

Syntax

initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }

initializer-list:
initializer
initializer-list , initializer


Further, all but one C compiler that I use also allow the final
comma in an enum (which indeed is not in C89/C90), and the vendor
for said compiler has promised to improve that real soon now.

> why does it have to be _self_ inclusion?

Of course C does not require it, and most of the time
using a separate file is just fine. But there might be a
rule that the interface and implementation of a compilation
unit is split in exactly two files named like "foo.h"
and "foo.c". And the convention that the interface for a
compilation unit is exactly one file named like "foo.h"
is very common.
>
> I don't really understand the example you're trying to give.
> Manually padding structs is difficult with or without macros.
> The simple option is to use a union...

The same message points that with union, either you need
anonymous union, or break compatibility with former code.
> [snip example of structure padding with macro]

One advantage of doing basically that with self-inclusion
rather than macro is that the location with struct declaration
and list of fields can be identified as such by a wider range
of programmers, and by development environments like Visual
Studio.

Also, I think that your padding size computation
> [...] 128 - sizeof(struct abc) [...]
is not robust enough. In fact I can't find a single way to
do it in a fully conformant way (and won't post my best
approximation without prior deep thinking about it).


Francois Grieu
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
[ considering cases, eg, #define X "x.h" / #include X ]
I think there just needs to be an additional statement that there's an
implementation-defined mapping of a string literal to header name
preprocessing token. I would hope that this mapping would be required
to be the same as the mapping for an explicit #include "filename"
directive, so that this:

#include "filename"

and this:

#define HEADER "filename"
#include HEADER

are required to be equivalent.

As I explained in my last response, the Standard doesn't require a
header-name preprocessing token in a #include directive. A string
literal (that doesn't have a " in it) preprocessing token matches
the form described in 6.10.2p3, and no additional language is
needed to define what happens in such cases. Arguably the existing
text should be clarified, but at worst it's just unclear, not
incomplete.

Ok, but I think the existing text makes some implicit assumptions.

I would say this differently, which is it doesn't express itself
as clearly as it could (and arguably should). But let's read on.
Let's see what happens in the course of the translation phases for the
following translation unit:

#define HEADER "foo.h"
#include HEADER

What happens in phases 1 and 2 isn't relevant to the current
discussion.

Phase 3 decomposes the translation unit into preprocessing tokens
and whitespace. The resulting preprocessing tokens are:

#
define
HEADER
"foo.h"
#
include
HEADER

where HEADER is an identifier and "foo.h" is a string literal. The
new-line after "foo.h" is retained.

You forgot to say 'define' and 'include' are identifiers. They
are not preprocessing keywords (as there are no such things).
In phase 4, preprocessing directives are executed. The execution of
the #define directive causes the macro HEADER to be defined. The #include
directive is processed in accordance with C99 6.10.2p4:

A preprocessing directive of the form
# include pp-tokens new-line
(that does not match one of the two previous forms) is
permitted. The preprocessing tokens after include in the
directive are processed just as in normal text. (Each identifier
currently defined as a macro name is replaced by its replacement
list of preprocessing tokens.) The directive resulting after
all replacements shall match one of the two previous forms.148)
The method by which a sequence of preprocessing tokens between
a < and a > preprocessing token pair or a pair of " characters
is combined into a single header name preprocessing token is
implementation-defined.

Footnote 148 (numbering is from N1256):

Note that adjacent string literals are not concatenated into a
single string literal (see the translation phases in 5.1.1.2);
thus, an expansion that results in two string literals is an
invalid directive.

HEADER is expanded to a single pp-token, the string literal "foo.h",
so the directive matches the specified form. But for this to be valid,
and equivalent to
#include "foo.h"
the single pp-token "foo.h" (a string literal) must "match"
"q-char-sequence"

It does "match" it in the sense that it's composed of the same
sequence of characters. I just find it slightly odd that, one
phase after the sequence of 7 characters "foo.h" has been converted
to a single pp-token, it apparently has to be converted *back* to
a sequence of 7 characters so it can be matched (or not) against
"q-char-sequence". And of course some string literals don't match
"q-char-sequence" (such as "foo\"bar"), and others that do match
might not or might not have the same meaning (such as "dir\foo.h").

Exactly the same kind of argument could be made about 'include',
since it's an identifier (or even just a preprocessing-token). I
think the problem with this argument is that it makes presumptions
that aren't consistent with how the Standard explains what goes
on during preprocessing. The discussion of what happens in the
preprocessing phase generally is much less particular about
specific syntactic categories. In most cases (there are a few
exceptions, but only a few), any syntactic category more specific
than preprocessing-token is never identified. So, when I see text
like

A preprocessing directive of the form
# include "q-char-sequence" new-line

I take this to mean: three preprocessing-tokens, followed by
new-line; the first preprocessing-token (of whatever category)
must be the character '#'; the second preprocessing-token (of
whatever category) must be the string 'include'; the third
preprocessing-token (of whatever category) must match the lexical
form '"q-char-sequence"'. Now it happens that a punctuator is
the only form of preprocessing-token that matches the first
string, and an identifier is the only form of preprocessing-token
that matches the second string, but the Standard never actually
says that these categories are the only acceptable ones. The
syntax given for #include (under control-line:) is

# include pp-tokens new-line

despite 'include' not being identified as some sort of keyword or
syntactic category. We understand what that means by analogy with
keywords in later processing stages, but the Standard never says
(as least not as far as I know) in just what category this
preprocessing-token must be (nor does it in most other cases, as I
mentioned above). This non-specificity explains why the text in
6.10.2p2 and 6.10.2p3 may be written the way it is -- these
paragraphs are not expressing syntax, but rather are expressing
conditions for matching whatever preprocessing tokens are there in
the respective cases.

Yes, this is nitpicking, and the intent (at least in most cases)
is crystal clear: the string literal that results from the macro
expansion is reinterpreted as "q-char-sequence". It's just that
the extra step of going back from a string literal to a sequence
of characters is implicitly assumed rather than stated.

I don't think it has to be 'reinterpreted', to use your word,
because the given form is not a syntax rule. Rather the
'"q-char-sequence"' item is expressing a _condition_ that
characters in the preprocessing-token (whatever category it might
be) must satisfy -- just the same as using 'include' to give a
condition that characters in the second preprocessing-token must
satisfy.
 

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

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,828
Latest member
LauraCastr

Latest Threads

Top