Topic: A preprocessor question


Author: Mark Williams <markw65@my-deja.com>
Date: Wed, 3 Jan 2001 17:39:09 GMT
Raw View
In article <vtq15tkj0qk5a823qh2hq5ggto918vu69a@4ax.com>,
  stephen.clamage@sun.com wrote:
> On Sun, 31 Dec 2000 02:23:35 GMT, Carlo Wood <carlo@alinoe.com> wrote:
>
> >... This clearly indicates that white-space can NOT be part
> >of a replacement-list.  Nevertheless, for C++ syntax to be
> >preserved, preprocessing-tokens need to stay seperated.
> >
> >Now consider the following program:
> >
> >#include <iostream>
> >
> >#define SPACES X /* more than one space here: */   X
> >#define _STR(x) #x
> >#define STR(x) _STR(x)
> >
> >int main(void)
> >{
> >  cout << STR(SPACES) << endl;
> >  return 0;
> >}
> >
> >
> >This program will print on most(?) compilers:
> >X X
> >
> >with just one space between the two Xs.
> >
> >My question is: is it garanteed that exactly one
> >space will be printed?  Or is a compiler allowed
> >to produce any arbitrary white-space characters
> >inbetween the two Xs?
>
> Neither the C nor the C++ standards address preprocessing as a
> stand-alone operation. No conforming implementation is required to
> produce as an output the result of preprocessing the source code. A
> conforming implementation can produce any output, even output that
> cannot be compiled, assuming it provides the option at all.

He didnt ask what the pre-processing output would look like. He asked
what the output of his program would be.

-------------
Mark Williams


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: Wed, 3 Jan 2001 19:15:33 GMT
Raw View
In article <92sa8a$85e6m$1@ID-62495.news.dfncis.de>,
  "Andrei Iltchenko" <Andrei.Iltchenko@openmarket.com> wrote:
> > #include <iostream>
> >
> > #define SPACES X /* more than one space here: */   X
> > #define _STR(x) #x
> > #define STR(x) _STR(x)
> >
> > int main(void)
> > {
> >   cout << STR(SPACES) << endl;
> >   return 0;
> > }
> >
> >
> > This program will print on most(?) compilers:
> > X X
> >
> > with just one space between the two Xs.
> >
> > My question is: is it garanteed that exactly one
> > space will be printed?
No.

> > Or is a compiler allowed
> > to produce any arbitrary white-space characters
> > inbetween the two Xs?
No again :-) The number of white spaces is implementation-defined, but
it must be either one or the original number of spaces (see discussion
below for details).

> Because of you having used the # preprocessing operator
> to make a string literal out of the preprocessing token sequence
> `X /* more than one space here: */   X`, the Standard does
> guarantee that the resultant string literal "X X" will have just one
> space character in between the two Xs.
No, it doesn't.

> Chapter 16.3.2 paragraph 2 of the Standard explicitly says
> that if a parameter of a function-like macro is preceeded by
> the # preprocessing operator, then every occurance of white
> space between the corresponding argument's preprocessing
> tokens is replaced by a single space character in the resultant
> string literal.
This paragraph is relevant, but does not convey the whole story. To
complete the story, you need the phases of translation (2.1).

Phases of translation (as applicable to this discussion) are, in this
order:
- Each comment is replaced by a single space character
- "Whether each nonempty sequence of white   space characters other
  than new   line is retained or replaced by one space character is
  implementation   defined." (2.1 para 3)
- macros are expanded

So the line
#define SPACES X /* more than one space here: */   X

becomes either
#define SPACES X     X

or
#define SPACES X X

depending on the implementation, and *then* the macros are evaluated.
Since the standard says this is implementation-defined, your compiler
documentation should specify which behaviour it has adopted.

--
Jim
To suppress Deja's product links, add this header:
x-noproductlinks: yes


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: wmm@fastdial.net
Date: Wed, 3 Jan 2001 20:20:49 GMT
Raw View
In article <20001231031127.A12265@a2000.nl>,
  Carlo Wood <carlo@alinoe.com> wrote:
> Hi, I am writing a C++ source code analyzer (a C++ compiler
> front-end), hence the following question:
>
> In the C++ standard, Annex A, the grammar rules for a
> 'define' control-line are defined as:
>
> # define identifier replacement-list new-line
>
> where the replacement-list is defined as:
>
> pp-tokens-opt
>
> which is defined as
>
> preprocessing-token
> or
> pp-tokens preprocessing-token
>
> and finally a preprocessing-token is defined as one of:
>
> header-name
> identifier
> pp-number
> character-literal
> string-literal
> preprocessing-op-or-punc
> each non-white-space character that cannot be one of the above
>
> This clearly indicates that white-space can NOT be part
> of a replacement-list.  Nevertheless, for C++ syntax to be
> preserved, preprocessing-tokens need to stay seperated.
>
> Now consider the following program:
>
> #include <iostream>
>
> #define SPACES X /* more than one space here: */   X
> #define _STR(x) #x
> #define STR(x) _STR(x)
>
> int main(void)
> {
>   cout << STR(SPACES) << endl;
>   return 0;
> }
>
> This program will print on most(?) compilers:
> X X
>
> with just one space between the two Xs.
>
> My question is: is it garanteed that exactly one
> space will be printed?  Or is a compiler allowed
> to produce any arbitrary white-space characters
> inbetween the two Xs?

It's implementation-defined whether multiple spaces between
preprocessing tokes are collapsed in translation phase 3
into a single space character (2.1p1).

However, a conforming implementation will output exactly one
space between the Xs.  See 16.3.2p2:

    If, in the replacement list, a parameter is immediately
    preceded by a # preprocessing token, both are replaced
    by a single character string literal preprocessing token
    that contains the spelling of the preprocessing token
    sequence for the corresponding argument. Each occurrence
    of white space between the argument   s preprocessing
    tokens becomes a single space character in the character
    string literal.

--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Andrei Iltchenko" <Andrei.Iltchenko@openmarket.com>
Date: Thu, 4 Jan 2001 18:42:33 GMT
Raw View
> > Because of you having used the # preprocessing operator
> > to make a string literal out of the preprocessing token sequence
> > `X /* more than one space here: */   X`, the Standard does
> > guarantee that the resultant string literal "X X" will have just one
> > space character in between the two Xs.
>
> > Chapter 16.3.2 paragraph 2 of the Standard explicitly says
> > that if a parameter of a function-like macro is preceeded by
> > the # preprocessing operator, then every occurance of white
> > space between the corresponding argument's preprocessing
> > tokens is replaced by a single space character in the resultant
> > string literal.
> This paragraph is relevant, but does not convey the whole story. To
> complete the story, you need the phases of translation (2.1).

The paragraph above concludes the story, as the expansion of macro
invocations happens after what you called:
 > "Whether each nonempty sequence of white   space characters other
 >   than new   line is retained or replaced by one space character is
 >   implementation   defined." (2.1 para 3)
and hence what you explained below bears little relation to the work
of the preprocessing operator #.

>
> Phases of translation (as applicable to this discussion) are, in this
> order:
> - Each comment is replaced by a single space character
> - "Whether each nonempty sequence of white   space characters other
>   than new   line is retained or replaced by one space character is
>   implementation   defined." (2.1 para 3)
> - macros are expanded
>
> So the line
> #define SPACES X /* more than one space here: */   X
>
> becomes either
> #define SPACES X     X
>
> or
> #define SPACES X X
>
> depending on the implementation, and *then* the macros are evaluated.
> Since the standard says this is implementation-defined, your compiler
> documentation should specify which behaviour it has adopted.
>

Once again, the question was not about the result of expanding the
object-like
macro SPACES, it was about the string literal that gets generated by the use
of the function-like macro STR with the only argument which is the call to
the
SPACES macro.

And I explained that the string literal "X X" generated with the call to the
STR macro will have exactly one space character in between the two Xs,
since that is how the Standard defines the functionality of the # operator,
which the function-like macro _STR makes use of.

Regards,

Andrei Iltchenko
Brainbench MVP for C++
http://www.brainbench.com



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: Fri, 5 Jan 2001 00:51:08 GMT
Raw View
In article <92thec$jqc$1@nnrp1.deja.com>,
  wmm@fastdial.net wrote:
> In article <20001231031127.A12265@a2000.nl>,
>   Carlo Wood <carlo@alinoe.com> wrote:
> > Hi, I am writing a C++ source code analyzer (a C++ compiler
> > front-end), hence the following question:
> >
> > In the C++ standard, Annex A, the grammar rules for a
> > 'define' control-line are defined as:
> >
> > # define identifier replacement-list new-line
> >
> > where the replacement-list is defined as:
> >
> > pp-tokens-opt
> >
> > which is defined as
> >
> > preprocessing-token
> > or
> > pp-tokens preprocessing-token
> >
> > and finally a preprocessing-token is defined as one of:
> >
> > header-name
> > identifier
> > pp-number
> > character-literal
> > string-literal
> > preprocessing-op-or-punc
> > each non-white-space character that cannot be one of the above
> >
> > This clearly indicates that white-space can NOT be part
> > of a replacement-list.  Nevertheless, for C++ syntax to be
> > preserved, preprocessing-tokens need to stay seperated.
> >
> > Now consider the following program:
> >
> > #include <iostream>
> >
> > #define SPACES X /* more than one space here: */   X
> > #define _STR(x) #x
> > #define STR(x) _STR(x)
> >
> > int main(void)
> > {
> >   cout << STR(SPACES) << endl;
> >   return 0;
> > }
> >
> > This program will print on most(?) compilers:
> > X X
> >
> > with just one space between the two Xs.
> >
> > My question is: is it garanteed that exactly one
> > space will be printed?  Or is a compiler allowed
> > to produce any arbitrary white-space characters
> > inbetween the two Xs?
>
> It's implementation-defined whether multiple spaces between
> preprocessing tokes are collapsed in translation phase 3
> into a single space character (2.1p1).
>
> However, a conforming implementation will output exactly one
> space between the Xs.  See 16.3.2p2:
>
>     If, in the replacement list, a parameter is immediately
>     preceded by a # preprocessing token, both are replaced
>     by a single character string literal preprocessing token
>     that contains the spelling of the preprocessing token
>     sequence for the corresponding argument. Each occurrence
>     of white space between the argument   s preprocessing
>     tokens becomes a single space character in the character
>     string literal.
OK, I think we have an ambiguity in the standard. I have interpreted
"Each occurrence of white space" to mean "Each white space character",
but you (and others) seem to have interpreted it to mean "Each
non-empty sequence of whitespace characters" (the phrase used in 2.1).
The Core Issues list does not have an entry in this section, so I'm
going to submit a DR.

--
Jim
To suppress Deja's product links, add this header:
x-noproductlinks: yes


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: Thu, 4 Jan 2001 19:04:16 CST
Raw View
In article <9328dn$8p1lv$1@ID-62495.news.dfncis.de>,
  "Andrei Iltchenko" <Andrei.Iltchenko@openmarket.com> wrote:
[snip]
> And I explained that the string literal "X X" generated with the call
> to the
> STR macro will have exactly one space character in between the two Xs,
> since that is how the Standard defines the functionality of the #
> operator,
> which the function-like macro _STR makes use of.
That depends on how you interpret the phrase "Each occurrence of white
space." :-)

I was interpreting it to mean "each whitespace character", and you were
interpreting it to mean "each sequence of whitespace characters."

On reflection, I am leaning towards your interpretation as the intended
one, but I think I prefer my interpretation, otherwise the stringize
operation is not as useful as it could be.

I have submitted (or tried to submit, at any rate) a defect report
pointing out the ambiguity and asking for a clarification.

--
Jim
To suppress Deja's product links, add this header:
x-noproductlinks: yes


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Carlo Wood <carlo@alinoe.com>
Date: Sun, 31 Dec 2000 02:23:35 GMT
Raw View
Hi, I am writing a C++ source code analyzer (a C++ compiler
front-end), hence the following question:

In the C++ standard, Annex A, the grammar rules for a
'define' control-line are defined as:

# define identifier replacement-list new-line

where the replacement-list is defined as:

pp-tokens-opt

which is defined as

preprocessing-token
or
pp-tokens preprocessing-token

and finally a preprocessing-token is defined as one of:

header-name
identifier
pp-number
character-literal
string-literal
preprocessing-op-or-punc
each non-white-space character that cannot be one of the above

This clearly indicates that white-space can NOT be part
of a replacement-list.  Nevertheless, for C++ syntax to be
preserved, preprocessing-tokens need to stay seperated.

Now consider the following program:

#include <iostream>

#define SPACES X /* more than one space here: */   X
#define _STR(x) #x
#define STR(x) _STR(x)

int main(void)
{
  cout << STR(SPACES) << endl;
  return 0;
}


This program will print on most(?) compilers:
X X

with just one space between the two Xs.

My question is: is it garanteed that exactly one
space will be printed?  Or is a compiler allowed
to produce any arbitrary white-space characters
inbetween the two Xs?

--
Carlo Wood <usenet@nospam.alinoe.com>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Andrei Iltchenko" <Andrei.Iltchenko@openmarket.com>
Date: Tue, 2 Jan 2001 20:52:10 GMT
Raw View
> #include <iostream>
>
> #define SPACES X /* more than one space here: */   X
> #define _STR(x) #x
> #define STR(x) _STR(x)
>
> int main(void)
> {
>   cout << STR(SPACES) << endl;
>   return 0;
> }
>
>
> This program will print on most(?) compilers:
> X X
>
> with just one space between the two Xs.
>
> My question is: is it garanteed that exactly one
> space will be printed?  Or is a compiler allowed
> to produce any arbitrary white-space characters
> inbetween the two Xs?

Because of you having used the # preprocessing operator
to make a string literal out of the preprocessing token sequence
`X /* more than one space here: */   X`, the Standard does
guarantee that the resultant string literal "X X" will have just one
space character in between the two Xs.

Chapter 16.3.2 paragraph 2 of the Standard explicitly says
that if a parameter of a function-like macro is preceeded by
the # preprocessing operator, then every occurance of white
space between the corresponding argument's preprocessing
tokens is replaced by a single space character in the resultant
string literal.

Andrei Iltchenko
Brainbench MVP for C++
http://www.brainbench.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Stephen Clamage <stephen.clamage@sun.com>
Date: Tue, 2 Jan 2001 20:57:49 GMT
Raw View
On Sun, 31 Dec 2000 02:23:35 GMT, Carlo Wood <carlo@alinoe.com> wrote:

>... This clearly indicates that white-space can NOT be part
>of a replacement-list.  Nevertheless, for C++ syntax to be
>preserved, preprocessing-tokens need to stay seperated.
>
>Now consider the following program:
>
>#include <iostream>
>
>#define SPACES X /* more than one space here: */   X
>#define _STR(x) #x
>#define STR(x) _STR(x)
>
>int main(void)
>{
>  cout << STR(SPACES) << endl;
>  return 0;
>}
>
>
>This program will print on most(?) compilers:
>X X
>
>with just one space between the two Xs.
>
>My question is: is it garanteed that exactly one
>space will be printed?  Or is a compiler allowed
>to produce any arbitrary white-space characters
>inbetween the two Xs?

Neither the C nor the C++ standards address preprocessing as a
stand-alone operation. No conforming implementation is required to
produce as an output the result of preprocessing the source code. A
conforming implementation can produce any output, even output that
cannot be compiled, assuming it provides the option at all.

As a practical matter, programmers expect to be able to get the result
of preprocessing, and implementations typically provide such output.
Implementations vary in the details of the output, however.


---
Steve Clamage, stephen.clamage@sun.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]