Re: Macro problems between GNU C and Microsoft C

Discussion in 'C Programming' started by spinoza1111, Jun 3, 2010.

  1. spinoza1111

    spinoza1111 Guest

    On Jun 3, 10:52 pm, Frank GOENNINGER <> wrote:
    > Hi all:
    >
    > Having been coding for more than 20 years in various Unix/Linux/OS X
    > flavors I am now challenged to work on Windows.
    >
    > I have:
    >
    > <code>
    >
    > #define AMQP_CHECK_RESULT_CLEANUP(expr, stmts)  \
    >   ({                                            \
    >     int _result = (expr);                       \
    >     if (_result < 0) { stmts; return _result; }      \
    >     _result;                                    \
    >   })
    >
    > </code>
    >
    > (this is from RabbitMQ's C client code, BTW)
    >
    > One use of this macro is:
    >
    > AMQP_CHECK_RESULT_CLEANUP(amqp_decode_field_value(encoded,
    >                                                                                       pool,
    >                                                                                       &entry->value,
    >                                                                                       &offset),
    >                                             free(entries));
    >
    > This should expand into:
    >
    >   {
    >     int _result = ( amqp_decode_field_value(encoded,
    >                                                                                 pool,
    >                                                                                 &entry->value,
    >                                                                                 &offset) );
    >     if ( _result < 0 )
    >     {
    >       free(entries);
    >       return _result;
    >     }
    >
    >     _result;
    >   }
    >
    > On Gnu C this works (although, now that I am writing this, I don't seem
    > to get what the lonely _result; actually does !!!).
    >
    > MS C barks on Syntax Error "{" illegal.
    >
    > Now, well, ok, macrology is sometimes spooky, but why does GNU C simply
    > accepts this of why does MS C not want to swallow it ?
    >
    > Thanks for any hints!!
    >
    > Frank


    Here is one, Frank: check for hidden spaces after the escape
    continuations...they cause an error in Microsoft C.
     
    spinoza1111, Jun 3, 2010
    #1
    1. Advertising

  2. spinoza1111

    James Guest

    "spinoza1111" <> wrote in message
    news:...
    On Jun 3, 10:52 pm, Frank GOENNINGER <> wrote:
    > > Hi all:
    > >
    > > Having been coding for more than 20 years in various Unix/Linux/OS X
    > > flavors I am now challenged to work on Windows.
    > >
    > > I have:

    [...]
    > > MS C barks on Syntax Error "{" illegal.
    > >
    > > Now, well, ok, macrology is sometimes spooky, but why does GNU C simply
    > > accepts this of why does MS C not want to swallow it ?
    > >
    > > Thanks for any hints!!


    > Here is one, Frank: check for hidden spaces after the escape
    > continuations...they cause an error in Microsoft C.


    I don't think MSVC understands the GCC extension.
     
    James, Jun 3, 2010
    #2
    1. Advertising

  3. spinoza1111

    spinoza1111 Guest

    On Jun 3, 11:50 pm, Richard Heathfield <> wrote:
    > spinoza1111wrote:
    > > On Jun 3, 10:52 pm, Frank GOENNINGER <> wrote:

    >
    > <snip>
    >
    > >> MS C barks on Syntax Error "{" illegal.

    >
    > >> Now, well, ok, macrology is sometimes spooky, but why does GNU C simply
    > >> accepts this of why does MS C not want to swallow it ?

    >
    > >> Thanks for any hints!!

    >
    > >> Frank

    >
    > > Here is one, Frank: check for hidden spaces after the escape
    > > continuations...they cause an error in Microsoft C.

    >
    > Nice try, actually, because that *could* have been the reason.
    >
    > James and Jacob have already reported the real reason - gcc offers quite
    > a few extensions to the capability of the C preprocessor, of which
    > assigning a value to a braced expression in a macro is one, and it is
    > one which MSVC does not support (and neither is there any particular
    > reason why it should).
    >
    > Nevertheless, when one uses the line continuation character to extend a
    > macro over more than one physical line, there *is* a danger - not just
    > under Microsoft C but under any implementation - that a stray space or
    > tab could sneak its way after the \, breaking the line-continuation
    > functionality.
    >
    > It was a great answer, in fact. Unfortunately, in this case you picked
    > the wrong question.
    >
    > --
    > Richard Heathfield <http://www.cpax.org.uk>
    > Email: -http://www. +rjh@
    > "Usenet is a strange place" - dmr 29 July 1999
    > Sig line vacant - apply within


    It was a great answer, since it took ten seconds on the Lamma Island
    ferry. And I'm obliged to you, you swine, for confirming my low
    attitude towards C. It's infantile to require the programmer to NOT
    put spaces after the continuation UNLESS there's a reason, and I can't
    think of one.

    Perhaps escape blank means something somewhere?

    I'm certain you won't pass up the opportunity to inform me of this
    rather useless bit of information.
     
    spinoza1111, Jun 4, 2010
    #3
  4. spinoza1111

    Tom St Denis Guest

    On Jun 4, 1:10 pm, Walter Banks <> wrote:
    > spinoza1111 wrote:
    > > It was a great answer, since it took ten seconds on the Lamma Island
    > > ferry. And I'm obliged to you, you swine, for confirming my low
    > > attitude towards C. It's infantile to require the programmer to NOT
    > > put spaces after the continuation UNLESS there's a reason, and I can't
    > > think of one.

    >
    > escape newline = continuation.
    >
    > \n (new line) Moves the active position to the initial position of the
    > next line


    OH SNAP.

    Tom
     
    Tom St Denis, Jun 4, 2010
    #4
  5. spinoza1111

    Guest

    In article <>,
    Walter Banks <> wrote:
    >
    >
    > spinoza1111 wrote:
    >
    > > It was a great answer, since it took ten seconds on the Lamma Island
    > > ferry. And I'm obliged to you, you swine, for confirming my low
    > > attitude towards C. It's infantile to require the programmer to NOT
    > > put spaces after the continuation UNLESS there's a reason, and I can't
    > > think of one.

    >


    Well, I can, and I *think* it's the reason Walter's getting at here:

    >
    > escape newline = continuation.
    >
    > \n (new line) Moves the active position to the initial position of the
    > next line
    >


    Normally "\" as an escape character means that the character
    immediately after the "\" is to be interpreted differently from
    how it's normally interpreted. I can understand how having a
    different rule if what comes after the "\" is one or more spaces
    followed by a newline might be in some ways easier, but it *would*
    be a different rule, no?

    --
    B. L. Massingill
    ObDisclaimer: I don't speak for my employers; they return the favor.
     
    , Jun 6, 2010
    #5
  6. spinoza1111

    Phil Carmody Guest

    Walter Banks <> writes:
    > "" wrote:
    > > Walter Banks <> wrote:
    > > > escape newline = continuation.
    > > >
    > > > \n (new line) Moves the active position to the initial position of the
    > > > next line
    > > >

    > >
    > > Normally "\" as an escape character means that the character
    > > immediately after the "\" is to be interpreted differently from
    > > how it's normally interpreted. I can understand how having a
    > > different rule if what comes after the "\" is one or more spaces
    > > followed by a newline might be in some ways easier, but it *would*
    > > be a different rule, no?

    >
    > There are some compilers that strip trailing spaces on source
    > lines. This makes it look like \ <space> <newline> works.


    However, these are not C compilers. C is not translated that way;
    The standard says so.

    Phil
    --
    I find the easiest thing to do is to k/f myself and just troll away
    -- David Melville on r.a.s.f1
     
    Phil Carmody, Jun 11, 2010
    #6
  7. Walter Banks <> writes:
    <snip>
    > Alternatively can anyone devise a program that would detect
    > trailing space stripping?


    I think this does C89 program does (it is rather contrived):

    #include <stdlib.h>

    int x = /**\
    /EXIT_FAILURE/**/;

    int main(void) { return x; }

    with an optional space in the obvious place (after the \).

    --
    Ben.
     
    Ben Bacarisse, Jun 11, 2010
    #7
  8. Richard Heathfield <> writes:
    > Walter Banks wrote:

    [...]
    > > Only the last backslash on
    >> any physical source line shall be eligible for being part
    >> of such a splice.

    >
    > This is redundant.


    That was my thought as well, but I presume the authors had something in
    mind when they wrote that sentence.

    The only case I can think of where it makes a difference is an
    implementation where physical source lines are terminated by something
    other than a new-line character but can contain embedded new-line
    characters. Assuming that physical source lines are terminated by '@',
    you could have a physical source line like this, where \n represents
    a new-line character:

    x = 42; \\n /* a comment */ \@

    After translation phase 1, we have:

    x = 42; \\n /* a comment */ \\n

    which makes two logical source lines. The first backslash is
    immediately followed by a new-line, so it would normally be spliced,
    but it's not the last backslash on the physical source line, so
    it's a syntax error.

    That might make some sense as a way to flag a certain kind of very
    obscure error, but if the second backslash is removed then the first one
    *is* the last backslash on the physical source line so it will be
    spliced.

    So what is the real purpose of the "Only the last backslash" rule?

    > <snip>
    >
    >> Byte Craft's compilers strip trailing white space.

    >
    > I think that renders those compilers non-conforming in that regard. In
    > this case, that may well be a price you're prepared to pay. Is there at
    > least some way of turning the stripping off?


    Trailing whitespace cannot be stripped in translation phase 2, but I
    believe it can be stripped in translation phase 1.

    For example, think about a system where lines in text files are
    fixed-length with trailing spaces. On such a system, it would be
    unpleasant to require line-splicing backslashes to appear in the
    last column of the physical line.

    Can anyone think of a case where stripping all trailing whitespace
    in phase 1 would either break or change the meaning of a valid
    translation unit? I can't. The only drawback is that it means
    a file that would be rejected by other compilers could compile
    without any diagnostics.

    If the standard were modified to require all trailing whitespace
    to be removed in translation phase 1, would that break anything?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 11, 2010
    #8
  9. Ben Bacarisse <> writes:
    > Walter Banks <> writes:
    > <snip>
    >> Alternatively can anyone devise a program that would detect
    >> trailing space stripping?

    >
    > I think this does C89 program does (it is rather contrived):
    >
    > #include <stdlib.h>
    >
    > int x = /**\
    > /EXIT_FAILURE/**/;
    >
    > int main(void) { return x; }
    >
    > with an optional space in the obvious place (after the \).


    If the lines are not spliced, the EXIT_FAILURE token is
    commented out, and the final result is

    int x = ;

    which is a syntax error.

    I think this should do the job:

    #include <stdlib.h>

    int x = /**\
    /EXIT_FAILURE/**/ + 0;

    int main(void) { return x; }

    If the lines are spliced, then we have (adding whitespace):

    int x = /**/ EXIT_FAILURE /**/ + 0;

    and removing comments:

    int x = EXIT_FAILURE + 0;

    If the lines are not spliced, then we have a single comment:

    int x = /**\\n/EXIT_FAILURE/**/ + 0;

    or:

    int x = +0;

    (I think gcc gets this wrong; when I add a space after the backslash,
    I still get "int x = 1 + 0;" after preprocessing. Or gcc gets it
    right and I'm misunderstanding something.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 11, 2010
    #9
  10. Keith Thompson <> writes:

    > Ben Bacarisse <> writes:
    >> Walter Banks <> writes:
    >> <snip>
    >>> Alternatively can anyone devise a program that would detect
    >>> trailing space stripping?

    >>
    >> I think this does C89 program does (it is rather contrived):
    >>
    >> #include <stdlib.h>
    >>
    >> int x = /**\
    >> /EXIT_FAILURE/**/;
    >>
    >> int main(void) { return x; }
    >>
    >> with an optional space in the obvious place (after the \).

    >
    > If the lines are not spliced, the EXIT_FAILURE token is
    > commented out, and the final result is
    >
    > int x = ;
    >
    > which is a syntax error.


    Yes. That'll teach me to edit just before posting! I started with

    int x = /**\
    /0/**/+1;

    and a printf in main. My *plan* was to edit this to:

    int x /**\
    /=EXIT_FAILURE/**/;

    to use static zero initialisation.

    <snip>
    > (I think gcc gets this wrong; when I add a space after the backslash,
    > I still get "int x = 1 + 0;" after preprocessing. Or gcc gets it
    > right and I'm misunderstanding something.)


    Interesting, gcc behaves differently depending on where the trailing
    scale is. If it is not in a comment, you get a warning:

    warning: backslash and newline separated by space

    but not for the example above. In both cases gcc strips the trailing
    space.

    --
    Ben.
     
    Ben Bacarisse, Jun 11, 2010
    #10
  11. Ben Bacarisse <> writes:
    > Keith Thompson <> writes:

    [...]
    > <snip>
    >> (I think gcc gets this wrong; when I add a space after the backslash,
    >> I still get "int x = 1 + 0;" after preprocessing. Or gcc gets it
    >> right and I'm misunderstanding something.)

    >
    > Interesting, gcc behaves differently depending on where the trailing
    > scale is. If it is not in a comment, you get a warning:
    >
    > warning: backslash and newline separated by space
    >
    > but not for the example above. In both cases gcc strips the trailing
    > space.


    In the normal case, a warning about a backslash-space-newline
    sequence within a /*...*/ comment would be superfluous; the entire
    comment is removed anyway, so the presence or absence of trailing
    whitespace has no effect.

    The only case where it seems to matter is when line-splicing creates
    a */ that closes the comment. Possibly the authors of the GNU C
    preprocessor just didn't think of that case.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 11, 2010
    #11
  12. Kenneth Brody <> writes:
    > On 6/11/2010 10:42 AM, Walter Banks wrote:
    >> Kenneth Brody wrote:

    > [...]
    >>> #define add(foo,bar) ( \
    >>> (foo) + (bar) \
    >>> )
    >>>
    >>> Note the whitespace at the end of the first line.

    >>
    >> Presumably would no longer compile because \<space> is not
    >> defined as part of the language. Can anyone think of a case
    >> where a trailing space stripping would change the meaning of
    >> a conforming program that would still compile?
    >>
    >> Alternatively can anyone devise a program that would detect
    >> trailing space stripping?

    >
    > What about this (*untested*) example:
    >
    > /* Note: the #define of "foo" has trailing whitespace */
    > #define foo \
    > #define bar
    >
    > #ifndef bar
    > #error Oops! Trailing whitespace after backslash was stripped!
    > #endif


    Good, I had a hunch there were cases involving preprocessor directives.

    Here's one that shows the difference at run time:

    #include <stdio.h>

    #define foo \
    #define bar

    int main(void)
    {
    #ifdef bar
    puts("lines were not spliced");
    #else
    puts("lines were spliced");
    #endif
    return 0;
    }

    gcc produces a compile-time warning:
    c:3:13: warning: backslash and newline separated by space

    and the output:
    lines were spliced

    Sun's cc produces no warnings and the output:

    lines were not spliced

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 11, 2010
    #12
  13. Walter Banks <> writes:
    [...]
    > The draft standard words for whitespace before a # preprocessor
    > directive is
    >
    > WG14/N1336 Committee Draft — August 11, 2008 ISO/IEC 9899:201x


    Why are you using that document?

    If you want the latest version of the C99 standard, it's

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

    which includes the C99 standard plus all three Technical Corrigenda.

    The C201x drafts do not (yet) have any official standing, though
    they're certainly of interest to anyone who wants to know where the
    language is going. A more recent C201x draft (and the latest one,
    as far as I know) is

    http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1425.pdf

    > 6.10 Preprocessing directives
    >
    > A preprocessing directive consists of a sequence of preprocessing
    > tokens that satisfies the following constraints: The first token
    > in the sequence is a # preprocessing token that (at the start
    > of translation phase 4) is either the first character in the
    > source file (optionally after white space containing no new-line
    > characters) or that follows white space containing at least
    > one new-line character. The last token in the sequence is the
    > first newline character that follows the first token in the
    > sequence.) A new-line character ends the preprocessing
    > directive even if it occurs within what would otherwise be an
    > invocation of a function-like macro.


    The wording in N1256 is identical to this. The wording is somewhat
    different than in the C99 standard itself; apparently it was changed
    in response to DRs 250 and 303.

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_250.htm
    http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_303.htm

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 11, 2010
    #13
  14. spinoza1111

    Guest

    Richard Heathfield <> wrote [quoting the Standard]:
    > > Only the last backslash on
    > > any physical source line shall be eligible for being part
    > > of such a splice.

    >
    > This is redundant.


    No, it's not. It covers the case where there are multiple backslashes
    at the end of a physical source line and the following line is empty.
    In that case, after the first line splice, the previous backslash is now
    immediately followed by a newline and thus would cause another splice if
    that statement were omitted.
    --
    Larry Jones

    Even if lives DID hang in the balance, it would depend on whose they were.
    -- Calvin
     
    , Jun 11, 2010
    #14
  15. spinoza1111

    Phil Carmody Guest

    Walter Banks <> writes:
    > Phil Carmody wrote:
    > >
    > > Walter Banks <> writes:
    > > > "" wrote:
    > > > > Walter Banks <> wrote:
    > > > > > escape newline = continuation.
    > > > > >
    > > > > > \n (new line) Moves the active position to the initial position of the
    > > > > > next line
    > > > > >
    > > > >
    > > > > Normally "\" as an escape character means that the character
    > > > > immediately after the "\" is to be interpreted differently from
    > > > > how it's normally interpreted. I can understand how having a
    > > > > different rule if what comes after the "\" is one or more spaces
    > > > > followed by a newline might be in some ways easier, but it *would*
    > > > > be a different rule, no?
    > > >
    > > > There are some compilers that strip trailing spaces on source
    > > > lines. This makes it look like \ <space> <newline> works.

    > >
    > > However, these are not C compilers. C is not translated that way;
    > > The standard says so.

    >
    > I am actually not sure. The second line in the full quote from
    > the draft standard has a curious implication
    >
    > "Only the last backslash on any physical source line shall
    > be eligible for being part of such a splice. "
    >
    > I am not sure if this means that trailing white space can be ignored.
    > Maybe Larry Jones would like to weigh in on this.


    It's not "immediately followed" by a new-line character if there is
    something in between, surely?

    That "immediately" must have been added deliberately, so presumably
    for a well-thrashed-out reason.

    > The relevant section is
    >
    > WG14/N1336 Committee Draft — August 11, 2008 ISO/IEC 9899:201x
    >
    > 5.1.1.2 Translation phases
    >
    > 2.


    As has been pointed out, phase 1 carries some flexibility such
    that you could define the text file's encoding such that arbitrary
    trailing space is part of the end-of-line indicator.

    However, I'd say in that case you don't actually have trailing
    spaces, you just have flexibly-sized ends of lines.

    > Each instance of a backslash character (\) immediately followed
    > by a new-line character is deleted, splicing physical source
    > lines to form logical source lines. Only the last backslash on
    > any physical source line shall be eligible for being part
    > of such a splice. A source file that is not empty shall end in
    > a new-line character, which shall not be immediately preceded
    > by a backslash character before any such splicing takes place.
    >
    > Byte Craft's compilers strip trailing white space. This was done
    > some time ago to reduce the number of support calls we were getting
    > on line splicing and because we found that some editors always left
    > lines with a trailing space or did not remove a trailing space
    > when the user split a line with a newline.


    As this can be detected very early on in the parsing phase, could
    it not be 'solved' just by more helpful diagnostics?

    Phil
    --
    I find the easiest thing to do is to k/f myself and just troll away
    -- David Melville on r.a.s.f1
     
    Phil Carmody, Jun 13, 2010
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charles A. Lackman
    Replies:
    1
    Views:
    1,376
    smith
    Dec 8, 2004
  2. SpamProof
    Replies:
    0
    Views:
    584
    SpamProof
    Oct 21, 2003
  3. Peter

    1 day gnu, whole life gnu?

    Peter, Jan 10, 2005, in forum: Java
    Replies:
    3
    Views:
    348
    John C. Bollinger
    Jan 10, 2005
  4. Peter
    Replies:
    17
    Views:
    607
    Chris Smith
    Jan 13, 2005
  5. Markus Elfring
    Replies:
    2
    Views:
    373
    Markus Elfring
    Feb 23, 2005
Loading...

Share This Page